mirror of
https://github.com/arnaucube/Nova.git
synced 2026-01-10 16:11:29 +01:00
Add serde proof serialization (#123)
* Bump commit. * Bump commit. * (WIP) Add serde support * Minor fixes * Use neptune const generics * Use git patches * Impl serde for CompressedSNARK * Update dependencies, revert to typenum * Formatting * Update bellperson-nonnative patch * Cleanup * Remove bellperson-nonnative fork * Switch back to fil_pasta_curves * Update forked dependencies * Cleanup * Remove unnecessary patch * Update to lurk-pasta-msm --------- Co-authored-by: porcuquine <porcuquine@users.noreply.github.com>
This commit is contained in:
@@ -21,7 +21,7 @@ rand_core = { version = "0.5", default-features = false }
|
||||
rand_chacha = "0.3"
|
||||
itertools = "0.9.0"
|
||||
subtle = "2.4"
|
||||
pasta_curves = { version = "0.4.0", features = ["repr-c"] }
|
||||
pasta_curves = { version = "0.5.2", features = ["repr-c", "serde"], package = "fil_pasta_curves" }
|
||||
neptune = { version = "8.1.0", default-features = false }
|
||||
generic-array = "0.14.4"
|
||||
num-bigint = { version = "0.4", features = ["serde", "rand"] }
|
||||
@@ -34,7 +34,7 @@ bitvec = "1.0"
|
||||
byteorder = "1.4.3"
|
||||
|
||||
[target.'cfg(any(target_arch = "x86_64", target_arch = "aarch64"))'.dependencies]
|
||||
pasta-msm = "0.1.3"
|
||||
pasta-msm = { version = "0.1.0", package = "lurk-pasta-msm" }
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.3.1"
|
||||
|
||||
@@ -28,8 +28,9 @@ use bellperson::{
|
||||
Circuit, ConstraintSystem, SynthesisError,
|
||||
};
|
||||
use ff::Field;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct NovaAugmentedCircuitParams {
|
||||
limb_width: usize,
|
||||
n_limbs: usize,
|
||||
@@ -46,7 +47,8 @@ impl NovaAugmentedCircuitParams {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(bound = "")]
|
||||
pub struct NovaAugmentedCircuitInputs<G: Group> {
|
||||
params: G::Scalar, // Hash(Shape of u2, Gens for u2). Needed for computing the challenge.
|
||||
i: G::Base,
|
||||
|
||||
@@ -10,19 +10,22 @@ use core::{
|
||||
use ff::Field;
|
||||
use merlin::Transcript;
|
||||
use rayon::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct CommitGens<G: Group> {
|
||||
gens: Vec<G::PreprocessedGroupElement>,
|
||||
_p: PhantomData<G>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(bound = "")]
|
||||
pub struct Commitment<G: Group> {
|
||||
pub(crate) comm: G,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(bound = "")]
|
||||
pub struct CompressedCommitment<C: CompressedGroup> {
|
||||
comm: C,
|
||||
}
|
||||
|
||||
@@ -35,12 +35,15 @@ use nifs::NIFS;
|
||||
use r1cs::{
|
||||
R1CSGens, R1CSInstance, R1CSShape, R1CSWitness, RelaxedR1CSInstance, RelaxedR1CSWitness,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use traits::{
|
||||
circuit::StepCircuit, snark::RelaxedR1CSSNARKTrait, AbsorbInROTrait, Group, ROConstants,
|
||||
ROConstantsCircuit, ROConstantsTrait, ROTrait,
|
||||
};
|
||||
|
||||
/// A type that holds public parameters of Nova
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(bound = "")]
|
||||
pub struct PublicParams<G1, G2, C1, C2>
|
||||
where
|
||||
G1: Group<Base = <G2 as Group>::Scalar>,
|
||||
@@ -152,7 +155,8 @@ where
|
||||
}
|
||||
|
||||
/// A SNARK that proves the correct execution of an incremental computation
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(bound = "")]
|
||||
pub struct RecursiveSNARK<G1, G2, C1, C2>
|
||||
where
|
||||
G1: Group<Base = <G2 as Group>::Scalar>,
|
||||
@@ -497,7 +501,8 @@ where
|
||||
}
|
||||
|
||||
/// A SNARK that proves the knowledge of a valid `RecursiveSNARK`
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(bound = "")]
|
||||
pub struct CompressedSNARK<G1, G2, C1, C2, S1, S2>
|
||||
where
|
||||
G1: Group<Base = <G2 as Group>::Scalar>,
|
||||
|
||||
@@ -10,10 +10,11 @@ use super::{
|
||||
traits::{AbsorbInROTrait, Group, ROTrait},
|
||||
};
|
||||
use core::marker::PhantomData;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A SNARK that holds the proof of a step of an incremental computation
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct NIFS<G: Group> {
|
||||
pub(crate) comm_T: CompressedCommitment<G::CompressedGroupElement>,
|
||||
_p: PhantomData<G>,
|
||||
|
||||
@@ -15,6 +15,7 @@ use pasta_curves::{
|
||||
pallas, vesta, Ep, Eq,
|
||||
};
|
||||
use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha3::Shake256;
|
||||
use std::io::Read;
|
||||
|
||||
@@ -151,7 +152,7 @@ fn cpu_best_multiexp<C: CurveAffine>(coeffs: &[C::Scalar], bases: &[C]) -> C::Cu
|
||||
//////////////////////////////////////Pallas///////////////////////////////////////////////
|
||||
|
||||
/// A wrapper for compressed group elements that come from the pallas curve
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub struct PallasCompressedElementWrapper {
|
||||
repr: [u8; 32],
|
||||
}
|
||||
@@ -266,7 +267,7 @@ impl CompressedGroup for PallasCompressedElementWrapper {
|
||||
//////////////////////////////////////Vesta////////////////////////////////////////////////
|
||||
|
||||
/// A wrapper for compressed group elements that come from the vesta curve
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub struct VestaCompressedElementWrapper {
|
||||
repr: [u8; 32],
|
||||
}
|
||||
|
||||
@@ -20,9 +20,10 @@ use neptune::{
|
||||
},
|
||||
Strength,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// All Poseidon Constants that are used in Nova
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct PoseidonConstantsCircuit<Scalar: PrimeField>(PoseidonConstants<Scalar, U24>);
|
||||
|
||||
impl<Scalar> ROConstantsTrait<Scalar> for PoseidonConstantsCircuit<Scalar>
|
||||
@@ -37,6 +38,7 @@ where
|
||||
}
|
||||
|
||||
/// A Poseidon-based RO to use outside circuits
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct PoseidonRO<Base, Scalar>
|
||||
where
|
||||
Base: PrimeField + PrimeFieldBits,
|
||||
@@ -52,7 +54,7 @@ where
|
||||
|
||||
impl<Base, Scalar> ROTrait<Base, Scalar> for PoseidonRO<Base, Scalar>
|
||||
where
|
||||
Base: PrimeField + PrimeFieldBits,
|
||||
Base: PrimeField + PrimeFieldBits + Serialize + for<'de> Deserialize<'de>,
|
||||
Scalar: PrimeField + PrimeFieldBits,
|
||||
{
|
||||
type Constants = PoseidonConstantsCircuit<Base>;
|
||||
@@ -107,6 +109,7 @@ where
|
||||
}
|
||||
|
||||
/// A Poseidon-based RO gadget to use inside the verifier circuit.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct PoseidonROCircuit<Scalar>
|
||||
where
|
||||
Scalar: PrimeField + PrimeFieldBits,
|
||||
@@ -120,7 +123,7 @@ where
|
||||
|
||||
impl<Scalar> ROCircuitTrait<Scalar> for PoseidonROCircuit<Scalar>
|
||||
where
|
||||
Scalar: PrimeField + PrimeFieldBits,
|
||||
Scalar: PrimeField + PrimeFieldBits + Serialize + for<'de> Deserialize<'de>,
|
||||
{
|
||||
type Constants = PoseidonConstantsCircuit<Scalar>;
|
||||
|
||||
|
||||
15
src/r1cs.rs
15
src/r1cs.rs
@@ -18,13 +18,14 @@ use serde::{Deserialize, Serialize};
|
||||
use sha3::{Digest, Sha3_256};
|
||||
|
||||
/// Public parameters for a given R1CS
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[serde(bound = "")]
|
||||
pub struct R1CSGens<G: Group> {
|
||||
pub(crate) gens: CommitGens<G>,
|
||||
}
|
||||
|
||||
/// A type that holds the shape of the R1CS matrices
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct R1CSShape<G: Group> {
|
||||
pub(crate) num_cons: usize,
|
||||
pub(crate) num_vars: usize,
|
||||
@@ -36,27 +37,29 @@ pub struct R1CSShape<G: Group> {
|
||||
}
|
||||
|
||||
/// A type that holds a witness for a given R1CS instance
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct R1CSWitness<G: Group> {
|
||||
W: Vec<G::Scalar>,
|
||||
}
|
||||
|
||||
/// A type that holds an R1CS instance
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(bound = "")]
|
||||
pub struct R1CSInstance<G: Group> {
|
||||
pub(crate) comm_W: Commitment<G>,
|
||||
pub(crate) X: Vec<G::Scalar>,
|
||||
}
|
||||
|
||||
/// A type that holds a witness for a given Relaxed R1CS instance
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct RelaxedR1CSWitness<G: Group> {
|
||||
pub(crate) W: Vec<G::Scalar>,
|
||||
pub(crate) E: Vec<G::Scalar>,
|
||||
}
|
||||
|
||||
/// A type that holds a Relaxed R1CS instance
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(bound = "")]
|
||||
pub struct RelaxedR1CSInstance<G: Group> {
|
||||
pub(crate) comm_W: Commitment<G>,
|
||||
pub(crate) comm_E: Commitment<G>,
|
||||
|
||||
@@ -6,6 +6,7 @@ use core::{cmp::max, iter};
|
||||
use ff::Field;
|
||||
use merlin::Transcript;
|
||||
use rayon::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub fn inner_product<T>(a: &[T], b: &[T]) -> T
|
||||
@@ -66,6 +67,7 @@ impl<G: Group> InnerProductWitness<G> {
|
||||
}
|
||||
|
||||
/// A non-interactive folding scheme (NIFS) for inner product relations
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct NIFSForInnerProduct<G: Group> {
|
||||
cross_term: G::Scalar,
|
||||
}
|
||||
@@ -181,7 +183,7 @@ impl<G: Group> NIFSForInnerProduct<G> {
|
||||
}
|
||||
|
||||
/// An inner product argument
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct InnerProductArgument<G: Group> {
|
||||
L_vec: Vec<CompressedCommitment<G::CompressedGroupElement>>,
|
||||
R_vec: Vec<CompressedCommitment<G::CompressedGroupElement>>,
|
||||
|
||||
@@ -20,9 +20,12 @@ use itertools::concat;
|
||||
use merlin::Transcript;
|
||||
use polynomial::{EqPolynomial, MultilinearPolynomial, SparsePolynomial};
|
||||
use rayon::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sumcheck::SumcheckProof;
|
||||
|
||||
/// A type that represents the prover's key
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(bound = "")]
|
||||
pub struct ProverKey<G: Group> {
|
||||
gens_r1cs: R1CSGens<G>,
|
||||
gens_ipa: CommitGens<G>,
|
||||
@@ -40,6 +43,8 @@ impl<G: Group> ProverKeyTrait<G> for ProverKey<G> {
|
||||
}
|
||||
|
||||
/// A type that represents the verifier's key
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(bound = "")]
|
||||
pub struct VerifierKey<G: Group> {
|
||||
gens_r1cs: R1CSGens<G>,
|
||||
gens_ipa: CommitGens<G>,
|
||||
@@ -59,6 +64,8 @@ impl<G: Group> VerifierKeyTrait<G> for VerifierKey<G> {
|
||||
/// A succinct proof of knowledge of a witness to a relaxed R1CS instance
|
||||
/// The proof is produced using Spartan's combination of the sum-check and
|
||||
/// the commitment to a vector viewed as a polynomial commitment
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(bound = "")]
|
||||
pub struct RelaxedR1CSSNARK<G: Group> {
|
||||
sc_proof_outer: SumcheckProof<G>,
|
||||
claims_outer: (G::Scalar, G::Scalar, G::Scalar),
|
||||
|
||||
@@ -7,8 +7,10 @@ use core::marker::PhantomData;
|
||||
use ff::Field;
|
||||
use merlin::Transcript;
|
||||
use rayon::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(bound = "")]
|
||||
pub struct SumcheckProof<G: Group> {
|
||||
compressed_polys: Vec<CompressedUniPoly<G>>,
|
||||
}
|
||||
@@ -226,7 +228,7 @@ pub struct UniPoly<G: Group> {
|
||||
|
||||
// ax^2 + bx + c stored as vec![a,c]
|
||||
// ax^3 + bx^2 + cx + d stored as vec![a,c,d]
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CompressedUniPoly<G: Group> {
|
||||
coeffs_except_linear_term: Vec<G::Scalar>,
|
||||
_p: PhantomData<G>,
|
||||
|
||||
@@ -10,6 +10,7 @@ use core::{
|
||||
use ff::{PrimeField, PrimeFieldBits};
|
||||
use merlin::Transcript;
|
||||
use num_bigint::BigInt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Represents an element of a group
|
||||
/// This is currently tailored for an elliptic curve group
|
||||
@@ -25,25 +26,35 @@ pub trait Group:
|
||||
+ ScalarMulOwned<<Self as Group>::Scalar>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ Serialize
|
||||
+ for<'de> Deserialize<'de>
|
||||
{
|
||||
/// A type representing an element of the base field of the group
|
||||
type Base: PrimeField + PrimeFieldBits;
|
||||
type Base: PrimeField + PrimeFieldBits + Serialize + for<'de> Deserialize<'de>;
|
||||
|
||||
/// A type representing an element of the scalar field of the group
|
||||
type Scalar: PrimeField + PrimeFieldBits + ChallengeTrait + Send + Sync;
|
||||
type Scalar: PrimeField
|
||||
+ PrimeFieldBits
|
||||
+ ChallengeTrait
|
||||
+ Send
|
||||
+ Sync
|
||||
+ Serialize
|
||||
+ for<'de> Deserialize<'de>;
|
||||
|
||||
/// A type representing the compressed version of the group element
|
||||
type CompressedGroupElement: CompressedGroup<GroupElement = Self>;
|
||||
type CompressedGroupElement: CompressedGroup<GroupElement = Self>
|
||||
+ Serialize
|
||||
+ for<'de> Deserialize<'de>;
|
||||
|
||||
/// A type representing preprocessed group element
|
||||
type PreprocessedGroupElement: Clone + Send + Sync;
|
||||
type PreprocessedGroupElement: Clone + Send + Sync + Serialize + for<'de> Deserialize<'de>;
|
||||
|
||||
/// A type that represents a hash function that consumes elements
|
||||
/// from the base field and squeezes out elements of the scalar field
|
||||
type RO: ROTrait<Self::Base, Self::Scalar>;
|
||||
type RO: ROTrait<Self::Base, Self::Scalar> + Serialize + for<'de> Deserialize<'de>;
|
||||
|
||||
/// An alternate implementation of Self::RO in the circuit model
|
||||
type ROCircuit: ROCircuitTrait<Self::Base>;
|
||||
type ROCircuit: ROCircuitTrait<Self::Base> + Serialize + for<'de> Deserialize<'de>;
|
||||
|
||||
/// A method to compute a multiexponentation
|
||||
fn vartime_multiscalar_mul(
|
||||
@@ -74,9 +85,11 @@ pub trait Group:
|
||||
}
|
||||
|
||||
/// Represents a compressed version of a group element
|
||||
pub trait CompressedGroup: Clone + Copy + Debug + Eq + Sized + Send + Sync + 'static {
|
||||
pub trait CompressedGroup:
|
||||
Clone + Copy + Debug + Eq + Sized + Send + Sync + Serialize + for<'de> Deserialize<'de> + 'static
|
||||
{
|
||||
/// A type that holds the decompressed version of the compressed group element
|
||||
type GroupElement: Group;
|
||||
type GroupElement: Group + Serialize + for<'de> Deserialize<'de>;
|
||||
|
||||
/// Decompresses the compressed group element
|
||||
fn decompress(&self) -> Option<Self::GroupElement>;
|
||||
@@ -106,7 +119,12 @@ pub trait ChallengeTrait {
|
||||
/// A helper trait that defines the behavior of a hash function that we use as an RO
|
||||
pub trait ROTrait<Base, Scalar> {
|
||||
/// A type representing constants/parameters associated with the hash function
|
||||
type Constants: ROConstantsTrait<Base> + Clone + Send + Sync;
|
||||
type Constants: ROConstantsTrait<Base>
|
||||
+ Clone
|
||||
+ Send
|
||||
+ Sync
|
||||
+ Serialize
|
||||
+ for<'de> Deserialize<'de>;
|
||||
|
||||
/// Initializes the hash function
|
||||
fn new(constants: Self::Constants, num_absorbs: usize) -> Self;
|
||||
@@ -121,7 +139,12 @@ pub trait ROTrait<Base, Scalar> {
|
||||
/// A helper trait that defines the behavior of a hash function that we use as an RO in the circuit model
|
||||
pub trait ROCircuitTrait<Base: PrimeField> {
|
||||
/// A type representing constants/parameters associated with the hash function
|
||||
type Constants: ROConstantsTrait<Base> + Clone + Send + Sync;
|
||||
type Constants: ROConstantsTrait<Base>
|
||||
+ Clone
|
||||
+ Send
|
||||
+ Sync
|
||||
+ Serialize
|
||||
+ for<'de> Deserialize<'de>;
|
||||
|
||||
/// Initializes the hash function
|
||||
fn new(constants: Self::Constants, num_absorbs: usize) -> Self;
|
||||
|
||||
@@ -5,6 +5,8 @@ use crate::{
|
||||
traits::Group,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A trait that defines the behavior of a zkSNARK's prover key
|
||||
pub trait ProverKeyTrait<G: Group>: Send + Sync {
|
||||
/// Produces a new prover's key
|
||||
@@ -18,12 +20,14 @@ pub trait VerifierKeyTrait<G: Group>: Send + Sync {
|
||||
}
|
||||
|
||||
/// A trait that defines the behavior of a zkSNARK
|
||||
pub trait RelaxedR1CSSNARKTrait<G: Group>: Sized + Send + Sync {
|
||||
pub trait RelaxedR1CSSNARKTrait<G: Group>:
|
||||
Sized + Send + Sync + Serialize + for<'de> Deserialize<'de>
|
||||
{
|
||||
/// A type that represents the prover's key
|
||||
type ProverKey: ProverKeyTrait<G>;
|
||||
type ProverKey: ProverKeyTrait<G> + Serialize + for<'de> Deserialize<'de>;
|
||||
|
||||
/// A type that represents the verifier's key
|
||||
type VerifierKey: VerifierKeyTrait<G>;
|
||||
type VerifierKey: VerifierKeyTrait<G> + Serialize + for<'de> Deserialize<'de>;
|
||||
|
||||
/// Produces a prover key
|
||||
fn prover_key(gens: &R1CSGens<G>, S: &R1CSShape<G>) -> Self::ProverKey {
|
||||
|
||||
Reference in New Issue
Block a user