From 1d8ed2ceb74e4fd77d11f3ef0e68277b10ad9da6 Mon Sep 17 00:00:00 2001 From: Sai Deng Date: Fri, 3 Apr 2026 04:05:05 +0000 Subject: [PATCH 1/3] feat: add built-in zero wire (Aux(0)) to constraint system Reserve Aux(0) as a built-in zero variable, enforced with a single 0 * 0 = Aux(0) constraint at CS construction time. This makes AllocatedNum::zero() and alloc_zero() free (zero additional constraints or variables), mirroring AllocatedNum::one(). - Add CS::zero() -> Variable to ConstraintSystem trait + all impls - All CS types (ShapeCS, WitnessCS, TestShapeCS, TestConstraintSystem) initialize with Aux(0)=0 and the enforcement constraint - WitnessCS::extend() skips aux[0] like it skips input[0] - AllocatedNum::zero() wraps CS::zero() with no constraints - alloc_zero() delegates to AllocatedNum::zero() - Net savings: ~7 constraints per augmented circuit --- src/frontend/constraint_system.rs | 13 +++++++++++++ src/frontend/gadgets/multieq.rs | 4 ++++ src/frontend/gadgets/num.rs | 16 ++++++++++++++-- src/frontend/shape_cs.rs | 9 +++++++-- src/frontend/test_shape_cs.rs | 9 +++++++-- src/frontend/util_cs/test_cs.rs | 10 ++++++++-- src/frontend/util_cs/witness_cs.rs | 11 ++++++++--- src/gadgets/utils.rs | 14 ++++---------- src/nova/circuit/mod.rs | 6 +++--- src/nova/mod.rs | 6 +++--- 10 files changed, 71 insertions(+), 27 deletions(-) diff --git a/src/frontend/constraint_system.rs b/src/frontend/constraint_system.rs index f8030f3aa..f38d141e3 100644 --- a/src/frontend/constraint_system.rs +++ b/src/frontend/constraint_system.rs @@ -69,6 +69,11 @@ pub trait ConstraintSystem: Sized + Send { Variable::new_unchecked(Index::Input(0)) } + /// Return the "zero" auxiliary variable (Aux(0), enforced to equal zero) + fn zero() -> Variable { + Variable::new_unchecked(Index::Aux(0)) + } + /// Allocate a private variable in the constraint system. The provided function is used to /// determine the assignment of the variable. The given `annotation` function is invoked /// in testing contexts in order to derive a unique name for this variable in the current @@ -244,6 +249,10 @@ impl> ConstraintSystem CS::one() } + fn zero() -> Variable { + CS::zero() + } + fn alloc(&mut self, annotation: A, f: F) -> Result where F: FnOnce() -> Result, @@ -332,6 +341,10 @@ impl> ConstraintSystem CS::one() } + fn zero() -> Variable { + CS::zero() + } + fn alloc(&mut self, annotation: A, f: F) -> Result where F: FnOnce() -> Result, diff --git a/src/frontend/gadgets/multieq.rs b/src/frontend/gadgets/multieq.rs index 3c7e48753..eb73f7f85 100644 --- a/src/frontend/gadgets/multieq.rs +++ b/src/frontend/gadgets/multieq.rs @@ -81,6 +81,10 @@ impl> ConstraintSystem CS::one() } + fn zero() -> Variable { + CS::zero() + } + fn alloc(&mut self, annotation: A, f: F) -> Result where F: FnOnce() -> Result, diff --git a/src/frontend/gadgets/num.rs b/src/frontend/gadgets/num.rs index 3641b3a9f..9d8e69359 100644 --- a/src/frontend/gadgets/num.rs +++ b/src/frontend/gadgets/num.rs @@ -47,6 +47,15 @@ impl AllocatedNum { } } + /// Returns an `AllocatedNum` wrapping the built-in `CS::zero()` variable. + /// Costs zero constraints since Aux(0) is pre-constrained to zero by the CS. + pub fn zero>() -> Self { + AllocatedNum { + value: Some(Scalar::ZERO), + variable: CS::zero(), + } + } + /// Allocate a `Variable(Aux)` in a `ConstraintSystem`. pub fn alloc(mut cs: CS, value: F) -> Result where @@ -585,11 +594,14 @@ mod tests { fn test_allocated_num_one() { let mut cs = TestConstraintSystem::::new(); + // TestConstraintSystem starts with 1 constraint (the built-in zero enforcement) + let base_constraints = cs.num_constraints(); + // AllocatedNum::one() should add zero constraints let one = AllocatedNum::::one::>(); assert_eq!(one.get_value(), Some(Fr::ONE)); assert_eq!(one.get_variable(), TestConstraintSystem::::one()); - assert_eq!(cs.num_constraints(), 0); + assert_eq!(cs.num_constraints(), base_constraints); // Compare: the old alloc + enforce pattern adds 1 constraint let one_old = AllocatedNum::alloc_infallible(cs.namespace(|| "alloc"), || Fr::ONE); @@ -599,6 +611,6 @@ mod tests { |lc| lc + TestConstraintSystem::::one(), |lc| lc + one_old.get_variable(), ); - assert_eq!(cs.num_constraints(), 1); + assert_eq!(cs.num_constraints(), base_constraints + 1); } } diff --git a/src/frontend/shape_cs.rs b/src/frontend/shape_cs.rs index 05a4e996f..3b044765b 100644 --- a/src/frontend/shape_cs.rs +++ b/src/frontend/shape_cs.rs @@ -45,10 +45,15 @@ impl ShapeCS { impl Default for ShapeCS { fn default() -> Self { + let zero_var = Variable::new_unchecked(Index::Aux(0)); + // Enforce Aux(0) = 0: the constraint 0 * 0 = Aux(0) + let a = LinearCombination::<::Scalar>::zero(); + let b = LinearCombination::<::Scalar>::zero(); + let c = LinearCombination::<::Scalar>::zero() + zero_var; ShapeCS { - constraints: vec![], + constraints: vec![(a, b, c)], inputs: 1, - aux: 0, + aux: 1, // Aux(0) reserved for zero } } } diff --git a/src/frontend/test_shape_cs.rs b/src/frontend/test_shape_cs.rs index dfa2e419e..cd003bcd2 100644 --- a/src/frontend/test_shape_cs.rs +++ b/src/frontend/test_shape_cs.rs @@ -220,12 +220,17 @@ impl Default for TestShapeCS { fn default() -> Self { let mut map = HashMap::new(); map.insert("ONE".into(), NamedObject::Var(TestShapeCS::::one())); + map.insert("ZERO".into(), NamedObject::Var(TestShapeCS::::zero())); + let zero_var = Variable::new_unchecked(Index::Aux(0)); + let a = LinearCombination::<::Scalar>::zero(); + let b = LinearCombination::<::Scalar>::zero(); + let c = LinearCombination::<::Scalar>::zero() + zero_var; TestShapeCS { named_objects: map, current_namespace: vec![], - constraints: vec![], + constraints: vec![(a, b, c, "ZERO".into())], inputs: vec![String::from("ONE")], - aux: vec![], + aux: vec![String::from("ZERO")], } } } diff --git a/src/frontend/util_cs/test_cs.rs b/src/frontend/util_cs/test_cs.rs index cd8567c0b..2ad82ea6b 100644 --- a/src/frontend/util_cs/test_cs.rs +++ b/src/frontend/util_cs/test_cs.rs @@ -73,13 +73,19 @@ impl Default for TestConstraintSystem { fn default() -> Self { let mut map = HashMap::new(); map.insert("ONE".into(), NamedObject::Var); + map.insert("ZERO".into(), NamedObject::Var); + + let zero_var = Variable::new_unchecked(Index::Aux(0)); + let a = LinearCombination::::zero(); + let b = LinearCombination::::zero(); + let c = LinearCombination::::zero() + zero_var; TestConstraintSystem { named_objects: map, current_namespace: vec![], - constraints: vec![], + constraints: vec![(a, b, c, "ZERO".into())], inputs: vec![(Scalar::ONE, "ONE".into())], - aux: vec![], + aux: vec![(Scalar::ZERO, "ZERO".into())], } } } diff --git a/src/frontend/util_cs/witness_cs.rs b/src/frontend/util_cs/witness_cs.rs index 22db16f3a..3960590e7 100644 --- a/src/frontend/util_cs/witness_cs.rs +++ b/src/frontend/util_cs/witness_cs.rs @@ -51,9 +51,11 @@ where pub fn with_capacity(aux_capacity: usize, input_capacity: usize) -> Self { let mut input_assignment = Vec::with_capacity(input_capacity + 1); input_assignment.push(Scalar::ONE); + let mut aux_assignment = Vec::with_capacity(aux_capacity + 1); + aux_assignment.push(Scalar::ZERO); Self { input_assignment, - aux_assignment: Vec::with_capacity(aux_capacity), + aux_assignment, } } @@ -62,6 +64,7 @@ where self.input_assignment.clear(); self.input_assignment.push(Scalar::ONE); self.aux_assignment.clear(); + self.aux_assignment.push(Scalar::ZERO); } /// Get input assignment @@ -83,10 +86,11 @@ where fn new() -> Self { let input_assignment = vec![Scalar::ONE]; + let aux_assignment = vec![Scalar::ZERO]; Self { input_assignment, - aux_assignment: vec![], + aux_assignment, } } @@ -149,7 +153,8 @@ where self.input_assignment // Skip first input, which must have been a temporarily allocated one variable. .extend(&other.input_assignment[1..]); - self.aux_assignment.extend(&other.aux_assignment); + // Skip first aux, which must have been a temporarily allocated zero variable. + self.aux_assignment.extend(&other.aux_assignment[1..]); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gadgets/utils.rs b/src/gadgets/utils.rs index be092dc67..a95a9586d 100644 --- a/src/gadgets/utils.rs +++ b/src/gadgets/utils.rs @@ -41,16 +41,10 @@ where 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); - cs.enforce( - || "check zero is valid", - |lc| lc, - |lc| lc, - |lc| lc + zero.get_variable(), - ); - zero +/// Allocate a variable that is set to zero. +/// Uses the built-in CS::zero() wire (Aux(0)), so this is free (no extra constraints). +pub fn alloc_zero>(_cs: CS) -> AllocatedNum { + AllocatedNum::zero::() } /// Allocate a scalar as a base. Only to be used is the scalar fits in base! diff --git a/src/nova/circuit/mod.rs b/src/nova/circuit/mod.rs index 7b8b608cf..0ffeac929 100644 --- a/src/nova/circuit/mod.rs +++ b/src/nova/circuit/mod.rs @@ -451,8 +451,8 @@ mod tests { #[test] fn test_recursive_circuit() { - test_recursive_circuit_with::(9830, 10361); - test_recursive_circuit_with::(9998, 10550); - test_recursive_circuit_with::(10277, 10973); + test_recursive_circuit_with::(9823, 10354); + test_recursive_circuit_with::(9991, 10543); + test_recursive_circuit_with::(10270, 10966); } } diff --git a/src/nova/mod.rs b/src/nova/mod.rs index 5d6208288..2d72d6e6f 100644 --- a/src/nova/mod.rs +++ b/src/nova/mod.rs @@ -1125,17 +1125,17 @@ mod tests { fn test_pp_digest() { test_pp_digest_with::( &TrivialCircuit::<_>::default(), - &expect!["5554dcef9f66efdf2477d0ada1f553f0e7edd9191391156edfca338cb270aa02"], + &expect!["79427ff4955e7cf8112f37965e3922ef166cb650f93578db5c65b045d0a71300"], ); test_pp_digest_with::( &TrivialCircuit::<_>::default(), - &expect!["a5ad54e26a84517739bde0fd1e56f10aa1f8321bfee234c347af0fb9b14bfb00"], + &expect!["a091b0952ea6c6b7247d3de59dac55c39236e4eec78519608a9572370d88e600"], ); test_pp_digest_with::( &TrivialCircuit::<_>::default(), - &expect!["b403daf596511f975656f8621269c1e885b60863aebd7a095000b599f6ed2802"], + &expect!["45c048e2413bafd2433432357aa88f343ee9106827f5dced2718c5b95f3c8601"], ); } From 5f13aabf994b4644869e74e7f5d121bdbde249ca Mon Sep 17 00:00:00 2001 From: Sai Deng Date: Fri, 3 Apr 2026 04:32:04 +0000 Subject: [PATCH 2/3] address review: remove default zero(), add test, fix comments, update neutron expects - Remove default impl for CS::zero(); all root CS types now provide explicit impls. Prevents soundness footgun for external impls. - Add doc comment on zero() specifying implementor invariants (reserve Aux(0), enforce 0*0=Aux(0), exclude from alloc). - Add test_allocated_num_zero unit test. - Fix extend() comments to say 'built-in reserved slot' not 'temporarily allocated'. - Update neutron circuit constraint counts and pp_digest expects (behind 'experimental' feature). --- src/frontend/constraint_system.rs | 13 +++++++++---- src/frontend/gadgets/num.rs | 12 ++++++++++++ src/frontend/shape_cs.rs | 4 ++++ src/frontend/test_shape_cs.rs | 4 ++++ src/frontend/util_cs/test_cs.rs | 4 ++++ src/frontend/util_cs/witness_cs.rs | 8 ++++++-- src/neutron/circuit/mod.rs | 6 +++--- src/neutron/mod.rs | 6 +++--- 8 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/frontend/constraint_system.rs b/src/frontend/constraint_system.rs index f38d141e3..a51bb17b5 100644 --- a/src/frontend/constraint_system.rs +++ b/src/frontend/constraint_system.rs @@ -69,10 +69,15 @@ pub trait ConstraintSystem: Sized + Send { Variable::new_unchecked(Index::Input(0)) } - /// Return the "zero" auxiliary variable (Aux(0), enforced to equal zero) - fn zero() -> Variable { - Variable::new_unchecked(Index::Aux(0)) - } + /// Return the "zero" auxiliary variable. + /// + /// # Implementor invariants + /// + /// * `Aux(0)` **must** be reserved at construction time and **must not** be + /// returned by [`alloc`](ConstraintSystem::alloc). + /// * A constraint `0 * 0 = Aux(0)` (i.e. `Aux(0) == 0`) **must** be added + /// by the constructor so the variable is properly enforced. + fn zero() -> Variable; /// Allocate a private variable in the constraint system. The provided function is used to /// determine the assignment of the variable. The given `annotation` function is invoked diff --git a/src/frontend/gadgets/num.rs b/src/frontend/gadgets/num.rs index 9d8e69359..a63bfd74b 100644 --- a/src/frontend/gadgets/num.rs +++ b/src/frontend/gadgets/num.rs @@ -613,4 +613,16 @@ mod tests { ); assert_eq!(cs.num_constraints(), base_constraints + 1); } + + #[test] + fn test_allocated_num_zero() { + let cs = TestConstraintSystem::::new(); + let base_constraints = cs.num_constraints(); + + // AllocatedNum::zero() should add zero constraints + let zero = AllocatedNum::::zero::>(); + assert_eq!(zero.get_value(), Some(Fr::ZERO)); + assert_eq!(zero.get_variable(), TestConstraintSystem::::zero()); + assert_eq!(cs.num_constraints(), base_constraints); + } } diff --git a/src/frontend/shape_cs.rs b/src/frontend/shape_cs.rs index 3b044765b..7f1f428a3 100644 --- a/src/frontend/shape_cs.rs +++ b/src/frontend/shape_cs.rs @@ -61,6 +61,10 @@ impl Default for ShapeCS { impl ConstraintSystem for ShapeCS { type Root = Self; + fn zero() -> Variable { + Variable::new_unchecked(Index::Aux(0)) + } + fn alloc(&mut self, _annotation: A, _f: F) -> Result where F: FnOnce() -> Result, diff --git a/src/frontend/test_shape_cs.rs b/src/frontend/test_shape_cs.rs index cd003bcd2..ac7e07a0a 100644 --- a/src/frontend/test_shape_cs.rs +++ b/src/frontend/test_shape_cs.rs @@ -241,6 +241,10 @@ where { type Root = Self; + fn zero() -> Variable { + Variable::new_unchecked(Index::Aux(0)) + } + fn alloc(&mut self, annotation: A, _f: F) -> Result where F: FnOnce() -> Result, diff --git a/src/frontend/util_cs/test_cs.rs b/src/frontend/util_cs/test_cs.rs index 2ad82ea6b..1b5861fdd 100644 --- a/src/frontend/util_cs/test_cs.rs +++ b/src/frontend/util_cs/test_cs.rs @@ -159,6 +159,10 @@ fn compute_path(ns: &[String], this: &str) -> String { impl ConstraintSystem for TestConstraintSystem { type Root = Self; + fn zero() -> Variable { + Variable::new_unchecked(Index::Aux(0)) + } + fn alloc(&mut self, annotation: A, f: F) -> Result where F: FnOnce() -> Result, diff --git a/src/frontend/util_cs/witness_cs.rs b/src/frontend/util_cs/witness_cs.rs index 3960590e7..5024cde99 100644 --- a/src/frontend/util_cs/witness_cs.rs +++ b/src/frontend/util_cs/witness_cs.rs @@ -84,6 +84,10 @@ where { type Root = Self; + fn zero() -> Variable { + Variable::new_unchecked(Index::Aux(0)) + } + fn new() -> Self { let input_assignment = vec![Scalar::ONE]; let aux_assignment = vec![Scalar::ZERO]; @@ -151,9 +155,9 @@ where fn extend(&mut self, other: &Self) { self.input_assignment - // Skip first input, which must have been a temporarily allocated one variable. + // Skip built-in Input(0) = ONE, which is always the first input. .extend(&other.input_assignment[1..]); - // Skip first aux, which must have been a temporarily allocated zero variable. + // Skip built-in Aux(0) = ZERO, which is always the first aux. self.aux_assignment.extend(&other.aux_assignment[1..]); } diff --git a/src/neutron/circuit/mod.rs b/src/neutron/circuit/mod.rs index be4acd6b8..371ab04e8 100644 --- a/src/neutron/circuit/mod.rs +++ b/src/neutron/circuit/mod.rs @@ -436,8 +436,8 @@ mod tests { #[test] fn test_neutron_recursive_circuit_pasta() { - test_recursive_circuit_with::(&expect!["5493"]); - test_recursive_circuit_with::(&expect!["5773"]); - test_recursive_circuit_with::(&expect!["6238"]); + test_recursive_circuit_with::(&expect!["5492"]); + test_recursive_circuit_with::(&expect!["5772"]); + test_recursive_circuit_with::(&expect!["6237"]); } } diff --git a/src/neutron/mod.rs b/src/neutron/mod.rs index 457f81e8d..33d365400 100644 --- a/src/neutron/mod.rs +++ b/src/neutron/mod.rs @@ -544,17 +544,17 @@ mod tests { fn test_pp_digest() { test_pp_digest_with::( &TrivialCircuit::<_>::default(), - &expect!["4d22b1021985b02532b1cc83ab566d503d8db8cf7de1acac525d39e3c2508e03"], + &expect!["750b49c7d61647ff4805affb81358ed9fc7ba107fd2395ee252350d9039ba203"], ); test_pp_digest_with::( &TrivialCircuit::<_>::default(), - &expect!["fdea1f44a4d102141c6f31efa72c04606c5e6d3ec9a6b37208238152717a4c03"], + &expect!["816fb0f716c65cf700e357f9dcf5a7238933b16af89ab428d63f5c976438f700"], ); test_pp_digest_with::( &TrivialCircuit::<_>::default(), - &expect!["bdcf8157e37b5d99c5c7168774e16ec11a24594833b078ebe6312e83fdfda600"], + &expect!["e9ece80b99b3a82b1c1a29bce4f1148186888754ef9f74b96f6244578cb2e902"], ); } From 6c1b4a0d6542e4d6ffd636c72904c5295be1503c Mon Sep 17 00:00:00 2001 From: Sai Deng Date: Fri, 3 Apr 2026 04:45:40 +0000 Subject: [PATCH 3/3] refactor: remove alloc_zero, use AllocatedNum::zero() directly Replace all 8 alloc_zero() call sites with AllocatedNum::zero::() and remove the alloc_zero function entirely, matching how alloc_one was previously removed in favor of AllocatedNum::one(). --- src/gadgets/ecc.rs | 8 ++++---- src/gadgets/utils.rs | 6 ------ src/neutron/circuit/mod.rs | 4 ++-- src/neutron/circuit/relation.rs | 7 ++----- src/nova/circuit/mod.rs | 6 ++---- src/nova/circuit/r1cs.rs | 10 +++++----- 6 files changed, 15 insertions(+), 26 deletions(-) diff --git a/src/gadgets/ecc.rs b/src/gadgets/ecc.rs index a8a264f8c..44c23266a 100644 --- a/src/gadgets/ecc.rs +++ b/src/gadgets/ecc.rs @@ -8,7 +8,7 @@ use crate::{ gadgets::{ nonnative::{bignat::BigNat, util::f_to_nat}, utils::{ - alloc_bignat_constant, alloc_constant, alloc_num_equals, alloc_zero, conditionally_select, + alloc_bignat_constant, alloc_constant, alloc_num_equals, conditionally_select, conditionally_select2, conditionally_select_bignat, select_num_or_one, select_num_or_zero, select_num_or_zero2, select_one_or_diff2, select_one_or_num2, select_zero_or_num2, }, @@ -109,8 +109,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")); + pub fn default>(_cs: CS) -> Result { + let zero = AllocatedNum::zero::(); let one = AllocatedNum::one::(); Ok(AllocatedPoint { @@ -607,7 +607,7 @@ where ) -> Result<(), SynthesisError> { let (_, b, _, _) = E::GE::group_params(); if b != E::Base::ZERO { - let zero = alloc_zero(cs.namespace(|| "zero for absorb")); + let zero = AllocatedNum::zero::(); let x = conditionally_select2( cs.namespace(|| "select x"), &zero, diff --git a/src/gadgets/utils.rs b/src/gadgets/utils.rs index a95a9586d..22d45e4de 100644 --- a/src/gadgets/utils.rs +++ b/src/gadgets/utils.rs @@ -41,12 +41,6 @@ where Ok(num) } -/// Allocate a variable that is set to zero. -/// Uses the built-in CS::zero() wire (Aux(0)), so this is free (no extra constraints). -pub fn alloc_zero>(_cs: CS) -> AllocatedNum { - AllocatedNum::zero::() -} - /// Allocate a scalar as a base. Only to be used is the scalar fits in base! pub fn alloc_scalar_as_base( mut cs: CS, diff --git a/src/neutron/circuit/mod.rs b/src/neutron/circuit/mod.rs index 371ab04e8..552365ea4 100644 --- a/src/neutron/circuit/mod.rs +++ b/src/neutron/circuit/mod.rs @@ -11,7 +11,7 @@ use crate::{ }, gadgets::{ ecc::AllocatedNonnativePoint, - utils::{alloc_num_equals, alloc_zero, conditionally_select_vec, le_bits_to_num}, + utils::{alloc_num_equals, conditionally_select_vec, le_bits_to_num}, }, neutron::{nifs::NIFS, relation::FoldedInstance}, r1cs::R1CSInstance, @@ -283,7 +283,7 @@ impl> NeutronAugmentedCircuit<'_, E, SC> { self.alloc_witness(cs.namespace(|| "allocate the circuit witness"), arity)?; // Compute variable indicating if this is the base case - let zero = alloc_zero(cs.namespace(|| "zero")); + let zero = AllocatedNum::zero::(); let is_base_case = alloc_num_equals(cs.namespace(|| "Check if base case"), &i.clone(), &zero)?; // synthesize base case diff --git a/src/neutron/circuit/relation.rs b/src/neutron/circuit/relation.rs index ab36555cd..38435f4ee 100644 --- a/src/neutron/circuit/relation.rs +++ b/src/neutron/circuit/relation.rs @@ -1,10 +1,7 @@ //! This module implements various gadgets necessary for folding R1CS types with NeutronNova folding scheme. use crate::{ frontend::{num::AllocatedNum, Boolean, ConstraintSystem, SynthesisError}, - gadgets::{ - ecc::AllocatedNonnativePoint, - utils::{alloc_zero, conditionally_select}, - }, + gadgets::{ecc::AllocatedNonnativePoint, utils::conditionally_select}, neutron::{circuit::r1cs::AllocatedNonnativeR1CSInstance, relation::FoldedInstance}, traits::{commitment::CommitmentTrait, Engine, ROCircuitTrait}, }; @@ -71,7 +68,7 @@ impl AllocatedFoldedInstance { let comm_E = comm_W.clone(); // Allocate T = 0. Similar to X0 and X1, we do not need to check that T is well-formed - let T = alloc_zero(cs.namespace(|| "allocate T")); + let T = AllocatedNum::zero::(); let u = T.clone(); diff --git a/src/nova/circuit/mod.rs b/src/nova/circuit/mod.rs index 0ffeac929..855a2e019 100644 --- a/src/nova/circuit/mod.rs +++ b/src/nova/circuit/mod.rs @@ -11,9 +11,7 @@ use crate::{ }, gadgets::{ ecc::AllocatedPoint, - utils::{ - alloc_num_equals, alloc_scalar_as_base, alloc_zero, conditionally_select_vec, le_bits_to_num, - }, + utils::{alloc_num_equals, alloc_scalar_as_base, conditionally_select_vec, le_bits_to_num}, }, r1cs::{R1CSInstance, RelaxedR1CSInstance}, traits::{ @@ -254,7 +252,7 @@ impl> NovaAugmentedCircuit<'_, E, SC> { self.alloc_witness(cs.namespace(|| "allocate the circuit witness"), arity)?; // Compute variable indicating if this is the base case - let zero = alloc_zero(cs.namespace(|| "zero")); + let zero = AllocatedNum::zero::(); let is_base_case = alloc_num_equals(cs.namespace(|| "Check if base case"), &i.clone(), &zero)?; // compute hash of the non-deterministic inputs diff --git a/src/nova/circuit/r1cs.rs b/src/nova/circuit/r1cs.rs index b8b3ed8be..4a4892e4c 100644 --- a/src/nova/circuit/r1cs.rs +++ b/src/nova/circuit/r1cs.rs @@ -9,8 +9,8 @@ use crate::{ util::{f_to_nat, Num}, }, utils::{ - alloc_bignat_constant, alloc_scalar_as_base, alloc_zero, conditionally_select, - conditionally_select2, conditionally_select_bignat, le_bits_to_num, + alloc_bignat_constant, alloc_scalar_as_base, conditionally_select, conditionally_select2, + conditionally_select_bignat, le_bits_to_num, }, }, r1cs::{R1CSInstance, RelaxedR1CSInstance}, @@ -55,7 +55,7 @@ impl AllocatedR1CSInstance { // so we can use it as a canonical representation for infinity. let (_, b, _, _) = E::GE::group_params(); if b != E::Base::ZERO { - let zero = alloc_zero(cs.namespace(|| "zero for absorb")); + let zero = AllocatedNum::zero::(); let x = conditionally_select2( cs.namespace(|| "select x"), &zero, @@ -205,7 +205,7 @@ impl AllocatedRelaxedR1CSInstance { // so we can use it as a canonical representation for infinity. let (_, b, _, _) = E::GE::group_params(); if b != E::Base::ZERO { - let zero = alloc_zero(cs.namespace(|| "zero for absorb")); + let zero = AllocatedNum::zero::(); // Absorb W let w_x = conditionally_select2( cs.namespace(|| "select W.x"), @@ -300,7 +300,7 @@ impl AllocatedRelaxedR1CSInstance { // When B != 0, use (0,0) for infinity let (_, b, _, _) = E::GE::group_params(); if b != E::Base::ZERO { - let zero = alloc_zero(cs.namespace(|| "zero for T absorb")); + let zero = AllocatedNum::zero::(); let t_x = conditionally_select2(cs.namespace(|| "select T.x"), &zero, &T.x, &T.is_infinity)?; let t_y = conditionally_select2(cs.namespace(|| "select T.y"), &zero, &T.y, &T.is_infinity)?; ro.absorb(&t_x);