arnaucube
arnaucube/NovaPublic Self-hosted repository
optimize the non-native arithmetic and hashing costs by using 4 limbs instead of 8 (#102)

Srinath Setty srinath@microsoft.com
Wed, 27 Jul 2022 17:09:49 -0700
commit

a56f823ace825d0277699c58ac2cad2066e012cb

parent

111abcab3822e1180aba71f262e8df8f48062e3c

4 files changed, 22 insertions(+), 22 deletions(-)

jump to
M src/bellperson/mod.rs → src/bellperson/mod.rs

@@ -354,14 +354,14 @@ .unwrap();

// First create the shape let mut cs: ShapeCS<G> = ShapeCS::new(); - let _ = synthesize_add(&mut cs, &a_val, &b_val, &c_val, 32, 8); + let _ = synthesize_add(&mut cs, &a_val, &b_val, &c_val, 64, 4); let shape = cs.r1cs_shape(); let gens = cs.r1cs_gens(); println!("Add mod constraint no: {}", cs.num_constraints()); // Now get the assignment let mut cs: SatisfyingAssignment<G> = SatisfyingAssignment::new(); - let _ = synthesize_add(&mut cs, &a_val, &b_val, &c_val, 32, 8); + let _ = synthesize_add(&mut cs, &a_val, &b_val, &c_val, 64, 4); let (inst, witness) = cs.r1cs_instance_and_witness(&shape, &gens).unwrap(); // Make sure that this is satisfiable
M src/circuit.rs → src/circuit.rs

@@ -379,7 +379,7 @@ );

let mut cs: ShapeCS<G1> = ShapeCS::new(); let _ = circuit1.synthesize(&mut cs); let (shape1, gens1) = (cs.r1cs_shape(), cs.r1cs_gens()); - assert_eq!(cs.num_constraints(), 20584); + assert_eq!(cs.num_constraints(), 20122); // Initialize the shape and gens for the secondary let circuit2: NovaAugmentedCircuit<G1, TrivialTestCircuit<<G1 as Group>::Base>> =

@@ -392,7 +392,7 @@ );

let mut cs: ShapeCS<G2> = ShapeCS::new(); let _ = circuit2.synthesize(&mut cs); let (shape2, gens2) = (cs.r1cs_shape(), cs.r1cs_gens()); - assert_eq!(cs.num_constraints(), 21124); + assert_eq!(cs.num_constraints(), 20654); // Execute the base case for the primary let zero1 = <<G2 as Group>::Base as Field>::zero();
M src/constants.rs → src/constants.rs

@@ -1,4 +1,4 @@

pub(crate) const NUM_CHALLENGE_BITS: usize = 128; pub(crate) const NUM_HASH_BITS: usize = 250; -pub(crate) const BN_LIMB_WIDTH: usize = 32; -pub(crate) const BN_N_LIMBS: usize = 8; +pub(crate) const BN_LIMB_WIDTH: usize = 64; +pub(crate) const BN_N_LIMBS: usize = 4;
M src/poseidon.rs → src/poseidon.rs

@@ -9,7 +9,7 @@ ConstraintSystem, SynthesisError,

}; use core::marker::PhantomData; use ff::{PrimeField, PrimeFieldBits}; -use generic_array::typenum::{U27, U32}; +use generic_array::typenum::{U19, U24}; use neptune::{ circuit::poseidon_hash, poseidon::{Poseidon, PoseidonConstants},

@@ -22,8 +22,8 @@ pub struct PoseidonConstantsCircuit<Scalar>

where Scalar: PrimeField, { - constants27: PoseidonConstants<Scalar, U27>, - constants32: PoseidonConstants<Scalar, U32>, + constants19: PoseidonConstants<Scalar, U19>, + constants24: PoseidonConstants<Scalar, U24>, } impl<Scalar> ROConstantsTrait<Scalar> for PoseidonConstantsCircuit<Scalar>

@@ -33,11 +33,11 @@ {

/// Generate Poseidon constants for the arities that Nova uses #[allow(clippy::new_without_default)] fn new() -> Self { - let constants27 = PoseidonConstants::<Scalar, U27>::new_with_strength(Strength::Standard); - let constants32 = PoseidonConstants::<Scalar, U32>::new_with_strength(Strength::Standard); + let constants19 = PoseidonConstants::<Scalar, U19>::new_with_strength(Strength::Standard); + let constants24 = PoseidonConstants::<Scalar, U24>::new_with_strength(Strength::Standard); Self { - constants27, - constants32, + constants19, + constants24, } } }

@@ -78,11 +78,11 @@

/// Compute a challenge by hashing the current state fn squeeze(&self, num_bits: usize) -> Scalar { let hash = match self.state.len() { - 27 => { - Poseidon::<Base, U27>::new_with_preimage(&self.state, &self.constants.constants27).hash() + 19 => { + Poseidon::<Base, U19>::new_with_preimage(&self.state, &self.constants.constants19).hash() } - 32 => { - Poseidon::<Base, U32>::new_with_preimage(&self.state, &self.constants.constants32).hash() + 24 => { + Poseidon::<Base, U24>::new_with_preimage(&self.state, &self.constants.constants24).hash() } _ => { panic!(

@@ -145,15 +145,15 @@ where

CS: ConstraintSystem<Scalar>, { let hash = match self.state.len() { - 27 => poseidon_hash( + 19 => poseidon_hash( cs.namespace(|| "Poseidon hash"), self.state.clone(), - &self.constants.constants27, + &self.constants.constants19, )?, - 32 => poseidon_hash( + 24 => poseidon_hash( cs.namespace(|| "Posideon hash"), self.state.clone(), - &self.constants.constants32, + &self.constants.constants24, )?, _ => { panic!(

@@ -199,7 +199,7 @@ let constants = PoseidonConstantsCircuit::new();

let mut ro: PoseidonRO<S, B> = PoseidonRO::new(constants.clone()); let mut ro_gadget: PoseidonROCircuit<S> = PoseidonROCircuit::new(constants); let mut cs: SatisfyingAssignment<G> = SatisfyingAssignment::new(); - for i in 0..27 { + for i in 0..19 { let num = S::random(&mut csprng); ro.absorb(num); let num_gadget =