mirror of
https://github.com/arnaucube/sonobe.git
synced 2026-01-07 14:31:31 +01:00
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
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -44,6 +44,14 @@ impl<F: PrimeField> Arith<F> for R1CS<F> {
|
||||
}
|
||||
|
||||
impl<F: PrimeField> R1CS<F> {
|
||||
pub fn empty() -> Self {
|
||||
R1CS {
|
||||
l: 0,
|
||||
A: SparseMatrix::empty(),
|
||||
B: SparseMatrix::empty(),
|
||||
C: SparseMatrix::empty(),
|
||||
}
|
||||
}
|
||||
pub fn rand<R: Rng>(rng: &mut R, n_rows: usize, n_cols: usize) -> Self {
|
||||
Self {
|
||||
l: 1,
|
||||
|
||||
@@ -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<C: CurveGroup> {
|
||||
a: C::ScalarField,
|
||||
l: Vec<C::ScalarField>,
|
||||
|
||||
@@ -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<C: CurveGroup> {
|
||||
pub eval: C::ScalarField,
|
||||
pub proof: C,
|
||||
|
||||
@@ -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<C: CurveGroup, const H: bool = false>: 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;
|
||||
|
||||
|
||||
@@ -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<C: CurveGroup> {
|
||||
pub R: C,
|
||||
pub u: Vec<C::ScalarField>,
|
||||
|
||||
@@ -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<C1, CS1, S>
|
||||
where
|
||||
C1: CurveGroup,
|
||||
@@ -40,6 +41,18 @@ where
|
||||
kzg_challenges: [C1::ScalarField; 2],
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
|
||||
pub struct VerifierParam<C1, CS_VerifyingKey, S_VerifyingKey>
|
||||
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<C1, GC1, C2, GC2, FC, CS1, CS2, S, FS> {
|
||||
@@ -90,8 +103,7 @@ where
|
||||
type PreprocessorParam = (FS::ProverParam, FS::VerifierParam);
|
||||
type ProverParam = (S::ProvingKey, CS1::ProverParams);
|
||||
type Proof = Proof<C1, CS1, S>;
|
||||
/// VerifierParam = (pp_hash, snark::vk, commitment_scheme::vk)
|
||||
type VerifierParam = (C1::ScalarField, S::VerifyingKey, CS1::VerifierParams);
|
||||
type VerifierParam = VerifierParam<C1, CS1::VerifierParams, S::VerifyingKey>;
|
||||
type PublicInput = Vec<C1::ScalarField>;
|
||||
type CommittedInstance = CommittedInstance<C1>;
|
||||
|
||||
@@ -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::<C1, CS1>::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<C1::ScalarField> = [
|
||||
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,27 @@ 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::<Fr>();
|
||||
|
||||
let F_circuit = CubicFCircuit::<Fr>::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
|
||||
|
||||
let mut rng = rand::rngs::OsRng;
|
||||
|
||||
// prepare the Decider prover & verifier params
|
||||
let (decider_pp, decider_vp) = D::preprocess(&mut rng, &nova_params, nova.clone()).unwrap();
|
||||
|
||||
// decider proof generation
|
||||
let start = Instant::now();
|
||||
let proof = D::prove(rng, decider_pp, nova.clone()).unwrap();
|
||||
@@ -385,10 +399,194 @@ 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());
|
||||
|
||||
// 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<Fr>,
|
||||
KZG<'static, Bn254>,
|
||||
Pedersen<Projective2>,
|
||||
false,
|
||||
>;
|
||||
type D = Decider<
|
||||
Projective,
|
||||
GVar,
|
||||
Projective2,
|
||||
GVar2,
|
||||
CubicFCircuit<Fr>,
|
||||
KZG<'static, Bn254>,
|
||||
Pedersen<Projective2>,
|
||||
Groth16<Bn254>, // 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::<Fr>();
|
||||
|
||||
let F_circuit = CubicFCircuit::<Fr>::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<Projective2>,
|
||||
>::deserialize_compressed(
|
||||
&mut nova_pp_serialized.as_slice()
|
||||
)
|
||||
.unwrap();
|
||||
let nova_vp_deserialized = NovaVerifierParams::<
|
||||
Projective,
|
||||
Projective2,
|
||||
KZG<'static, Bn254>,
|
||||
Pedersen<Projective2>,
|
||||
>::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();
|
||||
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());
|
||||
|
||||
// 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,
|
||||
<KZG<'static, Bn254> as CommitmentScheme<Projective>>::VerifierParams,
|
||||
<Groth16<Bn254> as SNARK<Fr>>::VerifyingKey,
|
||||
>::deserialize_compressed(&mut decider_vp_serialized.as_slice())
|
||||
.unwrap();
|
||||
let proof_deserialized =
|
||||
Proof::<Projective, KZG<'static, Bn254>, Groth16<Bn254>>::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::<Fr>::deserialize_compressed(&mut reader).unwrap();
|
||||
let z_i_deserialized = Vec::<Fr>::deserialize_compressed(&mut reader).unwrap();
|
||||
let U_i_deserialized =
|
||||
CommittedInstance::<Projective>::deserialize_compressed(&mut reader).unwrap();
|
||||
let u_i_deserialized =
|
||||
CommittedInstance::<Projective>::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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<C1, C2, FC, CS1, CS2, const H: bool>
|
||||
pub struct PreprocessorParam<C1, C2, FC, CS1, CS2, const H: bool = false>
|
||||
where
|
||||
C1: CurveGroup,
|
||||
C2: CurveGroup,
|
||||
@@ -228,7 +228,7 @@ where
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ProverParams<C1, C2, CS1, CS2, const H: bool>
|
||||
pub struct ProverParams<C1, C2, CS1, CS2, const H: bool = false>
|
||||
where
|
||||
C1: CurveGroup,
|
||||
C2: CurveGroup,
|
||||
@@ -240,8 +240,70 @@ where
|
||||
pub cf_cs_pp: CS2::ProverParams,
|
||||
}
|
||||
|
||||
impl<C1, C2, CS1, CS2, const H: bool> Valid for ProverParams<C1, C2, CS1, CS2, H>
|
||||
where
|
||||
C1: CurveGroup,
|
||||
C2: CurveGroup,
|
||||
CS1: CommitmentScheme<C1, H>,
|
||||
CS2: CommitmentScheme<C2, H>,
|
||||
{
|
||||
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<C1, C2, CS1, CS2, const H: bool> CanonicalSerialize for ProverParams<C1, C2, CS1, CS2, H>
|
||||
where
|
||||
C1: CurveGroup,
|
||||
C2: CurveGroup,
|
||||
CS1: CommitmentScheme<C1, H>,
|
||||
CS2: CommitmentScheme<C2, H>,
|
||||
{
|
||||
fn serialize_with_mode<W: std::io::prelude::Write>(
|
||||
&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<C1, C2, CS1, CS2, const H: bool> CanonicalDeserialize for ProverParams<C1, C2, CS1, CS2, H>
|
||||
where
|
||||
C1: CurveGroup,
|
||||
C2: CurveGroup,
|
||||
CS1: CommitmentScheme<C1, H>,
|
||||
CS2: CommitmentScheme<C2, H>,
|
||||
{
|
||||
fn deserialize_with_mode<R: std::io::prelude::Read>(
|
||||
mut reader: R,
|
||||
compress: ark_serialize::Compress,
|
||||
validate: ark_serialize::Validate,
|
||||
) -> Result<Self, ark_serialize::SerializationError> {
|
||||
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::<C1::ScalarField>(),
|
||||
cs_pp,
|
||||
cf_cs_pp,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VerifierParams<C1, C2, CS1, CS2, const H: bool>
|
||||
pub struct VerifierParams<C1, C2, CS1, CS2, const H: bool = false>
|
||||
where
|
||||
C1: CurveGroup,
|
||||
C2: CurveGroup,
|
||||
@@ -255,6 +317,79 @@ where
|
||||
pub cf_cs_vp: CS2::VerifierParams,
|
||||
}
|
||||
|
||||
impl<C1, C2, CS1, CS2, const H: bool> Valid for VerifierParams<C1, C2, CS1, CS2, H>
|
||||
where
|
||||
C1: CurveGroup,
|
||||
C2: CurveGroup,
|
||||
CS1: CommitmentScheme<C1, H>,
|
||||
CS2: CommitmentScheme<C2, H>,
|
||||
{
|
||||
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<C1, C2, CS1, CS2, const H: bool> CanonicalSerialize for VerifierParams<C1, C2, CS1, CS2, H>
|
||||
where
|
||||
C1: CurveGroup,
|
||||
C2: CurveGroup,
|
||||
CS1: CommitmentScheme<C1, H>,
|
||||
CS2: CommitmentScheme<C2, H>,
|
||||
{
|
||||
fn serialize_with_mode<W: std::io::prelude::Write>(
|
||||
&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<C1, C2, CS1, CS2, const H: bool> CanonicalDeserialize for VerifierParams<C1, C2, CS1, CS2, H>
|
||||
where
|
||||
C1: CurveGroup,
|
||||
C2: CurveGroup,
|
||||
CS1: CommitmentScheme<C1, H>,
|
||||
CS2: CommitmentScheme<C2, H>,
|
||||
{
|
||||
fn deserialize_with_mode<R: std::io::prelude::Read>(
|
||||
mut reader: R,
|
||||
compress: ark_serialize::Compress,
|
||||
validate: ark_serialize::Validate,
|
||||
) -> Result<Self, ark_serialize::SerializationError> {
|
||||
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::<C1::ScalarField>(),
|
||||
r1cs,
|
||||
cf_r1cs,
|
||||
cs_vp,
|
||||
cf_cs_vp,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<C1, C2, CS1, CS2, const H: bool> VerifierParams<C1, C2, CS1, CS2, H>
|
||||
where
|
||||
C1: CurveGroup,
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -20,6 +20,13 @@ pub struct SparseMatrix<F: PrimeField> {
|
||||
}
|
||||
|
||||
impl<F: PrimeField> SparseMatrix<F> {
|
||||
pub fn empty() -> Self {
|
||||
Self {
|
||||
n_rows: 0,
|
||||
n_cols: 0,
|
||||
coeffs: vec![],
|
||||
}
|
||||
}
|
||||
pub fn rand<R: Rng>(rng: &mut R, n_rows: usize, n_cols: usize) -> Self {
|
||||
const ZERO_VAL_PROBABILITY: f64 = 0.8f64;
|
||||
|
||||
|
||||
@@ -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<Bn254>, ArkKZG10VerifierKey<Bn254>),
|
||||
DeciderVerifierParam<G1Projective, ArkKZG10VerifierKey<Bn254>, ArkG16VerifierKey<Bn254>>,
|
||||
usize,
|
||||
)> for NovaCycleFoldVerifierKey
|
||||
{
|
||||
fn from(
|
||||
value: (
|
||||
(Fr, ArkG16VerifierKey<Bn254>, ArkKZG10VerifierKey<Bn254>),
|
||||
DeciderVerifierParam<
|
||||
G1Projective,
|
||||
ArkKZG10VerifierKey<Bn254>,
|
||||
ArkG16VerifierKey<Bn254>,
|
||||
>,
|
||||
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::<NovaCycleFoldDecider>::builder()
|
||||
.template(nova_cyclefold_vk)
|
||||
|
||||
Reference in New Issue
Block a user