arnaucube
arnaucube/NovaPublic Self-hosted repository
cleanup how points are allocated (#29)

Srinath Setty srinath@microsoft.com
Fri, 15 Apr 2022 12:04:52 -0700
commit

866717a8f2ba6a907e294dcd11a5e1a805d8b8c1

parent

9a44d06aec19cacdb2658934659db873d5b05d07

3 files changed, 71 insertions(+), 102 deletions(-)

jump to
M src/circuit.rs → src/circuit.rs

@@ -177,42 +177,22 @@ // Allocate u2 by allocating W_r, E_r, u_r, X_r

/***********************************************************************/ // W_r = (x, y, infinity) - let W_r_x = AllocatedNum::alloc(cs.namespace(|| "W_r.x"), || { - Ok(self.inputs.get()?.u2.comm_W.comm.to_coordinates().0) - })?; - let W_r_y = AllocatedNum::alloc(cs.namespace(|| "W_r.y"), || { - Ok(self.inputs.get()?.u2.comm_W.comm.to_coordinates().1) - })?; - let W_r_inf = AllocatedNum::alloc(cs.namespace(|| "W_r.inf"), || { - let infty = self.inputs.get()?.u2.comm_W.comm.to_coordinates().2; - if infty { - Ok(G::Base::one()) - } else { - Ok(G::Base::zero()) - } - })?; - - let W_r = AllocatedPoint::new(W_r_x.clone(), W_r_y.clone(), W_r_inf.clone()); - let _ = W_r.check_is_infinity(cs.namespace(|| "W_r check is_infinity"))?; + let W_r = AllocatedPoint::alloc( + cs.namespace(|| "allocate W_r"), + self + .inputs + .get() + .map_or(None, |inputs| Some(inputs.u2.comm_W.comm.to_coordinates())), + )?; // E_r = (x, y, infinity) - let E_r_x = AllocatedNum::alloc(cs.namespace(|| "E_r.x"), || { - Ok(self.inputs.get()?.u2.comm_E.comm.to_coordinates().0) - })?; - let E_r_y = AllocatedNum::alloc(cs.namespace(|| "E_r.y"), || { - Ok(self.inputs.get()?.u2.comm_E.comm.to_coordinates().1) - })?; - let E_r_inf = AllocatedNum::alloc(cs.namespace(|| "E_r.inf"), || { - let infty = self.inputs.get()?.u2.comm_E.comm.to_coordinates().2; - if infty { - Ok(G::Base::one()) - } else { - Ok(G::Base::zero()) - } - })?; - - let E_r = AllocatedPoint::new(E_r_x.clone(), E_r_y.clone(), E_r_inf.clone()); - let _ = E_r.check_is_infinity(cs.namespace(|| "E_r check is_infinity")); + let E_r = AllocatedPoint::alloc( + cs.namespace(|| "allocate E_r"), + self + .inputs + .get() + .map_or(None, |inputs| Some(inputs.u2.comm_E.comm.to_coordinates())), + )?; // u_r << |G::Base| despite the fact that u_r is a scalar. // So we parse all of its bytes as a G::Base element

@@ -277,23 +257,14 @@ // Allocate T

/***********************************************************************/ // T = (x, y, infinity) - let T_x = AllocatedNum::alloc(cs.namespace(|| "T.x"), || { - Ok(self.inputs.get()?.T.comm.to_coordinates().0) - })?; - let T_y = AllocatedNum::alloc(cs.namespace(|| "T.y"), || { - Ok(self.inputs.get()?.T.comm.to_coordinates().1) - })?; - let T_inf = AllocatedNum::alloc(cs.namespace(|| "T.inf"), || { - let infty = self.inputs.get()?.T.comm.to_coordinates().2; - if infty { - Ok(G::Base::one()) - } else { - Ok(G::Base::zero()) - } - })?; - let T = AllocatedPoint::new(T_x.clone(), T_y.clone(), T_inf.clone()); - let _ = T.check_is_infinity(cs.namespace(|| "T check is_infinity")); + let T = AllocatedPoint::alloc( + cs.namespace(|| "allocate T"), + self + .inputs + .get() + .map_or(None, |inputs| Some(inputs.T.comm.to_coordinates())), + )?; /***********************************************************************/ // Allocate params

@@ -306,23 +277,13 @@ // Allocate W

/***********************************************************************/ // W = (x, y, infinity) - let W_x = AllocatedNum::alloc(cs.namespace(|| "W.x"), || { - Ok(self.inputs.get()?.w.comm.to_coordinates().0) - })?; - let W_y = AllocatedNum::alloc(cs.namespace(|| "W.y"), || { - Ok(self.inputs.get()?.w.comm.to_coordinates().1) - })?; - let W_inf = AllocatedNum::alloc(cs.namespace(|| "w.inf"), || { - let infty = self.inputs.get()?.w.comm.to_coordinates().2; - if infty { - Ok(G::Base::one()) - } else { - Ok(G::Base::zero()) - } - })?; - - let W = AllocatedPoint::new(W_x.clone(), W_y.clone(), W_inf.clone()); - let _ = W.check_is_infinity(cs.namespace(|| "W check is_infinity")); + let W = AllocatedPoint::alloc( + cs.namespace(|| "allocate W"), + self + .inputs + .get() + .map_or(None, |inputs| Some(inputs.w.comm.to_coordinates())), + )?; /***********************************************************************/ // U2' = default if i == 0, otherwise NIFS.V(pp, u_new, U, T)

@@ -371,12 +332,12 @@ let limb_num = limb

.as_sapling_allocated_num(cs.namespace(|| format!("convert limb {} of h2 to num", i)))?; ro.absorb(limb_num); } - ro.absorb(W_x); - ro.absorb(W_y); - ro.absorb(W_inf); - ro.absorb(T_x); - ro.absorb(T_y); - ro.absorb(T_inf); + ro.absorb(W.x.clone()); + ro.absorb(W.y.clone()); + ro.absorb(W.is_infinity.clone()); + ro.absorb(T.x.clone()); + ro.absorb(T.y.clone()); + ro.absorb(T.is_infinity.clone()); // absorb each of the limbs of X_r[0] for limb in Xr0_bn.clone().into_iter() { ro.absorb(limb);

@@ -554,12 +515,12 @@ let mut h1_hash: PoseidonROGadget<G::Base> =

PoseidonROGadget::new(self.poseidon_constants.clone()); h1_hash.absorb(params.clone()); - h1_hash.absorb(W_r_x); - h1_hash.absorb(W_r_y); - h1_hash.absorb(W_r_inf); - h1_hash.absorb(E_r_x); - h1_hash.absorb(E_r_y); - h1_hash.absorb(E_r_inf); + h1_hash.absorb(W_r.x); + h1_hash.absorb(W_r.y); + h1_hash.absorb(W_r.is_infinity); + h1_hash.absorb(E_r.x); + h1_hash.absorb(E_r.y); + h1_hash.absorb(E_r.is_infinity); h1_hash.absorb(u_r.clone()); // absorb each of the limbs of X_r[0]

@@ -633,12 +594,12 @@

let mut h1_hash: PoseidonROGadget<G::Base> = PoseidonROGadget::new(self.poseidon_constants); h1_hash.absorb(params.clone()); - h1_hash.absorb(W_r_x); - h1_hash.absorb(W_r_y); - h1_hash.absorb(W_r_inf); - h1_hash.absorb(E_r_x); - h1_hash.absorb(E_r_y); - h1_hash.absorb(E_r_inf); + h1_hash.absorb(W_r.x); + h1_hash.absorb(W_r.y); + h1_hash.absorb(W_r.is_infinity); + h1_hash.absorb(E_r.x); + h1_hash.absorb(E_r.y); + h1_hash.absorb(E_r.is_infinity); h1_hash.absorb(u_r); h1_hash.absorb(i.clone());
M src/gadgets/ecc.rs → src/gadgets/ecc.rs

@@ -26,24 +26,32 @@ impl<Fp> AllocatedPoint<Fp>

where Fp: PrimeField, { - // Creates a new allocated point from allocated nums. - pub fn new(x: AllocatedNum<Fp>, y: AllocatedNum<Fp>, is_infinity: AllocatedNum<Fp>) -> Self { - Self { x, y, is_infinity } - } - - // Check that is infinity is 0/1 - pub fn check_is_infinity<CS: ConstraintSystem<Fp>>( - &self, - mut cs: CS, - ) -> Result<(), SynthesisError> { - // Check that is_infinity * ( 1 - is_infinity ) = 0 + pub fn alloc<CS>(mut cs: CS, coords: Option<(Fp, Fp, bool)>) -> Result<Self, SynthesisError> + where + CS: ConstraintSystem<Fp>, + { + let x = AllocatedNum::alloc(cs.namespace(|| "x"), || Ok(coords.unwrap().0))?; + let y = AllocatedNum::alloc(cs.namespace(|| "y"), || Ok(coords.unwrap().1))?; + let is_infinity = AllocatedNum::alloc(cs.namespace(|| "is_infinity"), || { + Ok(if coords.unwrap().2 { + Fp::one() + } else { + Fp::zero() + }) + })?; cs.enforce( || "is_infinity is bit", - |lc| lc + self.is_infinity.get_variable(), - |lc| lc + CS::one() - self.is_infinity.get_variable(), + |lc| lc + is_infinity.get_variable(), + |lc| lc + CS::one() - is_infinity.get_variable(), |lc| lc, ); - Ok(()) + + Ok(AllocatedPoint { x, y, is_infinity }) + } + + // Creates a new allocated point from allocated nums. + pub fn new(x: AllocatedNum<Fp>, y: AllocatedNum<Fp>, is_infinity: AllocatedNum<Fp>) -> Self { + Self { x, y, is_infinity } } // Allocate a random point. Only used for testing
M src/poseidon.rs → src/poseidon.rs

@@ -22,9 +22,9 @@ pub struct NovaPoseidonConstants<F>

where F: PrimeField, { - pub(crate) constants25: PoseidonConstants<F, U25>, - pub(crate) constants27: PoseidonConstants<F, U27>, - pub(crate) constants31: PoseidonConstants<F, U31>, + constants25: PoseidonConstants<F, U25>, + constants27: PoseidonConstants<F, U27>, + constants31: PoseidonConstants<F, U31>, } #[cfg(test)]