From 93f5686446564aed13aa7a684d32b992c0b5bd4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= <4142+huitseeker@users.noreply.github.com> Date: Thu, 9 Nov 2023 16:51:25 -0500 Subject: [PATCH] Update Neptune & simplify SatisfyingAssignment (Arecibo backport) (#256) * chore: Update bellpepper and neptune dependencies - Updated `bellpepper-core` and `bellpepper` dependencies to version `0.4.0` - Upgraded `neptune` dependency to version `13.0.0` * refactor of SatisfyingAssignment as type alias of WitnessCS (#89) * initial refactor of WitnessCS with ex of new constr generic changes * explicit type information for usages of `SatisfyingAssignment::new` * use `scalar_` public getters for the aliased WitnessCS * go back to `_assignment` public fields * remove reference --------- Co-authored-by: johann bestowrous --- Cargo.toml | 6 +- src/bellpepper/mod.rs | 2 +- src/bellpepper/r1cs.rs | 4 +- src/bellpepper/solver.rs | 150 +-------------------------------------- src/circuit.rs | 4 +- src/gadgets/ecc.rs | 6 +- src/lib.rs | 8 +-- src/nifs.rs | 4 +- src/provider/poseidon.rs | 2 +- src/spartan/direct.rs | 2 +- 10 files changed, 21 insertions(+), 167 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6916ca2f3..e18973b5f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,8 +12,8 @@ keywords = ["zkSNARKs", "cryptography", "proofs"] rust-version="1.67.1" [dependencies] -bellpepper-core = { version="0.3.0", default-features = false } -bellpepper = { version="0.3.0", default-features = false } +bellpepper-core = { version="0.4.0", default-features = false } +bellpepper = { version="0.4.0", default-features = false } ff = { version = "0.13.0", features = ["derive"] } digest = "0.10" sha3 = "0.10" @@ -22,7 +22,7 @@ rand_core = { version = "0.6", default-features = false } rand_chacha = "0.3" subtle = "2.5" pasta_curves = { version = "0.5", features = ["repr-c", "serde"] } -neptune = { version = "12.0.0", default-features = false } +neptune = { version = "13.0.0", default-features = false } generic-array = "0.14" num-bigint = { version = "0.4", features = ["serde", "rand"] } num-traits = "0.2" diff --git a/src/bellpepper/mod.rs b/src/bellpepper/mod.rs index 282d75330..4795844a1 100644 --- a/src/bellpepper/mod.rs +++ b/src/bellpepper/mod.rs @@ -50,7 +50,7 @@ mod tests { let (shape, ck) = cs.r1cs_shape(&*default_commitment_key_hint()); // Now get the assignment - let mut cs: SatisfyingAssignment = SatisfyingAssignment::new(); + let mut cs = SatisfyingAssignment::::new(); synthesize_alloc_bit(&mut cs); let (inst, witness) = cs.r1cs_instance_and_witness(&shape, &ck).unwrap(); diff --git a/src/bellpepper/r1cs.rs b/src/bellpepper/r1cs.rs index af2245bc1..bca4ec097 100644 --- a/src/bellpepper/r1cs.rs +++ b/src/bellpepper/r1cs.rs @@ -36,8 +36,8 @@ impl NovaWitness for SatisfyingAssignment { shape: &R1CSShape, ck: &CommitmentKey, ) -> Result<(R1CSInstance, R1CSWitness), NovaError> { - let W = R1CSWitness::::new(shape, &self.aux_assignment)?; - let X = &self.input_assignment[1..]; + let W = R1CSWitness::::new(shape, self.aux_assignment())?; + let X = &self.input_assignment()[1..]; let comm_W = W.commit(ck); diff --git a/src/bellpepper/solver.rs b/src/bellpepper/solver.rs index c8fd6fa11..516d0df93 100644 --- a/src/bellpepper/solver.rs +++ b/src/bellpepper/solver.rs @@ -1,154 +1,8 @@ //! Support for generating R1CS witness using bellpepper. use crate::traits::Group; -use ff::Field; -use bellpepper_core::{ConstraintSystem, Index, LinearCombination, SynthesisError, Variable}; +use bellpepper::util_cs::witness_cs::WitnessCS; /// A `ConstraintSystem` which calculates witness values for a concrete instance of an R1CS circuit. -pub struct SatisfyingAssignment { - // Assignments of variables - pub(crate) input_assignment: Vec, - pub(crate) aux_assignment: Vec, -} -use std::fmt; - -impl fmt::Debug for SatisfyingAssignment { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt - .debug_struct("SatisfyingAssignment") - .field("input_assignment", &self.input_assignment) - .field("aux_assignment", &self.aux_assignment) - .finish() - } -} - -impl PartialEq for SatisfyingAssignment { - fn eq(&self, other: &SatisfyingAssignment) -> bool { - self.input_assignment == other.input_assignment && self.aux_assignment == other.aux_assignment - } -} - -impl ConstraintSystem for SatisfyingAssignment { - type Root = Self; - - fn new() -> Self { - let input_assignment = vec![G::Scalar::ONE]; - - Self { - input_assignment, - aux_assignment: vec![], - } - } - - fn alloc(&mut self, _: A, f: F) -> Result - where - F: FnOnce() -> Result, - A: FnOnce() -> AR, - AR: Into, - { - self.aux_assignment.push(f()?); - - Ok(Variable(Index::Aux(self.aux_assignment.len() - 1))) - } - - fn alloc_input(&mut self, _: A, f: F) -> Result - where - F: FnOnce() -> Result, - A: FnOnce() -> AR, - AR: Into, - { - self.input_assignment.push(f()?); - - Ok(Variable(Index::Input(self.input_assignment.len() - 1))) - } - - fn enforce(&mut self, _: A, _a: LA, _b: LB, _c: LC) - where - A: FnOnce() -> AR, - AR: Into, - LA: FnOnce(LinearCombination) -> LinearCombination, - LB: FnOnce(LinearCombination) -> LinearCombination, - LC: FnOnce(LinearCombination) -> LinearCombination, - { - // Do nothing: we don't care about linear-combination evaluations in this context. - } - - fn push_namespace(&mut self, _: N) - where - NR: Into, - N: FnOnce() -> NR, - { - // Do nothing; we don't care about namespaces in this context. - } - - fn pop_namespace(&mut self) { - // Do nothing; we don't care about namespaces in this context. - } - - fn get_root(&mut self) -> &mut Self::Root { - self - } - - fn is_extensible() -> bool { - true - } - - fn extend(&mut self, other: &Self) { - 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); - } - - fn is_witness_generator(&self) -> bool { - true - } - - fn extend_inputs(&mut self, new_inputs: &[G::Scalar]) { - self.input_assignment.extend(new_inputs); - } - - fn extend_aux(&mut self, new_aux: &[G::Scalar]) { - self.aux_assignment.extend(new_aux); - } - - fn allocate_empty( - &mut self, - aux_n: usize, - inputs_n: usize, - ) -> (&mut [G::Scalar], &mut [G::Scalar]) { - let allocated_aux = { - let i = self.aux_assignment.len(); - self.aux_assignment.resize(aux_n + i, G::Scalar::ZERO); - &mut self.aux_assignment[i..] - }; - - let allocated_inputs = { - let i = self.input_assignment.len(); - self.input_assignment.resize(inputs_n + i, G::Scalar::ZERO); - &mut self.input_assignment[i..] - }; - - (allocated_aux, allocated_inputs) - } - - fn inputs_slice(&self) -> &[G::Scalar] { - &self.input_assignment - } - - fn aux_slice(&self) -> &[G::Scalar] { - &self.aux_assignment - } -} - -#[allow(dead_code)] -impl SatisfyingAssignment { - pub fn scalar_inputs(&self) -> Vec { - self.input_assignment.clone() - } - - pub fn scalar_aux(&self) -> Vec { - self.aux_assignment.clone() - } -} +pub type SatisfyingAssignment = WitnessCS<::Scalar>; diff --git a/src/circuit.rs b/src/circuit.rs index 1f76264bb..bfb158969 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -407,7 +407,7 @@ mod tests { // Execute the base case for the primary let zero1 = <::Base as Field>::ZERO; - let mut cs1: SatisfyingAssignment = SatisfyingAssignment::new(); + let mut cs1 = SatisfyingAssignment::::new(); let inputs1: NovaAugmentedCircuitInputs = NovaAugmentedCircuitInputs::new( scalar_as_base::(zero1), // pass zero for testing zero1, @@ -426,7 +426,7 @@ mod tests { // Execute the base case for the secondary let zero2 = <::Base as Field>::ZERO; - let mut cs2: SatisfyingAssignment = SatisfyingAssignment::new(); + let mut cs2 = SatisfyingAssignment::::new(); let inputs2: NovaAugmentedCircuitInputs = NovaAugmentedCircuitInputs::new( scalar_as_base::(zero2), // pass zero for testing zero2, diff --git a/src/gadgets/ecc.rs b/src/gadgets/ecc.rs index 05a07a149..d20507c80 100644 --- a/src/gadgets/ecc.rs +++ b/src/gadgets/ecc.rs @@ -1006,7 +1006,7 @@ mod tests { let (shape, ck) = cs.r1cs_shape(&*default_commitment_key_hint()); // Then the satisfying assignment - let mut cs: SatisfyingAssignment = SatisfyingAssignment::new(); + let mut cs = SatisfyingAssignment::::new(); let (a, e, s) = synthesize_smul::(cs.namespace(|| "synthesize")); let (inst, witness) = cs.r1cs_instance_and_witness(&shape, &ck).unwrap(); @@ -1062,7 +1062,7 @@ mod tests { let (shape, ck) = cs.r1cs_shape(&*default_commitment_key_hint()); // Then the satisfying assignment - let mut cs: SatisfyingAssignment = SatisfyingAssignment::new(); + let mut cs = SatisfyingAssignment::::new(); let (a, e) = synthesize_add_equal::(cs.namespace(|| "synthesize add equal")); let (inst, witness) = cs.r1cs_instance_and_witness(&shape, &ck).unwrap(); let a_p: Point = Point::new( @@ -1122,7 +1122,7 @@ mod tests { let (shape, ck) = cs.r1cs_shape(&*default_commitment_key_hint()); // Then the satisfying assignment - let mut cs: SatisfyingAssignment = SatisfyingAssignment::new(); + let mut cs = SatisfyingAssignment::::new(); let e = synthesize_add_negation::(cs.namespace(|| "synthesize add negation")); let (inst, witness) = cs.r1cs_instance_and_witness(&shape, &ck).unwrap(); let e_p: Point = Point::new( diff --git a/src/lib.rs b/src/lib.rs index 24015d8d3..17b6c0577 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -270,7 +270,7 @@ where } // base case for the primary - let mut cs_primary: SatisfyingAssignment = SatisfyingAssignment::new(); + let mut cs_primary = SatisfyingAssignment::::new(); let inputs_primary: NovaAugmentedCircuitInputs = NovaAugmentedCircuitInputs::new( scalar_as_base::(pp.digest()), G1::Scalar::ZERO, @@ -297,7 +297,7 @@ where .expect("Nova error unsat"); // base case for the secondary - let mut cs_secondary: SatisfyingAssignment = SatisfyingAssignment::new(); + let mut cs_secondary = SatisfyingAssignment::::new(); let inputs_secondary: NovaAugmentedCircuitInputs = NovaAugmentedCircuitInputs::new( pp.digest(), G2::Scalar::ZERO, @@ -397,7 +397,7 @@ where ) .expect("Unable to fold secondary"); - let mut cs_primary: SatisfyingAssignment = SatisfyingAssignment::new(); + let mut cs_primary = SatisfyingAssignment::::new(); let inputs_primary: NovaAugmentedCircuitInputs = NovaAugmentedCircuitInputs::new( scalar_as_base::(pp.digest()), G1::Scalar::from(self.i as u64), @@ -436,7 +436,7 @@ where ) .expect("Unable to fold primary"); - let mut cs_secondary: SatisfyingAssignment = SatisfyingAssignment::new(); + let mut cs_secondary = SatisfyingAssignment::::new(); let inputs_secondary: NovaAugmentedCircuitInputs = NovaAugmentedCircuitInputs::new( pp.digest(), G2::Scalar::from(self.i as u64), diff --git a/src/nifs.rs b/src/nifs.rs index 49c3c8e34..bc89b43c9 100644 --- a/src/nifs.rs +++ b/src/nifs.rs @@ -173,7 +173,7 @@ mod tests { <::RO as ROTrait<::Base, ::Scalar>>::Constants::default(); // Now get the instance and assignment for one instance - let mut cs: SatisfyingAssignment = SatisfyingAssignment::new(); + let mut cs = SatisfyingAssignment::::new(); let _ = synthesize_tiny_r1cs_bellpepper(&mut cs, Some(G::Scalar::from(5))); let (U1, W1) = cs.r1cs_instance_and_witness(&shape, &ck).unwrap(); @@ -181,7 +181,7 @@ mod tests { assert!(shape.is_sat(&ck, &U1, &W1).is_ok()); // Now get the instance and assignment for second instance - let mut cs: SatisfyingAssignment = SatisfyingAssignment::new(); + let mut cs = SatisfyingAssignment::::new(); let _ = synthesize_tiny_r1cs_bellpepper(&mut cs, Some(G::Scalar::from(135))); let (U2, W2) = cs.r1cs_instance_and_witness(&shape, &ck).unwrap(); diff --git a/src/provider/poseidon.rs b/src/provider/poseidon.rs index 76f20953e..a406018bd 100644 --- a/src/provider/poseidon.rs +++ b/src/provider/poseidon.rs @@ -220,7 +220,7 @@ mod tests { let mut ro: PoseidonRO = PoseidonRO::new(constants.clone(), num_absorbs); let mut ro_gadget: PoseidonROCircuit = PoseidonROCircuit::new(constants, num_absorbs); - let mut cs: SatisfyingAssignment = SatisfyingAssignment::new(); + let mut cs = SatisfyingAssignment::::new(); for i in 0..num_absorbs { let num = G::Scalar::random(&mut csprng); ro.absorb(num); diff --git a/src/spartan/direct.rs b/src/spartan/direct.rs index a7b4ebb60..ca261b3ae 100644 --- a/src/spartan/direct.rs +++ b/src/spartan/direct.rs @@ -122,7 +122,7 @@ impl, C: StepCircuit> DirectSNA /// Produces a proof of satisfiability of the provided circuit pub fn prove(pk: &ProverKey, sc: C, z_i: &[G::Scalar]) -> Result { - let mut cs: SatisfyingAssignment = SatisfyingAssignment::new(); + let mut cs = SatisfyingAssignment::::new(); let circuit: DirectCircuit = DirectCircuit { z_i: Some(z_i.to_vec()),