diff --git a/Cargo.toml b/Cargo.toml index c58bcd291..60dc2974d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nova-snark" -version = "0.31.0" +version = "0.32.0" authors = ["Srinath Setty "] edition = "2021" description = "High-speed recursive arguments from folding schemes" diff --git a/examples/minroot.rs b/examples/minroot.rs index 773b7f816..cfc057392 100644 --- a/examples/minroot.rs +++ b/examples/minroot.rs @@ -2,47 +2,54 @@ //! iterations of the `MinRoot` function, thereby realizing a Nova-based verifiable delay function (VDF). //! We execute a configurable number of iterations of the `MinRoot` function per step of Nova's recursion. use bellpepper_core::{num::AllocatedNum, ConstraintSystem, SynthesisError}; -use ff::PrimeField; +use ff::Field; use flate2::{write::ZlibEncoder, Compression}; use nova_snark::{ - provider::{PallasEngine, VestaEngine}, + provider::{mlkzg::Bn256EngineKZG, GrumpkinEngine}, traits::{ circuit::{StepCircuit, TrivialCircuit}, - snark::default_ck_hint, - Engine, + snark::RelaxedR1CSSNARKTrait, + Engine, Group, }, CompressedSNARK, PublicParams, RecursiveSNARK, }; use num_bigint::BigUint; use std::time::Instant; -type E1 = PallasEngine; -type E2 = VestaEngine; +type E1 = Bn256EngineKZG; +type E2 = GrumpkinEngine; +type EE1 = nova_snark::provider::mlkzg::EvaluationEngine; +type EE2 = nova_snark::provider::ipa_pc::EvaluationEngine; +type S1 = nova_snark::spartan::snark::RelaxedR1CSSNARK; // non-preprocessing SNARK +type S2 = nova_snark::spartan::snark::RelaxedR1CSSNARK; // non-preprocessing SNARK #[derive(Clone, Debug)] -struct MinRootIteration { - x_i: F, - y_i: F, - x_i_plus_1: F, - y_i_plus_1: F, +struct MinRootIteration { + x_i: G::Scalar, + y_i: G::Scalar, + x_i_plus_1: G::Scalar, + y_i_plus_1: G::Scalar, } -impl MinRootIteration { +impl MinRootIteration { // produces a sample non-deterministic advice, executing one invocation of MinRoot per step - fn new(num_iters: usize, x_0: &F, y_0: &F) -> (Vec, Vec) { - // although this code is written generically, it is tailored to Pallas' scalar field - // (p - 3 / 5) - let exp = BigUint::parse_bytes( - b"23158417847463239084714197001737581570690445185553317903743794198714690358477", - 10, - ) - .unwrap(); + fn new(num_iters: usize, x_0: &G::Scalar, y_0: &G::Scalar) -> (Vec, Vec) { + // exp = (p - 3 / 5), where p is the order of the group + // x^{exp} mod p provides the fifth root of x + let exp = { + let p = G::group_params().2.to_biguint().unwrap(); + let two = BigUint::parse_bytes(b"2", 10).unwrap(); + let three = BigUint::parse_bytes(b"3", 10).unwrap(); + let five = BigUint::parse_bytes(b"5", 10).unwrap(); + let five_inv = five.modpow(&(&p - &two), &p); + (&five_inv * (&p - &three)) % &p + }; let mut res = Vec::new(); let mut x_i = *x_0; let mut y_i = *y_0; for _i in 0..num_iters { - let x_i_plus_1 = (x_i + y_i).pow_vartime(exp.to_u64_digits()); // computes the fifth root of x_i + y_i + let x_i_plus_1 = (x_i + y_i).pow_vartime(&exp.to_u64_digits()); // computes the fifth root of x_i + y_i // sanity check if cfg!(debug_assertions) { @@ -72,21 +79,21 @@ impl MinRootIteration { } #[derive(Clone, Debug)] -struct MinRootCircuit { - seq: Vec>, +struct MinRootCircuit { + seq: Vec>, } -impl StepCircuit for MinRootCircuit { +impl StepCircuit for MinRootCircuit { fn arity(&self) -> usize { 2 } - fn synthesize>( + fn synthesize>( &self, cs: &mut CS, - z: &[AllocatedNum], - ) -> Result>, SynthesisError> { - let mut z_out: Result>, SynthesisError> = + z: &[AllocatedNum], + ) -> Result>, SynthesisError> { + let mut z_out: Result>, SynthesisError> = Err(SynthesisError::AssignmentMissing); // use the provided inputs @@ -161,13 +168,13 @@ fn main() { let pp = PublicParams::< E1, E2, - MinRootCircuit<::Scalar>, + MinRootCircuit<::GE>, TrivialCircuit<::Scalar>, >::setup( &circuit_primary, &circuit_secondary, - &*default_ck_hint(), - &*default_ck_hint(), + &*S1::ck_floor(), + &*S2::ck_floor(), ); println!("PublicParams::setup, took {:?} ", start.elapsed()); @@ -190,7 +197,7 @@ fn main() { ); // produce non-deterministic advice - let (z0_primary, minroot_iterations) = MinRootIteration::new( + let (z0_primary, minroot_iterations) = MinRootIteration::<::GE>::new( num_iters_per_step * num_steps, &::Scalar::zero(), &::Scalar::one(), @@ -210,7 +217,7 @@ fn main() { let z0_secondary = vec![::Scalar::zero()]; - type C1 = MinRootCircuit<::Scalar>; + type C1 = MinRootCircuit<::GE>; type C2 = TrivialCircuit<::Scalar>; // produce a recursive SNARK println!("Generating a RecursiveSNARK..."); @@ -248,14 +255,10 @@ fn main() { assert!(res.is_ok()); // produce a compressed SNARK - println!("Generating a CompressedSNARK using Spartan with IPA-PC..."); + println!("Generating a CompressedSNARK using Spartan with multilinear KZG..."); let (pk, vk) = CompressedSNARK::<_, _, _, _, S1, S2>::setup(&pp).unwrap(); let start = Instant::now(); - type EE1 = nova_snark::provider::ipa_pc::EvaluationEngine; - type EE2 = nova_snark::provider::ipa_pc::EvaluationEngine; - type S1 = nova_snark::spartan::snark::RelaxedR1CSSNARK; - type S2 = nova_snark::spartan::snark::RelaxedR1CSSNARK; let res = CompressedSNARK::<_, _, _, _, S1, S2>::prove(&pp, &pk, &recursive_snark); println!(