arnaucube
arnaucube/NovaPublic Self-hosted repository
Nova/benches/recursive-snark.rs
benches/recursive-snark.rsRaw
  1#![allow(non_snake_case)]
  2
  3use nova_snark::{
  4  traits::{Group, StepCircuit},
  5  PublicParams, RecursiveSNARK,
  6};
  7
  8type G1 = pasta_curves::pallas::Point;
  9type G2 = pasta_curves::vesta::Point;
 10
 11#[derive(Clone, Debug)]
 12struct TrivialTestCircuit<F: PrimeField> {
 13  _p: PhantomData<F>,
 14}
 15
 16impl<F> StepCircuit<F> for TrivialTestCircuit<F>
 17where
 18  F: PrimeField,
 19{
 20  fn synthesize<CS: ConstraintSystem<F>>(
 21    &self,
 22    _cs: &mut CS,
 23    z: AllocatedNum<F>,
 24  ) -> Result<AllocatedNum<F>, SynthesisError> {
 25    Ok(z)
 26  }
 27
 28  fn compute(&self, z: &F) -> F {
 29    *z
 30  }
 31}
 32
 33type C1 = TrivialTestCircuit<<G1 as Group>::Scalar>;
 34type C2 = TrivialTestCircuit<<G2 as Group>::Scalar>;
 35
 36use bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError};
 37use core::marker::PhantomData;
 38use criterion::*;
 39use ff::PrimeField;
 40use std::time::Duration;
 41
 42fn recursive_snark_benchmark(c: &mut Criterion) {
 43  let num_samples = 10;
 44  bench_recursive_snark(c, num_samples);
 45}
 46
 47fn set_duration() -> Criterion {
 48  Criterion::default().warm_up_time(Duration::from_millis(3000))
 49}
 50
 51criterion_group! {
 52name = recursive_snark;
 53config = set_duration();
 54targets = recursive_snark_benchmark
 55}
 56
 57criterion_main!(recursive_snark);
 58
 59fn bench_recursive_snark(c: &mut Criterion, num_samples: usize) {
 60  let mut group = c.benchmark_group("RecursiveSNARK".to_string());
 61  group.sample_size(num_samples);
 62
 63  // Produce public parameters
 64  let pp = PublicParams::<G1, G2, C1, C2>::setup(
 65    TrivialTestCircuit {
 66      _p: Default::default(),
 67    },
 68    TrivialTestCircuit {
 69      _p: Default::default(),
 70    },
 71  );
 72
 73  // Bench time to produce a recursive SNARK;
 74  // we execute a certain number of warm-up steps since executing
 75  // the first step is cheaper than other steps owing to the presence of
 76  // a lot of zeros in the satisfying assignment
 77  let num_warmup_steps = 10;
 78  let mut recursive_snark: Option<RecursiveSNARK<G1, G2, C1, C2>> = None;
 79
 80  for i in 0..num_warmup_steps {
 81    let res = RecursiveSNARK::prove_step(
 82      &pp,
 83      recursive_snark,
 84      TrivialTestCircuit {
 85        _p: Default::default(),
 86      },
 87      TrivialTestCircuit {
 88        _p: Default::default(),
 89      },
 90      <G1 as Group>::Scalar::one(),
 91      <G2 as Group>::Scalar::zero(),
 92    );
 93    assert!(res.is_ok());
 94    let recursive_snark_unwrapped = res.unwrap();
 95
 96    // verify the recursive snark at each step of recursion
 97    let res = recursive_snark_unwrapped.verify(
 98      &pp,
 99      i + 1,
100      <G1 as Group>::Scalar::one(),
101      <G2 as Group>::Scalar::zero(),
102    );
103    assert!(res.is_ok());
104
105    // set the running variable for the next iteration
106    recursive_snark = Some(recursive_snark_unwrapped);
107  }
108
109  group.bench_function("Prove", |b| {
110    b.iter(|| {
111      // produce a recursive SNARK for a step of the recursion
112      assert!(RecursiveSNARK::prove_step(
113        black_box(&pp),
114        black_box(recursive_snark.clone()),
115        black_box(TrivialTestCircuit {
116          _p: Default::default(),
117        }),
118        black_box(TrivialTestCircuit {
119          _p: Default::default(),
120        }),
121        black_box(<G1 as Group>::Scalar::zero()),
122        black_box(<G2 as Group>::Scalar::zero()),
123      )
124      .is_ok());
125    })
126  });
127
128  let recursive_snark = recursive_snark.unwrap();
129
130  // Benchmark the verification time
131  let name = "Verify";
132  group.bench_function(name, |b| {
133    b.iter(|| {
134      assert!(black_box(&recursive_snark)
135        .verify(
136          black_box(&pp),
137          black_box(num_warmup_steps),
138          black_box(<G1 as Group>::Scalar::zero()),
139          black_box(<G2 as Group>::Scalar::zero()),
140        )
141        .is_ok());
142    });
143  });
144  group.finish();
145}