make gadgets public, expose coords, cleanup (#39) * make gadgets public, expose coords, cleanup * fix clippy
Srinath Setty srinath@microsoft.com
Mon, 25 Apr 2022 16:11:56 -0700
6 files changed,
56 insertions(+),
45 deletions(-)
M
src/gadgets/ecc.rs
→
src/gadgets/ecc.rs
@@ -1,3 +1,4 @@
+//! This module implements various elliptic curve gadgets #![allow(non_snake_case)] use crate::gadgets::utils::{ alloc_one, alloc_zero, conditionally_select, conditionally_select2, select_one_or, select_zero_or,@@ -12,6 +13,7 @@ ConstraintSystem, SynthesisError,
}; use ff::PrimeField; +/// AllocatedPoint provides an elliptic curve abstraction inside a circuit. #[derive(Clone)] pub struct AllocatedPoint<Fp> where@@ -26,6 +28,7 @@ impl<Fp> AllocatedPoint<Fp>
where Fp: PrimeField, { + /// Allocates a new point on the curve using coordinates provided by `coords`. pub fn alloc<CS>(mut cs: CS, coords: Option<(Fp, Fp, bool)>) -> Result<Self, SynthesisError> where CS: ConstraintSystem<Fp>,@@ -49,9 +52,24 @@
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 } + /// Allocates a default point on the curve. + pub fn default<CS>(mut cs: CS) -> Result<Self, SynthesisError> + where + CS: ConstraintSystem<Fp>, + { + let zero = alloc_zero(cs.namespace(|| "zero"))?; + let one = alloc_one(cs.namespace(|| "one"))?; + + Ok(AllocatedPoint { + x: zero.clone(), + y: zero, + is_infinity: one, + }) + } + + /// Returns coordinates associated with the point. + pub fn get_coordinates(&self) -> (&AllocatedNum<Fp>, &AllocatedNum<Fp>, &AllocatedNum<Fp>) { + (&self.x, &self.y, &self.is_infinity) } // Allocate a random point. Only used for testing@@ -64,7 +82,11 @@ if y.is_some().unwrap_u8() == 1 {
let x_alloc = AllocatedNum::alloc(cs.namespace(|| "x"), || Ok(x))?; let y_alloc = AllocatedNum::alloc(cs.namespace(|| "y"), || Ok(y.unwrap()))?; let is_infinity = alloc_zero(cs.namespace(|| "Is Infinity"))?; - return Ok(Self::new(x_alloc, y_alloc, is_infinity)); + return Ok(Self { + x: x_alloc, + y: y_alloc, + is_infinity, + }); } } }@@ -80,8 +102,8 @@ .inputize(cs.namespace(|| "Input point.is_infinity"));
Ok(()) } - // Adds other point to this point and returns the result - // Assumes that both other.is_infinity and this.is_infinty are bits + /// Adds other point to this point and returns the result + /// Assumes that both other.is_infinity and this.is_infinty are bits pub fn add<CS: ConstraintSystem<Fp>>( &self, mut cs: CS,@@ -208,7 +230,7 @@ &self.x,
&x, &other.is_infinity, )?; - let final_x = conditionally_select2( + let x = conditionally_select2( cs.namespace(|| "final x: outer if"), &other.x, &inner_x,@@ -222,7 +244,7 @@ &self.y,
&y, &other.is_infinity, )?; - let final_y = conditionally_select2( + let y = conditionally_select2( cs.namespace(|| "final y: outer if"), &other.y, &inner_y,@@ -236,15 +258,16 @@ &self.is_infinity,
&is_infinity, &other.is_infinity, )?; - let final_is_infinity = conditionally_select2( + let is_infinity = conditionally_select2( cs.namespace(|| "final is infinity: outer if"), &other.is_infinity, &inner_is_infinity, &self.is_infinity, )?; - Ok(Self::new(final_x, final_y, final_is_infinity)) + Ok(Self { x, y, is_infinity }) } + /// Doubles the supplied point. pub fn double<CS: ConstraintSystem<Fp>>(&self, mut cs: CS) -> Result<Self, SynthesisError> { //*************************************************************/ // lambda = (Fp::one() + Fp::one() + Fp::one())@@ -359,35 +382,24 @@ // Only return the computed x and y if the point is not infinity
/*************************************************************/ // x - let final_x = select_zero_or(cs.namespace(|| "final x"), &x, &self.is_infinity)?; + let x = select_zero_or(cs.namespace(|| "final x"), &x, &self.is_infinity)?; // y - let final_y = select_zero_or(cs.namespace(|| "final y"), &y, &self.is_infinity)?; + let y = select_zero_or(cs.namespace(|| "final y"), &y, &self.is_infinity)?; // is_infinity - let final_is_infinity = self.is_infinity.clone(); + let is_infinity = self.is_infinity.clone(); - Ok(Self::new(final_x, final_y, final_is_infinity)) + Ok(Self { x, y, is_infinity }) } + /// A gadget for scalar multiplication. pub fn scalar_mul<CS: ConstraintSystem<Fp>>( &self, mut cs: CS, scalar: Vec<AllocatedBit>, ) -> Result<Self, SynthesisError> { - /*************************************************************/ - // Initialize res = Self { - // x: Fp::zero(), - // y: Fp::zero(), - // is_infinity: true, - // _p: Default::default(), - //}; - /*************************************************************/ - - let zero = alloc_zero(cs.namespace(|| "Allocate zero"))?; - let one = alloc_one(cs.namespace(|| "Allocate one"))?; - let mut res = Self::new(zero.clone(), zero, one); - + let mut res = Self::default(cs.namespace(|| "res"))?; for i in (0..scalar.len()).rev() { /*************************************************************/ // res = res.double();@@ -430,7 +442,7 @@ &b.is_infinity,
condition, )?; - Ok(Self::new(x, y, is_infinity)) + Ok(Self { x, y, is_infinity }) } }
M
src/gadgets/mod.rs
→
src/gadgets/mod.rs
@@ -1,3 +1,5 @@
+//! This module implements various gadgets necessary for Nova +//! and applications built with Nova. pub mod ecc; pub mod r1cs; pub mod utils;
M
src/gadgets/r1cs.rs
→
src/gadgets/r1cs.rs
@@ -1,8 +1,9 @@
+//! This module implements various gadgets necessary for folding R1CS types. use crate::{ gadgets::{ ecc::AllocatedPoint, utils::{ - alloc_bignat_constant, alloc_one, alloc_scalar_as_base, alloc_zero, conditionally_select, + alloc_bignat_constant, alloc_scalar_as_base, conditionally_select, conditionally_select_bignat, le_bits_to_num, }, },@@ -59,6 +60,7 @@
Ok(AllocatedR1CSInstance { W, X0, X1 }) } + /// Absorb the provided instance in the RO pub fn absorb_in_ro(&self, ro: &mut PoseidonROGadget<G::Base>) { ro.absorb(self.W.x.clone()); ro.absorb(self.W.y.clone());@@ -136,36 +138,29 @@ mut cs: CS,
limb_width: usize, n_limbs: usize, ) -> Result<Self, SynthesisError> { - let zero = alloc_zero(cs.namespace(|| "zero"))?; - let one = alloc_one(cs.namespace(|| "one"))?; - - let W_default = AllocatedPoint::new(zero.clone(), zero.clone(), one); - let E_default = W_default.clone(); + let W = AllocatedPoint::default(cs.namespace(|| "allocate W"))?; + let E = W.clone(); - let u_default = zero; + let u = W.x.clone(); // In the default case, W.x = u = 0 - let X0_default = BigNat::alloc_from_nat( + let X0 = BigNat::alloc_from_nat( cs.namespace(|| "allocate x_default[0]"), || Ok(f_to_nat(&G::Scalar::zero())), limb_width, n_limbs, )?; - let X1_default = BigNat::alloc_from_nat( + let X1 = BigNat::alloc_from_nat( cs.namespace(|| "allocate x_default[1]"), || Ok(f_to_nat(&G::Scalar::zero())), limb_width, n_limbs, )?; - Ok(AllocatedRelaxedR1CSInstance { - W: W_default, - E: E_default, - u: u_default, - X0: X0_default, - X1: X1_default, - }) + + Ok(AllocatedRelaxedR1CSInstance { W, E, u, X0, X1 }) } + /// Absorb the provided instance in the RO pub fn absorb_in_ro<CS: ConstraintSystem<<G as Group>::Base>>( &self, mut cs: CS,
M
src/gadgets/utils.rs
→
src/gadgets/utils.rs
@@ -1,3 +1,4 @@
+//! This module implements various low-level gadgets use crate::traits::Group; use bellperson::{ gadgets::{
M
src/lib.rs
→
src/lib.rs
@@ -8,7 +8,7 @@
pub mod bellperson; mod circuit; pub mod errors; -mod gadgets; +pub mod gadgets; pub mod pasta; mod poseidon; pub mod r1cs;
M
src/poseidon.rs
→
src/poseidon.rs
@@ -34,6 +34,7 @@ where
F: PrimeField, { /// Generate Poseidon constants for the arities that Nova uses + #[allow(clippy::new_without_default)] pub fn new() -> Self { let constants8 = PoseidonConstants::<F, U8>::new_with_strength(Strength::Strengthened); let constants25 = PoseidonConstants::<F, U25>::new_with_strength(Strength::Strengthened);