diff --git a/src/circuit.rs b/src/circuit.rs index f7054eb..e7a3832 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -54,7 +54,7 @@ where G: Group, { h1: G::Base, - h2: G::Scalar, + h2: G::Base, u2: RelaxedR1CSInstance, i: G::Base, z0: G::Base, @@ -76,7 +76,7 @@ where i: G::Base, z0: G::Base, zi: G::Base, - h2: G::Scalar, + h2: G::Base, params: G::Base, T: Commitment, w: Commitment, @@ -146,32 +146,33 @@ where cs: &mut CS, ) -> Result<(), SynthesisError> { /***********************************************************************/ - // This circuit does not modify h2 but it outputs it. - // Allocate it and output it. + // Allocate h1 /***********************************************************************/ - // Allocate h2 as a big number with 8 limbs - let h2_bn = BigNat::alloc_from_nat( - cs.namespace(|| "allocate h2"), - || Ok(f_to_nat(&self.inputs.get()?.h2)), + let h1 = AllocatedNum::alloc(cs.namespace(|| "allocate h1"), || Ok(self.inputs.get()?.h1))?; + let h1_bn = BigNat::from_num( + cs.namespace(|| "allocate h1_bn"), + Num::from(h1.clone()), self.params.limb_width, self.params.n_limbs, )?; - let _ = h2_bn.inputize(cs.namespace(|| "Output 1"))?; - /***********************************************************************/ - // Allocate h1 + // This circuit does not modify h2 but it outputs it. + // Allocate it and output it. /***********************************************************************/ - let h1 = AllocatedNum::alloc(cs.namespace(|| "allocate h1"), || Ok(self.inputs.get()?.h1))?; - let h1_bn = BigNat::from_num( - cs.namespace(|| "allocate h1_bn"), - Num::from(h1.clone()), + // Allocate h2 as a big number with 8 limbs + let h2 = AllocatedNum::alloc(cs.namespace(|| "allocate h2"), || Ok(self.inputs.get()?.h2))?; + let h2_bn = BigNat::from_num( + cs.namespace(|| "allocate h2_bn"), + Num::from(h2.clone()), self.params.limb_width, self.params.n_limbs, )?; + let _ = h2.inputize(cs.namespace(|| "Output 1"))?; + /***********************************************************************/ // Allocate u2 by allocating W_r, E_r, u_r, X_r /***********************************************************************/ @@ -291,8 +292,6 @@ where // Allocate 0 and 1 let zero = alloc_zero(cs.namespace(|| "zero"))?; - // Hack: We just do this because the number of inputs must be even!! - zero.inputize(cs.namespace(|| "allocate zero as input"))?; let one = alloc_one(cs.namespace(|| "one"))?; // Compute default values of U2': @@ -325,13 +324,7 @@ where let mut ro: PoseidonROGadget = PoseidonROGadget::new(self.poseidon_constants.clone()); ro.absorb(h1.clone()); - // absorb each of the limbs of h2 - // TODO: Check if it is more efficient to treat h2 as allocNum - for (i, limb) in h2_bn.as_limbs::().iter().enumerate() { - let limb_num = limb - .as_sapling_allocated_num(cs.namespace(|| format!("convert limb {} of h2 to num", i)))?; - ro.absorb(limb_num); - } + ro.absorb(h2); ro.absorb(W.x.clone()); ro.absorb(W.y.clone()); ro.absorb(W.is_infinity.clone()); @@ -684,7 +677,7 @@ mod tests { <::Base as Field>::zero(), // TODO: provide real inputs <::Base as Field>::zero(), // TODO: provide real inputs <::Base as Field>::zero(), // TODO: provide real inputs - <::Scalar as Field>::zero(), // TODO: provide real inputs + <::Base as Field>::zero(), // TODO: provide real inputs <::Base as Field>::zero(), // TODO: provide real inputs T, // TODO: provide real inputs w, diff --git a/src/poseidon.rs b/src/poseidon.rs index 0d22b44..9a8672c 100644 --- a/src/poseidon.rs +++ b/src/poseidon.rs @@ -7,7 +7,7 @@ use bellperson::{ ConstraintSystem, SynthesisError, }; use ff::{PrimeField, PrimeFieldBits}; -use generic_array::typenum::{U25, U27, U31}; +use generic_array::typenum::{U24, U25, U27, U31}; use neptune::{ circuit::poseidon_hash, poseidon::{Poseidon, PoseidonConstants}, @@ -22,6 +22,7 @@ pub struct NovaPoseidonConstants where F: PrimeField, { + constants24: PoseidonConstants, constants25: PoseidonConstants, constants27: PoseidonConstants, constants31: PoseidonConstants, @@ -34,10 +35,12 @@ where { /// Generate Poseidon constants for the arities that Nova uses pub fn new() -> Self { + let constants24 = PoseidonConstants::::new_with_strength(Strength::Strengthened); let constants25 = PoseidonConstants::::new_with_strength(Strength::Strengthened); let constants27 = PoseidonConstants::::new_with_strength(Strength::Strengthened); let constants31 = PoseidonConstants::::new_with_strength(Strength::Strengthened); Self { + constants24, constants25, constants27, constants31, @@ -82,6 +85,9 @@ where fn hash_inner(&mut self) -> Scalar { match self.state.len() { + 24 => { + Poseidon::::new_with_preimage(&self.state, &self.constants.constants24).hash() + } 25 => { Poseidon::::new_with_preimage(&self.state, &self.constants.constants25).hash() } @@ -170,6 +176,11 @@ where CS: ConstraintSystem, { let out = match self.state.len() { + 24 => poseidon_hash( + cs.namespace(|| "Posideon hash"), + self.state.clone(), + &self.constants.constants24, + )?, 25 => poseidon_hash( cs.namespace(|| "Poseidon hash"), self.state.clone(), @@ -186,7 +197,10 @@ where &self.constants.constants31, )?, _ => { - panic!("Number of elements in the RO state does not match any of the arities used in Nova") + panic!( + "Number of elements in the RO state does not match any of the arities used in Nova {}", + self.state.len() + ) } };