Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate Old Poseidon Hash #168

Merged
merged 11 commits into from
Jul 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
### Deprecated

### Removed
- [\#168](https://github.com/Manta-Network/manta-rs/pull/168) Remove old Poseidon hash

### Fixed

Expand Down
6 changes: 3 additions & 3 deletions manta-pay/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ ark-std = { version = "0.3.0", optional = true, default-features = false }
bip32 = { version = "0.3.0", optional = true, default-features = false, features = ["bip39", "secp256k1"] }
blake2 = { version = "0.10.4", default-features = false }
bs58 = { version = "0.4.0", optional = true, default-features = false, features = ["alloc"] }
clap = { version = "3.2.10", optional = true, default-features = false, features = ["color", "derive", "std", "suggestions", "unicode", "wrap_help"] }
clap = { version = "3.2.12", optional = true, default-features = false, features = ["color", "derive", "std", "suggestions", "unicode", "wrap_help"] }
derivative = { version = "2.2.0", default-features = false, features = ["use_core"] }
futures = { version = "0.3.21", optional = true, default-features = false }
indexmap = { version = "1.8.2", optional = true, default-features = false }
Expand All @@ -134,8 +134,8 @@ scale-info = { version = "2.1.2", optional = true, default-features = false, fea
serde_json = { version = "1.0.82", optional = true, default-features = false, features = ["alloc"] }
tempfile = { version = "3.3.0", optional = true, default-features = false }
tide = { version = "0.16.0", optional = true, default-features = false, features = ["h1-server"] }
tokio = { version = "1.18.2", optional = true, default-features = false }
tokio-tungstenite = { version = "0.17.1", optional = true, default-features = false, features = ["native-tls"] }
tokio = { version = "1.20.0", optional = true, default-features = false }
tokio-tungstenite = { version = "0.17.2", optional = true, default-features = false, features = ["native-tls"] }
workspace-hack = { version = "0.1.0", path = "../workspace-hack" }
ws_stream_wasm = { version = "0.7.3", optional = true, default-features = false }

Expand Down
36 changes: 27 additions & 9 deletions manta-pay/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::crypto::{
ecc,
encryption::aes::{self, FixedNonceAesGcm},
key::Blake2sKdf,
poseidon::compat as poseidon,
poseidon::{self, arkworks::TwoPowerMinusOneDomainTag, hash::Hasher},
};
use alloc::vec::Vec;
use ark_ff::ToConstraintField;
Expand Down Expand Up @@ -107,29 +107,47 @@ pub type ProofSystemError = groth16::Error;
/// Poseidon Specification
pub struct PoseidonSpec<const ARITY: usize>;

impl<COM, const ARITY: usize> Constant<COM> for PoseidonSpec<ARITY> {
type Type = Self;

#[inline]
fn new_constant(this: &Self::Type, compiler: &mut COM) -> Self {
let _ = (this, compiler);
Self
}
}

/// Poseidon-2 Hash Parameters
pub type Poseidon2 = poseidon::Hasher<PoseidonSpec<2>, 2>;
pub type Poseidon2 = Hasher<PoseidonSpec<2>, TwoPowerMinusOneDomainTag, 2>;

/// Poseidon-2 Hash Parameters Variable
pub type Poseidon2Var = poseidon::Hasher<PoseidonSpec<2>, 2, Compiler>;
pub type Poseidon2Var = Hasher<PoseidonSpec<2>, TwoPowerMinusOneDomainTag, 2, Compiler>;

impl poseidon::Constants for PoseidonSpec<2> {
const WIDTH: usize = 3;
const FULL_ROUNDS: usize = 8;
const PARTIAL_ROUNDS: usize = 55;
}

impl poseidon::arkworks::Specification for PoseidonSpec<2> {
type Field = ConstraintField;
const FULL_ROUNDS: usize = 8;
const PARTIAL_ROUNDS: usize = 57;
const SBOX_EXPONENT: u64 = 5;
}

/// Poseidon-4 Hash Parameters
pub type Poseidon4 = poseidon::Hasher<PoseidonSpec<4>, 4>;
pub type Poseidon4 = Hasher<PoseidonSpec<4>, TwoPowerMinusOneDomainTag, 4>;

/// Poseidon-4 Hash Parameters Variable
pub type Poseidon4Var = poseidon::Hasher<PoseidonSpec<4>, 4, Compiler>;
pub type Poseidon4Var = Hasher<PoseidonSpec<4>, TwoPowerMinusOneDomainTag, 4, Compiler>;

impl poseidon::Constants for PoseidonSpec<4> {
const WIDTH: usize = 5;
const FULL_ROUNDS: usize = 8;
const PARTIAL_ROUNDS: usize = 56;
}

impl poseidon::arkworks::Specification for PoseidonSpec<4> {
type Field = ConstraintField;
const FULL_ROUNDS: usize = 8;
const PARTIAL_ROUNDS: usize = 60;
const SBOX_EXPONENT: u64 = 5;
}

Expand Down
13 changes: 13 additions & 0 deletions manta-pay/src/crypto/constraint/arkworks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,19 @@ where
}
}

impl<F> Constant<R1CS<F>> for Fp<F>
where
F: PrimeField,
{
type Type = Self;

#[inline]
fn new_constant(this: &Self::Type, compiler: &mut R1CS<F>) -> Self {
let _ = compiler;
*this
}
}

impl<F> Variable<Public, R1CS<F>> for FpVar<F>
where
F: PrimeField,
Expand Down
13 changes: 12 additions & 1 deletion manta-pay/src/crypto/poseidon/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

## Code Structure

* `compat.rs`: Contains legacy implementation for Poseidon hash that is kept for compatibility.
* `constants.rs`: Generates poseidon permutation round numbers.
* `lfsr.rs`: Implements linear feedback shift register as a random number generator.
* `matrix.rs`: Implements basic linear algebra.
Expand All @@ -12,6 +11,8 @@
* `round_constants.rs`: Generates round constants.
* `mds_hardcoded_tests/correct_mds_generation.sage`: Generates hardcoded tests based on sage script adapted from [here](https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/generate_parameters_grain.sage).
* `mds_hardcoded_tests/width*n*`: Contains a hardcoded $n\times n$ MDS matrix generated from the sage script.
* `permutation_hardcoded_test/poseidonperm_bls381_width3.sage`: Generates hardcoded tests based on sage script adapted from [here](https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/poseidonperm_x5_255_3.sage).
* `permutation_hardcoded_test/width3`: Contains a hardcoded width-3 permutation outputs generated from the sage script.

## Generate MDS Hardcoded Tests from SAGE

Expand All @@ -25,3 +26,13 @@ do
done
cd ..
```

## Generate permutation Hardcoded Tests for BLS12-381 from SAGE

The following script generates permutation hardcoded test values:

```sh
cd permutation_hardcoded_test
sage poseidonperm_bls381_width3.sage
cd ..
```
77 changes: 35 additions & 42 deletions manta-pay/src/crypto/poseidon/arkworks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@

use crate::crypto::{
constraint::arkworks::{Fp, FpVar, R1CS},
poseidon::{self, encryption::BlockElement, Field, FieldGeneration},
poseidon::{
self, encryption::BlockElement, hash::DomainTag, Constants, Field, FieldGeneration,
ParameterFieldType,
},
};
use ark_ff::{BigInteger, Field as _, FpParameters, PrimeField};
use ark_r1cs_std::fields::FieldVar;
Expand All @@ -28,44 +31,14 @@ use manta_crypto::constraint::Constant;
type Compiler<S> = R1CS<<S as Specification>::Field>;

/// Poseidon Permutation Specification.
pub trait Specification {
pub trait Specification: Constants {
/// Field Type
type Field: PrimeField;

/// Width of the Permutation
///
/// This number is the total number `t` of field elements in the state which is `F^t`.
const WIDTH: usize;

/// Number of Full Rounds
///
/// The total number of full rounds in Poseidon Hash, including the first set
/// of full rounds and then the second set after the partial rounds.
const FULL_ROUNDS: usize;

/// Number of Partial Rounds
const PARTIAL_ROUNDS: usize;

/// S-BOX Exponenet
const SBOX_EXPONENT: u64;
}

impl<S> Constant<Compiler<S>> for super::Permutation<S, Compiler<S>>
where
S: Specification,
{
type Type = super::Permutation<S>;

#[inline]
fn new_constant(this: &Self::Type, compiler: &mut Compiler<S>) -> Self {
let _ = compiler;
Self {
additive_round_keys: this.additive_round_keys.clone(),
mds_matrix: this.mds_matrix.clone(),
}
}
}

impl<F> Field for Fp<F>
where
F: PrimeField,
Expand Down Expand Up @@ -128,16 +101,18 @@ where
}
}

impl<S> poseidon::Specification for S
impl<S> ParameterFieldType for S
where
S: Specification,
{
type Field = Fp<S::Field>;
type ParameterField = Fp<S::Field>;
}

const WIDTH: usize = S::WIDTH;
const PARTIAL_ROUNDS: usize = S::PARTIAL_ROUNDS;
const FULL_ROUNDS: usize = S::FULL_ROUNDS;
impl<S> poseidon::Specification for S
where
S: Specification,
{
type Field = Fp<S::Field>;

#[inline]
fn add(lhs: &Self::Field, rhs: &Self::Field, _: &mut ()) -> Self::Field {
Expand Down Expand Up @@ -185,11 +160,6 @@ where
S: Specification,
{
type Field = FpVar<S::Field>;
type ParameterField = Fp<S::Field>;

const WIDTH: usize = S::WIDTH;
const PARTIAL_ROUNDS: usize = S::PARTIAL_ROUNDS;
const FULL_ROUNDS: usize = S::FULL_ROUNDS;

#[inline]
fn add(lhs: &Self::Field, rhs: &Self::Field, _: &mut Compiler<S>) -> Self::Field {
Expand Down Expand Up @@ -271,3 +241,26 @@ where
self - rhs
}
}

/// Domain tag as 2^arity - 1
pub struct TwoPowerMinusOneDomainTag;

impl<COM> Constant<COM> for TwoPowerMinusOneDomainTag {
type Type = Self;

#[inline]
fn new_constant(this: &Self::Type, compiler: &mut COM) -> Self {
let _ = (this, compiler);
Self
}
}

impl<S> DomainTag<S> for TwoPowerMinusOneDomainTag
where
S: Specification,
{
#[inline]
fn domain_tag() -> Fp<S::Field> {
Fp(S::Field::from(((1 << (S::WIDTH - 1)) - 1) as u128))
}
}
Loading