mirror of
https://github.com/arnaucube/sonobe.git
synced 2026-01-09 07:21:28 +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_json = "1.0.85" # to (de)serialize JSON
|
||||||
serde = "1.0.203"
|
serde = "1.0.203"
|
||||||
acvm = { git = "https://github.com/noir-lang/noir", rev="2b4853e", default-features = false }
|
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"
|
log = "0.4"
|
||||||
|
|
||||||
# tmp import for espresso's sumcheck
|
# tmp import for espresso's sumcheck
|
||||||
|
|||||||
@@ -44,6 +44,14 @@ impl<F: PrimeField> Arith<F> for R1CS<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<F: PrimeField> 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 {
|
pub fn rand<R: Rng>(rng: &mut R, n_rows: usize, n_cols: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
l: 1,
|
l: 1,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ use ark_r1cs_std::{
|
|||||||
ToBitsGadget,
|
ToBitsGadget,
|
||||||
};
|
};
|
||||||
use ark_relations::r1cs::{Namespace, SynthesisError};
|
use ark_relations::r1cs::{Namespace, SynthesisError};
|
||||||
|
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
|
||||||
use ark_std::{cfg_iter, rand::RngCore, UniformRand, Zero};
|
use ark_std::{cfg_iter, rand::RngCore, UniformRand, Zero};
|
||||||
use core::{borrow::Borrow, marker::PhantomData};
|
use core::{borrow::Borrow, marker::PhantomData};
|
||||||
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
||||||
@@ -30,7 +31,7 @@ use crate::utils::{
|
|||||||
};
|
};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
|
||||||
pub struct Proof<C: CurveGroup> {
|
pub struct Proof<C: CurveGroup> {
|
||||||
a: C::ScalarField,
|
a: C::ScalarField,
|
||||||
l: Vec<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 struct Proof<C: CurveGroup> {
|
||||||
pub eval: C::ScalarField,
|
pub eval: C::ScalarField,
|
||||||
pub proof: C,
|
pub proof: C,
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ pub mod pedersen;
|
|||||||
/// CommitmentScheme defines the vector commitment scheme trait. Where `H` indicates if to use the
|
/// CommitmentScheme defines the vector commitment scheme trait. Where `H` indicates if to use the
|
||||||
/// commitment in hiding mode or not.
|
/// commitment in hiding mode or not.
|
||||||
pub trait CommitmentScheme<C: CurveGroup, const H: bool = false>: Clone + Debug {
|
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 VerifierParams: Clone + Debug + CanonicalSerialize + CanonicalDeserialize;
|
||||||
type Proof: Clone + Debug;
|
type Proof: Clone + Debug + CanonicalSerialize + CanonicalDeserialize;
|
||||||
type ProverChallenge: Clone + Debug;
|
type ProverChallenge: Clone + Debug;
|
||||||
type Challenge: 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::utils::vec::{vec_add, vec_scalar_mul};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
|
||||||
pub struct Proof<C: CurveGroup> {
|
pub struct Proof<C: CurveGroup> {
|
||||||
pub R: C,
|
pub R: C,
|
||||||
pub u: Vec<C::ScalarField>,
|
pub u: Vec<C::ScalarField>,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use ark_ec::{AffineRepr, CurveGroup, Group};
|
|||||||
use ark_ff::{BigInteger, PrimeField};
|
use ark_ff::{BigInteger, PrimeField};
|
||||||
use ark_groth16::Groth16;
|
use ark_groth16::Groth16;
|
||||||
use ark_r1cs_std::{groups::GroupOpsBounds, prelude::CurveVar, ToConstraintFieldGadget};
|
use ark_r1cs_std::{groups::GroupOpsBounds, prelude::CurveVar, ToConstraintFieldGadget};
|
||||||
|
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
|
||||||
use ark_snark::SNARK;
|
use ark_snark::SNARK;
|
||||||
use ark_std::rand::{CryptoRng, RngCore};
|
use ark_std::rand::{CryptoRng, RngCore};
|
||||||
use ark_std::{One, Zero};
|
use ark_std::{One, Zero};
|
||||||
@@ -22,7 +23,7 @@ use crate::frontend::FCircuit;
|
|||||||
use crate::Error;
|
use crate::Error;
|
||||||
use crate::{Decider as DeciderTrait, FoldingScheme};
|
use crate::{Decider as DeciderTrait, FoldingScheme};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
|
||||||
pub struct Proof<C1, CS1, S>
|
pub struct Proof<C1, CS1, S>
|
||||||
where
|
where
|
||||||
C1: CurveGroup,
|
C1: CurveGroup,
|
||||||
@@ -40,6 +41,18 @@ where
|
|||||||
kzg_challenges: [C1::ScalarField; 2],
|
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
|
/// Onchain Decider, for ethereum use cases
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Decider<C1, GC1, C2, GC2, FC, CS1, CS2, S, FS> {
|
pub struct Decider<C1, GC1, C2, GC2, FC, CS1, CS2, S, FS> {
|
||||||
@@ -90,8 +103,7 @@ where
|
|||||||
type PreprocessorParam = (FS::ProverParam, FS::VerifierParam);
|
type PreprocessorParam = (FS::ProverParam, FS::VerifierParam);
|
||||||
type ProverParam = (S::ProvingKey, CS1::ProverParams);
|
type ProverParam = (S::ProvingKey, CS1::ProverParams);
|
||||||
type Proof = Proof<C1, CS1, S>;
|
type Proof = Proof<C1, CS1, S>;
|
||||||
/// VerifierParam = (pp_hash, snark::vk, commitment_scheme::vk)
|
type VerifierParam = VerifierParam<C1, CS1::VerifierParams, S::VerifyingKey>;
|
||||||
type VerifierParam = (C1::ScalarField, S::VerifyingKey, CS1::VerifierParams);
|
|
||||||
type PublicInput = Vec<C1::ScalarField>;
|
type PublicInput = Vec<C1::ScalarField>;
|
||||||
type CommittedInstance = CommittedInstance<C1>;
|
type CommittedInstance = CommittedInstance<C1>;
|
||||||
|
|
||||||
@@ -122,7 +134,11 @@ where
|
|||||||
let pp_hash = nova_vp.pp_hash()?;
|
let pp_hash = nova_vp.pp_hash()?;
|
||||||
|
|
||||||
let pp = (g16_pk, nova_pp.cs_pp);
|
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))
|
Ok((pp, vp))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,9 +207,6 @@ where
|
|||||||
return Err(Error::NotEnoughSteps);
|
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)
|
// 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);
|
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 (cmT_x, cmT_y) = NonNativeAffineVar::inputize(proof.cmT)?;
|
||||||
|
|
||||||
let public_input: Vec<C1::ScalarField> = [
|
let public_input: Vec<C1::ScalarField> = [
|
||||||
vec![pp_hash, i],
|
vec![vp.pp_hash, i],
|
||||||
z_0,
|
z_0,
|
||||||
z_i,
|
z_i,
|
||||||
vec![U.u],
|
vec![U.u],
|
||||||
@@ -222,7 +235,7 @@ where
|
|||||||
]
|
]
|
||||||
.concat();
|
.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()))?;
|
.map_err(|e| Error::Other(e.to_string()))?;
|
||||||
if !snark_v {
|
if !snark_v {
|
||||||
return Err(Error::SNARKVerificationFail);
|
return Err(Error::SNARKVerificationFail);
|
||||||
@@ -230,13 +243,13 @@ where
|
|||||||
|
|
||||||
// we're at the Ethereum EVM case, so the CS1 is KZG commitments
|
// we're at the Ethereum EVM case, so the CS1 is KZG commitments
|
||||||
CS1::verify_with_challenge(
|
CS1::verify_with_challenge(
|
||||||
&cs_vk,
|
&vp.cs_vp,
|
||||||
proof.kzg_challenges[0],
|
proof.kzg_challenges[0],
|
||||||
&U.cmW,
|
&U.cmW,
|
||||||
&proof.kzg_proofs[0],
|
&proof.kzg_proofs[0],
|
||||||
)?;
|
)?;
|
||||||
CS1::verify_with_challenge(
|
CS1::verify_with_challenge(
|
||||||
&cs_vk,
|
&vp.cs_vp,
|
||||||
proof.kzg_challenges[1],
|
proof.kzg_challenges[1],
|
||||||
&U.cmE,
|
&U.cmE,
|
||||||
&proof.kzg_proofs[1],
|
&proof.kzg_proofs[1],
|
||||||
@@ -326,7 +339,9 @@ pub mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::commitment::pedersen::Pedersen;
|
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::frontend::tests::CubicFCircuit;
|
||||||
use crate::transcript::poseidon::poseidon_canonical_config;
|
use crate::transcript::poseidon::poseidon_canonical_config;
|
||||||
|
|
||||||
@@ -355,28 +370,27 @@ pub mod tests {
|
|||||||
N, // here we define the FoldingScheme to use
|
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 poseidon_config = poseidon_canonical_config::<Fr>();
|
||||||
|
|
||||||
let F_circuit = CubicFCircuit::<Fr>::new(()).unwrap();
|
let F_circuit = CubicFCircuit::<Fr>::new(()).unwrap();
|
||||||
let z_0 = vec![Fr::from(3_u32)];
|
let z_0 = vec![Fr::from(3_u32)];
|
||||||
|
|
||||||
let prep_param = PreprocessorParam::new(poseidon_config, F_circuit);
|
let preprocessor_param = PreprocessorParam::new(poseidon_config, F_circuit);
|
||||||
let nova_params = N::preprocess(&mut rng, &prep_param).unwrap();
|
let nova_params = N::preprocess(&mut rng, &preprocessor_param).unwrap();
|
||||||
|
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let mut nova = N::init(&nova_params, F_circuit, z_0.clone()).unwrap();
|
let mut nova = N::init(&nova_params, F_circuit, z_0.clone()).unwrap();
|
||||||
println!("Nova initialized, {:?}", start.elapsed());
|
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();
|
let start = Instant::now();
|
||||||
nova.prove_step(&mut rng, vec![], None).unwrap();
|
nova.prove_step(&mut rng, vec![], None).unwrap();
|
||||||
println!("prove_step, {:?}", start.elapsed());
|
println!("prove_step, {:?}", start.elapsed());
|
||||||
nova.prove_step(&mut rng, vec![], None).unwrap(); // do a 2nd step
|
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
|
// decider proof generation
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let proof = D::prove(rng, decider_pp, nova.clone()).unwrap();
|
let proof = D::prove(rng, decider_pp, nova.clone()).unwrap();
|
||||||
@@ -385,10 +399,194 @@ pub mod tests {
|
|||||||
// decider proof verification
|
// decider proof verification
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let verified = D::verify(
|
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();
|
.unwrap();
|
||||||
assert!(verified);
|
assert!(verified);
|
||||||
println!("Decider verify, {:?}", start.elapsed());
|
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_ff::{BigInteger, PrimeField};
|
||||||
use ark_r1cs_std::{groups::GroupOpsBounds, prelude::CurveVar, ToConstraintFieldGadget};
|
use ark_r1cs_std::{groups::GroupOpsBounds, prelude::CurveVar, ToConstraintFieldGadget};
|
||||||
use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystem};
|
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::fmt::Debug;
|
||||||
use ark_std::rand::RngCore;
|
use ark_std::rand::RngCore;
|
||||||
use ark_std::{One, UniformRand, Zero};
|
use ark_std::{One, UniformRand, Zero};
|
||||||
@@ -21,7 +21,7 @@ use crate::folding::circuits::cyclefold::{
|
|||||||
};
|
};
|
||||||
use crate::folding::circuits::CF2;
|
use crate::folding::circuits::CF2;
|
||||||
use crate::frontend::FCircuit;
|
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::utils::vec::is_zero_vec;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
use crate::FoldingScheme;
|
use crate::FoldingScheme;
|
||||||
@@ -190,7 +190,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[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
|
where
|
||||||
C1: CurveGroup,
|
C1: CurveGroup,
|
||||||
C2: CurveGroup,
|
C2: CurveGroup,
|
||||||
@@ -228,7 +228,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[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
|
where
|
||||||
C1: CurveGroup,
|
C1: CurveGroup,
|
||||||
C2: CurveGroup,
|
C2: CurveGroup,
|
||||||
@@ -240,8 +240,70 @@ where
|
|||||||
pub cf_cs_pp: CS2::ProverParams,
|
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)]
|
#[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
|
where
|
||||||
C1: CurveGroup,
|
C1: CurveGroup,
|
||||||
C2: CurveGroup,
|
C2: CurveGroup,
|
||||||
@@ -255,6 +317,79 @@ where
|
|||||||
pub cf_cs_vp: CS2::VerifierParams,
|
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>
|
impl<C1, C2, CS1, CS2, const H: bool> VerifierParams<C1, C2, CS1, CS2, H>
|
||||||
where
|
where
|
||||||
C1: CurveGroup,
|
C1: CurveGroup,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use ark_ff::PrimeField;
|
|||||||
use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar, R1CSVar};
|
use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar, R1CSVar};
|
||||||
use ark_relations::r1cs::ConstraintSynthesizer;
|
use ark_relations::r1cs::ConstraintSynthesizer;
|
||||||
use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError};
|
use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError};
|
||||||
use arkworks_backend::{
|
use noir_arkworks_backend::{
|
||||||
read_program_from_binary, read_program_from_file, sonobe_bridge::AcirCircuitSonobe,
|
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> {
|
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 {
|
pub fn rand<R: Rng>(rng: &mut R, n_rows: usize, n_cols: usize) -> Self {
|
||||||
const ZERO_VAL_PROBABILITY: f64 = 0.8f64;
|
const ZERO_VAL_PROBABILITY: f64 = 0.8f64;
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,14 @@
|
|||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![allow(clippy::upper_case_acronyms)]
|
#![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_groth16::VerifyingKey as ArkG16VerifierKey;
|
||||||
use ark_poly_commit::kzg10::VerifierKey as ArkKZG10VerifierKey;
|
use ark_poly_commit::kzg10::VerifierKey as ArkKZG10VerifierKey;
|
||||||
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
|
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
|
|
||||||
use folding_schemes::folding::circuits::nonnative::uint::NonNativeUintVar;
|
use folding_schemes::folding::circuits::nonnative::uint::NonNativeUintVar;
|
||||||
|
use folding_schemes::folding::nova::decider_eth::VerifierParam as DeciderVerifierParam;
|
||||||
|
|
||||||
use super::g16::Groth16Verifier;
|
use super::g16::Groth16Verifier;
|
||||||
use super::kzg::KZG10Verifier;
|
use super::kzg::KZG10Verifier;
|
||||||
@@ -92,22 +93,26 @@ impl From<(Fr, Groth16VerifierKey, KZG10VerifierKey, usize)> for NovaCycleFoldVe
|
|||||||
// in the NovaCycleFoldDecider verifier contract
|
// in the NovaCycleFoldDecider verifier contract
|
||||||
impl
|
impl
|
||||||
From<(
|
From<(
|
||||||
(Fr, ArkG16VerifierKey<Bn254>, ArkKZG10VerifierKey<Bn254>),
|
DeciderVerifierParam<G1Projective, ArkKZG10VerifierKey<Bn254>, ArkG16VerifierKey<Bn254>>,
|
||||||
usize,
|
usize,
|
||||||
)> for NovaCycleFoldVerifierKey
|
)> for NovaCycleFoldVerifierKey
|
||||||
{
|
{
|
||||||
fn from(
|
fn from(
|
||||||
value: (
|
value: (
|
||||||
(Fr, ArkG16VerifierKey<Bn254>, ArkKZG10VerifierKey<Bn254>),
|
DeciderVerifierParam<
|
||||||
|
G1Projective,
|
||||||
|
ArkKZG10VerifierKey<Bn254>,
|
||||||
|
ArkG16VerifierKey<Bn254>,
|
||||||
|
>,
|
||||||
usize,
|
usize,
|
||||||
),
|
),
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let decider_vp = value.0;
|
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
|
// 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 {
|
Self {
|
||||||
pp_hash: decider_vp.0,
|
pp_hash: decider_vp.pp_hash,
|
||||||
g16_vk,
|
g16_vk,
|
||||||
kzg_vk,
|
kzg_vk,
|
||||||
z_len: value.1,
|
z_len: value.1,
|
||||||
@@ -157,7 +162,7 @@ mod tests {
|
|||||||
Decider, Error, FoldingScheme,
|
Decider, Error, FoldingScheme,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::NovaCycleFoldDecider;
|
use super::{DeciderVerifierParam, NovaCycleFoldDecider};
|
||||||
use crate::verifiers::tests::{setup, DEFAULT_SETUP_LEN};
|
use crate::verifiers::tests::{setup, DEFAULT_SETUP_LEN};
|
||||||
use crate::{
|
use crate::{
|
||||||
evm::{compile_solidity, save_solidity, Evm},
|
evm::{compile_solidity, save_solidity, Evm},
|
||||||
@@ -286,9 +291,14 @@ mod tests {
|
|||||||
fn nova_cyclefold_vk_serde_roundtrip() {
|
fn nova_cyclefold_vk_serde_roundtrip() {
|
||||||
let (pp_hash, _, kzg_vk, _, g16_vk, _) = setup(DEFAULT_SETUP_LEN);
|
let (pp_hash, _, kzg_vk, _, g16_vk, _) = setup(DEFAULT_SETUP_LEN);
|
||||||
|
|
||||||
let mut bytes = vec![];
|
let decider_vp = DeciderVerifierParam {
|
||||||
let nova_cyclefold_vk = NovaCycleFoldVerifierKey::from(((pp_hash, g16_vk, kzg_vk), 1));
|
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
|
nova_cyclefold_vk
|
||||||
.serialize_protocol_verifier_key(&mut bytes)
|
.serialize_protocol_verifier_key(&mut bytes)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -301,7 +311,12 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn nova_cyclefold_decider_template_renders() {
|
fn nova_cyclefold_decider_template_renders() {
|
||||||
let (pp_hash, _, kzg_vk, _, g16_vk, _) = setup(DEFAULT_SETUP_LEN);
|
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()
|
let decider_solidity_code = HeaderInclusion::<NovaCycleFoldDecider>::builder()
|
||||||
.template(nova_cyclefold_vk)
|
.template(nova_cyclefold_vk)
|
||||||
|
|||||||
Reference in New Issue
Block a user