diff --git a/src/folding/nova/circuits.rs b/src/folding/nova/circuits.rs index f9773750..a014017a 100644 --- a/src/folding/nova/circuits.rs +++ b/src/folding/nova/circuits.rs @@ -15,6 +15,7 @@ use ark_r1cs_std::{ ToConstraintFieldGadget, }; use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; +use ark_std::fmt::Debug; use ark_std::Zero; use core::{borrow::Borrow, marker::PhantomData}; @@ -209,15 +210,15 @@ where /// FCircuit defines the trait of the circuit of the F function, which is the one being executed /// inside the agmented F' function. -pub trait FCircuit: Clone { - // TODO Copy - /// method that returns z_i (input), z_{i+1} (output) - fn public(self) -> (Vec, Vec); - - /// method that computes the next state values in place, assigning z_{i+1} into z_i, and +pub trait FCircuit: Clone + Copy + Debug { + /// computes the next state values in place, assigning z_{i+1} into z_i, and /// computing the new z_i - fn step_native(&mut self); - fn step_circuit( + fn step_native(z_i: Vec) -> Vec; + + /// generates the constraints for the step of F for the given z_i + fn generate_step_constraints( + // this method uses self, so that each FCircuit implementation (and different frontends) + // can hold a state if needed to store data to generate the constraints. self, cs: ConstraintSystemRef, z_i: Vec>, @@ -258,7 +259,7 @@ where })?; // get z_{i+1} from the F circuit - let z_i1 = self.F.step_circuit(cs.clone(), z_i.clone())?; + let z_i1 = self.F.generate_step_constraints(cs.clone(), z_i.clone())?; let u_dummy_native = CommittedInstance { cmE: C::zero(), @@ -357,25 +358,19 @@ mod tests { use crate::transcript::poseidon::{tests::poseidon_test_config, PoseidonTranscript}; use crate::transcript::Transcript; - #[derive(Clone, Debug)] // TODO Copy + #[derive(Clone, Copy, Debug)] /// TestFCircuit is a variation of `x^3 + x + 5 = y` (as in /// src/frontend/arkworks/mod.rs#tests::TestCircuit), adapted to have 2 public inputs which are /// used as the state. `z_i` is used as `x`, and `z_{i+1}` is used as `y`, and at the next /// step, `z_{i+1}` will be assigned to `z_i`, and a new `z+{i+1}` will be computted. pub struct TestFCircuit { - z_i: Vec, // z_i - z_i1: Vec, // z_{i+1} + _f: PhantomData, } impl FCircuit for TestFCircuit { - fn public(self) -> (Vec, Vec) { - (self.z_i, self.z_i1) + fn step_native(z_i: Vec) -> Vec { + vec![z_i[0] * z_i[0] * z_i[0] + z_i[0] + F::from(5_u32)] } - fn step_native(&mut self) { - self.z_i = self.z_i1.clone(); - self.z_i1 = - vec![self.z_i[0] * self.z_i[0] * self.z_i[0] + self.z_i[0] + F::from(5_u32)]; - } - fn step_circuit( + fn generate_step_constraints( self, cs: ConstraintSystemRef, z_i: Vec>, @@ -553,10 +548,7 @@ mod tests { let cs = ConstraintSystem::::new_ref(); // prepare the circuit to obtain its R1CS - let test_F_circuit_dummy = TestFCircuit:: { - z_i: vec![Fr::zero()], - z_i1: vec![Fr::zero()], - }; + let F_circuit = TestFCircuit:: { _f: PhantomData }; let mut augmented_F_circuit = AugmentedFCircuit::> { poseidon_config: poseidon_config.clone(), i: None, @@ -567,7 +559,7 @@ mod tests { U_i1: None, cmT: None, r: None, - F: test_F_circuit_dummy, + F: F_circuit, x: None, }; augmented_F_circuit @@ -584,17 +576,11 @@ mod tests { let pedersen_params = Pedersen::::new_params(&mut rng, r1cs.A.n_rows); - // first step + // first step, set z_i=z_0=3 and z_{i+1}=35 (initial values) let z_0 = vec![Fr::from(3_u32)]; let mut z_i = z_0.clone(); let mut z_i1 = vec![Fr::from(35_u32)]; - // set the circuit to be folded with z_i=z_0=3 and z_{i+1}=35 (initial values) - let mut test_F_circuit = TestFCircuit:: { - z_i: z_i.clone(), - z_i1: z_i1.clone(), - }; - let w_dummy = Witness::::new(vec![Fr::zero(); F_witness_len], r1cs.A.n_rows); let u_dummy = CommittedInstance::::dummy(x.len()); @@ -624,7 +610,7 @@ mod tests { // base case: i=0, z_i=z_0, U_i = U_d := dummy instance // u_1.x = H(1, z_0, z_i, U_i) u_i1_x = U_i - .hash(&poseidon_config, Fr::one(), z_0.clone(), z_i1) + .hash(&poseidon_config, Fr::one(), z_0.clone(), z_i1.clone()) .unwrap(); // base case @@ -638,7 +624,7 @@ mod tests { U_i1: Some(U_i1.clone()), // = dummy cmT: Some(cmT), r: Some(Fr::one()), - F: test_F_circuit.clone(), + F: F_circuit, x: Some(u_i1_x), }; } else { @@ -667,20 +653,20 @@ mod tests { // folded instance output (public input, x) // u_{i+1}.x = H(i+1, z_0, z_{i+1}, U_{i+1}) u_i1_x = U_i1 - .hash(&poseidon_config, i + Fr::one(), z_0.clone(), z_i1) + .hash(&poseidon_config, i + Fr::one(), z_0.clone(), z_i1.clone()) .unwrap(); augmented_F_circuit = AugmentedFCircuit::> { poseidon_config: poseidon_config.clone(), i: Some(i), z_0: Some(z_0.clone()), - z_i: Some(z_i), + z_i: Some(z_i.clone()), u_i: Some(u_i), U_i: Some(U_i.clone()), U_i1: Some(U_i1.clone()), cmT: Some(cmT), r: Some(r_Fr), - F: test_F_circuit.clone(), + F: F_circuit, x: Some(u_i1_x), }; } @@ -715,8 +701,9 @@ mod tests { // set values for next iteration i += Fr::one(); - test_F_circuit.step_native(); // advance the F circuit state - (z_i, z_i1) = test_F_circuit.clone().public(); + // advance the F circuit state + z_i = z_i1.clone(); + z_i1 = TestFCircuit::::step_native(z_i.clone()); U_i = U_i1.clone(); W_i = W_i1.clone(); }