Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make Minroot example generic over the supported curve cycles #272

Merged
merged 2 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "nova-snark"
version = "0.31.0"
version = "0.32.0"
authors = ["Srinath Setty <[email protected]>"]
edition = "2021"
description = "High-speed recursive arguments from folding schemes"
Expand Down
79 changes: 41 additions & 38 deletions examples/minroot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<E1>;
type EE2 = nova_snark::provider::ipa_pc::EvaluationEngine<E2>;
type S1 = nova_snark::spartan::snark::RelaxedR1CSSNARK<E1, EE1>; // non-preprocessing SNARK
type S2 = nova_snark::spartan::snark::RelaxedR1CSSNARK<E2, EE2>; // non-preprocessing SNARK

#[derive(Clone, Debug)]
struct MinRootIteration<F: PrimeField> {
x_i: F,
y_i: F,
x_i_plus_1: F,
y_i_plus_1: F,
struct MinRootIteration<G: Group> {
x_i: G::Scalar,
y_i: G::Scalar,
x_i_plus_1: G::Scalar,
y_i_plus_1: G::Scalar,
}

impl<F: PrimeField> MinRootIteration<F> {
impl<G: Group> MinRootIteration<G> {
// 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<F>, Vec<Self>) {
// 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<G::Scalar>, Vec<Self>) {
// 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) {
Expand Down Expand Up @@ -72,21 +79,21 @@ impl<F: PrimeField> MinRootIteration<F> {
}

#[derive(Clone, Debug)]
struct MinRootCircuit<F: PrimeField> {
seq: Vec<MinRootIteration<F>>,
struct MinRootCircuit<G: Group> {
seq: Vec<MinRootIteration<G>>,
}

impl<F: PrimeField> StepCircuit<F> for MinRootCircuit<F> {
impl<G: Group> StepCircuit<G::Scalar> for MinRootCircuit<G> {
fn arity(&self) -> usize {
2
}

fn synthesize<CS: ConstraintSystem<F>>(
fn synthesize<CS: ConstraintSystem<G::Scalar>>(
&self,
cs: &mut CS,
z: &[AllocatedNum<F>],
) -> Result<Vec<AllocatedNum<F>>, SynthesisError> {
let mut z_out: Result<Vec<AllocatedNum<F>>, SynthesisError> =
z: &[AllocatedNum<G::Scalar>],
) -> Result<Vec<AllocatedNum<G::Scalar>>, SynthesisError> {
let mut z_out: Result<Vec<AllocatedNum<G::Scalar>>, SynthesisError> =
Err(SynthesisError::AssignmentMissing);

// use the provided inputs
Expand Down Expand Up @@ -161,13 +168,13 @@ fn main() {
let pp = PublicParams::<
E1,
E2,
MinRootCircuit<<E1 as Engine>::Scalar>,
MinRootCircuit<<E1 as Engine>::GE>,
TrivialCircuit<<E2 as Engine>::Scalar>,
>::setup(
&circuit_primary,
&circuit_secondary,
&*default_ck_hint(),
&*default_ck_hint(),
&*S1::ck_floor(),
&*S2::ck_floor(),
);
println!("PublicParams::setup, took {:?} ", start.elapsed());

Expand All @@ -190,7 +197,7 @@ fn main() {
);

// produce non-deterministic advice
let (z0_primary, minroot_iterations) = MinRootIteration::new(
let (z0_primary, minroot_iterations) = MinRootIteration::<<E1 as Engine>::GE>::new(
num_iters_per_step * num_steps,
&<E1 as Engine>::Scalar::zero(),
&<E1 as Engine>::Scalar::one(),
Expand All @@ -210,7 +217,7 @@ fn main() {

let z0_secondary = vec![<E2 as Engine>::Scalar::zero()];

type C1 = MinRootCircuit<<E1 as Engine>::Scalar>;
type C1 = MinRootCircuit<<E1 as Engine>::GE>;
type C2 = TrivialCircuit<<E2 as Engine>::Scalar>;
// produce a recursive SNARK
println!("Generating a RecursiveSNARK...");
Expand Down Expand Up @@ -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<E1>;
type EE2 = nova_snark::provider::ipa_pc::EvaluationEngine<E2>;
type S1 = nova_snark::spartan::snark::RelaxedR1CSSNARK<E1, EE1>;
type S2 = nova_snark::spartan::snark::RelaxedR1CSSNARK<E2, EE2>;

let res = CompressedSNARK::<_, _, _, _, S1, S2>::prove(&pp, &pk, &recursive_snark);
println!(
Expand Down
Loading