diff --git a/src/folding/nova/circuits.rs b/src/folding/nova/circuits.rs index 84ff07ee..9e4ba024 100644 --- a/src/folding/nova/circuits.rs +++ b/src/folding/nova/circuits.rs @@ -214,6 +214,9 @@ 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 + Copy + Debug { + /// returns a new FCircuit instance + fn new() -> Self; + /// computes the next state values in place, assigning z_{i+1} into z_i, and /// computing the new z_i fn step_native( @@ -448,9 +451,12 @@ pub mod tests { /// 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 { - pub _f: PhantomData, + _f: PhantomData, } impl FCircuit for TestFCircuit { + fn new() -> Self { + Self { _f: PhantomData } + } fn step_native(self, z_i: Vec) -> Vec { vec![z_i[0] * z_i[0] * z_i[0] + z_i[0] + F::from(5_u32)] } @@ -691,7 +697,7 @@ pub mod tests { let cs = ConstraintSystem::::new_ref(); // prepare the circuit to obtain its R1CS - let F_circuit = TestFCircuit:: { _f: PhantomData }; + let F_circuit = TestFCircuit::::new(); let mut augmented_F_circuit = AugmentedFCircuit::>::empty(&poseidon_config, F_circuit); augmented_F_circuit diff --git a/src/folding/nova/ivc.rs b/src/folding/nova/ivc.rs index 1bdbc49a..d4bb5b2e 100644 --- a/src/folding/nova/ivc.rs +++ b/src/folding/nova/ivc.rs @@ -8,30 +8,25 @@ use ark_std::{One, Zero}; use core::marker::PhantomData; use super::circuits::{AugmentedFCircuit, FCircuit}; -use super::{ - nifs::NIFS, - traits::{NovaR1CS, NovaTranscript}, - CommittedInstance, Witness, -}; +use super::{nifs::NIFS, traits::NovaR1CS, CommittedInstance, Witness}; use crate::ccs::r1cs::R1CS; use crate::frontend::arkworks::{extract_r1cs, extract_z}; // TODO once Frontend trait is ready, use that use crate::pedersen::{Params as PedersenParams, Pedersen}; -use crate::transcript::Transcript; use crate::{unwrap_or_return_err, Error}; -pub struct IVC +/// Implements the Incremental Verifiable Computation described in sections 1.2 and 5 of +/// [Nova](https://eprint.iacr.org/2021/370.pdf) +pub struct IVC where C1: CurveGroup, C2: CurveGroup, FC: FCircuit, - Tr: Transcript + NovaTranscript, { _c2: PhantomData, r1cs: R1CS, - pub poseidon_config: PoseidonConfig, - pub pedersen_params: PedersenParams, - pub F: FC, // F circuit - pub transcript: Tr, + poseidon_config: PoseidonConfig, + pedersen_params: PedersenParams, + F: FC, // F circuit i: C1::ScalarField, z_0: Vec, z_i: Vec, @@ -41,18 +36,17 @@ where U_i: CommittedInstance, } -impl IVC +impl IVC where C1: CurveGroup, C2: CurveGroup, FC: FCircuit, - Tr: Transcript + NovaTranscript, ::BaseField: PrimeField, ::ScalarField: Absorb, { + /// Initializes the IVC for the given parameters and initial state `z_0`. pub fn new( rng: &mut R, - transcript_config: Tr::TranscriptConfig, poseidon_config: PoseidonConfig, F: FC, z_0: Vec, @@ -67,8 +61,6 @@ where let cs = unwrap_or_return_err!(cs.into_inner(), Err(Error::NoInnerConstraintSystem)); let r1cs = extract_r1cs::(&cs); - let transcript = Tr::new(&transcript_config); - let pedersen_params = Pedersen::::new_params(rng, r1cs.A.n_rows); // setup the dummy instances @@ -83,14 +75,13 @@ where poseidon_config, pedersen_params, F, - transcript, i: C1::ScalarField::zero(), z_0: z_0.clone(), z_i: z_0, w_i: w_dummy.clone(), u_i: u_dummy.clone(), - W_i: w_dummy.clone(), - U_i: u_dummy.clone(), + W_i: w_dummy, + U_i: u_dummy, }) } @@ -242,25 +233,23 @@ mod tests { use ark_vesta::Projective as Projective2; use crate::folding::nova::circuits::tests::TestFCircuit; - use crate::transcript::poseidon::{tests::poseidon_test_config, PoseidonTranscript}; + use crate::transcript::poseidon::tests::poseidon_test_config; #[test] fn test_ivc() { let mut rng = ark_std::test_rng(); let poseidon_config = poseidon_test_config::(); - let F_circuit = TestFCircuit:: { _f: PhantomData }; + let F_circuit = TestFCircuit::::new(); let z_0 = vec![Fr::from(3_u32)]; - let mut ivc = - IVC::, PoseidonTranscript>::new( - &mut rng, - poseidon_config.clone(), // notice that transcript_config could be different than poseidon (eg. keccak's transcript config) - poseidon_config, // poseidon config - F_circuit, - z_0.clone(), - ) - .unwrap(); + let mut ivc = IVC::>::new( + &mut rng, + poseidon_config, // poseidon config + F_circuit, + z_0.clone(), + ) + .unwrap(); let num_steps: usize = 3; for _ in 0..num_steps { diff --git a/src/folding/nova/nifs.rs b/src/folding/nova/nifs.rs index 966f66d6..5b36ab65 100644 --- a/src/folding/nova/nifs.rs +++ b/src/folding/nova/nifs.rs @@ -11,7 +11,7 @@ use crate::utils::vec::*; use crate::Error; /// Implements the Non-Interactive Folding Scheme described in section 4 of -/// https://eprint.iacr.org/2021/370.pdf +/// [Nova](https://eprint.iacr.org/2021/370.pdf) pub struct NIFS { _phantom: PhantomData, } @@ -106,7 +106,9 @@ where Ok((T, cmT)) } - /// fold_instances is part of the NIFS.P logic + /// fold_instances is part of the NIFS.P logic described in + /// [Nova](https://eprint.iacr.org/2021/370.pdf)'s section 4. It returns the folded Committed + /// Instances and the Witness. pub fn fold_instances( // r comes from the transcript, and is a n-bit (N_BITS_CHALLENGE) element r: C::ScalarField, @@ -127,7 +129,8 @@ where Ok((w3, ci3)) } - /// verify implements NIFS.V logic + /// verify implements NIFS.V logic described in [Nova](https://eprint.iacr.org/2021/370.pdf)'s + /// section 4. It returns the folded Committed Instance pub fn verify( // r comes from the transcript, and is a n-bit (N_BITS_CHALLENGE) element r: C::ScalarField, @@ -148,11 +151,11 @@ where ci3: &CommittedInstance, cmT: &C, ) -> Result<(), Error> { - let r2 = r * r; - if ci3.cmE != (ci1.cmE + cmT.mul(r) + ci2.cmE.mul(r2)) - || ci3.u != ci1.u + r * ci2.u - || ci3.cmW != (ci1.cmW + ci2.cmW.mul(r)) - || ci3.x != vec_add(&ci1.x, &vec_scalar_mul(&ci2.x, &r))? + let expected = Self::fold_committed_instance(r, ci1, ci2, cmT); + if ci3.cmE != expected.cmE + || ci3.u != expected.u + || ci3.cmW != expected.cmW + || ci3.x != expected.x { return Err(Error::NotSatisfied); } diff --git a/src/folding/nova/traits.rs b/src/folding/nova/traits.rs index f0d42fa1..6b50da8b 100644 --- a/src/folding/nova/traits.rs +++ b/src/folding/nova/traits.rs @@ -4,7 +4,6 @@ use ark_std::{One, Zero}; use super::{CommittedInstance, Witness}; use crate::ccs::r1cs::R1CS; -use crate::transcript::{poseidon::PoseidonTranscript, Transcript}; use crate::Error; /// NovaR1CS extends R1CS methods with Nova specific methods @@ -66,20 +65,3 @@ where rel_r1cs.check_relation(&Z) } } - -/// NovaTranscript extends Transcript with the method to absorb CommittedInstance. -pub trait NovaTranscript: Transcript { - fn absorb_committed_instance(&mut self, ci: CommittedInstance) -> Result<(), Error> { - self.absorb_point(&ci.cmE)?; - self.absorb(&ci.u); - self.absorb_point(&ci.cmW)?; - self.absorb_vec(&ci.x); - Ok(()) - } -} - -// implements NovaTranscript for PoseidonTranscript -impl NovaTranscript for PoseidonTranscript where - ::ScalarField: Absorb -{ -}