arnaucube
arnaucube/NovaPublic Self-hosted repository
reorganize traits into a module; cut boilerplate code (#91)

use a default implementation for step circuit
Srinath Setty srinath@microsoft.com
Thu, 14 Jul 2022 16:15:45 -0700
commit

35cb03f977fd9ebe4d90de9ab74ab04765443cfa

parent

704d48b5281c74c7a2aaa29038b6c618f9934192

M benches/compressed-snark.rs → benches/compressed-snark.rs

@@ -1,45 +1,18 @@

#![allow(non_snake_case)] +use criterion::*; use nova_snark::{ - traits::{Group, StepCircuit}, + traits::{circuit::TrivialTestCircuit, Group}, CompressedSNARK, PublicParams, RecursiveSNARK, }; +use std::time::Duration; type G1 = pasta_curves::pallas::Point; type G2 = pasta_curves::vesta::Point; type S1 = nova_snark::spartan_with_ipa_pc::RelaxedR1CSSNARK<G1>; type S2 = nova_snark::spartan_with_ipa_pc::RelaxedR1CSSNARK<G2>; - -#[derive(Clone, Debug)] -struct TrivialTestCircuit<F: PrimeField> { - _p: PhantomData<F>, -} - -impl<F> StepCircuit<F> for TrivialTestCircuit<F> -where - F: PrimeField, -{ - fn synthesize<CS: ConstraintSystem<F>>( - &self, - _cs: &mut CS, - z: AllocatedNum<F>, - ) -> Result<AllocatedNum<F>, SynthesisError> { - Ok(z) - } - - fn compute(&self, z: &F) -> F { - *z - } -} - type C1 = TrivialTestCircuit<<G1 as Group>::Scalar>; type C2 = TrivialTestCircuit<<G2 as Group>::Scalar>; - -use bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError}; -use core::marker::PhantomData; -use criterion::*; -use ff::PrimeField; -use std::time::Duration; fn compressed_snark_benchmark(c: &mut Criterion) { let num_samples = 10;

@@ -64,12 +37,8 @@ group.sample_size(num_samples);

// Produce public parameters let pp = PublicParams::<G1, G2, C1, C2>::setup( - TrivialTestCircuit { - _p: Default::default(), - }, - TrivialTestCircuit { - _p: Default::default(), - }, + TrivialTestCircuit::default(), + TrivialTestCircuit::default(), ); // produce a recursive SNARK

@@ -80,12 +49,8 @@ for i in 0..num_steps {

let res = RecursiveSNARK::prove_step( &pp, recursive_snark, - TrivialTestCircuit { - _p: Default::default(), - }, - TrivialTestCircuit { - _p: Default::default(), - }, + TrivialTestCircuit::default(), + TrivialTestCircuit::default(), <G1 as Group>::Scalar::one(), <G2 as Group>::Scalar::zero(), );
M benches/recursive-snark.rs → benches/recursive-snark.rs

@@ -1,44 +1,17 @@

#![allow(non_snake_case)] +use criterion::*; use nova_snark::{ - traits::{Group, StepCircuit}, + traits::{circuit::TrivialTestCircuit, Group}, PublicParams, RecursiveSNARK, }; +use std::time::Duration; type G1 = pasta_curves::pallas::Point; type G2 = pasta_curves::vesta::Point; - -#[derive(Clone, Debug)] -struct TrivialTestCircuit<F: PrimeField> { - _p: PhantomData<F>, -} - -impl<F> StepCircuit<F> for TrivialTestCircuit<F> -where - F: PrimeField, -{ - fn synthesize<CS: ConstraintSystem<F>>( - &self, - _cs: &mut CS, - z: AllocatedNum<F>, - ) -> Result<AllocatedNum<F>, SynthesisError> { - Ok(z) - } - - fn compute(&self, z: &F) -> F { - *z - } -} - type C1 = TrivialTestCircuit<<G1 as Group>::Scalar>; type C2 = TrivialTestCircuit<<G2 as Group>::Scalar>; -use bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError}; -use core::marker::PhantomData; -use criterion::*; -use ff::PrimeField; -use std::time::Duration; - fn recursive_snark_benchmark(c: &mut Criterion) { let num_samples = 10; bench_recursive_snark(c, num_samples);

@@ -62,12 +35,8 @@ group.sample_size(num_samples);

// Produce public parameters let pp = PublicParams::<G1, G2, C1, C2>::setup( - TrivialTestCircuit { - _p: Default::default(), - }, - TrivialTestCircuit { - _p: Default::default(), - }, + TrivialTestCircuit::default(), + TrivialTestCircuit::default(), ); // Bench time to produce a recursive SNARK;

@@ -81,12 +50,8 @@ for i in 0..num_warmup_steps {

let res = RecursiveSNARK::prove_step( &pp, recursive_snark, - TrivialTestCircuit { - _p: Default::default(), - }, - TrivialTestCircuit { - _p: Default::default(), - }, + TrivialTestCircuit::default(), + TrivialTestCircuit::default(), <G1 as Group>::Scalar::one(), <G2 as Group>::Scalar::zero(), );

@@ -112,12 +77,8 @@ // produce a recursive SNARK for a step of the recursion

assert!(RecursiveSNARK::prove_step( black_box(&pp), black_box(recursive_snark.clone()), - black_box(TrivialTestCircuit { - _p: Default::default(), - }), - black_box(TrivialTestCircuit { - _p: Default::default(), - }), + black_box(TrivialTestCircuit::default()), + black_box(TrivialTestCircuit::default()), black_box(<G1 as Group>::Scalar::zero()), black_box(<G2 as Group>::Scalar::zero()), )
M examples/minroot.rs → examples/minroot.rs

@@ -12,11 +12,13 @@ poseidon::{Poseidon, PoseidonConstants},

Strength, }; use nova_snark::{ - traits::{Group, StepCircuit}, + traits::{ + circuit::{StepCircuit, TrivialTestCircuit}, + Group, + }, CompressedSNARK, PublicParams, RecursiveSNARK, }; use num_bigint::BigUint; -use std::marker::PhantomData; use std::time::Instant; #[derive(Clone, Debug)]

@@ -183,9 +185,7 @@ ],

pc: pc.clone(), }; - let circuit_secondary = TrivialTestCircuit { - _p: Default::default(), - }; + let circuit_secondary = TrivialTestCircuit::default(); println!("Nova-based VDF with MinRoot delay function"); println!("==========================================");

@@ -299,26 +299,3 @@ start.elapsed()

); assert!(res.is_ok()); } - -// A trivial test circuit that we use on the secondary curve -#[derive(Clone, Debug)] -struct TrivialTestCircuit<F: PrimeField> { - _p: PhantomData<F>, -} - -impl<F> StepCircuit<F> for TrivialTestCircuit<F> -where - F: PrimeField, -{ - fn synthesize<CS: ConstraintSystem<F>>( - &self, - _cs: &mut CS, - z: AllocatedNum<F>, - ) -> Result<AllocatedNum<F>, SynthesisError> { - Ok(z) - } - - fn compute(&self, z: &F) -> F { - *z - } -}
M src/circuit.rs → src/circuit.rs

@@ -16,7 +16,7 @@ alloc_num_equals, alloc_scalar_as_base, alloc_zero, conditionally_select, le_bits_to_num,

}, }, r1cs::{R1CSInstance, RelaxedR1CSInstance}, - traits::{Group, HashFuncCircuitTrait, HashFuncConstantsCircuit, StepCircuit}, + traits::{circuit::StepCircuit, Group, HashFuncCircuitTrait, HashFuncConstantsCircuit}, }; use bellperson::{ gadgets::{

@@ -355,32 +355,8 @@ use crate::constants::{BN_LIMB_WIDTH, BN_N_LIMBS};

use crate::{ bellperson::r1cs::{NovaShape, NovaWitness}, poseidon::PoseidonConstantsCircuit, - traits::HashFuncConstantsTrait, + traits::{circuit::TrivialTestCircuit, HashFuncConstantsTrait}, }; - use ff::PrimeField; - use std::marker::PhantomData; - - #[derive(Clone)] - struct TestCircuit<F: PrimeField> { - _p: PhantomData<F>, - } - - impl<F> StepCircuit<F> for TestCircuit<F> - where - F: PrimeField, - { - fn synthesize<CS: ConstraintSystem<F>>( - &self, - _cs: &mut CS, - z: AllocatedNum<F>, - ) -> Result<AllocatedNum<F>, SynthesisError> { - Ok(z) - } - - fn compute(&self, z: &F) -> F { - *z - } - } #[test] fn test_verification_circuit() {

@@ -391,13 +367,11 @@ let ro_consts1: HashFuncConstantsCircuit<G2> = PoseidonConstantsCircuit::new();

let ro_consts2: HashFuncConstantsCircuit<G1> = PoseidonConstantsCircuit::new(); // Initialize the shape and gens for the primary - let circuit1: NIFSVerifierCircuit<G2, TestCircuit<<G2 as Group>::Base>> = + let circuit1: NIFSVerifierCircuit<G2, TrivialTestCircuit<<G2 as Group>::Base>> = NIFSVerifierCircuit::new( params1.clone(), None, - TestCircuit { - _p: Default::default(), - }, + TrivialTestCircuit::default(), ro_consts1.clone(), ); let mut cs: ShapeCS<G1> = ShapeCS::new();

@@ -406,13 +380,11 @@ let (shape1, gens1) = (cs.r1cs_shape(), cs.r1cs_gens());

assert_eq!(cs.num_constraints(), 20584); // Initialize the shape and gens for the secondary - let circuit2: NIFSVerifierCircuit<G1, TestCircuit<<G1 as Group>::Base>> = + let circuit2: NIFSVerifierCircuit<G1, TrivialTestCircuit<<G1 as Group>::Base>> = NIFSVerifierCircuit::new( params2.clone(), None, - TestCircuit { - _p: Default::default(), - }, + TrivialTestCircuit::default(), ro_consts2.clone(), ); let mut cs: ShapeCS<G2> = ShapeCS::new();

@@ -425,13 +397,11 @@ let zero1 = <<G2 as Group>::Base as Field>::zero();

let mut cs1: SatisfyingAssignment<G1> = SatisfyingAssignment::new(); let inputs1: NIFSVerifierCircuitInputs<G2> = NIFSVerifierCircuitInputs::new(shape2.get_digest(), zero1, zero1, None, None, None, None); - let circuit1: NIFSVerifierCircuit<G2, TestCircuit<<G2 as Group>::Base>> = + let circuit1: NIFSVerifierCircuit<G2, TrivialTestCircuit<<G2 as Group>::Base>> = NIFSVerifierCircuit::new( params1, Some(inputs1), - TestCircuit { - _p: Default::default(), - }, + TrivialTestCircuit::default(), ro_consts1, ); let _ = circuit1.synthesize(&mut cs1);

@@ -451,13 +421,11 @@ None,

Some(inst1), None, ); - let circuit: NIFSVerifierCircuit<G1, TestCircuit<<G1 as Group>::Base>> = + let circuit: NIFSVerifierCircuit<G1, TrivialTestCircuit<<G1 as Group>::Base>> = NIFSVerifierCircuit::new( params2, Some(inputs2), - TestCircuit { - _p: Default::default(), - }, + TrivialTestCircuit::default(), ro_consts2, ); let _ = circuit.synthesize(&mut cs2);
M src/lib.rs → src/lib.rs

@@ -16,7 +16,6 @@ // public modules

pub mod errors; pub mod gadgets; pub mod pasta; -pub mod snark; pub mod spartan_with_ipa_pc; pub mod traits;

@@ -36,10 +35,9 @@ use nifs::NIFS;

use r1cs::{ R1CSGens, R1CSInstance, R1CSShape, R1CSWitness, RelaxedR1CSInstance, RelaxedR1CSWitness, }; -use snark::RelaxedR1CSSNARKTrait; use traits::{ - AbsorbInROTrait, Group, HashFuncConstants, HashFuncConstantsCircuit, HashFuncConstantsTrait, - HashFuncTrait, StepCircuit, + circuit::StepCircuit, snark::RelaxedR1CSSNARKTrait, AbsorbInROTrait, Group, HashFuncConstants, + HashFuncConstantsCircuit, HashFuncConstantsTrait, HashFuncTrait, }; /// A type that holds public parameters of Nova

@@ -665,32 +663,11 @@ type G2 = pasta_curves::vesta::Point;

type S1 = spartan_with_ipa_pc::RelaxedR1CSSNARK<G1>; type S2 = spartan_with_ipa_pc::RelaxedR1CSSNARK<G2>; use ::bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError}; + use core::marker::PhantomData; use ff::PrimeField; - use std::marker::PhantomData; - - #[derive(Clone, Debug)] - struct TrivialTestCircuit<F: PrimeField> { - _p: PhantomData<F>, - } - - impl<F> StepCircuit<F> for TrivialTestCircuit<F> - where - F: PrimeField, - { - fn synthesize<CS: ConstraintSystem<F>>( - &self, - _cs: &mut CS, - z: AllocatedNum<F>, - ) -> Result<AllocatedNum<F>, SynthesisError> { - Ok(z) - } - - fn compute(&self, z: &F) -> F { - *z - } - } + use traits::circuit::TrivialTestCircuit; - #[derive(Clone, Debug)] + #[derive(Clone, Debug, Default)] struct CubicCircuit<F: PrimeField> { _p: PhantomData<F>, }

@@ -743,14 +720,7 @@ G1,

G2, TrivialTestCircuit<<G1 as Group>::Scalar>, TrivialTestCircuit<<G2 as Group>::Scalar>, - >::setup( - TrivialTestCircuit { - _p: Default::default(), - }, - TrivialTestCircuit { - _p: Default::default(), - }, - ); + >::setup(TrivialTestCircuit::default(), TrivialTestCircuit::default()); let num_steps = 1;

@@ -758,12 +728,8 @@ // produce a recursive SNARK

let res = RecursiveSNARK::prove_step( &pp, None, - TrivialTestCircuit { - _p: Default::default(), - }, - TrivialTestCircuit { - _p: Default::default(), - }, + TrivialTestCircuit::default(), + TrivialTestCircuit::default(), <G1 as Group>::Scalar::zero(), <G2 as Group>::Scalar::zero(), );

@@ -782,12 +748,8 @@ }

#[test] fn test_ivc_nontrivial() { - let circuit_primary = TrivialTestCircuit { - _p: Default::default(), - }; - let circuit_secondary = CubicCircuit { - _p: Default::default(), - }; + let circuit_primary = TrivialTestCircuit::default(); + let circuit_secondary = CubicCircuit::default(); // produce public parameters let pp = PublicParams::<

@@ -852,10 +814,7 @@ // sanity: check the claimed output with a direct computation of the same

assert_eq!(zn_primary, <G1 as Group>::Scalar::one()); let mut zn_secondary_direct = <G2 as Group>::Scalar::zero(); for _i in 0..num_steps { - zn_secondary_direct = CubicCircuit { - _p: Default::default(), - } - .compute(&zn_secondary_direct); + zn_secondary_direct = CubicCircuit::default().compute(&zn_secondary_direct); } assert_eq!(zn_secondary, zn_secondary_direct); assert_eq!(zn_secondary, <G2 as Group>::Scalar::from(2460515u64));

@@ -863,12 +822,8 @@ }

#[test] fn test_ivc_nontrivial_with_compression() { - let circuit_primary = TrivialTestCircuit { - _p: Default::default(), - }; - let circuit_secondary = CubicCircuit { - _p: Default::default(), - }; + let circuit_primary = TrivialTestCircuit::default(); + let circuit_secondary = CubicCircuit::default(); // produce public parameters let pp = PublicParams::<

@@ -921,10 +876,7 @@ // sanity: check the claimed output with a direct computation of the same

assert_eq!(zn_primary, <G1 as Group>::Scalar::one()); let mut zn_secondary_direct = <G2 as Group>::Scalar::zero(); for _i in 0..num_steps { - zn_secondary_direct = CubicCircuit { - _p: Default::default(), - } - .compute(&zn_secondary_direct); + zn_secondary_direct = CubicCircuit::default().compute(&zn_secondary_direct); } assert_eq!(zn_secondary, zn_secondary_direct); assert_eq!(zn_secondary, <G2 as Group>::Scalar::from(2460515u64));

@@ -1027,9 +979,7 @@ let circuit_primary = FifthRootCheckingCircuit {

y: <G1 as Group>::Scalar::zero(), }; - let circuit_secondary = TrivialTestCircuit { - _p: Default::default(), - }; + let circuit_secondary = TrivialTestCircuit::default(); // produce public parameters let pp = PublicParams::<

@@ -1093,14 +1043,7 @@ G1,

G2, TrivialTestCircuit<<G1 as Group>::Scalar>, CubicCircuit<<G2 as Group>::Scalar>, - >::setup( - TrivialTestCircuit { - _p: Default::default(), - }, - CubicCircuit { - _p: Default::default(), - }, - ); + >::setup(TrivialTestCircuit::default(), CubicCircuit::default()); let num_steps = 1;

@@ -1108,12 +1051,8 @@ // produce a recursive SNARK

let res = RecursiveSNARK::prove_step( &pp, None, - TrivialTestCircuit { - _p: Default::default(), - }, - CubicCircuit { - _p: Default::default(), - }, + TrivialTestCircuit::default(), + CubicCircuit::default(), <G1 as Group>::Scalar::one(), <G2 as Group>::Scalar::zero(), );
M src/nifs.rs → src/nifs.rs

@@ -8,7 +8,7 @@ use super::r1cs::{

R1CSGens, R1CSInstance, R1CSShape, R1CSWitness, RelaxedR1CSInstance, RelaxedR1CSWitness, }; use super::traits::{AbsorbInROTrait, Group, HashFuncTrait}; -use std::marker::PhantomData; +use core::marker::PhantomData; /// A SNARK that holds the proof of a step of an incremental computation #[allow(clippy::upper_case_acronyms)]
M src/snark.rs → src/traits/snark.rs

@@ -1,5 +1,5 @@

-//! A collection of traits that define the behavior of a zkSNARK for RelaxedR1CS -use super::{ +//! This module defines a collection of traits that define the behavior of a zkSNARK for RelaxedR1CS +use crate::{ errors::NovaError, r1cs::{R1CSGens, R1CSShape, RelaxedR1CSInstance, RelaxedR1CSWitness}, traits::Group,
M src/spartan_with_ipa_pc/mod.rs → src/spartan_with_ipa_pc/mod.rs

@@ -8,8 +8,10 @@ use super::{

commitments::CommitGens, errors::NovaError, r1cs::{R1CSGens, R1CSShape, RelaxedR1CSInstance, RelaxedR1CSWitness}, - snark::{ProverKeyTrait, RelaxedR1CSSNARKTrait, VerifierKeyTrait}, - traits::{AppendToTranscriptTrait, ChallengeTrait, Group}, + traits::{ + snark::{ProverKeyTrait, RelaxedR1CSSNARKTrait, VerifierKeyTrait}, + AppendToTranscriptTrait, ChallengeTrait, Group, + }, }; use core::cmp::max; use ff::Field;
M src/traits.rs → src/traits/mod.rs

@@ -175,20 +175,6 @@ /// A helper trait for references implementing group scalar multiplication.

pub trait ScalarMulOwned<Rhs, Output = Self>: for<'r> ScalarMul<&'r Rhs, Output> {} impl<T, Rhs, Output> ScalarMulOwned<Rhs, Output> for T where T: for<'r> ScalarMul<&'r Rhs, Output> {} -/// A helper trait for a step of the incremental computation (i.e., circuit for F) -pub trait StepCircuit<F: PrimeField>: Send + Sync + Clone { - /// Sythesize the circuit for a computation step and return variable - /// that corresponds to the output of the step z_{i+1} - fn synthesize<CS: ConstraintSystem<F>>( - &self, - cs: &mut CS, - z: AllocatedNum<F>, - ) -> Result<AllocatedNum<F>, SynthesisError>; - - /// Execute the circuit for a computation step and return output - fn compute(&self, z: &F) -> F; -} - impl<F: PrimeField> AppendToTranscriptTrait for F { fn append_to_transcript(&self, label: &'static [u8], transcript: &mut Transcript) { transcript.append_message(label, self.to_repr().as_ref());

@@ -202,3 +188,6 @@ s.append_to_transcript(label, transcript);

} } } + +pub mod circuit; +pub mod snark;
A src/traits/circuit.rs

@@ -0,0 +1,41 @@

+//! This module defines traits that a step function must implement +use bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError}; +use core::marker::PhantomData; +use ff::PrimeField; + +/// A helper trait for a step of the incremental computation (i.e., circuit for F) +pub trait StepCircuit<F: PrimeField>: Send + Sync + Clone { + /// Sythesize the circuit for a computation step and return variable + /// that corresponds to the output of the step z_{i+1} + fn synthesize<CS: ConstraintSystem<F>>( + &self, + cs: &mut CS, + z: AllocatedNum<F>, + ) -> Result<AllocatedNum<F>, SynthesisError>; + + /// Execute the circuit for a computation step and return output + fn compute(&self, z: &F) -> F; +} + +/// A trivial step circuit that simply returns the input +#[derive(Clone, Debug, Default)] +pub struct TrivialTestCircuit<F: PrimeField> { + _p: PhantomData<F>, +} + +impl<F> StepCircuit<F> for TrivialTestCircuit<F> +where + F: PrimeField, +{ + fn synthesize<CS: ConstraintSystem<F>>( + &self, + _cs: &mut CS, + z: AllocatedNum<F>, + ) -> Result<AllocatedNum<F>, SynthesisError> { + Ok(z) + } + + fn compute(&self, z: &F) -> F { + *z + } +}