From 1f7bf0462b88252fa5a4783b598a8eed29fcc644 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Tue, 10 Sep 2024 14:38:31 +0200 Subject: [PATCH] Nova parameters & decider parameters and proofs serialization (#151) * Add nova's decider serialization & deserialization to proof, verifier_params and public inputs * polish * add serialization for nova's ivc proverparams & verifierparams --- folding-schemes/Cargo.toml | 2 +- folding-schemes/src/arith/r1cs.rs | 8 + folding-schemes/src/commitment/ipa.rs | 3 +- folding-schemes/src/commitment/kzg.rs | 2 +- folding-schemes/src/commitment/mod.rs | 4 +- folding-schemes/src/commitment/pedersen.rs | 2 +- .../src/folding/nova/decider_eth.rs | 230 ++++++++++++++++-- folding-schemes/src/folding/nova/mod.rs | 145 ++++++++++- folding-schemes/src/frontend/noir/mod.rs | 2 +- folding-schemes/src/utils/vec.rs | 7 + .../src/verifiers/nova_cyclefold.rs | 35 ++- 11 files changed, 402 insertions(+), 38 deletions(-) diff --git a/folding-schemes/Cargo.toml b/folding-schemes/Cargo.toml index 6fc5bc3..2fbbc3b 100644 --- a/folding-schemes/Cargo.toml +++ b/folding-schemes/Cargo.toml @@ -30,7 +30,7 @@ noname = { git = "https://github.com/dmpierre/noname" } serde_json = "1.0.85" # to (de)serialize JSON serde = "1.0.203" acvm = { git = "https://github.com/noir-lang/noir", rev="2b4853e", default-features = false } -arkworks_backend = { git = "https://github.com/dmpierre/arkworks_backend", branch = "feat/sonobe-integration" } +noir_arkworks_backend = { package="arkworks_backend", git = "https://github.com/dmpierre/arkworks_backend", branch = "feat/sonobe-integration" } log = "0.4" # tmp import for espresso's sumcheck diff --git a/folding-schemes/src/arith/r1cs.rs b/folding-schemes/src/arith/r1cs.rs index f6414c7..769daca 100644 --- a/folding-schemes/src/arith/r1cs.rs +++ b/folding-schemes/src/arith/r1cs.rs @@ -44,6 +44,14 @@ impl Arith for R1CS { } impl R1CS { + pub fn empty() -> Self { + R1CS { + l: 0, + A: SparseMatrix::empty(), + B: SparseMatrix::empty(), + C: SparseMatrix::empty(), + } + } pub fn rand(rng: &mut R, n_rows: usize, n_cols: usize) -> Self { Self { l: 1, diff --git a/folding-schemes/src/commitment/ipa.rs b/folding-schemes/src/commitment/ipa.rs index 4607834..a951e7f 100644 --- a/folding-schemes/src/commitment/ipa.rs +++ b/folding-schemes/src/commitment/ipa.rs @@ -18,6 +18,7 @@ use ark_r1cs_std::{ ToBitsGadget, }; use ark_relations::r1cs::{Namespace, SynthesisError}; +use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_std::{cfg_iter, rand::RngCore, UniformRand, Zero}; use core::{borrow::Borrow, marker::PhantomData}; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; @@ -30,7 +31,7 @@ use crate::utils::{ }; use crate::Error; -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)] pub struct Proof { a: C::ScalarField, l: Vec, diff --git a/folding-schemes/src/commitment/kzg.rs b/folding-schemes/src/commitment/kzg.rs index d034428..5bfce04 100644 --- a/folding-schemes/src/commitment/kzg.rs +++ b/folding-schemes/src/commitment/kzg.rs @@ -70,7 +70,7 @@ impl<'a, C: CurveGroup> Valid for ProverKey<'a, C> { } } -#[derive(Debug, Clone, Default, Eq, PartialEq)] +#[derive(Debug, Clone, Default, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)] pub struct Proof { pub eval: C::ScalarField, pub proof: C, diff --git a/folding-schemes/src/commitment/mod.rs b/folding-schemes/src/commitment/mod.rs index 58ecadd..a76ba15 100644 --- a/folding-schemes/src/commitment/mod.rs +++ b/folding-schemes/src/commitment/mod.rs @@ -13,9 +13,9 @@ pub mod pedersen; /// CommitmentScheme defines the vector commitment scheme trait. Where `H` indicates if to use the /// commitment in hiding mode or not. pub trait CommitmentScheme: Clone + Debug { - type ProverParams: Clone + Debug; + type ProverParams: Clone + Debug + CanonicalSerialize + CanonicalDeserialize; type VerifierParams: Clone + Debug + CanonicalSerialize + CanonicalDeserialize; - type Proof: Clone + Debug; + type Proof: Clone + Debug + CanonicalSerialize + CanonicalDeserialize; type ProverChallenge: Clone + Debug; type Challenge: Clone + Debug; diff --git a/folding-schemes/src/commitment/pedersen.rs b/folding-schemes/src/commitment/pedersen.rs index 4d225ce..0a5f42f 100644 --- a/folding-schemes/src/commitment/pedersen.rs +++ b/folding-schemes/src/commitment/pedersen.rs @@ -12,7 +12,7 @@ use crate::transcript::Transcript; use crate::utils::vec::{vec_add, vec_scalar_mul}; use crate::Error; -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)] pub struct Proof { pub R: C, pub u: Vec, diff --git a/folding-schemes/src/folding/nova/decider_eth.rs b/folding-schemes/src/folding/nova/decider_eth.rs index d1a3ed1..5a26813 100644 --- a/folding-schemes/src/folding/nova/decider_eth.rs +++ b/folding-schemes/src/folding/nova/decider_eth.rs @@ -5,6 +5,7 @@ use ark_ec::{AffineRepr, CurveGroup, Group}; use ark_ff::{BigInteger, PrimeField}; use ark_groth16::Groth16; use ark_r1cs_std::{groups::GroupOpsBounds, prelude::CurveVar, ToConstraintFieldGadget}; +use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use ark_snark::SNARK; use ark_std::rand::{CryptoRng, RngCore}; use ark_std::{One, Zero}; @@ -22,7 +23,7 @@ use crate::frontend::FCircuit; use crate::Error; use crate::{Decider as DeciderTrait, FoldingScheme}; -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)] pub struct Proof where C1: CurveGroup, @@ -40,6 +41,18 @@ where kzg_challenges: [C1::ScalarField; 2], } +#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)] +pub struct VerifierParam +where + C1: CurveGroup, + CS_VerifyingKey: Clone + CanonicalSerialize + CanonicalDeserialize, + S_VerifyingKey: Clone + CanonicalSerialize + CanonicalDeserialize, +{ + pub pp_hash: C1::ScalarField, + pub snark_vp: S_VerifyingKey, + pub cs_vp: CS_VerifyingKey, +} + /// Onchain Decider, for ethereum use cases #[derive(Clone, Debug)] pub struct Decider { @@ -90,8 +103,7 @@ where type PreprocessorParam = (FS::ProverParam, FS::VerifierParam); type ProverParam = (S::ProvingKey, CS1::ProverParams); type Proof = Proof; - /// VerifierParam = (pp_hash, snark::vk, commitment_scheme::vk) - type VerifierParam = (C1::ScalarField, S::VerifyingKey, CS1::VerifierParams); + type VerifierParam = VerifierParam; type PublicInput = Vec; type CommittedInstance = CommittedInstance; @@ -122,7 +134,11 @@ where let pp_hash = nova_vp.pp_hash()?; let pp = (g16_pk, nova_pp.cs_pp); - let vp = (pp_hash, g16_vk, nova_vp.cs_vp); + let vp = Self::VerifierParam { + pp_hash, + snark_vp: g16_vk, + cs_vp: nova_vp.cs_vp, + }; Ok((pp, vp)) } @@ -191,9 +207,6 @@ where return Err(Error::NotEnoughSteps); } - let (pp_hash, snark_vk, cs_vk): (C1::ScalarField, S::VerifyingKey, CS1::VerifierParams) = - vp; - // compute U = U_{d+1}= NIFS.V(U_d, u_d, cmT) let U = NIFS::::verify(proof.r, running_instance, incoming_instance, &proof.cmT); @@ -202,7 +215,7 @@ where let (cmT_x, cmT_y) = NonNativeAffineVar::inputize(proof.cmT)?; let public_input: Vec = [ - vec![pp_hash, i], + vec![vp.pp_hash, i], z_0, z_i, vec![U.u], @@ -222,7 +235,7 @@ where ] .concat(); - let snark_v = S::verify(&snark_vk, &public_input, &proof.snark_proof) + let snark_v = S::verify(&vp.snark_vp, &public_input, &proof.snark_proof) .map_err(|e| Error::Other(e.to_string()))?; if !snark_v { return Err(Error::SNARKVerificationFail); @@ -230,13 +243,13 @@ where // we're at the Ethereum EVM case, so the CS1 is KZG commitments CS1::verify_with_challenge( - &cs_vk, + &vp.cs_vp, proof.kzg_challenges[0], &U.cmW, &proof.kzg_proofs[0], )?; CS1::verify_with_challenge( - &cs_vk, + &vp.cs_vp, proof.kzg_challenges[1], &U.cmE, &proof.kzg_proofs[1], @@ -326,7 +339,9 @@ pub mod tests { use super::*; use crate::commitment::pedersen::Pedersen; - use crate::folding::nova::PreprocessorParam; + use crate::folding::nova::{ + PreprocessorParam, ProverParams as NovaProverParams, VerifierParams as NovaVerifierParams, + }; use crate::frontend::tests::CubicFCircuit; use crate::transcript::poseidon::poseidon_canonical_config; @@ -355,28 +370,140 @@ pub mod tests { N, // here we define the FoldingScheme to use >; - let mut rng = ark_std::test_rng(); + let mut rng = rand::rngs::OsRng; let poseidon_config = poseidon_canonical_config::(); let F_circuit = CubicFCircuit::::new(()).unwrap(); let z_0 = vec![Fr::from(3_u32)]; - let prep_param = PreprocessorParam::new(poseidon_config, F_circuit); - let nova_params = N::preprocess(&mut rng, &prep_param).unwrap(); + let preprocessor_param = PreprocessorParam::new(poseidon_config, F_circuit); + let nova_params = N::preprocess(&mut rng, &preprocessor_param).unwrap(); let start = Instant::now(); let mut nova = N::init(&nova_params, F_circuit, z_0.clone()).unwrap(); println!("Nova initialized, {:?}", start.elapsed()); + + // prepare the Decider prover & verifier params + let (decider_pp, decider_vp) = D::preprocess(&mut rng, &nova_params, nova.clone()).unwrap(); + let start = Instant::now(); nova.prove_step(&mut rng, vec![], None).unwrap(); println!("prove_step, {:?}", start.elapsed()); nova.prove_step(&mut rng, vec![], None).unwrap(); // do a 2nd step + // decider proof generation + let start = Instant::now(); + let proof = D::prove(rng, decider_pp, nova.clone()).unwrap(); + println!("Decider prove, {:?}", start.elapsed()); + + // decider proof verification + let start = Instant::now(); + let verified = D::verify( + decider_vp.clone(), + nova.i.clone(), + nova.z_0.clone(), + nova.z_i.clone(), + &nova.U_i, + &nova.u_i, + &proof, + ) + .unwrap(); + assert!(verified); + println!("Decider verify, {:?}", start.elapsed()); + + // decider proof verification using the deserialized data + let verified = D::verify( + decider_vp, nova.i, nova.z_0, nova.z_i, &nova.U_i, &nova.u_i, &proof, + ) + .unwrap(); + assert!(verified); + } + + // Test to check the serialization and deserialization of diverse Decider related parameters. + // This test is the same test as `test_decider` but it serializes values and then uses the + // deserialized values to continue the checks. + #[test] + fn test_decider_serialization() { + // use Nova as FoldingScheme + type N = Nova< + Projective, + GVar, + Projective2, + GVar2, + CubicFCircuit, + KZG<'static, Bn254>, + Pedersen, + false, + >; + type D = Decider< + Projective, + GVar, + Projective2, + GVar2, + CubicFCircuit, + KZG<'static, Bn254>, + Pedersen, + Groth16, // here we define the Snark to use in the decider + N, // here we define the FoldingScheme to use + >; + let mut rng = rand::rngs::OsRng; + let poseidon_config = poseidon_canonical_config::(); + + let F_circuit = CubicFCircuit::::new(()).unwrap(); + let z_0 = vec![Fr::from(3_u32)]; + + let preprocessor_param = PreprocessorParam::new(poseidon_config, F_circuit); + let nova_params = N::preprocess(&mut rng, &preprocessor_param).unwrap(); + + let start = Instant::now(); + let nova = N::init(&nova_params, F_circuit, z_0.clone()).unwrap(); + println!("Nova initialized, {:?}", start.elapsed()); // prepare the Decider prover & verifier params let (decider_pp, decider_vp) = D::preprocess(&mut rng, &nova_params, nova.clone()).unwrap(); + // serialize the Nova params. These params are the trusted setup of the commitment schemes used + // (ie. KZG & Pedersen in this case) + let mut nova_pp_serialized = vec![]; + nova_params + .0 + .serialize_compressed(&mut nova_pp_serialized) + .unwrap(); + let mut nova_vp_serialized = vec![]; + nova_params + .1 + .serialize_compressed(&mut nova_vp_serialized) + .unwrap(); + // deserialize the Nova params. This would be done by the client reading from a file + let nova_pp_deserialized = NovaProverParams::< + Projective, + Projective2, + KZG<'static, Bn254>, + Pedersen, + >::deserialize_compressed( + &mut nova_pp_serialized.as_slice() + ) + .unwrap(); + let nova_vp_deserialized = NovaVerifierParams::< + Projective, + Projective2, + KZG<'static, Bn254>, + Pedersen, + >::deserialize_compressed( + &mut nova_vp_serialized.as_slice() + ) + .unwrap(); + + // initialize nova again, but from the deserialized parameters + let nova_params = (nova_pp_deserialized, nova_vp_deserialized); + let mut nova = N::init(&nova_params, F_circuit, z_0).unwrap(); + + let start = Instant::now(); + nova.prove_step(&mut rng, vec![], None).unwrap(); + println!("prove_step, {:?}", start.elapsed()); + nova.prove_step(&mut rng, vec![], None).unwrap(); // do a 2nd step + // decider proof generation let start = Instant::now(); let proof = D::prove(rng, decider_pp, nova.clone()).unwrap(); @@ -385,10 +512,81 @@ pub mod tests { // decider proof verification let start = Instant::now(); let verified = D::verify( - decider_vp, nova.i, nova.z_0, nova.z_i, &nova.U_i, &nova.u_i, &proof, + decider_vp.clone(), + nova.i.clone(), + nova.z_0.clone(), + nova.z_i.clone(), + &nova.U_i, + &nova.u_i, + &proof, ) .unwrap(); assert!(verified); println!("Decider verify, {:?}", start.elapsed()); + + // The rest of this test will serialize the data and deserialize it back, and use it to + // verify the proof: + + // serialize the verifier_params, proof and public inputs + let mut decider_vp_serialized = vec![]; + decider_vp + .serialize_compressed(&mut decider_vp_serialized) + .unwrap(); + let mut proof_serialized = vec![]; + proof.serialize_compressed(&mut proof_serialized).unwrap(); + // serialize the public inputs in a single packet + let mut public_inputs_serialized = vec![]; + nova.i + .serialize_compressed(&mut public_inputs_serialized) + .unwrap(); + nova.z_0 + .serialize_compressed(&mut public_inputs_serialized) + .unwrap(); + nova.z_i + .serialize_compressed(&mut public_inputs_serialized) + .unwrap(); + nova.U_i + .serialize_compressed(&mut public_inputs_serialized) + .unwrap(); + nova.u_i + .serialize_compressed(&mut public_inputs_serialized) + .unwrap(); + + // deserialize back the verifier_params, proof and public inputs + let decider_vp_deserialized = + VerifierParam::< + Projective, + as CommitmentScheme>::VerifierParams, + as SNARK>::VerifyingKey, + >::deserialize_compressed(&mut decider_vp_serialized.as_slice()) + .unwrap(); + let proof_deserialized = + Proof::, Groth16>::deserialize_compressed( + &mut proof_serialized.as_slice(), + ) + .unwrap(); + + // deserialize the public inputs from the single packet 'public_inputs_serialized' + let mut reader = public_inputs_serialized.as_slice(); + let i_deserialized = Fr::deserialize_compressed(&mut reader).unwrap(); + let z_0_deserialized = Vec::::deserialize_compressed(&mut reader).unwrap(); + let z_i_deserialized = Vec::::deserialize_compressed(&mut reader).unwrap(); + let U_i_deserialized = + CommittedInstance::::deserialize_compressed(&mut reader).unwrap(); + let u_i_deserialized = + CommittedInstance::::deserialize_compressed(&mut reader).unwrap(); + + // decider proof verification using the deserialized data + let verified = D::verify( + decider_vp_deserialized, + i_deserialized, + z_0_deserialized, + z_i_deserialized, + &U_i_deserialized, + &u_i_deserialized, + &proof_deserialized, + ) + .unwrap(); + assert!(verified); } } diff --git a/folding-schemes/src/folding/nova/mod.rs b/folding-schemes/src/folding/nova/mod.rs index f0c07b1..be57fc9 100644 --- a/folding-schemes/src/folding/nova/mod.rs +++ b/folding-schemes/src/folding/nova/mod.rs @@ -8,7 +8,7 @@ use ark_ec::{CurveGroup, Group}; use ark_ff::{BigInteger, PrimeField}; use ark_r1cs_std::{groups::GroupOpsBounds, prelude::CurveVar, ToConstraintFieldGadget}; use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystem}; -use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; +use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Valid}; use ark_std::fmt::Debug; use ark_std::rand::RngCore; use ark_std::{One, UniformRand, Zero}; @@ -21,7 +21,7 @@ use crate::folding::circuits::cyclefold::{ }; use crate::folding::circuits::CF2; use crate::frontend::FCircuit; -use crate::transcript::{AbsorbNonNative, Transcript}; +use crate::transcript::{poseidon::poseidon_canonical_config, AbsorbNonNative, Transcript}; use crate::utils::vec::is_zero_vec; use crate::Error; use crate::FoldingScheme; @@ -190,7 +190,7 @@ where } #[derive(Debug, Clone)] -pub struct PreprocessorParam +pub struct PreprocessorParam where C1: CurveGroup, C2: CurveGroup, @@ -228,7 +228,7 @@ where } #[derive(Debug, Clone)] -pub struct ProverParams +pub struct ProverParams where C1: CurveGroup, C2: CurveGroup, @@ -240,8 +240,70 @@ where pub cf_cs_pp: CS2::ProverParams, } +impl Valid for ProverParams +where + C1: CurveGroup, + C2: CurveGroup, + CS1: CommitmentScheme, + CS2: CommitmentScheme, +{ + fn check(&self) -> Result<(), ark_serialize::SerializationError> { + self.poseidon_config.full_rounds.check()?; + self.poseidon_config.partial_rounds.check()?; + self.poseidon_config.alpha.check()?; + self.poseidon_config.ark.check()?; + self.poseidon_config.mds.check()?; + self.poseidon_config.rate.check()?; + self.poseidon_config.capacity.check()?; + self.cs_pp.check()?; + self.cf_cs_pp.check()?; + Ok(()) + } +} +impl CanonicalSerialize for ProverParams +where + C1: CurveGroup, + C2: CurveGroup, + CS1: CommitmentScheme, + CS2: CommitmentScheme, +{ + fn serialize_with_mode( + &self, + mut writer: W, + compress: ark_serialize::Compress, + ) -> Result<(), ark_serialize::SerializationError> { + self.cs_pp.serialize_with_mode(&mut writer, compress)?; + self.cf_cs_pp.serialize_with_mode(&mut writer, compress) + } + + fn serialized_size(&self, compress: ark_serialize::Compress) -> usize { + self.cs_pp.serialized_size(compress) + self.cf_cs_pp.serialized_size(compress) + } +} +impl CanonicalDeserialize for ProverParams +where + C1: CurveGroup, + C2: CurveGroup, + CS1: CommitmentScheme, + CS2: CommitmentScheme, +{ + fn deserialize_with_mode( + mut reader: R, + compress: ark_serialize::Compress, + validate: ark_serialize::Validate, + ) -> Result { + let cs_pp = CS1::ProverParams::deserialize_with_mode(&mut reader, compress, validate)?; + let cf_cs_pp = CS2::ProverParams::deserialize_with_mode(&mut reader, compress, validate)?; + Ok(ProverParams { + poseidon_config: poseidon_canonical_config::(), + cs_pp, + cf_cs_pp, + }) + } +} + #[derive(Debug, Clone)] -pub struct VerifierParams +pub struct VerifierParams where C1: CurveGroup, C2: CurveGroup, @@ -255,6 +317,79 @@ where pub cf_cs_vp: CS2::VerifierParams, } +impl Valid for VerifierParams +where + C1: CurveGroup, + C2: CurveGroup, + CS1: CommitmentScheme, + CS2: CommitmentScheme, +{ + fn check(&self) -> Result<(), ark_serialize::SerializationError> { + self.poseidon_config.full_rounds.check()?; + self.poseidon_config.partial_rounds.check()?; + self.poseidon_config.alpha.check()?; + self.poseidon_config.ark.check()?; + self.poseidon_config.mds.check()?; + self.poseidon_config.rate.check()?; + self.poseidon_config.capacity.check()?; + self.r1cs.check()?; + self.cf_r1cs.check()?; + self.cs_vp.check()?; + self.cf_cs_vp.check()?; + Ok(()) + } +} +impl CanonicalSerialize for VerifierParams +where + C1: CurveGroup, + C2: CurveGroup, + CS1: CommitmentScheme, + CS2: CommitmentScheme, +{ + fn serialize_with_mode( + &self, + mut writer: W, + compress: ark_serialize::Compress, + ) -> Result<(), ark_serialize::SerializationError> { + self.r1cs.serialize_with_mode(&mut writer, compress)?; + self.cf_r1cs.serialize_with_mode(&mut writer, compress)?; + self.cs_vp.serialize_with_mode(&mut writer, compress)?; + self.cf_cs_vp.serialize_with_mode(&mut writer, compress) + } + + fn serialized_size(&self, compress: ark_serialize::Compress) -> usize { + self.r1cs.serialized_size(compress) + + self.cf_r1cs.serialized_size(compress) + + self.cs_vp.serialized_size(compress) + + self.cf_cs_vp.serialized_size(compress) + } +} +impl CanonicalDeserialize for VerifierParams +where + C1: CurveGroup, + C2: CurveGroup, + CS1: CommitmentScheme, + CS2: CommitmentScheme, +{ + fn deserialize_with_mode( + mut reader: R, + compress: ark_serialize::Compress, + validate: ark_serialize::Validate, + ) -> Result { + let r1cs = R1CS::deserialize_with_mode(&mut reader, compress, validate)?; + let cf_r1cs = R1CS::deserialize_with_mode(&mut reader, compress, validate)?; + let cs_vp = CS1::VerifierParams::deserialize_with_mode(&mut reader, compress, validate)?; + let cf_cs_vp = CS2::VerifierParams::deserialize_with_mode(&mut reader, compress, validate)?; + Ok(VerifierParams { + poseidon_config: poseidon_canonical_config::(), + r1cs, + cf_r1cs, + cs_vp, + cf_cs_vp, + }) + } +} + impl VerifierParams where C1: CurveGroup, diff --git a/folding-schemes/src/frontend/noir/mod.rs b/folding-schemes/src/frontend/noir/mod.rs index 6709b20..b091091 100644 --- a/folding-schemes/src/frontend/noir/mod.rs +++ b/folding-schemes/src/frontend/noir/mod.rs @@ -16,7 +16,7 @@ use ark_ff::PrimeField; use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar, R1CSVar}; use ark_relations::r1cs::ConstraintSynthesizer; use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError}; -use arkworks_backend::{ +use noir_arkworks_backend::{ read_program_from_binary, read_program_from_file, sonobe_bridge::AcirCircuitSonobe, }; diff --git a/folding-schemes/src/utils/vec.rs b/folding-schemes/src/utils/vec.rs index 93c4b66..3ac9203 100644 --- a/folding-schemes/src/utils/vec.rs +++ b/folding-schemes/src/utils/vec.rs @@ -20,6 +20,13 @@ pub struct SparseMatrix { } impl SparseMatrix { + pub fn empty() -> Self { + Self { + n_rows: 0, + n_cols: 0, + coeffs: vec![], + } + } pub fn rand(rng: &mut R, n_rows: usize, n_cols: usize) -> Self { const ZERO_VAL_PROBABILITY: f64 = 0.8f64; diff --git a/solidity-verifiers/src/verifiers/nova_cyclefold.rs b/solidity-verifiers/src/verifiers/nova_cyclefold.rs index 391e485..9e896bd 100644 --- a/solidity-verifiers/src/verifiers/nova_cyclefold.rs +++ b/solidity-verifiers/src/verifiers/nova_cyclefold.rs @@ -2,13 +2,14 @@ #![allow(non_camel_case_types)] #![allow(clippy::upper_case_acronyms)] -use ark_bn254::{Bn254, Fq, Fr, G1Affine}; +use ark_bn254::{Bn254, Fq, Fr, G1Affine, G1Projective}; use ark_groth16::VerifyingKey as ArkG16VerifierKey; use ark_poly_commit::kzg10::VerifierKey as ArkKZG10VerifierKey; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use askama::Template; use folding_schemes::folding::circuits::nonnative::uint::NonNativeUintVar; +use folding_schemes::folding::nova::decider_eth::VerifierParam as DeciderVerifierParam; use super::g16::Groth16Verifier; use super::kzg::KZG10Verifier; @@ -92,22 +93,26 @@ impl From<(Fr, Groth16VerifierKey, KZG10VerifierKey, usize)> for NovaCycleFoldVe // in the NovaCycleFoldDecider verifier contract impl From<( - (Fr, ArkG16VerifierKey, ArkKZG10VerifierKey), + DeciderVerifierParam, ArkG16VerifierKey>, usize, )> for NovaCycleFoldVerifierKey { fn from( value: ( - (Fr, ArkG16VerifierKey, ArkKZG10VerifierKey), + DeciderVerifierParam< + G1Projective, + ArkKZG10VerifierKey, + ArkG16VerifierKey, + >, usize, ), ) -> Self { let decider_vp = value.0; - let g16_vk = Groth16VerifierKey::from(decider_vp.1); + let g16_vk = Groth16VerifierKey::from(decider_vp.snark_vp); // pass `Vec::new()` since batchCheck will not be used - let kzg_vk = KZG10VerifierKey::from((decider_vp.2, Vec::new())); + let kzg_vk = KZG10VerifierKey::from((decider_vp.cs_vp, Vec::new())); Self { - pp_hash: decider_vp.0, + pp_hash: decider_vp.pp_hash, g16_vk, kzg_vk, z_len: value.1, @@ -157,7 +162,7 @@ mod tests { Decider, Error, FoldingScheme, }; - use super::NovaCycleFoldDecider; + use super::{DeciderVerifierParam, NovaCycleFoldDecider}; use crate::verifiers::tests::{setup, DEFAULT_SETUP_LEN}; use crate::{ evm::{compile_solidity, save_solidity, Evm}, @@ -286,9 +291,14 @@ mod tests { fn nova_cyclefold_vk_serde_roundtrip() { let (pp_hash, _, kzg_vk, _, g16_vk, _) = setup(DEFAULT_SETUP_LEN); - let mut bytes = vec![]; - let nova_cyclefold_vk = NovaCycleFoldVerifierKey::from(((pp_hash, g16_vk, kzg_vk), 1)); + let decider_vp = DeciderVerifierParam { + pp_hash, + snark_vp: g16_vk, + cs_vp: kzg_vk, + }; + let nova_cyclefold_vk = NovaCycleFoldVerifierKey::from((decider_vp, 1)); + let mut bytes = vec![]; nova_cyclefold_vk .serialize_protocol_verifier_key(&mut bytes) .unwrap(); @@ -301,7 +311,12 @@ mod tests { #[test] fn nova_cyclefold_decider_template_renders() { let (pp_hash, _, kzg_vk, _, g16_vk, _) = setup(DEFAULT_SETUP_LEN); - let nova_cyclefold_vk = NovaCycleFoldVerifierKey::from(((pp_hash, g16_vk, kzg_vk), 1)); + let decider_vp = DeciderVerifierParam { + pp_hash, + snark_vp: g16_vk, + cs_vp: kzg_vk, + }; + let nova_cyclefold_vk = NovaCycleFoldVerifierKey::from((decider_vp, 1)); let decider_solidity_code = HeaderInclusion::::builder() .template(nova_cyclefold_vk)