From f85a056b6149045fe8fb1d8b2d965cd9d81464a3 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Tue, 30 Jan 2024 11:16:53 +0100 Subject: [PATCH] Adapt Nova usage of commitment to the generic trait (#63) --- rust-toolchain | 2 +- src/folding/hypernova/circuit.rs | 2 +- src/folding/nova/circuits.rs | 17 ++-- src/folding/nova/decider.rs | 61 ++++++++++--- src/folding/nova/ivc.rs | 107 +++++++++++++++------- src/folding/nova/mod.rs | 13 +-- src/folding/nova/nifs.rs | 152 ++++++++++++++++++------------- 7 files changed, 229 insertions(+), 125 deletions(-) diff --git a/rust-toolchain b/rust-toolchain index 5e3a425..7c7053a 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.73.0 +1.75.0 diff --git a/src/folding/hypernova/circuit.rs b/src/folding/hypernova/circuit.rs index 9b672ba..b769355 100644 --- a/src/folding/hypernova/circuit.rs +++ b/src/folding/hypernova/circuit.rs @@ -237,7 +237,7 @@ mod tests { // Initialize cs let cs = ConstraintSystem::::new_ref(); let vec_thetas = sigmas_thetas.1; - for (_, thetas) in vec_thetas.iter().enumerate() { + for thetas in vec_thetas.iter() { // sum c_i * prod theta_j let expected = sum_ci_mul_prod_thetaj(&ccs, thetas); // from `compute_c_from_sigmas_and_thetas` let mut prepared_thetas = Vec::new(); diff --git a/src/folding/nova/circuits.rs b/src/folding/nova/circuits.rs index e79de6d..faf56a6 100644 --- a/src/folding/nova/circuits.rs +++ b/src/folding/nova/circuits.rs @@ -503,7 +503,7 @@ pub mod tests { fn test_nifs_gadget() { let (_, _, _, _, ci1, _, ci2, _, ci3, _, cmT, _, r_Fr) = prepare_simple_fold_inputs(); - let ci3_verifier = NIFS::::verify(r_Fr, &ci1, &ci2, &cmT); + let ci3_verifier = NIFS::>::verify(r_Fr, &ci1, &ci2, &cmT); assert_eq!(ci3_verifier, ci3); let cs = ConstraintSystem::::new_ref(); @@ -721,7 +721,7 @@ pub mod tests { // U_{i+1} let T: Vec; - (T, cmT) = NIFS::::compute_cmT( + (T, cmT) = NIFS::>::compute_cmT( &pedersen_params, &r1cs, &w_i, @@ -741,9 +741,10 @@ pub mod tests { .unwrap(); let r_Fr = Fr::from_bigint(BigInteger::from_bits_le(&r_bits)).unwrap(); - (W_i1, U_i1) = - NIFS::::fold_instances(r_Fr, &w_i, &u_i, &W_i, &U_i, &T, cmT) - .unwrap(); + (W_i1, U_i1) = NIFS::>::fold_instances( + r_Fr, &w_i, &u_i, &W_i, &U_i, &T, cmT, + ) + .unwrap(); r1cs.check_relaxed_instance_relation(&W_i1, &U_i1).unwrap(); @@ -782,7 +783,7 @@ pub mod tests { ) .unwrap(); let cf_r_Fq = Fq::from_bigint(BigInteger::from_bits_le(&cf_r_bits)).unwrap(); - let (_, cf_U_i1) = NIFS::::fold_instances( + let (_, cf_U_i1) = NIFS::>::fold_instances( cf_r_Fq, &cf_W_i, &cf_U_i, &cf_w_i, &cf_u_i, &cf_T, cf_cmT, ) .unwrap(); @@ -828,7 +829,9 @@ pub mod tests { // compute committed instances, w_{i+1}, u_{i+1}, which will be used as w_i, u_i, so we // assign them directly to w_i, u_i. w_i = Witness::::new(w_i1.clone(), r1cs.A.n_rows); - u_i = w_i.commit(&pedersen_params, vec![u_i1_x]).unwrap(); + u_i = w_i + .commit::>(&pedersen_params, vec![u_i1_x]) + .unwrap(); r1cs.check_relaxed_instance_relation(&w_i, &u_i).unwrap(); r1cs.check_relaxed_instance_relation(&W_i1, &U_i1).unwrap(); diff --git a/src/folding/nova/decider.rs b/src/folding/nova/decider.rs index a3719ed..8f4cf40 100644 --- a/src/folding/nova/decider.rs +++ b/src/folding/nova/decider.rs @@ -18,7 +18,7 @@ use ark_std::{One, Zero}; use core::{borrow::Borrow, marker::PhantomData}; use crate::ccs::r1cs::R1CS; -use crate::commitment::pedersen::Params as PedersenParams; +use crate::commitment::{pedersen::Params as PedersenParams, CommitmentProver}; use crate::folding::nova::{ circuits::{CommittedInstanceVar, CF1, CF2}, ivc::IVC, @@ -179,17 +179,21 @@ where /// Circuit that implements the in-circuit checks needed for the onchain (Ethereum's EVM) /// verification. -pub struct DeciderCircuit +pub struct DeciderCircuit where C1: CurveGroup, GC1: CurveVar>, C2: CurveGroup, GC2: CurveVar>, + CP1: CommitmentProver, + CP2: CommitmentProver, { _c1: PhantomData, _gc1: PhantomData, _c2: PhantomData, _gc2: PhantomData, + _cp1: PhantomData, + _cp2: PhantomData, /// E vector's length of the Nova instance witness pub E_len: usize, @@ -199,7 +203,7 @@ where pub r1cs: R1CS, /// R1CS of the CycleFold circuit pub cf_r1cs: R1CS, - /// CycleFold PedersenParams, over C2 + /// CycleFold PedersenParams over C2 pub cf_pedersen_params: PedersenParams, pub poseidon_config: PoseidonConfig>, pub i: Option>, @@ -216,25 +220,32 @@ where pub cf_U_i: Option>, pub cf_W_i: Option>, } -impl DeciderCircuit +impl DeciderCircuit where C1: CurveGroup, C2: CurveGroup, GC1: CurveVar>, GC2: CurveVar>, + CP1: CommitmentProver, + // enforce that the CP2 is Pedersen commitment, since we're at Ethereum's EVM decider + CP2: CommitmentProver>, { - pub fn from_ivc>(ivc: IVC) -> Self { + pub fn from_ivc>( + ivc: IVC, + ) -> Self { Self { _c1: PhantomData, _gc1: PhantomData, _c2: PhantomData, _gc2: PhantomData, + _cp1: PhantomData, + _cp2: PhantomData, E_len: ivc.W_i.E.len(), cf_E_len: ivc.cf_W_i.E.len(), r1cs: ivc.r1cs, cf_r1cs: ivc.cf_r1cs, - cf_pedersen_params: ivc.cf_pedersen_params, + cf_pedersen_params: ivc.cf_cm_params, poseidon_config: ivc.poseidon_config, i: Some(ivc.i), z_0: Some(ivc.z_0), @@ -249,18 +260,21 @@ where } } -impl ConstraintSynthesizer> for DeciderCircuit +impl ConstraintSynthesizer> + for DeciderCircuit where C1: CurveGroup, C2: CurveGroup, GC1: CurveVar>, GC2: CurveVar>, + CP1: CommitmentProver, + CP2: CommitmentProver, ::BaseField: PrimeField, ::BaseField: PrimeField, ::ScalarField: Absorb, ::ScalarField: Absorb, C1: CurveGroup, - for<'a> &'a GC2: GroupOpsBounds<'a, C2, GC2>, + for<'b> &'b GC2: GroupOpsBounds<'b, C2, GC2>, { fn generate_constraints(self, cs: ConstraintSystemRef>) -> Result<(), SynthesisError> { let r1cs = @@ -437,7 +451,8 @@ pub mod tests { use ark_relations::r1cs::ConstraintSystem; use ark_vesta::{constraints::GVar as GVar2, Projective as Projective2}; - use crate::folding::nova::ivc::IVC; + use crate::commitment::pedersen::Pedersen; + use crate::folding::nova::ivc::tests::get_pedersen_params_len; use crate::frontend::tests::{CubicFCircuit, CustomFCircuit, WrapperCircuit}; use crate::transcript::poseidon::tests::poseidon_test_config; @@ -604,10 +619,25 @@ pub mod tests { let F_circuit = CubicFCircuit::::new(()); let z_0 = vec![Fr::from(3_u32)]; + let (pedersen_len, cf_pedersen_len) = + get_pedersen_params_len::>(&poseidon_config, F_circuit).unwrap(); + // generate the Pedersen params + let pedersen_params = Pedersen::::new_params(&mut rng, pedersen_len); + let cf_pedersen_params = Pedersen::::new_params(&mut rng, cf_pedersen_len); + // generate an IVC and do a step of it - let mut ivc = IVC::>::new( - &mut rng, + let mut ivc = IVC::< + Projective, + GVar, + Projective2, + GVar2, + CubicFCircuit, + Pedersen, + Pedersen, + >::new( poseidon_config, + pedersen_params, + cf_pedersen_params, F_circuit, z_0.clone(), ) @@ -616,7 +646,14 @@ pub mod tests { ivc.verify(z_0, 1).unwrap(); // load the DeciderCircuit from the generated IVC - let decider_circuit = DeciderCircuit::::from_ivc(ivc); + let decider_circuit = DeciderCircuit::< + Projective, + GVar, + Projective2, + GVar2, + Pedersen, + Pedersen, + >::from_ivc(ivc); let cs = ConstraintSystem::::new_ref(); diff --git a/src/folding/nova/ivc.rs b/src/folding/nova/ivc.rs index cdbdd7e..f9afe47 100644 --- a/src/folding/nova/ivc.rs +++ b/src/folding/nova/ivc.rs @@ -3,7 +3,6 @@ use ark_ec::{AffineRepr, CurveGroup, Group}; use ark_ff::{BigInteger, PrimeField}; use ark_r1cs_std::{groups::GroupOpsBounds, prelude::CurveVar}; use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystem}; -use ark_std::rand::Rng; use ark_std::{One, Zero}; use core::marker::PhantomData; @@ -12,9 +11,8 @@ use super::{ cyclefold::{CycleFoldChallengeGadget, CycleFoldCircuit}, }; use super::{nifs::NIFS, traits::NovaR1CS, CommittedInstance, Witness}; -use crate::ccs::r1cs::R1CS; -use crate::ccs::r1cs::{extract_r1cs, extract_w_x}; -use crate::commitment::pedersen::{Params as PedersenParams, Pedersen}; +use crate::ccs::r1cs::{extract_r1cs, extract_w_x, R1CS}; +use crate::commitment::CommitmentProver; use crate::frontend::FCircuit; use crate::Error; @@ -23,13 +21,15 @@ use super::cyclefold::CF_IO_LEN; /// Implements the Incremental Verifiable Computation described in sections 1.2 and 5 of /// [Nova](https://eprint.iacr.org/2021/370.pdf) -pub struct IVC +pub struct IVC where C1: CurveGroup, GC1: CurveVar>, C2: CurveGroup, GC2: CurveVar>, FC: FCircuit, + CP1: CommitmentProver, + CP2: CommitmentProver, { _gc1: PhantomData, _c2: PhantomData, @@ -39,10 +39,10 @@ where /// R1CS of the CycleFold circuit pub cf_r1cs: R1CS, pub poseidon_config: PoseidonConfig, - /// PedersenParams over C1 - pub pedersen_params: PedersenParams, - /// CycleFold PedersenParams, over C2 - pub cf_pedersen_params: PedersenParams, + /// CommitmentProver::Params over C1 + pub cm_params: CP1::Params, + /// CycleFold CommitmentProver::Params, over C2 + pub cf_cm_params: CP2::Params, /// F circuit, the circuit that is being folded pub F: FC, pub i: C1::ScalarField, @@ -61,13 +61,15 @@ where pub cf_U_i: CommittedInstance, } -impl IVC +impl IVC where C1: CurveGroup, GC1: CurveVar>, C2: CurveGroup, GC2: CurveVar>, FC: FCircuit, + CP1: CommitmentProver, + CP2: CommitmentProver, ::BaseField: PrimeField, ::BaseField: PrimeField, ::ScalarField: Absorb, @@ -77,9 +79,10 @@ where for<'a> &'a GC2: GroupOpsBounds<'a, C2, GC2>, { /// Initializes the IVC for the given parameters and initial state `z_0`. - pub fn new( - rng: &mut R, + pub fn new( poseidon_config: PoseidonConfig, + cm_params: CP1::Params, + cf_cm_params: CP2::Params, F: FC, z_0: Vec, ) -> Result { @@ -100,11 +103,6 @@ where let cs2 = cs2.into_inner().ok_or(Error::NoInnerConstraintSystem)?; let cf_r1cs = extract_r1cs::(&cs2); - // this will not be randomly generated in this method, and will come from above levels, so - // the same params can be loaded on multiple instances - let pedersen_params = Pedersen::::new_params(rng, r1cs.A.n_rows); - let cf_pedersen_params = Pedersen::::new_params(rng, cf_r1cs.A.n_rows); - // setup the dummy instances let (w_dummy, u_dummy) = r1cs.dummy_instance(); let (cf_w_dummy, cf_u_dummy) = cf_r1cs.dummy_instance(); @@ -118,8 +116,8 @@ where r1cs, cf_r1cs, poseidon_config, - pedersen_params, - cf_pedersen_params, + cm_params, + cf_cm_params, F, i: C1::ScalarField::zero(), z_0: z_0.clone(), @@ -154,8 +152,9 @@ where .ok_or(Error::OutOfBounds)?; // fold Nova instances - let (W_i1, U_i1): (Witness, CommittedInstance) = - NIFS::::fold_instances(r_Fr, &self.w_i, &self.u_i, &self.W_i, &self.U_i, &T, cmT)?; + let (W_i1, U_i1): (Witness, CommittedInstance) = NIFS::::fold_instances( + r_Fr, &self.w_i, &self.u_i, &self.W_i, &self.U_i, &T, cmT, + )?; // folded instance output (public input, x) // u_{i+1}.x = H(i+1, z_0, z_{i+1}, U_{i+1}) @@ -188,7 +187,7 @@ where }; #[cfg(test)] - NIFS::verify_folded_instance(r_Fr, &self.u_i, &self.U_i, &U_i1, &cmT)?; + NIFS::::verify_folded_instance(r_Fr, &self.u_i, &self.U_i, &U_i1, &cmT)?; } else { // CycleFold part: // get the vector used as public inputs 'x' in the CycleFold circuit @@ -226,7 +225,7 @@ where // fold cyclefold instances let cf_w_i = Witness::::new(cf_w_i.clone(), self.cf_r1cs.A.n_rows); let cf_u_i: CommittedInstance = - cf_w_i.commit(&self.cf_pedersen_params, cf_x_i.clone())?; + cf_w_i.commit::(&self.cf_cm_params, cf_x_i.clone())?; // compute T* and cmT* for CycleFoldCircuit let (cf_T, cf_cmT) = self.compute_cf_cmT(&cf_w_i, &cf_u_i)?; @@ -240,7 +239,7 @@ where let cf_r_Fq = C1::BaseField::from_bigint(BigInteger::from_bits_le(&cf_r_bits)) .ok_or(Error::OutOfBounds)?; - let (cf_W_i1, cf_U_i1) = NIFS::::fold_instances( + let (cf_W_i1, cf_U_i1) = NIFS::::fold_instances( cf_r_Fq, &self.cf_W_i, &self.cf_U_i, @@ -300,7 +299,7 @@ where self.i += C1::ScalarField::one(); self.z_i = z_i1.clone(); self.w_i = Witness::::new(w_i1, self.r1cs.A.n_rows); - self.u_i = self.w_i.commit(&self.pedersen_params, vec![u_i1_x])?; + self.u_i = self.w_i.commit::(&self.cm_params, vec![u_i1_x])?; self.W_i = W_i1.clone(); self.U_i = U_i1.clone(); @@ -353,8 +352,8 @@ where // computes T and cmT for the AugmentedFCircuit fn compute_cmT(&self) -> Result<(Vec, C1), Error> { - NIFS::::compute_cmT( - &self.pedersen_params, + NIFS::::compute_cmT( + &self.cm_params, &self.r1cs, &self.w_i, &self.u_i, @@ -368,8 +367,8 @@ where cf_w_i: &Witness, cf_u_i: &CommittedInstance, ) -> Result<(Vec, C2), Error> { - NIFS::::compute_cyclefold_cmT( - &self.cf_pedersen_params, + NIFS::::compute_cyclefold_cmT( + &self.cf_cm_params, &self.cf_r1cs, cf_w_i, cf_u_i, @@ -393,14 +392,43 @@ pub(crate) fn get_committed_instance_coordinates( } #[cfg(test)] -mod tests { +pub mod tests { use super::*; use ark_pallas::{constraints::GVar, Fr, Projective}; use ark_vesta::{constraints::GVar as GVar2, Projective as Projective2}; + use crate::commitment::pedersen::Pedersen; use crate::frontend::tests::CubicFCircuit; use crate::transcript::poseidon::tests::poseidon_test_config; + /// helper method to get the r1cs from the circuit + pub fn get_r1cs( + circuit: impl ConstraintSynthesizer, + ) -> Result, Error> { + let cs = ConstraintSystem::::new_ref(); + circuit.generate_constraints(cs.clone())?; + cs.finalize(); + let cs = cs.into_inner().ok_or(Error::NoInnerConstraintSystem)?; + let r1cs = extract_r1cs::(&cs); + Ok(r1cs) + } + + /// helper method to get the pedersen params length for both the AugmentedFCircuit and the + /// CycleFold circuit + pub fn get_pedersen_params_len>( + poseidon_config: &PoseidonConfig, + F_circuit: FC, + ) -> Result<(usize, usize), Error> { + let augmented_F_circuit = AugmentedFCircuit::::empty( + poseidon_config, + F_circuit, + ); + let cf_circuit = CycleFoldCircuit::::empty(); + let r1cs = get_r1cs(augmented_F_circuit)?; + let cf_r1cs = get_r1cs(cf_circuit)?; + Ok((r1cs.A.n_rows, cf_r1cs.A.n_rows)) + } + #[test] fn test_ivc() { let mut rng = ark_std::test_rng(); @@ -409,9 +437,24 @@ mod tests { let F_circuit = CubicFCircuit::::new(()); let z_0 = vec![Fr::from(3_u32)]; - let mut ivc = IVC::>::new( - &mut rng, + let (pedersen_len, cf_pedersen_len) = + get_pedersen_params_len::>(&poseidon_config, F_circuit).unwrap(); + // generate the Pedersen params + let pedersen_params = Pedersen::::new_params(&mut rng, pedersen_len); + let cf_pedersen_params = Pedersen::::new_params(&mut rng, cf_pedersen_len); + + let mut ivc = IVC::< + Projective, + GVar, + Projective2, + GVar2, + CubicFCircuit, + Pedersen, + Pedersen, + >::new( poseidon_config, + pedersen_params, + cf_pedersen_params, F_circuit, z_0.clone(), ) diff --git a/src/folding/nova/mod.rs b/src/folding/nova/mod.rs index 172864a..d060556 100644 --- a/src/folding/nova/mod.rs +++ b/src/folding/nova/mod.rs @@ -7,10 +7,7 @@ use ark_ec::{CurveGroup, Group}; use ark_std::fmt::Debug; use ark_std::{One, Zero}; -use crate::commitment::{ - pedersen::{Params as PedersenParams, Pedersen}, - CommitmentProver, -}; +use crate::commitment::CommitmentProver; use crate::folding::circuits::nonnative::point_to_nonnative_limbs; use crate::utils::vec::is_zero_vec; use crate::Error; @@ -101,16 +98,16 @@ where rW: C::ScalarField::zero(), } } - pub fn commit( + pub fn commit>( &self, - params: &PedersenParams, + params: &CP::Params, x: Vec, ) -> Result, Error> { let mut cmE = C::zero(); if !is_zero_vec::(&self.E) { - cmE = Pedersen::commit(params, &self.E, &self.rE)?; + cmE = CP::commit(params, &self.E, &self.rE)?; } - let cmW = Pedersen::commit(params, &self.W, &self.rW)?; + let cmW = CP::commit(params, &self.W, &self.rW)?; Ok(CommittedInstance { cmE, u: C::ScalarField::one(), diff --git a/src/folding/nova/nifs.rs b/src/folding/nova/nifs.rs index 289db07..a8670a1 100644 --- a/src/folding/nova/nifs.rs +++ b/src/folding/nova/nifs.rs @@ -5,21 +5,19 @@ use std::marker::PhantomData; use super::{CommittedInstance, Witness}; use crate::ccs::r1cs::R1CS; -use crate::commitment::{ - pedersen::{Params as PedersenParams, Pedersen, Proof as PedersenProof}, - CommitmentProver, -}; +use crate::commitment::CommitmentProver; use crate::transcript::Transcript; use crate::utils::vec::*; use crate::Error; /// Implements the Non-Interactive Folding Scheme described in section 4 of /// [Nova](https://eprint.iacr.org/2021/370.pdf) -pub struct NIFS { - _phantom: PhantomData, +pub struct NIFS> { + _c: PhantomData, + _cp: PhantomData, } -impl NIFS +impl> NIFS where ::ScalarField: Absorb, { @@ -92,7 +90,7 @@ where /// compute_cmT is part of the NIFS.P logic pub fn compute_cmT( - pedersen_params: &PedersenParams, + cm_prover_params: &CP::Params, r1cs: &R1CS, w1: &Witness, ci1: &CommittedInstance, @@ -105,11 +103,11 @@ where // compute cross terms let T = Self::compute_T(r1cs, ci1.u, ci2.u, &z1, &z2)?; // use r_T=1 since we don't need hiding property for cm(T) - let cmT = Pedersen::commit(pedersen_params, &T, &C::ScalarField::one())?; + let cmT = CP::commit(cm_prover_params, &T, &C::ScalarField::one())?; Ok((T, cmT)) } pub fn compute_cyclefold_cmT( - pedersen_params: &PedersenParams, + cm_prover_params: &CP::Params, r1cs: &R1CS, // R1CS over C2.Fr=C1.Fq (here C=C2) w1: &Witness, ci1: &CommittedInstance, @@ -125,7 +123,7 @@ where // compute cross terms let T = Self::compute_T(r1cs, ci1.u, ci2.u, &z1, &z2)?; // use r_T=1 since we don't need hiding property for cm(T) - let cmT = Pedersen::commit(pedersen_params, &T, &C::ScalarField::one())?; + let cmT = CP::commit(cm_prover_params, &T, &C::ScalarField::one())?; Ok((T, cmT)) } @@ -143,10 +141,10 @@ where ) -> Result<(Witness, CommittedInstance), Error> { // fold witness // use r_T=1 since we don't need hiding property for cm(T) - let w3 = NIFS::::fold_witness(r, w1, w2, T, C::ScalarField::one())?; + let w3 = NIFS::::fold_witness(r, w1, w2, T, C::ScalarField::one())?; // fold committed instancs - let ci3 = NIFS::::fold_committed_instance(r, ci1, ci2, &cmT); + let ci3 = NIFS::::fold_committed_instance(r, ci1, ci2, &cmT); Ok((w3, ci3)) } @@ -160,7 +158,7 @@ where ci2: &CommittedInstance, cmT: &C, ) -> CommittedInstance { - NIFS::::fold_committed_instance(r, ci1, ci2, cmT) + NIFS::::fold_committed_instance(r, ci1, ci2, cmT) } /// Verify commited folded instance (ci) relations. Notice that this method does not open the @@ -184,50 +182,35 @@ where Ok(()) } - pub fn open_commitments( + pub fn prove_commitments( tr: &mut impl Transcript, - pedersen_params: &PedersenParams, + cm_prover_params: &CP::Params, w: &Witness, ci: &CommittedInstance, T: Vec, cmT: &C, - ) -> Result<[PedersenProof; 3], Error> { - let cmE_proof = Pedersen::prove(pedersen_params, tr, &ci.cmE, &w.E, &w.rE)?; - let cmW_proof = Pedersen::prove(pedersen_params, tr, &ci.cmW, &w.W, &w.rW)?; - let cmT_proof = Pedersen::prove(pedersen_params, tr, cmT, &T, &C::ScalarField::one())?; // cm(T) is committed with rT=1 + ) -> Result<[CP::Proof; 3], Error> { + let cmE_proof = CP::prove(cm_prover_params, tr, &ci.cmE, &w.E, &w.rE)?; + let cmW_proof = CP::prove(cm_prover_params, tr, &ci.cmW, &w.W, &w.rW)?; + let cmT_proof = CP::prove(cm_prover_params, tr, cmT, &T, &C::ScalarField::one())?; // cm(T) is committed with rT=1 Ok([cmE_proof, cmW_proof, cmT_proof]) } - pub fn verify_commitments( - tr: &mut impl Transcript, - pedersen_params: &PedersenParams, - ci: CommittedInstance, - cmT: C, - cm_proofs: [PedersenProof; 3], - ) -> Result<(), Error> { - if cm_proofs.len() != 3 { - // cm_proofs should have length 3: [cmE_proof, cmW_proof, cmT_proof] - return Err(Error::NotExpectedLength(cm_proofs.len(), 3)); - } - Pedersen::verify(pedersen_params, tr, ci.cmE, cm_proofs[0].clone())?; - Pedersen::verify(pedersen_params, tr, ci.cmW, cm_proofs[1].clone())?; - Pedersen::verify(pedersen_params, tr, cmT, cm_proofs[2].clone())?; - Ok(()) - } } #[cfg(test)] pub mod tests { use super::*; + use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; use ark_ff::{BigInteger, PrimeField}; use ark_pallas::{Fr, Projective}; use ark_std::{ops::Mul, UniformRand, Zero}; use crate::ccs::r1cs::tests::{get_test_r1cs, get_test_z}; + use crate::commitment::pedersen::{Params as PedersenParams, Pedersen}; use crate::folding::nova::circuits::ChallengeGadget; use crate::folding::nova::traits::NovaR1CS; use crate::transcript::poseidon::{tests::poseidon_test_config, PoseidonTranscript}; use crate::utils::vec::vec_scalar_mul; - use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; #[allow(clippy::type_complexity)] pub(crate) fn prepare_simple_fold_inputs() -> ( @@ -258,12 +241,23 @@ pub mod tests { let pedersen_params = Pedersen::::new_params(&mut rng, r1cs.A.n_cols); // compute committed instances - let ci1 = w1.commit(&pedersen_params, x1.clone()).unwrap(); - let ci2 = w2.commit(&pedersen_params, x2.clone()).unwrap(); + let ci1 = w1 + .commit::>(&pedersen_params, x1.clone()) + .unwrap(); + let ci2 = w2 + .commit::>(&pedersen_params, x2.clone()) + .unwrap(); // NIFS.P - let (T, cmT) = - NIFS::::compute_cmT(&pedersen_params, &r1cs, &w1, &ci1, &w2, &ci2).unwrap(); + let (T, cmT) = NIFS::>::compute_cmT( + &pedersen_params, + &r1cs, + &w1, + &ci1, + &w2, + &ci2, + ) + .unwrap(); let poseidon_config = poseidon_test_config::(); @@ -276,8 +270,10 @@ pub mod tests { .unwrap(); let r_Fr = Fr::from_bigint(BigInteger::from_bits_le(&r_bits)).unwrap(); - let (w3, ci3) = - NIFS::::fold_instances(r_Fr, &w1, &ci1, &w2, &ci2, &T, cmT).unwrap(); + let (w3, ci3) = NIFS::>::fold_instances( + r_Fr, &w1, &ci1, &w2, &ci2, &T, cmT, + ) + .unwrap(); ( pedersen_params, @@ -309,7 +305,7 @@ pub mod tests { // dummy instance, witness and public inputs zeroes let w_dummy = Witness::::new(vec![Fr::zero(); w1.len()], r1cs.A.n_rows); let mut u_dummy = w_dummy - .commit(&pedersen_params, vec![Fr::zero(); x1.len()]) + .commit::>(&pedersen_params, vec![Fr::zero(); x1.len()]) .unwrap(); u_dummy.u = Fr::zero(); @@ -322,11 +318,19 @@ pub mod tests { let r_Fr = Fr::from(3_u32); - let (T, cmT) = - NIFS::::compute_cmT(&pedersen_params, &r1cs, &w_i, &u_i, &W_i, &U_i) - .unwrap(); - let (W_i1, U_i1) = - NIFS::::fold_instances(r_Fr, &w_i, &u_i, &W_i, &U_i, &T, cmT).unwrap(); + let (T, cmT) = NIFS::>::compute_cmT( + &pedersen_params, + &r1cs, + &w_i, + &u_i, + &W_i, + &U_i, + ) + .unwrap(); + let (W_i1, U_i1) = NIFS::>::fold_instances( + r_Fr, &w_i, &u_i, &W_i, &U_i, &T, cmT, + ) + .unwrap(); r1cs.check_relaxed_instance_relation(&W_i1, &U_i1).unwrap(); } @@ -337,7 +341,7 @@ pub mod tests { prepare_simple_fold_inputs(); // NIFS.V - let ci3_v = NIFS::::verify(r, &ci1, &ci2, &cmT); + let ci3_v = NIFS::>::verify(r, &ci1, &ci2, &cmT); assert_eq!(ci3_v, ci3); // check that relations hold for the 2 inputted instances and the folded one @@ -347,7 +351,9 @@ pub mod tests { // check that folded commitments from folded instance (ci) are equal to folding the // use folded rE, rW to commit w3 - let ci3_expected = w3.commit(&pedersen_params, ci3.x.clone()).unwrap(); + let ci3_expected = w3 + .commit::>(&pedersen_params, ci3.x.clone()) + .unwrap(); assert_eq!(ci3_expected.cmE, ci3.cmE); assert_eq!(ci3_expected.cmW, ci3.cmW); @@ -356,15 +362,16 @@ pub mod tests { assert_eq!(w3.E, vec_scalar_mul(&T, &r)); // NIFS.Verify_Folded_Instance: - NIFS::::verify_folded_instance(r, &ci1, &ci2, &ci3, &cmT).unwrap(); + NIFS::>::verify_folded_instance(r, &ci1, &ci2, &ci3, &cmT) + .unwrap(); // init Prover's transcript let mut transcript_p = PoseidonTranscript::::new(&poseidon_config); // init Verifier's transcript let mut transcript_v = PoseidonTranscript::::new(&poseidon_config); - // check openings of ci3.cmE, ci3.cmW and cmT - let cm_proofs = NIFS::::open_commitments( + // prove the ci3.cmE, ci3.cmW, cmT commitments + let cm_proofs = NIFS::>::prove_commitments( &mut transcript_p, &pedersen_params, &w3, @@ -374,12 +381,27 @@ pub mod tests { ) .unwrap(); - NIFS::::verify_commitments( + // verify the ci3.cmE, ci3.cmW, cmT commitments + assert_eq!(cm_proofs.len(), 3); + Pedersen::::verify( + &pedersen_params, &mut transcript_v, + ci3.cmE, + cm_proofs[0].clone(), + ) + .unwrap(); + Pedersen::::verify( &pedersen_params, - ci3, + &mut transcript_v, + ci3.cmW, + cm_proofs[1].clone(), + ) + .unwrap(); + Pedersen::::verify( + &pedersen_params, + &mut transcript_v, cmT, - cm_proofs, + cm_proofs[2].clone(), ) .unwrap(); } @@ -395,8 +417,9 @@ pub mod tests { // prepare the running instance let mut running_instance_w = Witness::::new(w.clone(), r1cs.A.n_rows); - let mut running_committed_instance = - running_instance_w.commit(&pedersen_params, x).unwrap(); + let mut running_committed_instance = running_instance_w + .commit::>(&pedersen_params, x) + .unwrap(); r1cs.check_relaxed_instance_relation(&running_instance_w, &running_committed_instance) .unwrap(); @@ -407,8 +430,9 @@ pub mod tests { let incomming_instance_z = get_test_z(i + 4); let (w, x) = r1cs.split_z(&incomming_instance_z); let incomming_instance_w = Witness::::new(w.clone(), r1cs.A.n_rows); - let incomming_committed_instance = - incomming_instance_w.commit(&pedersen_params, x).unwrap(); + let incomming_committed_instance = incomming_instance_w + .commit::>(&pedersen_params, x) + .unwrap(); r1cs.check_relaxed_instance_relation( &incomming_instance_w, &incomming_committed_instance, @@ -418,7 +442,7 @@ pub mod tests { let r = Fr::rand(&mut rng); // folding challenge would come from the RO // NIFS.P - let (T, cmT) = NIFS::::compute_cmT( + let (T, cmT) = NIFS::>::compute_cmT( &pedersen_params, &r1cs, &running_instance_w, @@ -427,7 +451,7 @@ pub mod tests { &incomming_committed_instance, ) .unwrap(); - let (folded_w, _) = NIFS::::fold_instances( + let (folded_w, _) = NIFS::>::fold_instances( r, &running_instance_w, &running_committed_instance, @@ -439,7 +463,7 @@ pub mod tests { .unwrap(); // NIFS.V - let folded_committed_instance = NIFS::::verify( + let folded_committed_instance = NIFS::>::verify( r, &running_committed_instance, &incomming_committed_instance,