mirror of https://github.com/zcash/halo2.git
poseidon: Make Spec trait methods not take (&self) parameter.
This commit is contained in:
parent
aa251befbc
commit
b63c868591
|
@ -21,7 +21,7 @@ fn bench_primitives(c: &mut Criterion) {
|
|||
let message = [pallas::Base::random(rng), pallas::Base::random(rng)];
|
||||
|
||||
group.bench_function("2-to-1", |b| {
|
||||
b.iter(|| poseidon::Hash::init(P128Pow5T3, ConstantLength).hash(message))
|
||||
b.iter(|| poseidon::Hash::<_, P128Pow5T3, _, 3, 2>::init(ConstantLength).hash(message))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -239,9 +239,8 @@ impl plonk::Circuit<pallas::Base> for Circuit {
|
|||
let ecc_config = EccChip::configure(meta, advices, lagrange_coeffs, range_check.clone());
|
||||
|
||||
// Configuration for the Poseidon hash.
|
||||
let poseidon_config = PoseidonChip::configure(
|
||||
let poseidon_config = PoseidonChip::configure::<poseidon::P128Pow5T3>(
|
||||
meta,
|
||||
poseidon::P128Pow5T3,
|
||||
// We place the state columns after the partial_sbox column so that the
|
||||
// pad-and-add region can be layed out more efficiently.
|
||||
advices[6..9].try_into().unwrap(),
|
||||
|
|
|
@ -52,7 +52,6 @@ impl<F: FieldExt, const WIDTH: usize, const RATE: usize> Pow5Chip<F, WIDTH, RATE
|
|||
// necessary for the permutation.
|
||||
pub fn configure<S: Spec<F, WIDTH, RATE>>(
|
||||
meta: &mut ConstraintSystem<F>,
|
||||
spec: S,
|
||||
state: [Column<Advice>; WIDTH],
|
||||
partial_sbox: Column<Advice>,
|
||||
rc_a: [Column<Fixed>; WIDTH],
|
||||
|
@ -65,7 +64,7 @@ impl<F: FieldExt, const WIDTH: usize, const RATE: usize> Pow5Chip<F, WIDTH, RATE
|
|||
assert!(S::partial_rounds() & 1 == 0);
|
||||
let half_full_rounds = S::full_rounds() / 2;
|
||||
let half_partial_rounds = S::partial_rounds() / 2;
|
||||
let (round_constants, m_reg, m_inv) = spec.constants();
|
||||
let (round_constants, m_reg, m_inv) = S::constants();
|
||||
|
||||
// This allows state words to be initialized (by constraining them equal to fixed
|
||||
// values), and used in a permutation from an arbitrary region. rc_a is used in
|
||||
|
@ -649,7 +648,7 @@ mod tests {
|
|||
meta.fixed_column(),
|
||||
];
|
||||
|
||||
Pow5Chip::configure(meta, OrchardNullifier, state, partial_sbox, rc_a, rc_b)
|
||||
Pow5Chip::configure::<OrchardNullifier>(meta, state, partial_sbox, rc_a, rc_b)
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
|
@ -685,7 +684,7 @@ mod tests {
|
|||
|
||||
// For the purpose of this test, compute the real final state inline.
|
||||
let mut expected_final_state = [Fp::zero(), Fp::one(), Fp::from_u64(2)];
|
||||
let (round_constants, mds, _) = OrchardNullifier.constants();
|
||||
let (round_constants, mds, _) = OrchardNullifier::constants();
|
||||
poseidon::permute::<_, OrchardNullifier, WIDTH, RATE>(
|
||||
&mut expected_final_state,
|
||||
&mds,
|
||||
|
@ -758,7 +757,7 @@ mod tests {
|
|||
|
||||
meta.enable_constant(rc_b[0]);
|
||||
|
||||
Pow5Chip::configure(meta, OrchardNullifier, state, partial_sbox, rc_a, rc_b)
|
||||
Pow5Chip::configure::<OrchardNullifier>(meta, state, partial_sbox, rc_a, rc_b)
|
||||
}
|
||||
|
||||
fn synthesize(
|
||||
|
@ -811,7 +810,8 @@ mod tests {
|
|||
#[test]
|
||||
fn poseidon_hash() {
|
||||
let message = [Fp::rand(), Fp::rand()];
|
||||
let output = poseidon::Hash::init(OrchardNullifier, ConstantLength::<2>).hash(message);
|
||||
let output =
|
||||
poseidon::Hash::<_, OrchardNullifier, _, 3, 2>::init(ConstantLength::<2>).hash(message);
|
||||
|
||||
let k = 6;
|
||||
let circuit = HashCircuit {
|
||||
|
@ -829,7 +829,8 @@ mod tests {
|
|||
pallas::Base::from_repr(tv.input[0]).unwrap(),
|
||||
pallas::Base::from_repr(tv.input[1]).unwrap(),
|
||||
];
|
||||
let output = poseidon::Hash::init(OrchardNullifier, ConstantLength).hash(message);
|
||||
let output =
|
||||
poseidon::Hash::<_, OrchardNullifier, _, 3, 2>::init(ConstantLength).hash(message);
|
||||
|
||||
let k = 6;
|
||||
let circuit = HashCircuit {
|
||||
|
|
|
@ -47,10 +47,10 @@ pub trait Spec<F: FieldExt, const T: usize, const RATE: usize> {
|
|||
///
|
||||
/// This is used by the default implementation of [`Spec::constants`]. If you are
|
||||
/// hard-coding the constants, you may leave this unimplemented.
|
||||
fn secure_mds(&self) -> usize;
|
||||
fn secure_mds() -> usize;
|
||||
|
||||
/// Generates `(round_constants, mds, mds^-1)` corresponding to this specification.
|
||||
fn constants(&self) -> (Vec<[F; T]>, Mds<F, T>, Mds<F, T>) {
|
||||
fn constants() -> (Vec<[F; T]>, Mds<F, T>, Mds<F, T>) {
|
||||
let r_f = Self::full_rounds();
|
||||
let r_p = Self::partial_rounds();
|
||||
|
||||
|
@ -69,7 +69,7 @@ pub trait Spec<F: FieldExt, const T: usize, const RATE: usize> {
|
|||
})
|
||||
.collect();
|
||||
|
||||
let (mds, mds_inv) = mds::generate_mds::<F, T>(&mut grain, self.secure_mds());
|
||||
let (mds, mds_inv) = mds::generate_mds::<F, T>(&mut grain, Self::secure_mds());
|
||||
|
||||
(round_constants, mds, mds_inv)
|
||||
}
|
||||
|
@ -167,11 +167,10 @@ pub(crate) struct Duplex<F: FieldExt, S: Spec<F, T, RATE>, const T: usize, const
|
|||
impl<F: FieldExt, S: Spec<F, T, RATE>, const T: usize, const RATE: usize> Duplex<F, S, T, RATE> {
|
||||
/// Constructs a new duplex sponge for the given Poseidon specification.
|
||||
pub(crate) fn new(
|
||||
spec: S,
|
||||
initial_capacity_element: F,
|
||||
pad_and_add: Box<dyn Fn(&mut State<F, T>, &SpongeState<F, RATE>)>,
|
||||
) -> Self {
|
||||
let (round_constants, mds_matrix, _) = spec.constants();
|
||||
let (round_constants, mds_matrix, _) = S::constants();
|
||||
|
||||
let input = [None; RATE];
|
||||
let mut state = [F::zero(); T];
|
||||
|
@ -336,13 +335,9 @@ impl<
|
|||
> Hash<F, S, D, T, RATE>
|
||||
{
|
||||
/// Initializes a new hasher.
|
||||
pub fn init(spec: S, domain: D) -> Self {
|
||||
pub fn init(domain: D) -> Self {
|
||||
Hash {
|
||||
duplex: Duplex::new(
|
||||
spec,
|
||||
domain.initial_capacity_element(),
|
||||
domain.pad_and_add(),
|
||||
),
|
||||
duplex: Duplex::new(domain.initial_capacity_element(), domain.pad_and_add()),
|
||||
domain,
|
||||
}
|
||||
}
|
||||
|
@ -371,9 +366,9 @@ mod tests {
|
|||
fn orchard_spec_equivalence() {
|
||||
let message = [pallas::Base::from_u64(6), pallas::Base::from_u64(42)];
|
||||
|
||||
let (round_constants, mds, _) = OrchardNullifier.constants();
|
||||
let (round_constants, mds, _) = OrchardNullifier::constants();
|
||||
|
||||
let hasher = Hash::init(OrchardNullifier, ConstantLength);
|
||||
let hasher = Hash::<_, OrchardNullifier, _, 3, 2>::init(ConstantLength);
|
||||
let result = hasher.hash(message);
|
||||
|
||||
// The result should be equivalent to just directly applying the permutation and
|
||||
|
|
|
@ -25,11 +25,11 @@ impl Spec<Fp, 3, 2> for P128Pow5T3 {
|
|||
val.pow_vartime(&[5])
|
||||
}
|
||||
|
||||
fn secure_mds(&self) -> usize {
|
||||
fn secure_mds() -> usize {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn constants(&self) -> (Vec<[Fp; 3]>, Mds<Fp, 3>, Mds<Fp, 3>) {
|
||||
fn constants() -> (Vec<[Fp; 3]>, Mds<Fp, 3>, Mds<Fp, 3>) {
|
||||
(
|
||||
super::fp::ROUND_CONSTANTS[..].to_vec(),
|
||||
super::fp::MDS,
|
||||
|
@ -51,11 +51,11 @@ impl Spec<Fq, 3, 2> for P128Pow5T3 {
|
|||
val.pow_vartime(&[5])
|
||||
}
|
||||
|
||||
fn secure_mds(&self) -> usize {
|
||||
fn secure_mds() -> usize {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn constants(&self) -> (Vec<[Fq; 3]>, Mds<Fq, 3>, Mds<Fq, 3>) {
|
||||
fn constants() -> (Vec<[Fq; 3]>, Mds<Fq, 3>, Mds<Fq, 3>) {
|
||||
(
|
||||
super::fq::ROUND_CONSTANTS[..].to_vec(),
|
||||
super::fq::MDS,
|
||||
|
@ -80,21 +80,15 @@ mod tests {
|
|||
/// The same Poseidon specification as poseidon::P128Pow5T3, but constructed
|
||||
/// such that its constants will be generated at runtime.
|
||||
#[derive(Debug)]
|
||||
pub struct P128Pow5T3Gen<F: FieldExt> {
|
||||
secure_mds: usize,
|
||||
_field: PhantomData<F>,
|
||||
}
|
||||
pub struct P128Pow5T3Gen<F: FieldExt, const SECURE_MDS: usize>(PhantomData<F>);
|
||||
|
||||
impl<F: FieldExt> P128Pow5T3Gen<F> {
|
||||
pub fn new(secure_mds: usize) -> Self {
|
||||
P128Pow5T3Gen {
|
||||
secure_mds,
|
||||
_field: PhantomData::default(),
|
||||
}
|
||||
impl<F: FieldExt, const SECURE_MDS: usize> P128Pow5T3Gen<F, SECURE_MDS> {
|
||||
pub fn new() -> Self {
|
||||
P128Pow5T3Gen(PhantomData::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: FieldExt> Spec<F, 3, 2> for P128Pow5T3Gen<F> {
|
||||
impl<F: FieldExt, const SECURE_MDS: usize> Spec<F, 3, 2> for P128Pow5T3Gen<F, SECURE_MDS> {
|
||||
fn full_rounds() -> usize {
|
||||
8
|
||||
}
|
||||
|
@ -107,8 +101,8 @@ mod tests {
|
|||
val.pow_vartime(&[5])
|
||||
}
|
||||
|
||||
fn secure_mds(&self) -> usize {
|
||||
self.secure_mds
|
||||
fn secure_mds() -> usize {
|
||||
SECURE_MDS
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,8 +113,7 @@ mod tests {
|
|||
expected_mds: [[F; 3]; 3],
|
||||
expected_mds_inv: [[F; 3]; 3],
|
||||
) {
|
||||
let poseidon = P128Pow5T3Gen::<F>::new(0);
|
||||
let (round_constants, mds, mds_inv) = poseidon.constants();
|
||||
let (round_constants, mds, mds_inv) = P128Pow5T3Gen::<F, 0>::constants();
|
||||
|
||||
for (actual, expected) in round_constants
|
||||
.iter()
|
||||
|
@ -196,7 +189,7 @@ mod tests {
|
|||
]),
|
||||
];
|
||||
|
||||
permute::<Fp, P128Pow5T3Gen<Fp>, 3, 2>(&mut input, &fp::MDS, &fp::ROUND_CONSTANTS);
|
||||
permute::<Fp, P128Pow5T3Gen<Fp, 0>, 3, 2>(&mut input, &fp::MDS, &fp::ROUND_CONSTANTS);
|
||||
assert_eq!(input, expected_output);
|
||||
}
|
||||
|
||||
|
@ -247,7 +240,7 @@ mod tests {
|
|||
]),
|
||||
];
|
||||
|
||||
permute::<Fq, P128Pow5T3Gen<Fq>, 3, 2>(&mut input, &fq::MDS, &fq::ROUND_CONSTANTS);
|
||||
permute::<Fq, P128Pow5T3Gen<Fq, 0>, 3, 2>(&mut input, &fq::MDS, &fq::ROUND_CONSTANTS);
|
||||
assert_eq!(input, expected_output);
|
||||
}
|
||||
}
|
||||
|
@ -255,7 +248,7 @@ mod tests {
|
|||
#[test]
|
||||
fn permute_test_vectors() {
|
||||
{
|
||||
let (round_constants, mds, _) = super::P128Pow5T3.constants();
|
||||
let (round_constants, mds, _) = super::P128Pow5T3::constants();
|
||||
|
||||
for tv in crate::primitives::poseidon::test_vectors::fp::permute() {
|
||||
let mut state = [
|
||||
|
@ -273,7 +266,7 @@ mod tests {
|
|||
}
|
||||
|
||||
{
|
||||
let (round_constants, mds, _) = super::P128Pow5T3.constants();
|
||||
let (round_constants, mds, _) = super::P128Pow5T3::constants();
|
||||
|
||||
for tv in crate::primitives::poseidon::test_vectors::fq::permute() {
|
||||
let mut state = [
|
||||
|
@ -299,7 +292,7 @@ mod tests {
|
|||
Fp::from_repr(tv.input[1]).unwrap(),
|
||||
];
|
||||
|
||||
let result = Hash::init(super::P128Pow5T3, ConstantLength).hash(message);
|
||||
let result = Hash::<_, super::P128Pow5T3, _, 3, 2>::init(ConstantLength).hash(message);
|
||||
|
||||
assert_eq!(result.to_repr(), tv.output);
|
||||
}
|
||||
|
@ -310,7 +303,7 @@ mod tests {
|
|||
Fq::from_repr(tv.input[1]).unwrap(),
|
||||
];
|
||||
|
||||
let result = Hash::init(super::P128Pow5T3, ConstantLength).hash(message);
|
||||
let result = Hash::<_, super::P128Pow5T3, _, 3, 2>::init(ConstantLength).hash(message);
|
||||
|
||||
assert_eq!(result.to_repr(), tv.output);
|
||||
}
|
||||
|
|
|
@ -212,7 +212,8 @@ pub(crate) fn diversify_hash(d: &[u8; 11]) -> NonIdentityPallasPoint {
|
|||
///
|
||||
/// [concreteprfs]: https://zips.z.cash/protocol/nu5.pdf#concreteprfs
|
||||
pub(crate) fn prf_nf(nk: pallas::Base, rho: pallas::Base) -> pallas::Base {
|
||||
poseidon::Hash::init(poseidon::P128Pow5T3, poseidon::ConstantLength).hash([nk, rho])
|
||||
poseidon::Hash::<_, poseidon::P128Pow5T3, _, 3, 2>::init(poseidon::ConstantLength)
|
||||
.hash([nk, rho])
|
||||
}
|
||||
|
||||
/// Defined in [Zcash Protocol Spec § 5.4.5.5: Orchard Key Agreement][concreteorchardkeyagreement].
|
||||
|
|
Loading…
Reference in New Issue