Skip to content

Commit

Permalink
Updates from review suggestions. Additionally refactored nova/nifs fo…
Browse files Browse the repository at this point in the history
…ld, and rm transcript from nova/IVC.

- Updates from PR suggestions
- Additionally updated:
  - in nova/nifs.rs: reuse folded_committed_instance for verify_folded_instance, computationally is the same, but reusing the same code so avoiding duplication and having an error on one of the two versions.
  - in nova/ivc.rs: remove transcript from IVC (not needed, it uses the RO)
  • Loading branch information
arnaucube committed Nov 22, 2023
1 parent d44c941 commit 99a2ebc
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 59 deletions.
10 changes: 8 additions & 2 deletions src/folding/nova/circuits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<F: PrimeField>: 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(
Expand Down Expand Up @@ -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<F: PrimeField> {
pub _f: PhantomData<F>,
_f: PhantomData<F>,
}
impl<F: PrimeField> FCircuit<F> for TestFCircuit<F> {
fn new() -> Self {
Self { _f: PhantomData }
}
fn step_native(self, z_i: Vec<F>) -> Vec<F> {
vec![z_i[0] * z_i[0] * z_i[0] + z_i[0] + F::from(5_u32)]
}
Expand Down Expand Up @@ -691,7 +697,7 @@ pub mod tests {
let cs = ConstraintSystem::<Fr>::new_ref();

// prepare the circuit to obtain its R1CS
let F_circuit = TestFCircuit::<Fr> { _f: PhantomData };
let F_circuit = TestFCircuit::<Fr>::new();
let mut augmented_F_circuit =
AugmentedFCircuit::<Projective, TestFCircuit<Fr>>::empty(&poseidon_config, F_circuit);
augmented_F_circuit
Expand Down
51 changes: 20 additions & 31 deletions src/folding/nova/ivc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<C1, C2, FC, Tr>
/// Implements the Incremental Verifiable Computation described in sections 1.2 and 5 of
/// [Nova](https://eprint.iacr.org/2021/370.pdf)
pub struct IVC<C1, C2, FC>
where
C1: CurveGroup,
C2: CurveGroup,
FC: FCircuit<C1::ScalarField>,
Tr: Transcript<C1> + NovaTranscript<C1>,
{
_c2: PhantomData<C2>,
r1cs: R1CS<C1::ScalarField>,
pub poseidon_config: PoseidonConfig<C1::ScalarField>,
pub pedersen_params: PedersenParams<C1>,
pub F: FC, // F circuit
pub transcript: Tr,
poseidon_config: PoseidonConfig<C1::ScalarField>,
pedersen_params: PedersenParams<C1>,
F: FC, // F circuit
i: C1::ScalarField,
z_0: Vec<C1::ScalarField>,
z_i: Vec<C1::ScalarField>,
Expand All @@ -41,18 +36,17 @@ where
U_i: CommittedInstance<C1>,
}

impl<C1, C2, FC, Tr> IVC<C1, C2, FC, Tr>
impl<C1, C2, FC> IVC<C1, C2, FC>
where
C1: CurveGroup,
C2: CurveGroup,
FC: FCircuit<C1::ScalarField>,
Tr: Transcript<C1> + NovaTranscript<C1>,
<C1 as CurveGroup>::BaseField: PrimeField,
<C1 as Group>::ScalarField: Absorb,
{
/// Initializes the IVC for the given parameters and initial state `z_0`.
pub fn new<R: Rng>(
rng: &mut R,
transcript_config: Tr::TranscriptConfig,
poseidon_config: PoseidonConfig<C1::ScalarField>,
F: FC,
z_0: Vec<C1::ScalarField>,
Expand All @@ -67,8 +61,6 @@ where
let cs = unwrap_or_return_err!(cs.into_inner(), Err(Error::NoInnerConstraintSystem));
let r1cs = extract_r1cs::<C1::ScalarField>(&cs);

let transcript = Tr::new(&transcript_config);

let pedersen_params = Pedersen::<C1>::new_params(rng, r1cs.A.n_rows);

// setup the dummy instances
Expand All @@ -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,
})
}

Expand Down Expand Up @@ -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::<Fr>();

let F_circuit = TestFCircuit::<Fr> { _f: PhantomData };
let F_circuit = TestFCircuit::<Fr>::new();
let z_0 = vec![Fr::from(3_u32)];

let mut ivc =
IVC::<Projective, Projective2, TestFCircuit<Fr>, PoseidonTranscript<Projective>>::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::<Projective, Projective2, TestFCircuit<Fr>>::new(
&mut rng,
poseidon_config, // poseidon config
F_circuit,
z_0.clone(),
)
.unwrap();

let num_steps: usize = 3;
for _ in 0..num_steps {
Expand Down
19 changes: 11 additions & 8 deletions src/folding/nova/nifs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<C: CurveGroup> {
_phantom: PhantomData<C>,
}
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -148,11 +151,11 @@ where
ci3: &CommittedInstance<C>,
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);
}
Expand Down
18 changes: 0 additions & 18 deletions src/folding/nova/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -66,20 +65,3 @@ where
rel_r1cs.check_relation(&Z)
}
}

/// NovaTranscript extends Transcript with the method to absorb CommittedInstance.
pub trait NovaTranscript<C: CurveGroup>: Transcript<C> {
fn absorb_committed_instance(&mut self, ci: CommittedInstance<C>) -> 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<C: CurveGroup> NovaTranscript<C> for PoseidonTranscript<C> where
<C as Group>::ScalarField: Absorb
{
}

0 comments on commit 99a2ebc

Please sign in to comment.