diff --git a/Cargo.toml b/Cargo.toml index ffa19656..4bed991f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,7 +72,7 @@ name = "ppsnark" harness = false [features] -default = ["halo2curves/asm"] +# default = ["halo2curves/asm"] # Compiles in portable mode, w/o ISA extensions => binary can be executed on all systems. portable = ["pasta-msm/portable"] flamegraph = ["pprof/flamegraph", "pprof/criterion"] diff --git a/examples/and.rs b/examples/and.rs index 24790720..3f694123 100644 --- a/examples/and.rs +++ b/examples/and.rs @@ -83,7 +83,7 @@ pub fn u64_into_bit_vec_le>( let bits = values .into_iter() .enumerate() - .map(|(i, b)| AllocatedBit::alloc(cs.namespace(|| format!("bit {}", i)), b)) + .map(|(i, b)| AllocatedBit::alloc(cs.namespace(|| (i, format!("bit {}", i))), b)) .collect::, SynthesisError>>()?; Ok(bits) @@ -114,11 +114,11 @@ where }); coeff = coeff.double(); } - let num = AllocatedNum::alloc(cs.namespace(|| "Field element"), || { + let num = AllocatedNum::alloc(cs.namespace(|| (0, "Field element")), || { fe.ok_or(SynthesisError::AssignmentMissing) })?; lc = lc - num.get_variable(); - cs.enforce(|| "compute number from bits", |lc| lc, |lc| lc, |_| lc); + cs.enforce(|| (1, "compute number from bits"), |lc| lc, |lc| lc, |_| lc); Ok(num) } @@ -134,35 +134,35 @@ impl StepCircuit for AndCircuit { ) -> Result>, SynthesisError> { for i in 0..self.batch.len() { // allocate a and b as field elements - let a = AllocatedNum::alloc(cs.namespace(|| format!("a_{}", i)), || { + let a = AllocatedNum::alloc(cs.namespace(|| (i, format!("a_{}", i))), || { Ok(G::Scalar::from(self.batch[i].a)) })?; - let b = AllocatedNum::alloc(cs.namespace(|| format!("b_{}", i)), || { + let b = AllocatedNum::alloc(cs.namespace(|| (i, format!("b_{}", i))), || { Ok(G::Scalar::from(self.batch[i].b)) })?; // obtain bit representations of a and b let a_bits = u64_into_bit_vec_le( - cs.namespace(|| format!("a_bits_{}", i)), + cs.namespace(|| (i, format!("a_bits_{}", i))), Some(self.batch[i].a), )?; // little endian let b_bits = u64_into_bit_vec_le( - cs.namespace(|| format!("b_bits_{}", i)), + cs.namespace(|| (i, format!("b_bits_{}", i))), Some(self.batch[i].b), )?; // little endian // enforce that bits of a and b are correct - let a_from_bits = le_bits_to_num(cs.namespace(|| format!("a_{}", i)), &a_bits)?; - let b_from_bits = le_bits_to_num(cs.namespace(|| format!("b_{}", i)), &b_bits)?; + let a_from_bits = le_bits_to_num(cs.namespace(|| (i, format!("a_{}", i))), &a_bits)?; + let b_from_bits = le_bits_to_num(cs.namespace(|| (i, format!("b_{}", i))), &b_bits)?; cs.enforce( - || format!("a_{} == a_from_bits", i), + || (i, format!("a_{} == a_from_bits", i)), |lc| lc + a.get_variable(), |lc| lc + CS::one(), |lc| lc + a_from_bits.get_variable(), ); cs.enforce( - || format!("b_{} == b_from_bits", i), + || (i, format!("b_{} == b_from_bits", i)), |lc| lc + b.get_variable(), |lc| lc + CS::one(), |lc| lc + b_from_bits.get_variable(), @@ -173,7 +173,7 @@ impl StepCircuit for AndCircuit { // perform bitwise AND for i in 0..64 { let c_bit = AllocatedBit::and( - cs.namespace(|| format!("and_bit_{}", i)), + cs.namespace(|| (i, format!("and_bit_{}", i))), &a_bits[i], &b_bits[i], )?; @@ -181,15 +181,15 @@ impl StepCircuit for AndCircuit { } // convert back to an allocated num - let c_from_bits = le_bits_to_num(cs.namespace(|| format!("c_{}", i)), &c_bits)?; + let c_from_bits = le_bits_to_num(cs.namespace(|| (i, format!("c_{}", i))), &c_bits)?; - let c = AllocatedNum::alloc(cs.namespace(|| format!("c_{}", i)), || { + let c = AllocatedNum::alloc(cs.namespace(|| (i, format!("c_{}", i))), || { Ok(G::Scalar::from(self.batch[i].a & self.batch[i].b)) })?; // enforce that c is correct cs.enforce( - || format!("c_{} == c_from_bits", i), + || (i, format!("c_{} == c_from_bits", i)), |lc| lc + c.get_variable(), |lc| lc + CS::one(), |lc| lc + c_from_bits.get_variable(), diff --git a/examples/hashchain.rs b/examples/hashchain.rs index da5bee5f..5f4ffb07 100644 --- a/examples/hashchain.rs +++ b/examples/hashchain.rs @@ -63,7 +63,7 @@ impl StepCircuit for HashChainCircuit { // allocate x_i let x_i = (0..self.num_elts_per_step) - .map(|i| AllocatedNum::alloc(cs.namespace(|| format!("x_{}", i)), || Ok(self.x_i[i]))) + .map(|i| AllocatedNum::alloc(cs.namespace(|| (i, format!("x_{}", i))), || Ok(self.x_i[i]))) .collect::, _>>()?; // concatenate z_in and x_i @@ -80,7 +80,7 @@ impl StepCircuit for HashChainCircuit { let parameter = IOPattern(vec![SpongeOp::Absorb(num_absorbs), SpongeOp::Squeeze(1u32)]); let pc = Sponge::::api_constants(Strength::Standard); - let mut ns = cs.namespace(|| "ns"); + let mut ns = cs.namespace(|| (0, "ns")); let z_out = { let mut sponge = SpongeCircuit::new_with_constants(&pc, Simplex); @@ -91,7 +91,7 @@ impl StepCircuit for HashChainCircuit { let output = SpongeAPI::squeeze(&mut sponge, 1, acc); sponge.finish(acc).unwrap(); - Elt::ensure_allocated(&output[0], &mut ns.namespace(|| "ensure allocated"), true)? + Elt::ensure_allocated(&output[0], &mut ns.namespace(|| (1, "ensure allocated")), true)? }; Ok(vec![z_out]) diff --git a/examples/minroot.rs b/examples/minroot.rs index 1bb78ef7..e67fd79a 100644 --- a/examples/minroot.rs +++ b/examples/minroot.rs @@ -106,7 +106,7 @@ impl StepCircuit for MinRootCircuit { for i in 0..self.seq.len() { // non deterministic advice let x_i_plus_1 = - AllocatedNum::alloc(cs.namespace(|| format!("x_i_plus_1_iter_{i}")), || { + AllocatedNum::alloc(cs.namespace(|| (i, format!("x_i_plus_1_iter_{i}"))), || { Ok(self.seq[i].x_i_plus_1) })?; @@ -115,11 +115,11 @@ impl StepCircuit for MinRootCircuit { // (ii) y_i_plus_1 = x_i // (1) constraints for condition (i) are below // (2) constraints for condition (ii) is avoided because we just used x_i wherever y_i_plus_1 is used - let x_i_plus_1_sq = x_i_plus_1.square(cs.namespace(|| format!("x_i_plus_1_sq_iter_{i}")))?; + let x_i_plus_1_sq = x_i_plus_1.square(cs.namespace(|| (i, format!("x_i_plus_1_sq_iter_{i}"))))?; let x_i_plus_1_quad = - x_i_plus_1_sq.square(cs.namespace(|| format!("x_i_plus_1_quad_{i}")))?; + x_i_plus_1_sq.square(cs.namespace(|| (i, format!("x_i_plus_1_quad_{i}"))))?; cs.enforce( - || format!("x_i_plus_1_quad * x_i_plus_1 = x_i + y_i_iter_{i}"), + || (i, format!("x_i_plus_1_quad * x_i_plus_1 = x_i + y_i_iter_{i}")), |lc| lc + x_i_plus_1_quad.get_variable(), |lc| lc + x_i_plus_1.get_variable(), |lc| lc + x_i.get_variable() + y_i.get_variable(), diff --git a/src/circuit.rs b/src/circuit.rs index d9b2e36e..9fedc691 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -129,17 +129,17 @@ impl<'a, E: Engine, SC: StepCircuit> NovaAugmentedCircuit<'a, E, SC> { > { // Allocate the params let params = alloc_scalar_as_base::( - cs.namespace(|| "params"), + cs.namespace(|| (0, "params")), self.inputs.as_ref().map(|inputs| inputs.params), )?; // Allocate i - let i = AllocatedNum::alloc(cs.namespace(|| "i"), || Ok(self.inputs.get()?.i))?; + let i = AllocatedNum::alloc(cs.namespace(|| (1, "i")), || Ok(self.inputs.get()?.i))?; // Allocate z0 let z_0 = (0..arity) .map(|i| { - AllocatedNum::alloc(cs.namespace(|| format!("z0_{i}")), || { + AllocatedNum::alloc(cs.namespace(|| (i, format!("z0_{i}"))), || { Ok(self.inputs.get()?.z0[i]) }) }) @@ -149,7 +149,7 @@ impl<'a, E: Engine, SC: StepCircuit> NovaAugmentedCircuit<'a, E, SC> { let zero = vec![E::Base::ZERO; arity]; let z_i = (0..arity) .map(|i| { - AllocatedNum::alloc(cs.namespace(|| format!("zi_{i}")), || { + AllocatedNum::alloc(cs.namespace(|| (i, format!("zi_{i}"))), || { Ok(self.inputs.get()?.zi.as_ref().unwrap_or(&zero)[i]) }) }) @@ -157,35 +157,35 @@ impl<'a, E: Engine, SC: StepCircuit> NovaAugmentedCircuit<'a, E, SC> { // Allocate the running instance let U: AllocatedRelaxedR1CSInstance = AllocatedRelaxedR1CSInstance::alloc( - cs.namespace(|| "Allocate U"), + cs.namespace(|| (2, "Allocate U")), self.inputs.as_ref().and_then(|inputs| inputs.U.as_ref()), self.params.limb_width, self.params.n_limbs, )?; // Allocate ri - let r_i = AllocatedNum::alloc(cs.namespace(|| "ri"), || { + let r_i = AllocatedNum::alloc(cs.namespace(|| (3, "ri")), || { Ok(self.inputs.get()?.ri.unwrap_or(E::Base::ZERO)) })?; // Allocate r_i+1 - let r_next = AllocatedNum::alloc(cs.namespace(|| "r_i+1"), || Ok(self.inputs.get()?.r_next))?; + let r_next = AllocatedNum::alloc(cs.namespace(|| (4, "r_i+1")), || Ok(self.inputs.get()?.r_next))?; // Allocate the instance to be folded in let u = AllocatedR1CSInstance::alloc( - cs.namespace(|| "allocate instance u to fold"), + cs.namespace(|| (5, "allocate instance u to fold")), self.inputs.as_ref().and_then(|inputs| inputs.u.as_ref()), )?; // Allocate T let T = AllocatedPoint::alloc( - cs.namespace(|| "allocate T"), + cs.namespace(|| (6, "allocate T")), self .inputs .as_ref() .and_then(|inputs| inputs.T.map(|T| T.to_coordinates())), )?; - T.check_on_curve(cs.namespace(|| "check T on curve"))?; + T.check_on_curve(cs.namespace(|| (7, "check T on curve")))?; Ok((params, i, z_0, z_i, U, r_i, r_next, u, T)) } @@ -199,14 +199,14 @@ impl<'a, E: Engine, SC: StepCircuit> NovaAugmentedCircuit<'a, E, SC> { let U_default: AllocatedRelaxedR1CSInstance = if self.params.is_primary_circuit { // The primary circuit just returns the default R1CS instance AllocatedRelaxedR1CSInstance::default( - cs.namespace(|| "Allocate U_default"), + cs.namespace(|| (0, "Allocate U_default")), self.params.limb_width, self.params.n_limbs, )? } else { // The secondary circuit returns the incoming R1CS instance AllocatedRelaxedR1CSInstance::from_r1cs_instance( - cs.namespace(|| "Allocate U_default"), + cs.namespace(|| (1, "Allocate U_default")), u, self.params.limb_width, self.params.n_limbs, @@ -243,20 +243,20 @@ impl<'a, E: Engine, SC: StepCircuit> NovaAugmentedCircuit<'a, E, SC> { for e in z_i { ro.absorb(e); } - U.absorb_in_ro(cs.namespace(|| "absorb U"), &mut ro)?; + U.absorb_in_ro(cs.namespace(|| (0, "absorb U")), &mut ro)?; ro.absorb(r_i); - let hash_bits = ro.squeeze(cs.namespace(|| "Input hash"), NUM_HASH_BITS)?; - let hash = le_bits_to_num(cs.namespace(|| "bits to hash"), &hash_bits)?; + let hash_bits = ro.squeeze(cs.namespace( || (1, "Input hash")), NUM_HASH_BITS)?; + let hash = le_bits_to_num(cs.namespace(|| (2, "bits to hash")), &hash_bits)?; let check_pass = alloc_num_equals( - cs.namespace(|| "check consistency of u.X[0] with H(params, U, i, z0, zi)"), + cs.namespace(|| (3, "check consistency of u.X[0] with H(params, U, i, z0, zi)")), &u.X0, &hash, )?; // Run NIFS Verifier let U_fold = U.fold_with_r1cs( - cs.namespace(|| "compute fold of U and u"), + cs.namespace(|| (4, "compute fold of U and u")), params, u, T, @@ -279,19 +279,19 @@ impl> NovaAugmentedCircuit<'_, E, SC> { // Allocate all witnesses let (params, i, z_0, z_i, U, r_i, r_next, u, T) = - self.alloc_witness(cs.namespace(|| "allocate the circuit witness"), arity)?; + self.alloc_witness(cs.namespace(|| (0, "allocate the circuit witness")), arity)?; // Compute variable indicating if this is the base case - let zero = alloc_zero(cs.namespace(|| "zero")); - let is_base_case = alloc_num_equals(cs.namespace(|| "Check if base case"), &i.clone(), &zero)?; + let zero = alloc_zero(cs.namespace(|| (1, "zero"))); + let is_base_case = alloc_num_equals(cs.namespace(|| (2, "Check if base case")), &i.clone(), &zero)?; // Synthesize the circuit for the base case and get the new running instance - let Unew_base = self.synthesize_base_case(cs.namespace(|| "base case"), u.clone())?; + let Unew_base = self.synthesize_base_case(cs.namespace(|| (3, "base case") ), u.clone())?; // Synthesize the circuit for the non-base case and get the new running // instance along with a boolean indicating if all checks have passed let (Unew_non_base, check_non_base_pass) = self.synthesize_non_base_case( - cs.namespace(|| "synthesize non base case"), + cs.namespace(|| (4, "synthesize non base case")), ¶ms, &i, &z_0, @@ -305,12 +305,12 @@ impl> NovaAugmentedCircuit<'_, E, SC> { // Either check_non_base_pass=true or we are in the base case let should_be_false = AllocatedBit::nor( - cs.namespace(|| "check_non_base_pass nor base_case"), + cs.namespace(|| (5, "check_non_base_pass nor base_case")), &check_non_base_pass, &is_base_case, )?; cs.enforce( - || "check_non_base_pass nor base_case = false", + || (6, "check_non_base_pass nor base_case = false"), |lc| lc + should_be_false.get_variable(), |lc| lc + CS::one(), |lc| lc, @@ -318,17 +318,17 @@ impl> NovaAugmentedCircuit<'_, E, SC> { // Compute the U_new let Unew = Unew_base.conditionally_select( - cs.namespace(|| "compute U_new"), + cs.namespace(|| (7, "compute U_new")), &Unew_non_base, &Boolean::from(is_base_case.clone()), )?; // Compute i + 1 - let i_new = AllocatedNum::alloc(cs.namespace(|| "i + 1"), || { + let i_new = AllocatedNum::alloc(cs.namespace(|| (8, "i + 1")), || { Ok(*i.get_value().get()? + E::Base::ONE) })?; cs.enforce( - || "check i + 1", + || (9, "check i + 1"), |lc| lc, |lc| lc, |lc| lc + i_new.get_variable() - CS::one() - i.get_variable(), @@ -336,7 +336,7 @@ impl> NovaAugmentedCircuit<'_, E, SC> { // Compute z_{i+1} let z_input = conditionally_select_vec( - cs.namespace(|| "select input to F"), + cs.namespace(|| (10, "select input to F")), &z_0, &z_i, &Boolean::from(is_base_case), @@ -344,7 +344,7 @@ impl> NovaAugmentedCircuit<'_, E, SC> { let z_next = self .step_circuit - .synthesize(&mut cs.namespace(|| "F"), &z_input)?; + .synthesize(&mut cs.namespace(|| (11, "F")), &z_input)?; if z_next.len() != arity { return Err(SynthesisError::IncompatibleLengthVector( @@ -362,15 +362,15 @@ impl> NovaAugmentedCircuit<'_, E, SC> { for e in &z_next { ro.absorb(e); } - Unew.absorb_in_ro(cs.namespace(|| "absorb U_new"), &mut ro)?; + Unew.absorb_in_ro(cs.namespace(|| (12, "absorb U_new") ), &mut ro)?; ro.absorb(&r_next); - let hash_bits = ro.squeeze(cs.namespace(|| "output hash bits"), NUM_HASH_BITS)?; - let hash = le_bits_to_num(cs.namespace(|| "convert hash to num"), &hash_bits)?; + let hash_bits = ro.squeeze(cs.namespace(|| (13, "output hash bits")), NUM_HASH_BITS)?; + let hash = le_bits_to_num(cs.namespace(|| (14, "convert hash to num")), &hash_bits)?; // Outputs the computed hash and u.X[1] that corresponds to the hash of the other circuit u.X1 - .inputize(cs.namespace(|| "Output unmodified hash of the other circuit"))?; - hash.inputize(cs.namespace(|| "output new hash of this circuit"))?; + .inputize(cs.namespace(|| (15, "Output unmodified hash of the other circuit")))?; + hash.inputize(cs.namespace(|| (16, "output new hash of this circuit")))?; Ok(z_next) } diff --git a/src/frontend/constraint_system.rs b/src/frontend/constraint_system.rs index 51306f71..4725ab66 100644 --- a/src/frontend/constraint_system.rs +++ b/src/frontend/constraint_system.rs @@ -94,7 +94,7 @@ pub trait ConstraintSystem: Sized + Send { /// in order to derive a unique name for the constraint in the current namespace. fn enforce(&mut self, annotation: A, a: LA, b: LB, c: LC) where - A: FnOnce() -> AR, + A: FnOnce() -> (usize, AR), AR: Into, LA: FnOnce(LinearCombination) -> LinearCombination, LB: FnOnce(LinearCombination) -> LinearCombination, @@ -105,7 +105,7 @@ pub trait ConstraintSystem: Sized + Send { fn push_namespace(&mut self, name_fn: N) where NR: Into, - N: FnOnce() -> NR; + N: FnOnce() -> (usize, NR); /// Exit out of the existing namespace. Not intended for /// downstream use; use `namespace` instead. @@ -119,7 +119,7 @@ pub trait ConstraintSystem: Sized + Send { fn namespace(&mut self, name_fn: N) -> Namespace<'_, Scalar, Self::Root> where NR: Into, - N: FnOnce() -> NR, + N: FnOnce() -> (usize, NR), { self.get_root().push_namespace(name_fn); @@ -238,8 +238,8 @@ pub struct Namespace<'a, Scalar: PrimeField, CS: ConstraintSystem>( PhantomData, ); -impl> ConstraintSystem - for Namespace<'_, Scalar, CS> +impl<'cs, Scalar: PrimeField, CS: ConstraintSystem> ConstraintSystem + for Namespace<'cs, Scalar, CS> { type Root = CS::Root; @@ -267,7 +267,7 @@ impl> ConstraintSystem fn enforce(&mut self, annotation: A, a: LA, b: LB, c: LC) where - A: FnOnce() -> AR, + A: FnOnce() -> (usize, AR), AR: Into, LA: FnOnce(LinearCombination) -> LinearCombination, LB: FnOnce(LinearCombination) -> LinearCombination, @@ -280,10 +280,10 @@ impl> ConstraintSystem // functions and they will never be invoked because the namespace is // never a root constraint system. - fn push_namespace(&mut self, _: N) + fn push_namespace(&mut self, _name_fn: N) where NR: Into, - N: FnOnce() -> NR, + N: FnOnce() -> (usize, NR), { panic!("only the root's push_namespace should be called"); } @@ -320,7 +320,7 @@ impl> ConstraintSystem } } -impl> Drop for Namespace<'_, Scalar, CS> { +impl<'a, Scalar: PrimeField, CS: ConstraintSystem> Drop for Namespace<'a, Scalar, CS> { fn drop(&mut self) { self.get_root().pop_namespace() } @@ -328,7 +328,9 @@ impl> Drop for Namespace<'_, Sc /// Convenience implementation of ConstraintSystem for mutable references to /// constraint systems. -impl> ConstraintSystem for &'_ mut CS { +impl<'cs, Scalar: PrimeField, CS: ConstraintSystem> ConstraintSystem + for &'cs mut CS +{ type Root = CS::Root; fn one() -> Variable { @@ -355,7 +357,7 @@ impl> ConstraintSystem fn enforce(&mut self, annotation: A, a: LA, b: LB, c: LC) where - A: FnOnce() -> AR, + A: FnOnce() -> (usize, AR), AR: Into, LA: FnOnce(LinearCombination) -> LinearCombination, LB: FnOnce(LinearCombination) -> LinearCombination, @@ -367,7 +369,7 @@ impl> ConstraintSystem fn push_namespace(&mut self, name_fn: N) where NR: Into, - N: FnOnce() -> NR, + N: FnOnce() -> (usize, NR), { (**self).push_namespace(name_fn) } @@ -383,7 +385,7 @@ impl> ConstraintSystem fn namespace(&mut self, name_fn: N) -> Namespace<'_, Scalar, Self::Root> where NR: Into, - N: FnOnce() -> NR, + N: FnOnce() -> (usize, NR), { (**self).namespace(name_fn) } diff --git a/src/frontend/gadgets/boolean.rs b/src/frontend/gadgets/boolean.rs index f5f0c656..ba0b9c5a 100644 --- a/src/frontend/gadgets/boolean.rs +++ b/src/frontend/gadgets/boolean.rs @@ -53,7 +53,7 @@ impl AllocatedBit { // reduces to (1 - a) * a = 0, which is a // traditional boolean constraint. cs.enforce( - || "boolean constraint", + || (0, "boolean constraint"), |lc| lc + CS::one() - must_be_false.variable - var, |lc| lc + var, |lc| lc, @@ -86,7 +86,7 @@ impl AllocatedBit { // Constrain: (1 - a) * a = 0 // This constrains a to be either 0 or 1. cs.enforce( - || "boolean constraint", + || (0, "boolean constraint"), |lc| lc + CS::one() - var, |lc| lc + var, |lc| lc, @@ -140,7 +140,7 @@ impl AllocatedBit { // 2a * b = a + b - c // (a + a) * b = a + b - c cs.enforce( - || "xor constraint", + || (0, "xor constraint"), |lc| lc + a.variable + a.variable, |lc| lc + b.variable, |lc| lc + a.variable + b.variable - result_var, @@ -181,7 +181,7 @@ impl AllocatedBit { // Constrain (a) * (b) = (c), ensuring c is 1 iff // a AND b are both 1. cs.enforce( - || "and constraint", + || (0, "and constraint"), |lc| lc + a.variable, |lc| lc + b.variable, |lc| lc + result_var, @@ -221,7 +221,7 @@ impl AllocatedBit { // Constrain (a) * (1 - b) = (c), ensuring c is 1 iff // a is true and b is false, and otherwise c is 0. cs.enforce( - || "and not constraint", + || (0, "and not constraint"), |lc| lc + a.variable, |lc| lc + CS::one() - b.variable, |lc| lc + result_var, @@ -261,7 +261,7 @@ impl AllocatedBit { // Constrain (1 - a) * (1 - b) = (c), ensuring c is 1 iff // a and b are both false, and otherwise c is 0. cs.enforce( - || "nor constraint", + || (0, "nor constraint"), |lc| lc + CS::one() - a.variable, |lc| lc + CS::one() - b.variable, |lc| lc + result_var, @@ -315,7 +315,7 @@ where .into_iter() .rev() .enumerate() - .map(|(i, b)| AllocatedBit::alloc(cs.namespace(|| format!("bit {}", i)), b)) + .map(|(i, b)| AllocatedBit::alloc(cs.namespace(|| (i, format!("bit {}", i))), b)) .collect::, SynthesisError>>()?; Ok(bits) @@ -355,7 +355,7 @@ impl Boolean { } (&Boolean::Constant(true), a) | (a, &Boolean::Constant(true)) => { cs.enforce( - || "enforce equal to one", + || (0, "enforce equal to one"), |lc| lc, |lc| lc, |lc| lc + CS::one() - &a.lc(CS::one(), Scalar::ONE), @@ -365,7 +365,7 @@ impl Boolean { } (&Boolean::Constant(false), a) | (a, &Boolean::Constant(false)) => { cs.enforce( - || "enforce equal to zero", + || (1, "enforce equal to zero"), |lc| lc, |lc| lc, |_| a.lc(CS::one(), Scalar::ONE), @@ -375,7 +375,7 @@ impl Boolean { } (a, b) => { cs.enforce( - || "enforce equal", + || (2, "enforce equal"), |lc| lc, |lc| lc, |_| a.lc(CS::one(), Scalar::ONE) - &b.lc(CS::one(), Scalar::ONE), @@ -483,7 +483,7 @@ impl Boolean { CS: ConstraintSystem, { Ok(Boolean::not(&Boolean::and( - cs.namespace(|| "not and (not a) (not b)"), + cs.namespace(|| (0, "not and (not a) (not b)")), &Boolean::not(a), &Boolean::not(b), )?)) @@ -584,7 +584,7 @@ impl Boolean { // a(b - c) = ch - c cs.enforce( - || "ch computation", + || (0, "ch computation"), |_| b.lc(CS::one(), Scalar::ONE) - &c.lc(CS::one(), Scalar::ONE), |_| a.lc(CS::one(), Scalar::ONE), |lc| lc + ch - &c.lc(CS::one(), Scalar::ONE), @@ -697,10 +697,10 @@ impl Boolean { // (b) * (c) = (bc) // (2bc - b - c) * (a) = bc - maj - let bc = Self::and(cs.namespace(|| "b and c"), b, c)?; + let bc = Self::and(cs.namespace(|| (0, "b and c")), b, c)?; cs.enforce( - || "maj computation", + || (1, "maj computation"), |_| { bc.lc(CS::one(), Scalar::ONE) + &bc.lc(CS::one(), Scalar::ONE) - &b.lc(CS::one(), Scalar::ONE) diff --git a/src/frontend/gadgets/multieq.rs b/src/frontend/gadgets/multieq.rs index 35a38800..78866948 100644 --- a/src/frontend/gadgets/multieq.rs +++ b/src/frontend/gadgets/multieq.rs @@ -27,7 +27,7 @@ impl> MultiEq { let lhs = self.lhs.clone(); let rhs = self.rhs.clone(); self.cs.enforce( - || format!("multieq {}", ops), + || (ops, format!("multieq {}", ops)), |_| lhs, |lc| lc + CS::one(), |_| rhs, @@ -95,7 +95,7 @@ impl> ConstraintSystem fn enforce(&mut self, annotation: A, a: LA, b: LB, c: LC) where - A: FnOnce() -> AR, + A: FnOnce() -> (usize, AR), AR: Into, LA: FnOnce(LinearCombination) -> LinearCombination, LB: FnOnce(LinearCombination) -> LinearCombination, @@ -107,7 +107,7 @@ impl> ConstraintSystem fn push_namespace(&mut self, name_fn: N) where NR: Into, - N: FnOnce() -> NR, + N: FnOnce() -> (usize, NR), { self.cs.get_root().push_namespace(name_fn) } diff --git a/src/frontend/gadgets/num.rs b/src/frontend/gadgets/num.rs index af324a56..18d845bd 100644 --- a/src/frontend/gadgets/num.rs +++ b/src/frontend/gadgets/num.rs @@ -109,7 +109,7 @@ impl AllocatedNum { )?; cs.enforce( - || "enforce input is correct", + || (0, "enforce input is correct"), |lc| lc + input, |lc| lc + CS::one(), |lc| lc + self.variable, @@ -147,7 +147,7 @@ impl AllocatedNum { cur = Some(v.clone()); } else { cur = Some(AllocatedBit::and( - cs.namespace(|| format!("and {}", i)), + cs.namespace(|| (i, format!("and {}", i))), cur.as_ref().unwrap(), v, )?); @@ -189,7 +189,7 @@ impl AllocatedNum { if b { // This is part of a run of ones. Let's just // allocate the boolean with the expected value. - let a_bit = AllocatedBit::alloc(cs.namespace(|| format!("bit {}", i)), a_bit)?; + let a_bit = AllocatedBit::alloc(cs.namespace(|| (i, format!("bit {}", i))), a_bit)?; // ... and add it to the current run of ones. current_run.push(a_bit.clone()); result.push(a_bit); @@ -202,7 +202,7 @@ impl AllocatedNum { current_run.push(last_run.clone().unwrap()); } last_run = Some(kary_and( - cs.namespace(|| format!("run ending at {}", i)), + cs.namespace(|| (i, format!("run ending at {}", i))), ¤t_run, )?); current_run.truncate(0); @@ -214,7 +214,7 @@ impl AllocatedNum { // If `last_run` is false, `a` can be true or false. let a_bit = AllocatedBit::alloc_conditionally( - cs.namespace(|| format!("bit {}", i)), + cs.namespace(|| (i, format!("bit {}", i))), a_bit, last_run.as_ref().expect("char always starts with a one"), )?; @@ -242,7 +242,7 @@ impl AllocatedNum { lc = lc - self.variable; - cs.enforce(|| "unpacking constraint", |lc| lc, |lc| lc, |_| lc); + cs.enforce(|| (0, "unpacking constraint"), |lc| lc, |lc| lc, |_| lc); // Convert into booleans, and reverse for little-endian bit order Ok(result.into_iter().map(Boolean::from).rev().collect()) @@ -269,7 +269,7 @@ impl AllocatedNum { lc = lc - self.variable; - cs.enforce(|| "unpacking constraint", |lc| lc, |lc| lc, |_| lc); + cs.enforce(|| (0, "unpacking constraint"), |lc| lc, |lc| lc, |_| lc); Ok(bits.into_iter().map(Boolean::from).collect()) } @@ -295,7 +295,7 @@ impl AllocatedNum { // Constrain: (a + b) * 1 = a + b cs.enforce( - || "addition constraint", + || (0, "addition constraint"), |lc| lc + self.variable + other.variable, |lc| lc + CS::one(), |lc| lc + var, @@ -328,7 +328,7 @@ impl AllocatedNum { // Constrain: a * b = ab cs.enforce( - || "multiplication constraint", + || (0, "multiplication constraint"), |lc| lc + self.variable, |lc| lc + other.variable, |lc| lc + var, @@ -361,7 +361,7 @@ impl AllocatedNum { // Constrain: a * a = aa cs.enforce( - || "squaring constraint", + || (0, "squaring constraint"), |lc| lc + self.variable, |lc| lc + self.variable, |lc| lc + var, @@ -395,7 +395,7 @@ impl AllocatedNum { // iff a has a multiplicative inverse, untrue // for zero. cs.enforce( - || "nonzero assertion constraint", + || (0, "nonzero assertion constraint"), |lc| lc + self.variable, |lc| lc + inv, |lc| lc + CS::one(), @@ -416,7 +416,7 @@ impl AllocatedNum { where CS: ConstraintSystem, { - let c = Self::alloc(cs.namespace(|| "conditional reversal result 1"), || { + let c = Self::alloc(cs.namespace(|| (0, "conditional reversal result 1")), || { if condition .get_value() .ok_or(SynthesisError::AssignmentMissing)? @@ -428,13 +428,13 @@ impl AllocatedNum { })?; cs.enforce( - || "first conditional reversal", + || (1, "first conditional reversal"), |lc| lc + a.variable - b.variable, |_| condition.lc(CS::one(), Scalar::ONE), |lc| lc + a.variable - c.variable, ); - let d = Self::alloc(cs.namespace(|| "conditional reversal result 2"), || { + let d = Self::alloc(cs.namespace(|| (2, "conditional reversal result 2")), || { if condition .get_value() .ok_or(SynthesisError::AssignmentMissing)? @@ -446,7 +446,7 @@ impl AllocatedNum { })?; cs.enforce( - || "second conditional reversal", + || (3, "second conditional reversal"), |lc| lc + b.variable - a.variable, |_| condition.lc(CS::one(), Scalar::ONE), |lc| lc + b.variable - d.variable, diff --git a/src/frontend/gadgets/sha256.rs b/src/frontend/gadgets/sha256.rs index a0408ad7..46ae00cc 100644 --- a/src/frontend/gadgets/sha256.rs +++ b/src/frontend/gadgets/sha256.rs @@ -51,7 +51,7 @@ where let mut cur = get_sha256_iv(); for (i, block) in padded.chunks(512).enumerate() { - cur = sha256_compression_function(cs.namespace(|| format!("block {}", i)), block, &cur)?; + cur = sha256_compression_function(cs.namespace(|| (i, format!("block {}", i))), block, &cur)?; } Ok(cur.into_iter().flat_map(|e| e.into_bits_be()).collect()) @@ -84,20 +84,20 @@ where let mut cs = MultiEq::new(cs); for i in 16..64 { - let cs = &mut cs.namespace(|| format!("w extension {}", i)); + let cs = &mut cs.namespace(|| (i, format!("w extension {}", i))); // s0 := (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor (w[i-15] rightshift 3) let mut s0 = w[i - 15].rotr(7); - s0 = s0.xor(cs.namespace(|| "first xor for s0"), &w[i - 15].rotr(18))?; - s0 = s0.xor(cs.namespace(|| "second xor for s0"), &w[i - 15].shr(3))?; + s0 = s0.xor(cs.namespace(|| (i, "first xor for s0")), &w[i - 15].rotr(18))?; + s0 = s0.xor(cs.namespace(|| (i, "second xor for s0")), &w[i - 15].shr(3))?; // s1 := (w[i-2] rightrotate 17) xor (w[i-2] rightrotate 19) xor (w[i-2] rightshift 10) let mut s1 = w[i - 2].rotr(17); - s1 = s1.xor(cs.namespace(|| "first xor for s1"), &w[i - 2].rotr(19))?; - s1 = s1.xor(cs.namespace(|| "second xor for s1"), &w[i - 2].shr(10))?; + s1 = s1.xor(cs.namespace(|| (i, "first xor for s1")), &w[i - 2].rotr(19))?; + s1 = s1.xor(cs.namespace(|| (i, "second xor for s1")), &w[i - 2].shr(10))?; let tmp = UInt32::addmany( - cs.namespace(|| "computation of w[i]"), + cs.namespace(|| (i, "computation of w[i]")), &[w[i - 16].clone(), s0, w[i - 7].clone(), s1], )?; @@ -139,16 +139,16 @@ where let mut h = current_hash_value[7].clone(); for i in 0..64 { - let cs = &mut cs.namespace(|| format!("compression round {}", i)); + let cs = &mut cs.namespace(|| (i, format!("compression round {}", i))); // S1 := (e rightrotate 6) xor (e rightrotate 11) xor (e rightrotate 25) - let new_e = e.compute(cs.namespace(|| "deferred e computation"), &[])?; + let new_e = e.compute(cs.namespace(|| (i, "deferred e computation")), &[])?; let mut s1 = new_e.rotr(6); - s1 = s1.xor(cs.namespace(|| "first xor for s1"), &new_e.rotr(11))?; - s1 = s1.xor(cs.namespace(|| "second xor for s1"), &new_e.rotr(25))?; + s1 = s1.xor(cs.namespace(|| (i, "first xor for s1")), &new_e.rotr(11))?; + s1 = s1.xor(cs.namespace(|| (i, "second xor for s1")), &new_e.rotr(25))?; // ch := (e and f) xor ((not e) and g) - let ch = UInt32::sha256_ch(cs.namespace(|| "ch"), &new_e, &f, &g)?; + let ch = UInt32::sha256_ch(cs.namespace(|| (i, "ch")), &new_e, &f, &g)?; // temp1 := h + S1 + ch + k[i] + w[i] let temp1 = [ @@ -160,15 +160,14 @@ where ]; // S0 := (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22) - let new_a = a.compute(cs.namespace(|| "deferred a computation"), &[])?; + let new_a = a.compute(cs.namespace(|| (i, "deferred a computation")), &[])?; let mut s0 = new_a.rotr(2); - s0 = s0.xor(cs.namespace(|| "first xor for s0"), &new_a.rotr(13))?; - s0 = s0.xor(cs.namespace(|| "second xor for s0"), &new_a.rotr(22))?; + s0 = s0.xor(cs.namespace(|| (i, "first xor for s0")), &new_a.rotr(13))?; + s0 = s0.xor(cs.namespace(|| (i, "second xor for s0")), &new_a.rotr(22))?; // maj := (a and b) xor (a and c) xor (b and c) - let maj = UInt32::sha256_maj(cs.namespace(|| "maj"), &new_a, &b, &c)?; + let maj = UInt32::sha256_maj(cs.namespace(|| (i, "maj")), &new_a, &b, &c)?; - // temp2 := S0 + maj let temp2 = [s0, maj]; /* @@ -211,42 +210,42 @@ where */ let h0 = a.compute( - cs.namespace(|| "deferred h0 computation"), + cs.namespace(|| (0, "deferred h0 computation")), &[current_hash_value[0].clone()], )?; let h1 = UInt32::addmany( - cs.namespace(|| "new h1"), + cs.namespace(|| (1, "new h1")), &[current_hash_value[1].clone(), b], )?; let h2 = UInt32::addmany( - cs.namespace(|| "new h2"), + cs.namespace(|| (2, "new h2")), &[current_hash_value[2].clone(), c], )?; let h3 = UInt32::addmany( - cs.namespace(|| "new h3"), + cs.namespace(|| (3, "new h3")), &[current_hash_value[3].clone(), d], )?; let h4 = e.compute( - cs.namespace(|| "deferred h4 computation"), + cs.namespace(|| (4, "deferred h4 computation")), &[current_hash_value[4].clone()], )?; let h5 = UInt32::addmany( - cs.namespace(|| "new h5"), + cs.namespace(|| (5, "new h5")), &[current_hash_value[5].clone(), f], )?; let h6 = UInt32::addmany( - cs.namespace(|| "new h6"), + cs.namespace(|| (6, "new h6")), &[current_hash_value[6].clone(), g], )?; let h7 = UInt32::addmany( - cs.namespace(|| "new h7"), + cs.namespace(|| (7, "new h7")), &[current_hash_value[7].clone(), h], )?; diff --git a/src/frontend/gadgets/uint32.rs b/src/frontend/gadgets/uint32.rs index ef0467e8..8689eb09 100644 --- a/src/frontend/gadgets/uint32.rs +++ b/src/frontend/gadgets/uint32.rs @@ -165,7 +165,7 @@ impl UInt32 { b, c, |a, b, c| (a & b) ^ (a & c) ^ (b & c), - |cs, i, a, b, c| Boolean::sha256_maj(cs.namespace(|| format!("maj {}", i)), a, b, c), + |cs, i, a, b, c| Boolean::sha256_maj(cs.namespace(|| (i, format!("maj {}", i))), a, b, c), ) } @@ -182,7 +182,7 @@ impl UInt32 { b, c, |a, b, c| (a & b) ^ ((!a) & c), - |cs, i, a, b, c| Boolean::sha256_ch(cs.namespace(|| format!("ch {}", i)), a, b, c), + |cs, i, a, b, c| Boolean::sha256_ch(cs.namespace(|| (i, format!("ch {}", i))), a, b, c), ) } @@ -202,7 +202,7 @@ impl UInt32 { .iter() .zip(other.bits.iter()) .enumerate() - .map(|(i, (a, b))| Boolean::xor(cs.namespace(|| format!("xor of bit {}", i)), a, b)) + .map(|(i, (a, b))| Boolean::xor(cs.namespace(|| (i, format!("xor of bit {}", i))), a, b)) .collect::>()?; Ok(UInt32 { @@ -289,7 +289,7 @@ impl UInt32 { while max_value != 0 { // Allocate the bit let b = AllocatedBit::alloc( - cs.namespace(|| format!("result bit {}", i)), + cs.namespace(|| (i, format!("result bit {}", i))), result_value.map(|v| (v >> i) & 1 == 1), )?; diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index 0a5f6b83..fd19da56 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -41,18 +41,18 @@ mod tests { fn synthesize_alloc_bit>(cs: &mut CS) { // get two bits as input and check that they are indeed bits - let a = AllocatedNum::alloc_infallible(cs.namespace(|| "a"), || Fr::ONE); - let _ = a.inputize(cs.namespace(|| "a is input")); + let a = AllocatedNum::alloc_infallible(cs.namespace(|| (0, "a")), || Fr::ONE); + let _ = a.inputize(cs.namespace(|| (1, "a is input"))); cs.enforce( - || "check a is 0 or 1", + || (2, "check a is 0 or 1"), |lc| lc + CS::one() - a.get_variable(), |lc| lc + a.get_variable(), |lc| lc, ); - let b = AllocatedNum::alloc_infallible(cs.namespace(|| "b"), || Fr::ONE); - let _ = b.inputize(cs.namespace(|| "b is input")); + let b = AllocatedNum::alloc_infallible(cs.namespace(|| (3, "b")), || Fr::ONE); + let _ = b.inputize(cs.namespace(|| (4, "b is input"))); cs.enforce( - || "check b is 0 or 1", + || (5, "check b is 0 or 1"), |lc| lc + CS::one() - b.get_variable(), |lc| lc + b.get_variable(), |lc| lc, diff --git a/src/frontend/shape_cs.rs b/src/frontend/shape_cs.rs index 05a4e996..2ee3199f 100644 --- a/src/frontend/shape_cs.rs +++ b/src/frontend/shape_cs.rs @@ -80,7 +80,7 @@ impl ConstraintSystem for ShapeCS { fn enforce(&mut self, _annotation: A, a: LA, b: LB, c: LC) where - A: FnOnce() -> AR, + A: FnOnce() -> (usize, AR), AR: Into, LA: FnOnce(LinearCombination) -> LinearCombination, LB: FnOnce(LinearCombination) -> LinearCombination, @@ -96,7 +96,7 @@ impl ConstraintSystem for ShapeCS { fn push_namespace(&mut self, _name_fn: N) where NR: Into, - N: FnOnce() -> NR, + N: FnOnce() -> (usize, NR), { } diff --git a/src/frontend/test_shape_cs.rs b/src/frontend/test_shape_cs.rs index dfa2e419..3424f96a 100644 --- a/src/frontend/test_shape_cs.rs +++ b/src/frontend/test_shape_cs.rs @@ -262,13 +262,13 @@ where fn enforce(&mut self, annotation: A, a: LA, b: LB, c: LC) where - A: FnOnce() -> AR, + A: FnOnce() -> (usize, AR), AR: Into, LA: FnOnce(LinearCombination) -> LinearCombination, LB: FnOnce(LinearCombination) -> LinearCombination, LC: FnOnce(LinearCombination) -> LinearCombination, { - let path = compute_path(&self.current_namespace, &annotation().into()); + let path = compute_path(&self.current_namespace, &annotation().1.into()); let index = self.constraints.len(); self.set_named_obj(path.clone(), NamedObject::Constraint(index)); @@ -282,9 +282,10 @@ where fn push_namespace(&mut self, name_fn: N) where NR: Into, - N: FnOnce() -> NR, + N: FnOnce() -> (usize, NR), { - let name = name_fn().into(); + let (_segment, name) = name_fn(); + let name = name.into(); let path = compute_path(&self.current_namespace, &name); self.set_named_obj(path, NamedObject::Namespace); self.current_namespace.push(name); @@ -300,6 +301,7 @@ where } fn compute_path(ns: &[String], this: &str) -> String { + assert!( !this.chars().any(|a| a == '/'), "'/' is not allowed in names" diff --git a/src/frontend/util_cs/test_cs.rs b/src/frontend/util_cs/test_cs.rs index a75f33d6..5313abb5 100644 --- a/src/frontend/util_cs/test_cs.rs +++ b/src/frontend/util_cs/test_cs.rs @@ -178,13 +178,14 @@ impl ConstraintSystem for TestConstraintSystem(&mut self, annotation: A, a: LA, b: LB, c: LC) where - A: FnOnce() -> AR, + A: FnOnce() -> (usize, AR), AR: Into, LA: FnOnce(LinearCombination) -> LinearCombination, LB: FnOnce(LinearCombination) -> LinearCombination, LC: FnOnce(LinearCombination) -> LinearCombination, { - let path = compute_path(&self.current_namespace, &annotation().into()); + let (_segment, name) = annotation(); + let path = compute_path(&self.current_namespace, &name.into()); self.set_named_obj(path.clone(), NamedObject::Constraint); let a = a(LinearCombination::zero()); @@ -197,9 +198,10 @@ impl ConstraintSystem for TestConstraintSystem(&mut self, name_fn: N) where NR: Into, - N: FnOnce() -> NR, + N: FnOnce() -> (usize, NR), { - let name = name_fn().into(); + let (_segment, name) = name_fn(); + let name = name.into(); let path = compute_path(&self.current_namespace, &name); self.set_named_obj(path, NamedObject::Namespace); self.current_namespace.push(name); diff --git a/src/frontend/util_cs/witness_cs.rs b/src/frontend/util_cs/witness_cs.rs index 40df6a74..9132fd11 100644 --- a/src/frontend/util_cs/witness_cs.rs +++ b/src/frontend/util_cs/witness_cs.rs @@ -97,7 +97,7 @@ where fn enforce(&mut self, _: A, _a: LA, _b: LB, _c: LC) where - A: FnOnce() -> AR, + A: FnOnce() -> (usize, AR), AR: Into, LA: FnOnce(LinearCombination) -> LinearCombination, LB: FnOnce(LinearCombination) -> LinearCombination, @@ -106,10 +106,10 @@ where // Do nothing: we don't care about linear-combination evaluations in this context. } - fn push_namespace(&mut self, _: N) + fn push_namespace(&mut self, _name_fn: N) where NR: Into, - N: FnOnce() -> NR, + N: FnOnce() -> (usize, NR), { // Do nothing; we don't care about namespaces in this context. } diff --git a/src/gadgets/ecc.rs b/src/gadgets/ecc.rs index 937fb009..dd4cd404 100644 --- a/src/gadgets/ecc.rs +++ b/src/gadgets/ecc.rs @@ -31,13 +31,13 @@ where mut cs: CS, coords: Option<(E::Base, E::Base, bool)>, ) -> Result { - let x = AllocatedNum::alloc(cs.namespace(|| "x"), || { + let x = AllocatedNum::alloc(cs.namespace(|| (0, "x")), || { Ok(coords.map_or(E::Base::ZERO, |c| c.0)) })?; - let y = AllocatedNum::alloc(cs.namespace(|| "y"), || { + let y = AllocatedNum::alloc(cs.namespace(|| (1, "y")), || { Ok(coords.map_or(E::Base::ZERO, |c| c.1)) })?; - let is_infinity = AllocatedNum::alloc(cs.namespace(|| "is_infinity"), || { + let is_infinity = AllocatedNum::alloc(cs.namespace(|| (2, "is_infinity")), || { Ok(if coords.map_or(true, |c| c.2) { E::Base::ONE } else { @@ -45,7 +45,7 @@ where }) })?; cs.enforce( - || "is_infinity is bit", + || (3, "is_infinity is bit"), |lc| lc + is_infinity.get_variable(), |lc| lc + CS::one() - is_infinity.get_variable(), |lc| lc, @@ -62,11 +62,11 @@ where // check that (x,y) is on the curve if it is not infinity // we will check that (1- is_infinity) * y^2 = (1-is_infinity) * (x^3 + Ax + B) // note that is_infinity is already restricted to be in the set {0, 1} - let y_square = self.y.square(cs.namespace(|| "y_square"))?; - let x_square = self.x.square(cs.namespace(|| "x_square"))?; - let x_cube = self.x.mul(cs.namespace(|| "x_cube"), &x_square)?; + let y_square = self.y.square(cs.namespace(|| (0, "y_square")))?; + let x_square = self.x.square(cs.namespace(|| (1, "x_square")))?; + let x_cube = self.x.mul(cs.namespace(|| (2, "x_cube")), &x_square)?; - let rhs = AllocatedNum::alloc(cs.namespace(|| "rhs"), || { + let rhs = AllocatedNum::alloc(cs.namespace(|| (3, "rhs")), || { if *self.is_infinity.get_value().get()? == E::Base::ONE { Ok(E::Base::ZERO) } else { @@ -79,7 +79,7 @@ where })?; cs.enforce( - || "rhs = (1-is_infinity) * (x^3 + Ax + B)", + || (4, "rhs = (1-is_infinity) * (x^3 + Ax + B)"), |lc| { lc + x_cube.get_variable() + (E::GE::group_params().0, self.x.get_variable()) @@ -91,7 +91,7 @@ where // check that (1-infinity) * y_square = rhs cs.enforce( - || "check that y_square * (1 - is_infinity) = rhs", + || (5, "check that y_square * (1 - is_infinity) = rhs"), |lc| lc + y_square.get_variable(), |lc| lc + CS::one() - self.is_infinity.get_variable(), |lc| lc + rhs.get_variable(), @@ -102,8 +102,8 @@ where /// Allocates a default point on the curve, set to the identity point. pub fn default>(mut cs: CS) -> Result { - let zero = alloc_zero(cs.namespace(|| "zero")); - let one = alloc_one(cs.namespace(|| "one")); + let zero = alloc_zero(cs.namespace(|| (0, "zero"))); + let one = alloc_one(cs.namespace(|| (1, "one"))); Ok(AllocatedPoint { x: zero.clone(), @@ -125,10 +125,10 @@ where /// Negates the provided point pub fn negate>(&self, mut cs: CS) -> Result { - let y = AllocatedNum::alloc(cs.namespace(|| "y"), || Ok(-*self.y.get_value().get()?))?; + let y = AllocatedNum::alloc(cs.namespace(|| (0, "y")), || Ok(-*self.y.get_value().get()?))?; cs.enforce( - || "check y = - self.y", + || (1, "check y = - self.y"), |lc| lc + self.y.get_variable(), |lc| lc + CS::one(), |lc| lc - y.get_variable(), @@ -150,20 +150,20 @@ where // Compute boolean equal indicating if self = other let equal_x = alloc_num_equals( - cs.namespace(|| "check self.x == other.x"), + cs.namespace(|| (0, "check self.x == other.x")), &self.x, &other.x, )?; let equal_y = alloc_num_equals( - cs.namespace(|| "check self.y == other.y"), + cs.namespace(|| (1, "check self.y == other.y")), &self.y, &other.y, )?; // Compute the result of the addition and the result of double self - let result_from_add = self.add_internal(cs.namespace(|| "add internal"), other, &equal_x)?; - let result_from_double = self.double(cs.namespace(|| "double"))?; + let result_from_add = self.add_internal(cs.namespace(|| (2, "add internal")), other, &equal_x)?; + let result_from_double = self.double(cs.namespace(|| (3, "double")))?; // Output: // If (self == other) { @@ -176,13 +176,13 @@ where // } // } let result_for_equal_x = AllocatedPoint::select_point_or_infinity( - cs.namespace(|| "equal_y ? result_from_double : infinity"), + cs.namespace(|| (4, "equal_y ? result_from_double : infinity")), &result_from_double, &Boolean::from(equal_y), )?; AllocatedPoint::conditionally_select( - cs.namespace(|| "equal ? result_from_double : result_from_add"), + cs.namespace(|| (5, "equal ? result_from_double : result_from_add")), &result_for_equal_x, &result_from_add, &Boolean::from(equal_x), @@ -207,7 +207,7 @@ where // Compute self.is_infinity OR other.is_infinity = // NOT(NOT(self.is_ifninity) AND NOT(other.is_infinity)) - let at_least_one_inf = AllocatedNum::alloc(cs.namespace(|| "at least one inf"), || { + let at_least_one_inf = AllocatedNum::alloc(cs.namespace(|| (0, "at least one inf")), || { Ok( E::Base::ONE - (E::Base::ONE - *self.is_infinity.get_value().get()?) @@ -215,7 +215,7 @@ where ) })?; cs.enforce( - || "1 - at least one inf = (1-self.is_infinity) * (1-other.is_infinity)", + || (1, "1 - at least one inf = (1-self.is_infinity) * (1-other.is_infinity)"), |lc| lc + CS::one() - self.is_infinity.get_variable(), |lc| lc + CS::one() - other.is_infinity.get_variable(), |lc| lc + CS::one() - at_least_one_inf.get_variable(), @@ -223,7 +223,7 @@ where // Now compute x_diff_is_actual = at_least_one_inf OR equal_x let x_diff_is_actual = - AllocatedNum::alloc(cs.namespace(|| "allocate x_diff_is_actual"), || { + AllocatedNum::alloc(cs.namespace(|| (2, "allocate x_diff_is_actual")), || { Ok(if *equal_x.get_value().get()? { E::Base::ONE } else { @@ -231,7 +231,7 @@ where }) })?; cs.enforce( - || "1 - x_diff_is_actual = (1-equal_x) * (1-at_least_one_inf)", + || (3, "1 - x_diff_is_actual = (1-equal_x) * (1-at_least_one_inf)"), |lc| lc + CS::one() - at_least_one_inf.get_variable(), |lc| lc + CS::one() - equal_x.get_variable(), |lc| lc + CS::one() - x_diff_is_actual.get_variable(), @@ -240,13 +240,13 @@ where // x_diff = 1 if either self.is_infinity or other.is_infinity or self.x = other.x else self.x - // other.x let x_diff = select_one_or_diff2( - cs.namespace(|| "Compute x_diff"), + cs.namespace(|| (4, "Compute x_diff")), &other.x, &self.x, &x_diff_is_actual, )?; - let lambda = AllocatedNum::alloc(cs.namespace(|| "lambda"), || { + let lambda = AllocatedNum::alloc(cs.namespace(|| (5, "lambda")), || { let x_diff_inv = if *x_diff_is_actual.get_value().get()? == E::Base::ONE { // Set to default E::Base::ONE @@ -260,7 +260,7 @@ where Ok((*other.y.get_value().get()? - *self.y.get_value().get()?) * x_diff_inv) })?; cs.enforce( - || "Check that lambda is correct", + || (6, "Check that lambda is correct"), |lc| lc + lambda.get_variable(), |lc| lc + x_diff.get_variable(), |lc| lc + other.y.get_variable() - self.y.get_variable(), @@ -269,7 +269,7 @@ where //************************************************************************/ // x = lambda * lambda - self.x - other.x; //************************************************************************/ - let x = AllocatedNum::alloc(cs.namespace(|| "x"), || { + let x = AllocatedNum::alloc(cs.namespace(|| (7, "x")), || { Ok( *lambda.get_value().get()? * lambda.get_value().get()? - *self.x.get_value().get()? @@ -277,7 +277,7 @@ where ) })?; cs.enforce( - || "check that x is correct", + || (8, "check that x is correct"), |lc| lc + lambda.get_variable(), |lc| lc + lambda.get_variable(), |lc| lc + x.get_variable() + self.x.get_variable() + other.x.get_variable(), @@ -286,7 +286,7 @@ where //************************************************************************/ // y = lambda * (self.x - x) - self.y; //************************************************************************/ - let y = AllocatedNum::alloc(cs.namespace(|| "y"), || { + let y = AllocatedNum::alloc(cs.namespace(|| (9, "y")), || { Ok( *lambda.get_value().get()? * (*self.x.get_value().get()? - *x.get_value().get()?) - *self.y.get_value().get()?, @@ -294,7 +294,7 @@ where })?; cs.enforce( - || "Check that y is correct", + || (10, "Check that y is correct"), |lc| lc + lambda.get_variable(), |lc| lc + self.x.get_variable() - x.get_variable(), |lc| lc + y.get_variable() + self.y.get_variable(), @@ -310,41 +310,41 @@ where // Now compute the output x let x1 = conditionally_select2( - cs.namespace(|| "x1 = other.is_infinity ? self.x : x"), + cs.namespace(|| (11, "x1 = other.is_infinity ? self.x : x")), &self.x, &x, &other.is_infinity, )?; let x = conditionally_select2( - cs.namespace(|| "x = self.is_infinity ? other.x : x1"), + cs.namespace(|| (12, "x = self.is_infinity ? other.x : x1")), &other.x, &x1, &self.is_infinity, )?; let y1 = conditionally_select2( - cs.namespace(|| "y1 = other.is_infinity ? self.y : y"), + cs.namespace(|| (13, "y1 = other.is_infinity ? self.y : y")), &self.y, &y, &other.is_infinity, )?; let y = conditionally_select2( - cs.namespace(|| "y = self.is_infinity ? other.y : y1"), + cs.namespace(|| (14, "y = self.is_infinity ? other.y : y1")), &other.y, &y1, &self.is_infinity, )?; let is_infinity1 = select_num_or_zero2( - cs.namespace(|| "is_infinity1 = other.is_infinity ? self.is_infinity : 0"), + cs.namespace(|| (15, "is_infinity1 = other.is_infinity ? self.is_infinity : 0")), &self.is_infinity, &other.is_infinity, )?; let is_infinity = conditionally_select2( - cs.namespace(|| "is_infinity = self.is_infinity ? other.is_infinity : is_infinity1"), + cs.namespace(|| (16, "is_infinity = self.is_infinity ? other.is_infinity : is_infinity1")), &other.is_infinity, &is_infinity1, &self.is_infinity, @@ -361,31 +361,31 @@ where /*************************************************************/ // Compute tmp = (E::Base::ONE + E::Base::ONE)* self.y ? self != inf : 1 - let tmp_actual = AllocatedNum::alloc(cs.namespace(|| "tmp_actual"), || { + let tmp_actual = AllocatedNum::alloc(cs.namespace(|| (0, "tmp_actual")), || { Ok(*self.y.get_value().get()? + *self.y.get_value().get()?) })?; cs.enforce( - || "check tmp_actual", + || (1, "check tmp_actual"), |lc| lc + CS::one() + CS::one(), |lc| lc + self.y.get_variable(), |lc| lc + tmp_actual.get_variable(), ); - let tmp = select_one_or_num2(cs.namespace(|| "tmp"), &tmp_actual, &self.is_infinity)?; + let tmp = select_one_or_num2(cs.namespace(|| (2, "tmp")), &tmp_actual, &self.is_infinity)?; // Now compute lambda as (E::Base::from(3) * self.x * self.x + E::GE::A()) * tmp_inv - let prod_1 = AllocatedNum::alloc(cs.namespace(|| "alloc prod 1"), || { + let prod_1 = AllocatedNum::alloc(cs.namespace(|| (3, "alloc prod 1")), || { Ok(E::Base::from(3) * self.x.get_value().get()? * self.x.get_value().get()?) })?; cs.enforce( - || "Check prod 1", + || (4, "Check prod 1"), |lc| lc + (E::Base::from(3), self.x.get_variable()), |lc| lc + self.x.get_variable(), |lc| lc + prod_1.get_variable(), ); - let lambda = AllocatedNum::alloc(cs.namespace(|| "alloc lambda"), || { + let lambda = AllocatedNum::alloc(cs.namespace(|| (5, "alloc lambda")), || { let tmp_inv = if *self.is_infinity.get_value().get()? == E::Base::ONE { // Return default value 1 E::Base::ONE @@ -398,7 +398,7 @@ where })?; cs.enforce( - || "Check lambda", + || (6, "Check lambda"), |lc| lc + tmp.get_variable(), |lc| lc + lambda.get_variable(), |lc| lc + prod_1.get_variable() + (E::GE::group_params().0, CS::one()), @@ -408,7 +408,7 @@ where // x = lambda * lambda - self.x - self.x; /*************************************************************/ - let x = AllocatedNum::alloc(cs.namespace(|| "x"), || { + let x = AllocatedNum::alloc(cs.namespace(|| (7, "x")), || { Ok( ((*lambda.get_value().get()?) * (*lambda.get_value().get()?)) - *self.x.get_value().get()? @@ -416,7 +416,7 @@ where ) })?; cs.enforce( - || "Check x", + || (8, "Check x"), |lc| lc + lambda.get_variable(), |lc| lc + lambda.get_variable(), |lc| lc + x.get_variable() + self.x.get_variable() + self.x.get_variable(), @@ -426,14 +426,14 @@ where // y = lambda * (self.x - x) - self.y; /*************************************************************/ - let y = AllocatedNum::alloc(cs.namespace(|| "y"), || { + let y = AllocatedNum::alloc(cs.namespace(|| (9, "y")), || { Ok( (*lambda.get_value().get()?) * (*self.x.get_value().get()? - x.get_value().get()?) - self.y.get_value().get()?, ) })?; cs.enforce( - || "Check y", + || (10, "Check y"), |lc| lc + lambda.get_variable(), |lc| lc + self.x.get_variable() - x.get_variable(), |lc| lc + y.get_variable() + self.y.get_variable(), @@ -444,10 +444,10 @@ where /*************************************************************/ // x - let x = select_zero_or_num2(cs.namespace(|| "final x"), &x, &self.is_infinity)?; + let x = select_zero_or_num2(cs.namespace(|| (11, "final x")), &x, &self.is_infinity)?; // y - let y = select_zero_or_num2(cs.namespace(|| "final y"), &y, &self.is_infinity)?; + let y = select_zero_or_num2(cs.namespace(|| (12, "final y")), &y, &self.is_infinity)?; // is_infinity let is_infinity = self.is_infinity.clone(); @@ -472,19 +472,19 @@ where // we assume the first bit to be 1, so we must initialize acc to self and double it // we remove this assumption below let mut acc = p; - p = acc.double_incomplete(cs.namespace(|| "double"))?; + p = acc.double_incomplete(cs.namespace(|| (0, "double")))?; // perform the double-and-add loop to compute the scalar mul using incomplete addition law for (i, bit) in incomplete_bits.iter().enumerate().skip(1) { - let temp = acc.add_incomplete(cs.namespace(|| format!("add {i}")), &p)?; + let temp = acc.add_incomplete(cs.namespace(|| (i, format!("add {i}"))), &p)?; acc = AllocatedPointNonInfinity::conditionally_select( - cs.namespace(|| format!("acc_iteration_{i}")), + cs.namespace(|| (i, format!("acc_iteration_{i}"))), &temp, &acc, &Boolean::from(bit.clone()), )?; - p = p.double_incomplete(cs.namespace(|| format!("double {i}")))?; + p = p.double_incomplete(cs.namespace(|| (i, format!("double {i}"))))?; } // convert back to AllocatedPoint @@ -494,12 +494,12 @@ where // we remove the initial slack if bits[0] is as not as assumed (i.e., it is not 1) let acc_minus_initial = { - let neg = self.negate(cs.namespace(|| "negate"))?; - acc.add(cs.namespace(|| "res minus self"), &neg) + let neg = self.negate(cs.namespace(|| (0, "negate")))?; + acc.add(cs.namespace(|| (1, "res minus self")), &neg) }?; AllocatedPoint::conditionally_select( - cs.namespace(|| "remove slack if necessary"), + cs.namespace(|| (2, "remove slack if necessary")), &acc, &acc_minus_initial, &Boolean::from(scalar_bits[0].clone()), @@ -508,16 +508,16 @@ where // when self.is_infinity = 1, return the default point, else return res // we already set res.is_infinity to be self.is_infinity, so we do not need to set it here - let default = Self::default(cs.namespace(|| "default"))?; + let default = Self::default(cs.namespace(|| (3, "default")))?; let x = conditionally_select2( - cs.namespace(|| "check if self.is_infinity is zero (x)"), + cs.namespace(|| (4, "check if self.is_infinity is zero (x)")), &default.x, &res.x, &self.is_infinity, )?; let y = conditionally_select2( - cs.namespace(|| "check if self.is_infinity is zero (y)"), + cs.namespace(|| (5, "check if self.is_infinity is zero (y)")), &default.y, &res.y, &self.is_infinity, @@ -532,15 +532,15 @@ where let mut p_complete = p.to_allocated_point(&self.is_infinity)?; for (i, bit) in complete_bits.iter().enumerate() { - let temp = acc.add(cs.namespace(|| format!("add_complete {i}")), &p_complete)?; + let temp = acc.add(cs.namespace(|| (i, format!("add_complete {i}"))), &p_complete)?; acc = AllocatedPoint::conditionally_select( - cs.namespace(|| format!("acc_complete_iteration_{i}")), + cs.namespace(|| (i, format!("acc_complete_iteration_{i}"))), &temp, &acc, &Boolean::from(bit.clone()), )?; - p_complete = p_complete.double(cs.namespace(|| format!("double_complete {i}")))?; + p_complete = p_complete.double(cs.namespace(|| (i, format!("double_complete {i}"))))?; } Ok(acc) @@ -553,12 +553,12 @@ where b: &Self, condition: &Boolean, ) -> Result { - let x = conditionally_select(cs.namespace(|| "select x"), &a.x, &b.x, condition)?; + let x = conditionally_select(cs.namespace(|| (0, "select x")), &a.x, &b.x, condition)?; - let y = conditionally_select(cs.namespace(|| "select y"), &a.y, &b.y, condition)?; + let y = conditionally_select(cs.namespace(|| (1, "select y")), &a.y, &b.y, condition)?; let is_infinity = conditionally_select( - cs.namespace(|| "select is_infinity"), + cs.namespace(|| (2, "select is_infinity")), &a.is_infinity, &b.is_infinity, condition, @@ -573,12 +573,12 @@ where a: &Self, condition: &Boolean, ) -> Result { - let x = select_num_or_zero(cs.namespace(|| "select x"), &a.x, condition)?; + let x = select_num_or_zero(cs.namespace(|| (0, "select x")), &a.x, condition)?; - let y = select_num_or_zero(cs.namespace(|| "select y"), &a.y, condition)?; + let y = select_num_or_zero(cs.namespace(|| (1, "select y")), &a.y, condition)?; let is_infinity = select_num_or_one( - cs.namespace(|| "select is_infinity"), + cs.namespace(|| (2, "select is_infinity")), &a.is_infinity, condition, )?; @@ -608,10 +608,10 @@ where mut cs: CS, coords: Option<(E::Base, E::Base)>, ) -> Result { - let x = AllocatedNum::alloc(cs.namespace(|| "x"), || { + let x = AllocatedNum::alloc(cs.namespace(|| (0, "x")), || { coords.map_or(Err(SynthesisError::AssignmentMissing), |c| Ok(c.0)) })?; - let y = AllocatedNum::alloc(cs.namespace(|| "y"), || { + let y = AllocatedNum::alloc(cs.namespace(|| (1, "y")), || { coords.map_or(Err(SynthesisError::AssignmentMissing), |c| Ok(c.1)) })?; @@ -649,7 +649,7 @@ where CS: ConstraintSystem, { // allocate a free variable that an honest prover sets to lambda = (y2-y1)/(x2-x1) - let lambda = AllocatedNum::alloc(cs.namespace(|| "lambda"), || { + let lambda = AllocatedNum::alloc(cs.namespace(|| (0, "lambda")), || { if *other.x.get_value().get()? == *self.x.get_value().get()? { Ok(E::Base::ONE) } else { @@ -662,7 +662,7 @@ where } })?; cs.enforce( - || "Check that lambda is computed correctly", + || (1, "Check that lambda is computed correctly"), |lc| lc + lambda.get_variable(), |lc| lc + other.x.get_variable() - self.x.get_variable(), |lc| lc + other.y.get_variable() - self.y.get_variable(), @@ -671,7 +671,7 @@ where //************************************************************************/ // x = lambda * lambda - self.x - other.x; //************************************************************************/ - let x = AllocatedNum::alloc(cs.namespace(|| "x"), || { + let x = AllocatedNum::alloc(cs.namespace(|| (2, "x")), || { Ok( *lambda.get_value().get()? * lambda.get_value().get()? - *self.x.get_value().get()? @@ -679,7 +679,7 @@ where ) })?; cs.enforce( - || "check that x is correct", + || (3, "check that x is correct"), |lc| lc + lambda.get_variable(), |lc| lc + lambda.get_variable(), |lc| lc + x.get_variable() + self.x.get_variable() + other.x.get_variable(), @@ -688,7 +688,7 @@ where //************************************************************************/ // y = lambda * (self.x - x) - self.y; //************************************************************************/ - let y = AllocatedNum::alloc(cs.namespace(|| "y"), || { + let y = AllocatedNum::alloc(cs.namespace(|| (4, "y")), || { Ok( *lambda.get_value().get()? * (*self.x.get_value().get()? - *x.get_value().get()?) - *self.y.get_value().get()?, @@ -696,7 +696,7 @@ where })?; cs.enforce( - || "Check that y is correct", + || (5, "Check that y is correct"), |lc| lc + lambda.get_variable(), |lc| lc + self.x.get_variable() - x.get_variable(), |lc| lc + y.get_variable() + self.y.get_variable(), @@ -712,9 +712,9 @@ where ) -> Result { // lambda = (3 x^2 + a) / 2 * y - let x_sq = self.x.square(cs.namespace(|| "x_sq"))?; + let x_sq = self.x.square(cs.namespace(|| (0, "x_sq")))?; - let lambda = AllocatedNum::alloc(cs.namespace(|| "lambda"), || { + let lambda = AllocatedNum::alloc(cs.namespace(|| (1, "lambda")), || { let n = E::Base::from(3) * x_sq.get_value().get()? + E::GE::group_params().0; let d = E::Base::from(2) * *self.y.get_value().get()?; if d == E::Base::ZERO { @@ -724,13 +724,13 @@ where } })?; cs.enforce( - || "Check that lambda is computed correctly", + || (2, "Check that lambda is computed correctly"), |lc| lc + lambda.get_variable(), |lc| lc + (E::Base::from(2), self.y.get_variable()), |lc| lc + (E::Base::from(3), x_sq.get_variable()) + (E::GE::group_params().0, CS::one()), ); - let x = AllocatedNum::alloc(cs.namespace(|| "x"), || { + let x = AllocatedNum::alloc(cs.namespace(|| (3, "x")), || { Ok( *lambda.get_value().get()? * *lambda.get_value().get()? - *self.x.get_value().get()? @@ -739,13 +739,13 @@ where })?; cs.enforce( - || "check that x is correct", + || (4, "check that x is correct"), |lc| lc + lambda.get_variable(), |lc| lc + lambda.get_variable(), |lc| lc + x.get_variable() + (E::Base::from(2), self.x.get_variable()), ); - let y = AllocatedNum::alloc(cs.namespace(|| "y"), || { + let y = AllocatedNum::alloc(cs.namespace(|| (5, "y")), || { Ok( *lambda.get_value().get()? * (*self.x.get_value().get()? - *x.get_value().get()?) - *self.y.get_value().get()?, @@ -753,7 +753,7 @@ where })?; cs.enforce( - || "Check that y is correct", + || (6, "Check that y is correct"), |lc| lc + lambda.get_variable(), |lc| lc + self.x.get_variable() - x.get_variable(), |lc| lc + y.get_variable() + self.y.get_variable(), @@ -769,8 +769,8 @@ where b: &Self, condition: &Boolean, ) -> Result { - let x = conditionally_select(cs.namespace(|| "select x"), &a.x, &b.x, condition)?; - let y = conditionally_select(cs.namespace(|| "select y"), &a.y, &b.y, condition)?; + let x = conditionally_select(cs.namespace(|| (0, "select x")), &a.x, &b.x, condition)?; + let y = conditionally_select(cs.namespace(|| (1, "select y")), &a.y, &b.y, condition)?; Ok(Self { x, y }) } @@ -907,7 +907,7 @@ mod tests { ) -> Result, SynthesisError> { // get a random point let p = Point::::random_vartime(); - AllocatedPoint::alloc(cs.namespace(|| "alloc p"), Some((p.x, p.y, p.is_infinity))) + AllocatedPoint::alloc(cs.namespace(|| (0, "alloc p")), Some((p.x, p.y, p.is_infinity))) } /// Make the point io @@ -915,11 +915,11 @@ mod tests { p: &AllocatedPoint, mut cs: CS, ) { - let _ = p.x.inputize(cs.namespace(|| "Input point.x")); - let _ = p.y.inputize(cs.namespace(|| "Input point.y")); + let _ = p.x.inputize(cs.namespace(|| (1, "Input point.x"))); + let _ = p.y.inputize(cs.namespace(|| (2, "Input point.y"))); let _ = p .is_infinity - .inputize(cs.namespace(|| "Input point.is_infinity")); + .inputize(cs.namespace(|| (3, "Input point.is_infinity"))); } #[test] @@ -992,8 +992,8 @@ mod tests { E: Engine, CS: ConstraintSystem, { - let a = alloc_random_point(cs.namespace(|| "a")).unwrap(); - inputize_allocted_point(&a, cs.namespace(|| "inputize a")); + let a = alloc_random_point(cs.namespace(|| (0, "a"))).unwrap(); + inputize_allocted_point(&a, cs.namespace(|| (1, "inputize a"))); let s = E::Scalar::random(&mut OsRng); // Allocate bits for s @@ -1001,11 +1001,11 @@ mod tests { .to_le_bits() .into_iter() .enumerate() - .map(|(i, bit)| AllocatedBit::alloc(cs.namespace(|| format!("bit {i}")), Some(bit))) + .map(|(i, bit)| AllocatedBit::alloc(cs.namespace(|| (i, format!("bit {i}"))), Some(bit))) .collect::, SynthesisError>>() .unwrap(); - let e = a.scalar_mul(cs.namespace(|| "Scalar Mul"), &bits).unwrap(); - inputize_allocted_point(&e, cs.namespace(|| "inputize e")); + let e = a.scalar_mul(cs.namespace(|| (2, "Scalar Mul")), &bits).unwrap(); + inputize_allocted_point(&e, cs.namespace(|| (3, "inputize e"))); (a, e, s) } @@ -1028,13 +1028,13 @@ mod tests { { // First create the shape let mut cs: TestShapeCS = TestShapeCS::new(); - let _ = synthesize_smul::(cs.namespace(|| "synthesize")); + let _ = synthesize_smul::(cs.namespace(|| (0, "synthesize"))); println!("Number of constraints: {}", cs.num_constraints()); let (shape, ck) = cs.r1cs_shape(&*default_ck_hint()); // Then the satisfying assignment let mut cs = SatisfyingAssignment::::new(); - let (a, e, s) = synthesize_smul::(cs.namespace(|| "synthesize")); + let (a, e, s) = synthesize_smul::(cs.namespace(|| (1, "synthesize"))); let (inst, witness) = cs.r1cs_instance_and_witness(&shape, &ck).unwrap(); let a_p: Point = Point::new( @@ -1058,10 +1058,10 @@ mod tests { E: Engine, CS: ConstraintSystem, { - let a = alloc_random_point(cs.namespace(|| "a")).unwrap(); - inputize_allocted_point(&a, cs.namespace(|| "inputize a")); - let e = a.add(cs.namespace(|| "add a to a"), &a).unwrap(); - inputize_allocted_point(&e, cs.namespace(|| "inputize e")); + let a = alloc_random_point(cs.namespace(|| (0, "a"))).unwrap(); + inputize_allocted_point(&a, cs.namespace(|| (1, "inputize a"))); + let e = a.add(cs.namespace(|| (2, "add a to a")), &a).unwrap(); + inputize_allocted_point(&e, cs.namespace(|| (3, "inputize e"))); (a, e) } @@ -1084,13 +1084,13 @@ mod tests { { // First create the shape let mut cs: TestShapeCS = TestShapeCS::new(); - let _ = synthesize_add_equal::(cs.namespace(|| "synthesize add equal")); + let _ = synthesize_add_equal::(cs.namespace(|| (0, "synthesize add equal"))); println!("Number of constraints: {}", cs.num_constraints()); let (shape, ck) = cs.r1cs_shape(&*default_ck_hint()); // Then the satisfying assignment let mut cs = SatisfyingAssignment::::new(); - let (a, e) = synthesize_add_equal::(cs.namespace(|| "synthesize add equal")); + let (a, e) = synthesize_add_equal::(cs.namespace(|| (1, "synthesize add equal"))); let (inst, witness) = cs.r1cs_instance_and_witness(&shape, &ck).unwrap(); let a_p: Point = Point::new( a.x.get_value().unwrap(), @@ -1113,15 +1113,15 @@ mod tests { E: Engine, CS: ConstraintSystem, { - let a = alloc_random_point(cs.namespace(|| "a")).unwrap(); - inputize_allocted_point(&a, cs.namespace(|| "inputize a")); + let a = alloc_random_point(cs.namespace(|| (0, "a"))).unwrap(); + inputize_allocted_point(&a, cs.namespace(|| (1, "inputize a"))); let b = &mut a.clone(); - b.y = AllocatedNum::alloc(cs.namespace(|| "allocate negation of a"), || { + b.y = AllocatedNum::alloc(cs.namespace(|| (2, "allocate negation of a")), || { Ok(E::Base::ZERO) }) .unwrap(); - inputize_allocted_point(b, cs.namespace(|| "inputize b")); - let e = a.add(cs.namespace(|| "add a to b"), b).unwrap(); + inputize_allocted_point(b, cs.namespace(|| (3, "inputize b"))); + let e = a.add(cs.namespace(|| (4, "add a to b")), b).unwrap(); e } @@ -1144,13 +1144,13 @@ mod tests { { // First create the shape let mut cs: TestShapeCS = TestShapeCS::new(); - let _ = synthesize_add_negation::(cs.namespace(|| "synthesize add equal")); + let _ = synthesize_add_negation::(cs.namespace(|| (0, "synthesize add equal"))); println!("Number of constraints: {}", cs.num_constraints()); let (shape, ck) = cs.r1cs_shape(&*default_ck_hint()); // Then the satisfying assignment let mut cs = SatisfyingAssignment::::new(); - let e = synthesize_add_negation::(cs.namespace(|| "synthesize add negation")); + let e = synthesize_add_negation::(cs.namespace(|| (1, "synthesize add negation"))); let (inst, witness) = cs.r1cs_instance_and_witness(&shape, &ck).unwrap(); let e_p: Point = Point::new( e.x.get_value().unwrap(), diff --git a/src/gadgets/nonnative/bignat.rs b/src/gadgets/nonnative/bignat.rs index 61ff1a4c..c619fc82 100644 --- a/src/gadgets/nonnative/bignat.rs +++ b/src/gadgets/nonnative/bignat.rs @@ -227,7 +227,7 @@ impl BigNat { n_limbs: usize, ) -> Result { let bignat = Self::alloc_from_nat( - cs.namespace(|| "bignat"), + cs.namespace(|| (0, "bignat")), || { Ok({ n.value @@ -242,9 +242,9 @@ impl BigNat { // check if bignat equals n // (1) decompose `bignat` into a bitvector `bv` - let bv = bignat.decompose(cs.namespace(|| "bv"))?; + let bv = bignat.decompose(cs.namespace(|| (1, "bv")))?; // (2) recompose bits and check if it equals n - n.is_equal(cs.namespace(|| "n"), &bv); + n.is_equal(cs.namespace(|| (2, "n")), &bv); Ok(bignat) } @@ -269,7 +269,7 @@ impl BigNat { (0..self.limbs.len()).map(|i| self.limb_values.as_ref().map(|vs| vs[i])); for (i, (limb, limb_value)) in self.limbs.iter().zip(limb_values_split).enumerate() { Num::new(limb_value, limb.clone()) - .fits_in_bits(cs.namespace(|| format!("{i}")), self.params.limb_width)?; + .fits_in_bits(cs.namespace(|| (i, format!("{i}"))), self.params.limb_width)?; } Ok(()) } @@ -288,7 +288,7 @@ impl BigNat { .enumerate() .map(|(i, (limb, limb_value))| { Num::new(limb_value, limb.clone()).decompose( - cs.namespace(|| format!("subdecmop {i}")), + cs.namespace(|| (i, format!("subdecmop {i}"))), self.params.limb_width, ) }) @@ -367,7 +367,7 @@ impl BigNat { let mut carry_in = Num::new(Some(Scalar::ZERO), LinearCombination::zero()); for i in 0..n { - let carry = Num::alloc(cs.namespace(|| format!("carry value {i}")), || { + let carry = Num::alloc(cs.namespace(|| (i, format!("carry value {i}"))), || { Ok( nat_to_f( &((f_to_nat(&self.limb_values.grab()?[i]) @@ -382,7 +382,7 @@ impl BigNat { accumulated_extra += max_word; cs.enforce( - || format!("carry {i}"), + || (i, format!("carry {i}")), |lc| lc, |lc| lc, |lc| { @@ -399,10 +399,10 @@ impl BigNat { accumulated_extra /= &target_base; if i < n - 1 { - carry.fits_in_bits(cs.namespace(|| format!("carry {i} decomp")), carry_bits)?; + carry.fits_in_bits(cs.namespace(|| (i, format!("carry {i} decomp"))), carry_bits)?; } else { cs.enforce( - || format!("carry {i} is out"), + || (i, format!("carry {i} is out")), |lc| lc, |lc| lc, |lc| lc + &carry.num - (nat_to_f(&accumulated_extra).unwrap(), CS::one()), @@ -413,7 +413,7 @@ impl BigNat { for (i, zero_limb) in self.limbs.iter().enumerate().skip(n) { cs.enforce( - || format!("zero self {i}"), + || (i, format!("zero self {i}")), |lc| lc, |lc| lc, |lc| lc + zero_limb, @@ -421,7 +421,7 @@ impl BigNat { } for (i, zero_limb) in other.limbs.iter().enumerate().skip(n) { cs.enforce( - || format!("zero other {i}"), + || (i, format!("zero other {i}")), |lc| lc, |lc| lc, |lc| lc + zero_limb, @@ -446,7 +446,7 @@ impl BigNat { let limbs_per_group = (Scalar::CAPACITY as usize - carry_bits) / self.params.limb_width; let self_grouped = self.group_limbs(limbs_per_group); let other_grouped = other.group_limbs(limbs_per_group); - self_grouped.equal_when_carried(cs.namespace(|| "grouped"), &other_grouped) + self_grouped.equal_when_carried(cs.namespace(|| (0, "grouped")), &other_grouped) } pub fn add(&self, other: &Self) -> Result, SynthesisError> { @@ -505,7 +505,7 @@ impl BigNat { let quotient_bits = (self.n_bits() + other.n_bits()).saturating_sub(modulus.params.min_bits); let quotient_limbs = quotient_bits.saturating_sub(1) / limb_width + 1; let quotient = BigNat::alloc_from_nat( - cs.namespace(|| "quotient"), + cs.namespace(|| (0, "quotient")), || { Ok({ let mut x = self.value.grab()?.clone(); @@ -517,9 +517,9 @@ impl BigNat { self.params.limb_width, quotient_limbs, )?; - quotient.assert_well_formed(cs.namespace(|| "quotient rangecheck"))?; + quotient.assert_well_formed(cs.namespace(|| (1, "quotient rangecheck")))?; let remainder = BigNat::alloc_from_nat( - cs.namespace(|| "remainder"), + cs.namespace(|| (2, "remainder")), || { Ok({ let mut x = self.value.grab()?.clone(); @@ -531,7 +531,7 @@ impl BigNat { self.params.limb_width, modulus.limbs.len(), )?; - remainder.assert_well_formed(cs.namespace(|| "remainder rangecheck"))?; + remainder.assert_well_formed(cs.namespace(|| (3, "remainder rangecheck")))?; let a_poly = Polynomial::from(self.clone()); let b_poly = Polynomial::from(other.clone()); let mod_poly = Polynomial::from(modulus.clone()); @@ -539,8 +539,8 @@ impl BigNat { let r_poly = Polynomial::from(remainder.clone()); // a * b - let left = a_poly.alloc_product(cs.namespace(|| "left"), &b_poly)?; - let right_product = q_poly.alloc_product(cs.namespace(|| "right_product"), &mod_poly)?; + let left = a_poly.alloc_product(cs.namespace(|| (4, "left")), &b_poly)?; + let right_product = q_poly.alloc_product(cs.namespace(|| (5, "right_product")), &mod_poly)?; // q * m + r let right = right_product.sum(&r_poly); @@ -560,7 +560,7 @@ impl BigNat { let left_int = BigNat::from_poly(left, limb_width, left_max_word); let right_int = BigNat::from_poly(right, limb_width, right_max_word); - left_int.equal_when_carried_regroup(cs.namespace(|| "carry"), &right_int)?; + left_int.equal_when_carried_regroup(cs.namespace(|| (6, "carry")), &right_int)?; Ok((quotient, remainder)) } @@ -575,25 +575,25 @@ impl BigNat { let quotient_bits = self.n_bits().saturating_sub(modulus.params.min_bits); let quotient_limbs = quotient_bits.saturating_sub(1) / limb_width + 1; let quotient = BigNat::alloc_from_nat( - cs.namespace(|| "quotient"), + cs.namespace(|| (0, "quotient")), || Ok(self.value.grab()? / modulus.value.grab()?), self.params.limb_width, quotient_limbs, )?; - quotient.assert_well_formed(cs.namespace(|| "quotient rangecheck"))?; + quotient.assert_well_formed(cs.namespace(|| (1, "quotient rangecheck")))?; let remainder = BigNat::alloc_from_nat( - cs.namespace(|| "remainder"), + cs.namespace(|| (2, "remainder")), || Ok(self.value.grab()? % modulus.value.grab()?), self.params.limb_width, modulus.limbs.len(), )?; - remainder.assert_well_formed(cs.namespace(|| "remainder rangecheck"))?; + remainder.assert_well_formed(cs.namespace(|| (2, "remainder rangecheck")))?; let mod_poly = Polynomial::from(modulus.clone()); let q_poly = Polynomial::from(quotient.clone()); let r_poly = Polynomial::from(remainder.clone()); // q * m + r - let right_product = q_poly.alloc_product(cs.namespace(|| "right_product"), &mod_poly)?; + let right_product = q_poly.alloc_product(cs.namespace(|| (3, "right_product")), &mod_poly)?; let right = right_product.sum(&r_poly); let right_max_word = { @@ -605,7 +605,7 @@ impl BigNat { }; let right_int = BigNat::from_poly(right, limb_width, right_max_word); - self.equal_when_carried_regroup(cs.namespace(|| "carry"), &right_int)?; + self.equal_when_carried_regroup(cs.namespace(|| (4, "carry")), &right_int)?; Ok(remainder) } @@ -709,10 +709,10 @@ impl Polynomial { }; let one = Scalar::ONE; let mut x = Scalar::ZERO; - for _ in 1..(n_product_coeffs + 1) { + for i in 1..(n_product_coeffs + 1) { x.add_assign(&one); cs.enforce( - || format!("pointwise product @ {x:?}"), + || (i, format!("pointwise product @ {x:?}")), |lc| { let mut i = Scalar::ONE; self.coefficients.iter().fold(lc, |lc, c| { @@ -815,7 +815,7 @@ mod tests { .collect::>, SynthesisError>>()?, values: Some(self.b), }; - let _prod = a.alloc_product(cs.namespace(|| "product"), &b)?; + let _prod = a.alloc_product(cs.namespace(|| (0, "product")), &b)?; Ok(()) } } @@ -854,12 +854,12 @@ mod tests { impl Circuit for BigNatBitDecomp { fn synthesize>(self, cs: &mut CS) -> Result<(), SynthesisError> { let n = BigNat::alloc_from_nat( - cs.namespace(|| "n"), + cs.namespace(|| (0, "n")), || Ok(self.inputs.grab()?.n.clone()), self.params.limb_width, self.params.n_limbs, )?; - n.decompose(cs.namespace(|| "decomp"))?; + n.decompose(cs.namespace(|| (1, "decomp")))?; Ok(()) } } diff --git a/src/gadgets/nonnative/util.rs b/src/gadgets/nonnative/util.rs index e0243566..39a161d7 100644 --- a/src/gadgets/nonnative/util.rs +++ b/src/gadgets/nonnative/util.rs @@ -49,7 +49,7 @@ impl Bit { // Constrain: (1 - a) * a = 0 // This constrains a to be either 0 or 1. cs.enforce( - || "boolean constraint", + || (0, "boolean constraint"), |lc| lc + CS::one() - var, |lc| lc + var, |lc| lc, @@ -119,7 +119,7 @@ impl Num { for (i, v) in bits.iter().enumerate() { cs.enforce( - || format!("{i} is bit"), + || (i, format!("{i} is bit")), |lc| lc + *v, |lc| lc + CS::one() - *v, |lc| lc, @@ -128,7 +128,7 @@ impl Num { // Last bit cs.enforce( - || "last bit", + || (n_bits - 1, "last bit"), |mut lc| { let mut f = Scalar::ONE; lc = lc + &self.num; @@ -166,7 +166,7 @@ impl Num { l }); let sum_lc = LinearCombination::zero() + &self.num - ∑ - cs.enforce(|| "sum", |lc| lc + &sum_lc, |lc| lc + CS::one(), |lc| lc); + cs.enforce(|| (0, "sum"), |lc| lc + &sum_lc, |lc| lc + CS::one(), |lc| lc); } /// Compute the natural number represented by an array of limbs. @@ -184,7 +184,7 @@ impl Num { let allocations: Vec> = (0..n_bits) .map(|bit_i| { Bit::alloc( - cs.namespace(|| format!("bit{bit_i}")), + cs.namespace(|| (bit_i, format!("bit{bit_i}"))), values.as_ref().map(|vs| vs[bit_i]), ) }) @@ -198,7 +198,7 @@ impl Num { l }); let sum_lc = LinearCombination::zero() + &self.num - ∑ - cs.enforce(|| "sum", |lc| lc + &sum_lc, |lc| lc + CS::one(), |lc| lc); + cs.enforce(|| (0, "sum"), |lc| lc + &sum_lc, |lc| lc + CS::one(), |lc| lc); let bits: Vec> = allocations .clone() .into_iter() @@ -215,9 +215,9 @@ impl Num { &self, mut cs: CS, ) -> Result, SynthesisError> { - let new = AllocatedNum::alloc(cs.namespace(|| "alloc"), || Ok(*self.value.grab()?))?; + let new = AllocatedNum::alloc(cs.namespace(|| (0, "alloc")), || Ok(*self.value.grab()?))?; cs.enforce( - || "eq", + || (1, "eq"), |lc| lc, |lc| lc, |lc| lc + new.get_variable() - &self.num, diff --git a/src/gadgets/r1cs.rs b/src/gadgets/r1cs.rs index 25167508..b1f65555 100644 --- a/src/gadgets/r1cs.rs +++ b/src/gadgets/r1cs.rs @@ -33,13 +33,13 @@ impl AllocatedR1CSInstance { u: Option<&R1CSInstance>, ) -> Result { let W = AllocatedPoint::alloc( - cs.namespace(|| "allocate W"), + cs.namespace(|| (0, "allocate W")), u.map(|u| u.comm_W.to_coordinates()), )?; - W.check_on_curve(cs.namespace(|| "check W on curve"))?; + W.check_on_curve(cs.namespace(|| (1, "check W on curve")))?; - let X0 = alloc_scalar_as_base::(cs.namespace(|| "allocate X[0]"), u.map(|u| u.X[0]))?; - let X1 = alloc_scalar_as_base::(cs.namespace(|| "allocate X[1]"), u.map(|u| u.X[1]))?; + let X0 = alloc_scalar_as_base::(cs.namespace(|| (2, "allocate X[0]")), u.map(|u| u.X[0]))?; + let X1 = alloc_scalar_as_base::(cs.namespace(|| (3, "allocate X[1]")), u.map(|u| u.X[1]))?; Ok(AllocatedR1CSInstance { W, X0, X1 }) } @@ -75,29 +75,29 @@ impl AllocatedRelaxedR1CSInstance { // in the Nova augmented circuit, which ensures that the relaxed instance // came from a prior iteration of Nova. let W = AllocatedPoint::alloc( - cs.namespace(|| "allocate W"), + cs.namespace(|| (0, "allocate W")), inst.map(|inst| inst.comm_W.to_coordinates()), )?; let E = AllocatedPoint::alloc( - cs.namespace(|| "allocate E"), + cs.namespace(|| (1, "allocate E")), inst.map(|inst| inst.comm_E.to_coordinates()), )?; // u << |E::Base| despite the fact that u is a scalar. // So we parse all of its bytes as a E::Base element - let u = alloc_scalar_as_base::(cs.namespace(|| "allocate u"), inst.map(|inst| inst.u))?; + let u = alloc_scalar_as_base::(cs.namespace(|| (2, "allocate u")), inst.map(|inst| inst.u))?; // Allocate X0 and X1. If the input instance is None, then allocate default values 0. let X0 = BigNat::alloc_from_nat( - cs.namespace(|| "allocate X[0]"), + cs.namespace(|| (3, "allocate X[0]")), || Ok(f_to_nat(&inst.map_or(E::Scalar::ZERO, |inst| inst.X[0]))), limb_width, n_limbs, )?; let X1 = BigNat::alloc_from_nat( - cs.namespace(|| "allocate X[1]"), + cs.namespace(|| (4, "allocate X[1]")), || Ok(f_to_nat(&inst.map_or(E::Scalar::ZERO, |inst| inst.X[1]))), limb_width, n_limbs, @@ -113,7 +113,7 @@ impl AllocatedRelaxedR1CSInstance { limb_width: usize, n_limbs: usize, ) -> Result { - let W = AllocatedPoint::default(cs.namespace(|| "allocate W"))?; + let W = AllocatedPoint::default(cs.namespace(|| (0, "allocate W")))?; let E = W.clone(); let u = W.x.clone(); // In the default case, W.x = u = 0 @@ -122,14 +122,14 @@ impl AllocatedRelaxedR1CSInstance { // If the prover is malicious, it can set to arbitrary values, but the resulting // relaxed R1CS instance with the checked default values of W, E, and u must still be satisfying let X0 = BigNat::alloc_from_nat( - cs.namespace(|| "allocate x_default[0]"), + cs.namespace(|| (1, "allocate x_default[0]")), || Ok(f_to_nat(&E::Scalar::ZERO)), limb_width, n_limbs, )?; let X1 = BigNat::alloc_from_nat( - cs.namespace(|| "allocate x_default[1]"), + cs.namespace(|| (2, "allocate x_default[1]")), || Ok(f_to_nat(&E::Scalar::ZERO)), limb_width, n_limbs, @@ -146,19 +146,19 @@ impl AllocatedRelaxedR1CSInstance { limb_width: usize, n_limbs: usize, ) -> Result { - let E = AllocatedPoint::default(cs.namespace(|| "allocate default E"))?; + let E = AllocatedPoint::default(cs.namespace(|| (0, "allocate default E")))?; - let u = alloc_one(cs.namespace(|| "one")); + let u = alloc_one(cs.namespace(|| (1, "one"))); let X0 = BigNat::from_num( - cs.namespace(|| "allocate X0 from relaxed r1cs"), + cs.namespace(|| (2, "allocate X0 from relaxed r1cs")), &Num::from(inst.X0), limb_width, n_limbs, )?; let X1 = BigNat::from_num( - cs.namespace(|| "allocate X1 from relaxed r1cs"), + cs.namespace(|| (3, "allocate X1 from relaxed r1cs")), &Num::from(inst.X1), limb_width, n_limbs, @@ -194,7 +194,7 @@ impl AllocatedRelaxedR1CSInstance { .iter() .enumerate() .map(|(i, limb)| { - limb.as_allocated_num(cs.namespace(|| format!("convert limb {i} of X_r[0] to num"))) + limb.as_allocated_num(cs.namespace(|| (i, format!("convert limb {i} of X_r[0] to num")))) }) .collect::>, _>>()?; @@ -210,7 +210,7 @@ impl AllocatedRelaxedR1CSInstance { .iter() .enumerate() .map(|(i, limb)| { - limb.as_allocated_num(cs.namespace(|| format!("convert limb {i} of X_r[1] to num"))) + limb.as_allocated_num(cs.namespace(|| (i, format!("convert limb {i} of X_r[1] to num")))) }) .collect::>, _>>()?; @@ -243,23 +243,23 @@ impl AllocatedRelaxedR1CSInstance { ro.absorb(&T.x); ro.absorb(&T.y); ro.absorb(&T.is_infinity); - let r_bits = ro.squeeze(cs.namespace(|| "r bits"), NUM_CHALLENGE_BITS)?; - let r = le_bits_to_num(cs.namespace(|| "r"), &r_bits)?; + let r_bits = ro.squeeze(cs.namespace(|| (0, "r bits")), NUM_CHALLENGE_BITS)?; + let r = le_bits_to_num(cs.namespace(|| (1, "r")), &r_bits)?; // W_fold = self.W + r * u.W - let rW = u.W.scalar_mul(cs.namespace(|| "r * u.W"), &r_bits)?; - let W_fold = self.W.add(cs.namespace(|| "self.W + r * u.W"), &rW)?; + let rW = u.W.scalar_mul(cs.namespace(|| (2, "r * u.W")), &r_bits)?; + let W_fold = self.W.add(cs.namespace(|| (3, "self.W + r * u.W")), &rW)?; // E_fold = self.E + r * T - let rT = T.scalar_mul(cs.namespace(|| "r * T"), &r_bits)?; - let E_fold = self.E.add(cs.namespace(|| "self.E + r * T"), &rT)?; + let rT = T.scalar_mul(cs.namespace(|| (4, "r * T")), &r_bits)?; + let E_fold = self.E.add(cs.namespace(|| (5, "self.E + r * T")), &rT)?; // u_fold = u_r + r - let u_fold = AllocatedNum::alloc(cs.namespace(|| "u_fold"), || { + let u_fold = AllocatedNum::alloc(cs.namespace(|| (6, "u_fold")), || { Ok(*self.u.get_value().get()? + r.get_value().get()?) })?; cs.enforce( - || "Check u_fold", + || (7, "Check u_fold"), |lc| lc, |lc| lc, |lc| lc + u_fold.get_variable() - self.u.get_variable() - r.get_variable(), @@ -268,7 +268,7 @@ impl AllocatedRelaxedR1CSInstance { // Fold the IO: // Analyze r into limbs let r_bn = BigNat::from_num( - cs.namespace(|| "allocate r_bn"), + cs.namespace(|| (8, "allocate r_bn")), &Num::from(r), limb_width, n_limbs, @@ -276,7 +276,7 @@ impl AllocatedRelaxedR1CSInstance { // Allocate the order of the non-native field as a constant let m_bn = alloc_bignat_constant( - cs.namespace(|| "alloc m"), + cs.namespace(|| (9, "alloc m")), &E::GE::group_params().2, limb_width, n_limbs, @@ -284,33 +284,33 @@ impl AllocatedRelaxedR1CSInstance { // Analyze X0 to bignat let X0_bn = BigNat::from_num( - cs.namespace(|| "allocate X0_bn"), + cs.namespace(|| (10, "allocate X0_bn")), &Num::from(u.X0.clone()), limb_width, n_limbs, )?; // Fold self.X[0] + r * X[0] - let (_, r_0) = X0_bn.mult_mod(cs.namespace(|| "r*X[0]"), &r_bn, &m_bn)?; + let (_, r_0) = X0_bn.mult_mod(cs.namespace(|| (11, "r*X[0]")), &r_bn, &m_bn)?; // add X_r[0] let r_new_0 = self.X0.add(&r_0)?; // Now reduce - let X0_fold = r_new_0.red_mod(cs.namespace(|| "reduce folded X[0]"), &m_bn)?; + let X0_fold = r_new_0.red_mod(cs.namespace(|| (12, "reduce folded X[0]")), &m_bn)?; // Analyze X1 to bignat let X1_bn = BigNat::from_num( - cs.namespace(|| "allocate X1_bn"), + cs.namespace(|| (13, "allocate X1_bn")), &Num::from(u.X1.clone()), limb_width, n_limbs, )?; // Fold self.X[1] + r * X[1] - let (_, r_1) = X1_bn.mult_mod(cs.namespace(|| "r*X[1]"), &r_bn, &m_bn)?; + let (_, r_1) = X1_bn.mult_mod(cs.namespace(|| (14, "r*X[1]")), &r_bn, &m_bn)?; // add X_r[1] let r_new_1 = self.X1.add(&r_1)?; // Now reduce - let X1_fold = r_new_1.red_mod(cs.namespace(|| "reduce folded X[1]"), &m_bn)?; + let X1_fold = r_new_1.red_mod(cs.namespace(|| (15, "reduce folded X[1]")), &m_bn)?; Ok(Self { W: W_fold, @@ -329,35 +329,35 @@ impl AllocatedRelaxedR1CSInstance { condition: &Boolean, ) -> Result, SynthesisError> { let W = AllocatedPoint::conditionally_select( - cs.namespace(|| "W = cond ? self.W : other.W"), + cs.namespace(|| (0, "W = cond ? self.W : other.W")), &self.W, &other.W, condition, )?; let E = AllocatedPoint::conditionally_select( - cs.namespace(|| "E = cond ? self.E : other.E"), + cs.namespace(|| (1, "E = cond ? self.E : other.E")), &self.E, &other.E, condition, )?; let u = conditionally_select( - cs.namespace(|| "u = cond ? self.u : other.u"), + cs.namespace(|| (2, "u = cond ? self.u : other.u")), &self.u, &other.u, condition, )?; let X0 = conditionally_select_bignat( - cs.namespace(|| "X[0] = cond ? self.X[0] : other.X[0]"), + cs.namespace(|| (3, "X[0] = cond ? self.X[0] : other.X[0]")), &self.X0, &other.X0, condition, )?; let X1 = conditionally_select_bignat( - cs.namespace(|| "X[1] = cond ? self.X[1] : other.X[1]"), + cs.namespace(|| (4, "X[1] = cond ? self.X[1] : other.X[1]")), &self.X1, &other.X1, condition, diff --git a/src/gadgets/utils.rs b/src/gadgets/utils.rs index 86779076..460b437e 100644 --- a/src/gadgets/utils.rs +++ b/src/gadgets/utils.rs @@ -35,19 +35,19 @@ where }); coeff = coeff.double(); } - let num = AllocatedNum::alloc(cs.namespace(|| "Field element"), || { + let num = AllocatedNum::alloc(cs.namespace(|| (0, "Field element")), || { fe.ok_or(SynthesisError::AssignmentMissing) })?; lc = lc - num.get_variable(); - cs.enforce(|| "compute number from bits", |lc| lc, |lc| lc, |_| lc); + cs.enforce(|| (0, "compute number from bits"), |lc| lc, |lc| lc, |_| lc); Ok(num) } /// Allocate a variable that is set to zero pub fn alloc_zero>(mut cs: CS) -> AllocatedNum { - let zero = AllocatedNum::alloc_infallible(cs.namespace(|| "alloc"), || F::ZERO); + let zero = AllocatedNum::alloc_infallible(cs.namespace(|| (0, "alloc")), || F::ZERO); cs.enforce( - || "check zero is valid", + || (0, "check zero is valid"), |lc| lc, |lc| lc, |lc| lc + zero.get_variable(), @@ -57,9 +57,9 @@ pub fn alloc_zero>(mut cs: CS) -> Allocat /// Allocate a variable that is set to one pub fn alloc_one>(mut cs: CS) -> AllocatedNum { - let one = AllocatedNum::alloc_infallible(cs.namespace(|| "alloc"), || F::ONE); + let one = AllocatedNum::alloc_infallible(cs.namespace(|| (0, "alloc")), || F::ONE); cs.enforce( - || "check one is valid", + || (0, "check one is valid"), |lc| lc + CS::one(), |lc| lc + CS::one(), |lc| lc + one.get_variable(), @@ -78,7 +78,7 @@ where ::Scalar: PrimeFieldBits, CS: ConstraintSystem<::Base>, { - AllocatedNum::alloc(cs.namespace(|| "allocate scalar as base"), || { + AllocatedNum::alloc(cs.namespace(|| (0, "allocate scalar as base")), || { let input_bits = input.unwrap_or(E::Scalar::ZERO).clone().to_le_bits(); let mut mult = E::Base::ONE; let mut val = E::Base::ZERO; @@ -115,7 +115,7 @@ pub fn alloc_bignat_constant>( ) -> Result, SynthesisError> { let limbs = nat_to_limbs(val, limb_width, n_limbs).unwrap(); let bignat = BigNat::alloc_from_limbs( - cs.namespace(|| "alloc bignat"), + cs.namespace(|| (0, "alloc bignat")), || Ok(limbs.clone()), None, limb_width, @@ -124,7 +124,7 @@ pub fn alloc_bignat_constant>( // Now enforce that the limbs are all equal to the constants (0..n_limbs).for_each(|i| { cs.enforce( - || format!("check limb {i}"), + || (i, format!("check limb {i}")), |lc| lc + &bignat.limbs[i], |lc| lc + CS::one(), |lc| lc + (limbs[i], CS::one()), @@ -146,11 +146,11 @@ pub fn alloc_num_equals>( _ => None, }; - let r = AllocatedBit::alloc(cs.namespace(|| "r"), r_value)?; + let r = AllocatedBit::alloc(cs.namespace(|| (0, "r")), r_value)?; // Allocate t s.t. t=1 if z1 == z2 else 1/(z1 - z2) - let t = AllocatedNum::alloc(cs.namespace(|| "t"), || { + let t = AllocatedNum::alloc(cs.namespace(|| (1, "t")), || { Ok(if *a.get_value().get()? == *b.get_value().get()? { F::ONE } else { @@ -161,14 +161,14 @@ pub fn alloc_num_equals>( })?; cs.enforce( - || "t*(a - b) = 1 - r", + || (2, "t*(a - b) = 1 - r"), |lc| lc + t.get_variable(), |lc| lc + a.get_variable() - b.get_variable(), |lc| lc + CS::one() - r.get_variable(), ); cs.enforce( - || "r*(a - b) = 0", + || (3, "r*(a - b) = 0"), |lc| lc + r.get_variable(), |lc| lc + a.get_variable() - b.get_variable(), |lc| lc, @@ -184,7 +184,7 @@ pub fn conditionally_select>( b: &AllocatedNum, condition: &Boolean, ) -> Result, SynthesisError> { - let c = AllocatedNum::alloc(cs.namespace(|| "conditional select result"), || { + let c = AllocatedNum::alloc(cs.namespace(|| (0, "conditional select result")), || { if *condition.get_value().get()? { Ok(*a.get_value().get()?) } else { @@ -195,7 +195,7 @@ pub fn conditionally_select>( // a * condition + b*(1-condition) = c -> // a * condition - b*condition = c - b cs.enforce( - || "conditional select constraint", + || (0, "conditional select constraint"), |lc| lc + a.get_variable() - b.get_variable(), |_| condition.lc(CS::one(), F::ONE), |lc| lc + c.get_variable() - b.get_variable(), @@ -215,7 +215,7 @@ pub fn conditionally_select_vec>( .zip(b.iter()) .enumerate() .map(|(i, (a, b))| { - conditionally_select(cs.namespace(|| format!("select_{i}")), a, b, condition) + conditionally_select(cs.namespace(|| (i, format!("select_{i}"))), a, b, condition) }) .collect::>, SynthesisError>>() } @@ -229,7 +229,7 @@ pub fn conditionally_select_bignat>( ) -> Result, SynthesisError> { assert!(a.limbs.len() == b.limbs.len()); let c = BigNat::alloc_from_nat( - cs.namespace(|| "conditional select result"), + cs.namespace(|| (0, "conditional select result")), || { if *condition.get_value().get()? { Ok(a.value.get()?.clone()) @@ -245,7 +245,7 @@ pub fn conditionally_select_bignat>( // a * condition - b*condition = c - b for i in 0..c.limbs.len() { cs.enforce( - || format!("conditional select constraint {i}"), + || (i, format!("conditional select constraint {i}")), |lc| lc + &a.limbs[i] - &b.limbs[i], |_| condition.lc(CS::one(), F::ONE), |lc| lc + &c.limbs[i] - &b.limbs[i], @@ -262,7 +262,7 @@ pub fn conditionally_select2>( b: &AllocatedNum, condition: &AllocatedNum, ) -> Result, SynthesisError> { - let c = AllocatedNum::alloc(cs.namespace(|| "conditional select result"), || { + let c = AllocatedNum::alloc(cs.namespace(|| (0, "conditional select result")), || { if *condition.get_value().get()? == F::ONE { Ok(*a.get_value().get()?) } else { @@ -273,7 +273,7 @@ pub fn conditionally_select2>( // a * condition + b*(1-condition) = c -> // a * condition - b*condition = c - b cs.enforce( - || "conditional select constraint", + || (0, "conditional select constraint"), |lc| lc + a.get_variable() - b.get_variable(), |lc| lc + condition.get_variable(), |lc| lc + c.get_variable() - b.get_variable(), @@ -288,7 +288,7 @@ pub fn select_zero_or_num2>( a: &AllocatedNum, condition: &AllocatedNum, ) -> Result, SynthesisError> { - let c = AllocatedNum::alloc(cs.namespace(|| "conditional select result"), || { + let c = AllocatedNum::alloc(cs.namespace(|| (0, "conditional select result")), || { if *condition.get_value().get()? == F::ONE { Ok(F::ZERO) } else { @@ -298,7 +298,7 @@ pub fn select_zero_or_num2>( // a * (1 - condition) = c cs.enforce( - || "conditional select constraint", + || (0, "conditional select constraint"), |lc| lc + a.get_variable(), |lc| lc + CS::one() - condition.get_variable(), |lc| lc + c.get_variable(), @@ -313,7 +313,7 @@ pub fn select_num_or_zero2>( a: &AllocatedNum, condition: &AllocatedNum, ) -> Result, SynthesisError> { - let c = AllocatedNum::alloc(cs.namespace(|| "conditional select result"), || { + let c = AllocatedNum::alloc(cs.namespace(|| (0, "conditional select result")), || { if *condition.get_value().get()? == F::ONE { Ok(*a.get_value().get()?) } else { @@ -322,7 +322,7 @@ pub fn select_num_or_zero2>( })?; cs.enforce( - || "conditional select constraint", + || (0, "conditional select constraint"), |lc| lc + a.get_variable(), |lc| lc + condition.get_variable(), |lc| lc + c.get_variable(), @@ -337,7 +337,7 @@ pub fn select_num_or_zero>( a: &AllocatedNum, condition: &Boolean, ) -> Result, SynthesisError> { - let c = AllocatedNum::alloc(cs.namespace(|| "conditional select result"), || { + let c = AllocatedNum::alloc(cs.namespace(|| (0, "conditional select result")), || { if *condition.get_value().get()? { Ok(*a.get_value().get()?) } else { @@ -346,7 +346,7 @@ pub fn select_num_or_zero>( })?; cs.enforce( - || "conditional select constraint", + || (0, "conditional select constraint"), |lc| lc + a.get_variable(), |_| condition.lc(CS::one(), F::ONE), |lc| lc + c.get_variable(), @@ -361,7 +361,7 @@ pub fn select_one_or_num2>( a: &AllocatedNum, condition: &AllocatedNum, ) -> Result, SynthesisError> { - let c = AllocatedNum::alloc(cs.namespace(|| "conditional select result"), || { + let c = AllocatedNum::alloc(cs.namespace(|| (0, "conditional select result")), || { if *condition.get_value().get()? == F::ONE { Ok(F::ONE) } else { @@ -370,7 +370,7 @@ pub fn select_one_or_num2>( })?; cs.enforce( - || "conditional select constraint", + || (0, "conditional select constraint"), |lc| lc + CS::one() - a.get_variable(), |lc| lc + condition.get_variable(), |lc| lc + c.get_variable() - a.get_variable(), @@ -385,7 +385,7 @@ pub fn select_one_or_diff2>( b: &AllocatedNum, condition: &AllocatedNum, ) -> Result, SynthesisError> { - let c = AllocatedNum::alloc(cs.namespace(|| "conditional select result"), || { + let c = AllocatedNum::alloc(cs.namespace(|| (0, "conditional select result")), || { if *condition.get_value().get()? == F::ONE { Ok(F::ONE) } else { @@ -394,7 +394,7 @@ pub fn select_one_or_diff2>( })?; cs.enforce( - || "conditional select constraint", + || (0, "conditional select constraint"), |lc| lc + CS::one() - a.get_variable() + b.get_variable(), |lc| lc + condition.get_variable(), |lc| lc + c.get_variable() - a.get_variable() + b.get_variable(), @@ -408,7 +408,7 @@ pub fn select_num_or_one>( a: &AllocatedNum, condition: &Boolean, ) -> Result, SynthesisError> { - let c = AllocatedNum::alloc(cs.namespace(|| "conditional select result"), || { + let c = AllocatedNum::alloc(cs.namespace(|| (0, "conditional select result")), || { if *condition.get_value().get()? { Ok(*a.get_value().get()?) } else { @@ -417,7 +417,7 @@ pub fn select_num_or_one>( })?; cs.enforce( - || "conditional select constraint", + || (0, "conditional select constraint"), |lc| lc + a.get_variable() - CS::one(), |_| condition.lc(CS::one(), F::ONE), |lc| lc + c.get_variable() - CS::one(), diff --git a/src/lib.rs b/src/lib.rs index a56845a3..93b82b57 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1023,14 +1023,14 @@ mod tests { ) -> Result>, SynthesisError> { // Consider a cubic equation: `x^3 + x + 5 = y`, where `x` and `y` are respectively the input and output. let x = &z[0]; - let x_sq = x.square(cs.namespace(|| "x_sq"))?; - let x_cu = x_sq.mul(cs.namespace(|| "x_cu"), x)?; - let y = AllocatedNum::alloc(cs.namespace(|| "y"), || { + let x_sq = x.square(cs.namespace(|| (0, "x_sq")))?; + let x_cu = x_sq.mul(cs.namespace(|| (1, "x_cu")), x)?; + let y = AllocatedNum::alloc(cs.namespace(|| (2, "y")), || { Ok(x_cu.get_value().unwrap() + x.get_value().unwrap() + F::from(5u64)) })?; cs.enforce( - || "y = x^3 + x + 5", + || (3, "y = x^3 + x + 5"), |lc| { lc + x_cu.get_variable() + x.get_variable() @@ -1489,15 +1489,15 @@ mod tests { let x = &z[0]; // we allocate a variable and set it to the provided non-deterministic advice. - let y = AllocatedNum::alloc_infallible(cs.namespace(|| "y"), || self.y); + let y = AllocatedNum::alloc_infallible(cs.namespace(|| (0, "y")), || self.y); // We now check if y = x^{1/5} by checking if y^5 = x - let y_sq = y.square(cs.namespace(|| "y_sq"))?; - let y_quad = y_sq.square(cs.namespace(|| "y_quad"))?; - let y_pow_5 = y_quad.mul(cs.namespace(|| "y_fifth"), &y)?; + let y_sq = y.square(cs.namespace(|| (1, "y_sq")))?; + let y_quad = y_sq.square(cs.namespace(|| (2, "y_quad")))?; + let y_pow_5 = y_quad.mul(cs.namespace(|| (3, "y_fifth")), &y)?; cs.enforce( - || "y^5 = x", + || (4, "y^5 = x"), |lc| lc + y_pow_5.get_variable(), |lc| lc + CS::one(), |lc| lc + x.get_variable(), @@ -1670,8 +1670,8 @@ mod tests { z: &[AllocatedNum], ) -> Result>, SynthesisError> { let x = &z[0]; - let y = x.square(cs.namespace(|| "x_sq"))?; - y.inputize(cs.namespace(|| "y"))?; // inputize y + let y = x.square(cs.namespace(|| (0, "x_sq")))?; + y.inputize(cs.namespace(|| (1, "y")))?; // inputize y Ok(vec![y]) } } diff --git a/src/nifs.rs b/src/nifs.rs index ca0e3e83..44a3bb0b 100644 --- a/src/nifs.rs +++ b/src/nifs.rs @@ -229,18 +229,18 @@ mod tests { x_val: Option, ) -> Result<(), SynthesisError> { // Consider a cubic equation: `x^3 + x + 5 = y`, where `x` and `y` are respectively the input and output. - let x = AllocatedNum::alloc_infallible(cs.namespace(|| "x"), || x_val.unwrap()); - let _ = x.inputize(cs.namespace(|| "x is input")); + let x = AllocatedNum::alloc_infallible(cs.namespace(|| (0, "x")), || x_val.unwrap()); + let _ = x.inputize(cs.namespace(|| (1, "x is input"))); - let x_sq = x.square(cs.namespace(|| "x_sq"))?; - let x_cu = x_sq.mul(cs.namespace(|| "x_cu"), &x)?; - let y = AllocatedNum::alloc(cs.namespace(|| "y"), || { + let x_sq = x.square(cs.namespace(|| (2, "x_sq")))?; + let x_cu = x_sq.mul(cs.namespace(|| (3, "x_cu")), &x)?; + let y = AllocatedNum::alloc(cs.namespace(|| (4, "y")), || { Ok(x_cu.get_value().unwrap() + x.get_value().unwrap() + Scalar::from(5u64)) })?; - let _ = y.inputize(cs.namespace(|| "y is output")); + let _ = y.inputize(cs.namespace(|| (5, "y is output"))); cs.enforce( - || "y = x^3 + x + 5", + || (6, "y = x^3 + x + 5"), |lc| { lc + x_cu.get_variable() + x.get_variable() diff --git a/src/provider/poseidon/circuit2.rs b/src/provider/poseidon/circuit2.rs index e0085d78..f5d1c93a 100644 --- a/src/provider/poseidon/circuit2.rs +++ b/src/provider/poseidon/circuit2.rs @@ -45,13 +45,13 @@ impl Elt { match self { Self::Allocated(v) => Ok(v.clone()), Self::Num(num) => { - let v = AllocatedNum::alloc(cs.namespace(|| "allocate for Elt::Num"), || { + let v = AllocatedNum::alloc(cs.namespace(|| (0, "allocate for Elt::Num")), || { num.get_value().ok_or(SynthesisError::AssignmentMissing) })?; if enforce { cs.enforce( - || "enforce num allocation preserves lc".to_string(), + || (1, "enforce num allocation preserves lc"), |_| num.lc(Scalar::ONE), |lc| lc + CS::one(), |lc| lc + v.get_variable(), @@ -113,14 +113,14 @@ impl Elt { ) -> Result, SynthesisError> { match self { Elt::Num(num) => { - let allocated = AllocatedNum::alloc(&mut cs.namespace(|| "squared num"), || { + let allocated = AllocatedNum::alloc(&mut cs.namespace(|| (0, "squared num")), || { num .get_value() .ok_or(SynthesisError::AssignmentMissing) .map(|tmp| tmp * tmp) })?; cs.enforce( - || "squaring constraint", + || (1, "squaring constraint"), |_| num.lc(Scalar::ONE), |_| num.lc(Scalar::ONE), |lc| lc + allocated.get_variable(), @@ -187,28 +187,32 @@ where &mut self, cs: &mut CS, ) -> Result, SynthesisError> { - self.full_round(cs.namespace(|| "first round"), true, false)?; + self.full_round(cs.namespace(|| (0, "first round")), true, false)?; for i in 1..self.constants.full_rounds / 2 { self.full_round( - cs.namespace(|| format!("initial full round {i}")), + cs.namespace(|| (1 + i, format!("initial full round {i}"))), false, false, )?; } for i in 0..self.constants.partial_rounds { - self.partial_round(cs.namespace(|| format!("partial round {i}")))?; + self.partial_round(cs.namespace(|| (1 + self.constants.full_rounds / 2 + i, format!("partial round {i}"))))?; } for i in 0..(self.constants.full_rounds / 2) - 1 { self.full_round( - cs.namespace(|| format!("final full round {i}")), + cs.namespace(|| (1 + self.constants.full_rounds / 2 + self.constants.partial_rounds + i, format!("final full round {i}"))), false, false, )?; } - self.full_round(cs.namespace(|| "terminal full round"), false, true)?; + self.full_round( + cs.namespace(|| (1 + self.constants.full_rounds / 2 + self.constants.partial_rounds + (self.constants.full_rounds / 2 - 1), "terminal full round")), + false, + true, + )?; let elt = self.elements[1].clone(); self.reset_offsets(); @@ -282,7 +286,7 @@ where if first_round { { self.elements[i] = quintic_s_box_pre_add( - cs.namespace(|| format!("quintic s-box {i}")), + cs.namespace(|| (self.constants_offset + i, format!("quintic s-box {i}"))), &self.elements[i], pre_round_key, post_round_key, @@ -290,7 +294,7 @@ where } } else { self.elements[i] = quintic_s_box( - cs.namespace(|| format!("quintic s-box {i}")), + cs.namespace(|| (self.constants_offset + i, format!("quintic s-box {i}"))), &self.elements[i], post_round_key, )?; @@ -311,7 +315,7 @@ where self.constants_offset += 1; // Apply the quintic S-Box to the first element. self.elements[0] = quintic_s_box( - cs.namespace(|| "solitary quintic s-box"), + cs.namespace(|| (self.constants_offset, "solitary quintic s-box")), &self.elements[0], Some(round_key), )?; @@ -417,10 +421,10 @@ fn quintic_s_box, Scalar: PrimeField>( post_round_key: Option, ) -> Result, SynthesisError> { // If round_key was supplied, add it after all exponentiation. - let l2 = l.square(cs.namespace(|| "l^2"))?; - let l4 = l2.square(cs.namespace(|| "l^4"))?; + let l2 = l.square(cs.namespace(|| (1, "l^2")))?; + let l4 = l2.square(cs.namespace(|| (2, "l^4")))?; let l5 = mul_sum( - cs.namespace(|| "(l4 * l) + rk)"), + cs.namespace(|| (3, "(l4 * l) + rk")), &l4, l, None, @@ -440,10 +444,10 @@ fn quintic_s_box_pre_add, Scalar: PrimeField>( ) -> Result, SynthesisError> { if let (Some(pre_round_key), Some(post_round_key)) = (pre_round_key, post_round_key) { // If round_key was supplied, add it to l before squaring. - let l2 = square_sum(cs.namespace(|| "(l+rk)^2"), pre_round_key, l, true)?; - let l4 = l2.square(cs.namespace(|| "l^4"))?; + let l2 = square_sum(cs.namespace(|| (1, "(l+rk)^2")), pre_round_key, l, true)?; + let l4 = l2.square(cs.namespace(|| (2, "l^4")))?; let l5 = mul_sum( - cs.namespace(|| "l4 * (l + rk)"), + cs.namespace(|| (3, "l4 * (l + rk)")), &l4, l, Some(pre_round_key), @@ -464,7 +468,7 @@ pub fn square_sum, Scalar: PrimeField>( elt: &Elt, enforce: bool, ) -> Result, SynthesisError> { - let res = AllocatedNum::alloc(cs.namespace(|| "squared sum"), || { + let res = AllocatedNum::alloc(cs.namespace(|| (0, "squared sum")), || { let mut tmp = elt.val().ok_or(SynthesisError::AssignmentMissing)?; tmp.add_assign(&to_add); tmp = tmp.square(); @@ -473,7 +477,7 @@ pub fn square_sum, Scalar: PrimeField>( if enforce { cs.enforce( - || "squared sum constraint", + || (1, "squared sum constraint"), |_| elt.lc() + (to_add, CS::one()), |_| elt.lc() + (to_add, CS::one()), |lc| lc + res.get_variable(), @@ -492,7 +496,7 @@ pub fn mul_sum, Scalar: PrimeField>( post_add: Option, enforce: bool, ) -> Result, SynthesisError> { - let res = AllocatedNum::alloc(cs.namespace(|| "mul_sum"), || { + let res = AllocatedNum::alloc(cs.namespace(|| (0, "mul_sum")), || { let mut tmp = b.val().ok_or(SynthesisError::AssignmentMissing)?; if let Some(x) = pre_add { tmp.add_assign(&x); @@ -511,14 +515,14 @@ pub fn mul_sum, Scalar: PrimeField>( if let Some(pre) = pre_add { cs.enforce( - || "mul sum constraint pre-post-add", + || (1, "mul sum constraint pre-post-add"), |_| b.lc() + (pre, CS::one()), |lc| lc + a.get_variable(), |lc| lc + res.get_variable() + (neg, CS::one()), ); } else { cs.enforce( - || "mul sum constraint post-add", + || (2, "mul sum constraint post-add"), |_| b.lc(), |lc| lc + a.get_variable(), |lc| lc + res.get_variable() + (neg, CS::one()), @@ -527,14 +531,14 @@ pub fn mul_sum, Scalar: PrimeField>( } else { if let Some(pre) = pre_add { cs.enforce( - || "mul sum constraint pre-add", + || (3, "mul sum constraint pre-add"), |_| b.lc() + (pre, CS::one()), |lc| lc + a.get_variable(), |lc| lc + res.get_variable(), ); } else { cs.enforce( - || "mul sum constraint", + || (4, "mul sum constraint"), |_| b.lc(), |lc| lc + a.get_variable(), |lc| lc + res.get_variable(), diff --git a/src/provider/poseidon/circuit2_witness.rs b/src/provider/poseidon/circuit2_witness.rs index af9bb21d..8d8828f0 100644 --- a/src/provider/poseidon/circuit2_witness.rs +++ b/src/provider/poseidon/circuit2_witness.rs @@ -5,7 +5,7 @@ use crate::frontend::util_cs::witness_cs::SizedWitness; use ff::PrimeField; use generic_array::{sequence::GenericSequence, typenum::Unsigned, GenericArray}; -impl SizedWitness for Poseidon<'_, Scalar, A> +impl<'a, Scalar, A> SizedWitness for Poseidon<'a, Scalar, A> where Scalar: PrimeField, A: Arity, diff --git a/src/provider/poseidon/mod.rs b/src/provider/poseidon/mod.rs index f80bb0c9..87bb5ac8 100644 --- a/src/provider/poseidon/mod.rs +++ b/src/provider/poseidon/mod.rs @@ -221,7 +221,7 @@ where SpongeOp::Absorb(self.num_absorbs as u32), SpongeOp::Squeeze(1u32), ]); - let mut ns = cs.namespace(|| "ns"); + let mut ns = cs.namespace(|| (0, "ns")); let hash = { let mut sponge = SpongeCircuit::new_with_constants(&self.constants.0, Simplex); @@ -243,12 +243,12 @@ where output }; - let hash = Elt::ensure_allocated(&hash[0], &mut ns.namespace(|| "ensure allocated"), true)?; + let hash = Elt::ensure_allocated(&hash[0], &mut ns.namespace(|| (1, "ensure allocated")), true)?; // return the hash as a vector of bits, truncated Ok( hash - .to_bits_le_strict(ns.namespace(|| "poseidon hash to boolean"))? + .to_bits_le_strict(ns.namespace(|| (2, "poseidon hash to boolean")))? .iter() .map(|boolean| match boolean { Boolean::Is(ref x) => x.clone(), @@ -295,9 +295,9 @@ mod tests { for i in 0..num_absorbs { let num = E::Scalar::random(&mut csprng); ro.absorb(num); - let num_gadget = AllocatedNum::alloc_infallible(cs.namespace(|| format!("data {i}")), || num); + let num_gadget = AllocatedNum::alloc_infallible(cs.namespace(|| (i, format!("data {i}"))), || num); num_gadget - .inputize(&mut cs.namespace(|| format!("input {i}"))) + .inputize(&mut cs.namespace(|| (i, format!("input {i}")))) .unwrap(); ro_gadget.absorb(&num_gadget); } diff --git a/src/provider/poseidon/round_constants.rs b/src/provider/poseidon/round_constants.rs index c5182432..20d196f0 100644 --- a/src/provider/poseidon/round_constants.rs +++ b/src/provider/poseidon/round_constants.rs @@ -165,3 +165,31 @@ impl Iterator for Grain { Some(new_bit) } } + +#[allow(dead_code)] +#[inline] +const fn bool_to_u8(bit: bool, offset: usize) -> u8 { + if bit { + 1u8 << offset + } else { + 0u8 + } +} + +/// Converts a slice of bools into their byte representation, in little endian. +#[allow(dead_code)] +pub(crate) fn bits_to_bytes(bits: &[bool]) -> Vec { + bits + .chunks(8) + .map(|bits| { + bool_to_u8(bits[7], 7) + | bool_to_u8(bits[6], 6) + | bool_to_u8(bits[5], 5) + | bool_to_u8(bits[4], 4) + | bool_to_u8(bits[3], 3) + | bool_to_u8(bits[2], 2) + | bool_to_u8(bits[1], 1) + | bool_to_u8(bits[0], 0) + }) + .collect() +} diff --git a/src/provider/poseidon/sponge/circuit.rs b/src/provider/poseidon/sponge/circuit.rs index d1b0ec0f..ade1f1dc 100644 --- a/src/provider/poseidon/sponge/circuit.rs +++ b/src/provider/poseidon/sponge/circuit.rs @@ -138,7 +138,8 @@ impl<'a, F: PrimeField, A: Arity, CS: 'a + ConstraintSystem> SpongeTrait<' } else { self .state - .hash(&mut ns.namespace(|| format!("permutation {}", self.permutation_count)))?; + .hash(&mut ns.namespace(|| (self.permutation_count, format!("permutation {}", self.permutation_count)))) + ?; }; Ok(()) diff --git a/src/spartan/direct.rs b/src/spartan/direct.rs index 885495ad..ca7622c9 100644 --- a/src/spartan/direct.rs +++ b/src/spartan/direct.rs @@ -37,20 +37,20 @@ impl> Circuit for DirectCircuit let zero = vec![E::Scalar::ZERO; arity]; let z_i = (0..arity) .map(|i| { - AllocatedNum::alloc(cs.namespace(|| format!("zi_{i}")), || { + AllocatedNum::alloc(cs.namespace(|| (i, format!("zi_{i}"))), || { Ok(self.z_i.as_ref().unwrap_or(&zero)[i]) }) }) .collect::>, _>>()?; - let z_i_plus_one = self.sc.synthesize(&mut cs.namespace(|| "F"), &z_i)?; + let z_i_plus_one = self.sc.synthesize(&mut cs.namespace(|| (arity, "F".to_string())), &z_i)?; // inputize both z_i and z_i_plus_one for (j, input) in z_i.iter().enumerate().take(arity) { - let _ = input.inputize(cs.namespace(|| format!("input {j}"))); + let _ = input.inputize(cs.namespace(|| (arity + j, format!("input {j}")))); } for (j, output) in z_i_plus_one.iter().enumerate().take(arity) { - let _ = output.inputize(cs.namespace(|| format!("output {j}"))); + let _ = output.inputize(cs.namespace(|| (arity + z_i.len() + j, format!("output {j}")))); } Ok(()) @@ -209,14 +209,14 @@ mod tests { ) -> Result>, SynthesisError> { // Consider a cubic equation: `x^3 + x + 5 = y`, where `x` and `y` are respectively the input and output. let x = &z[0]; - let x_sq = x.square(cs.namespace(|| "x_sq"))?; - let x_cu = x_sq.mul(cs.namespace(|| "x_cu"), x)?; - let y = AllocatedNum::alloc(cs.namespace(|| "y"), || { + let x_sq = x.square(cs.namespace(|| (0, "x_sq")))?; + let x_cu = x_sq.mul(cs.namespace(|| (1, "x_cu")), x)?; + let y = AllocatedNum::alloc(cs.namespace(|| (2, "y")), || { Ok(x_cu.get_value().unwrap() + x.get_value().unwrap() + F::from(5u64)) })?; cs.enforce( - || "y = x^3 + x + 5", + || (3, "y = x^3 + x + 5"), |lc| { lc + x_cu.get_variable() + x.get_variable()