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