hyperplonk/hyperplonk/benches/bench.rs
hyperplonk/benches/bench.rsRaw
1// Copyright (c) 2023 Espresso Systems (espressosys.com)
2// This file is part of the HyperPlonk library.
3
4// You should have received a copy of the MIT License
5// along with the HyperPlonk library. If not, see <https://mit-license.org/>.
6
7use std::{fs::File, io, time::Instant};
8
9use ark_bls12_381::{Bls12_381, Fr};
10use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Write};
11use ark_std::test_rng;
12use hyperplonk::{
13 prelude::{CustomizedGates, HyperPlonkErrors, MockCircuit},
14 HyperPlonkSNARK,
15};
16use subroutines::{
17 pcs::{
18 prelude::{MultilinearKzgPCS, MultilinearUniversalParams},
19 PolynomialCommitmentScheme,
20 },
21 poly_iop::PolyIOP,
22};
23
24const SUPPORTED_SIZE: usize = 20;
25const MIN_NUM_VARS: usize = 8;
26const MAX_NUM_VARS: usize = 20;
27const MIN_CUSTOM_DEGREE: usize = 1;
28const MAX_CUSTOM_DEGREE: usize = 32;
29const HIGH_DEGREE_TEST_NV: usize = 15;
30
31fn main() -> Result<(), HyperPlonkErrors> {
32 let thread = rayon::current_num_threads();
33 println!("start benchmark with #{} threads", thread);
34 let mut rng = test_rng();
35 let pcs_srs = {
36 match read_srs() {
37 Ok(p) => p,
38 Err(_e) => {
39 let srs =
40 MultilinearKzgPCS::<Bls12_381>::gen_srs_for_testing(&mut rng, SUPPORTED_SIZE)?;
41 write_srs(&srs);
42 srs
43 },
44 }
45 };
46 bench_jellyfish_plonk(&pcs_srs, thread)?;
47 println!();
48 bench_vanilla_plonk(&pcs_srs, thread)?;
49 println!();
50 for degree in MIN_CUSTOM_DEGREE..=MAX_CUSTOM_DEGREE {
51 bench_high_degree_plonk(&pcs_srs, degree, thread)?;
52 println!();
53 }
54 println!();
55
56 Ok(())
57}
58
59fn read_srs() -> Result<MultilinearUniversalParams<Bls12_381>, io::Error> {
60 let mut f = File::open("srs.params")?;
61 Ok(MultilinearUniversalParams::<Bls12_381>::deserialize_unchecked(&mut f).unwrap())
62}
63
64fn write_srs(pcs_srs: &MultilinearUniversalParams<Bls12_381>) {
65 let mut f = File::create("srs.params").unwrap();
66 pcs_srs.serialize_uncompressed(&mut f).unwrap();
67}
68
69fn bench_vanilla_plonk(
70 pcs_srs: &MultilinearUniversalParams<Bls12_381>,
71 thread: usize,
72) -> Result<(), HyperPlonkErrors> {
73 let filename = format!("vanilla threads {}.txt", thread);
74 let mut file = File::create(filename).unwrap();
75 for nv in MIN_NUM_VARS..=MAX_NUM_VARS {
76 let vanilla_gate = CustomizedGates::vanilla_plonk_gate();
77 bench_mock_circuit_zkp_helper(&mut file, nv, &vanilla_gate, &pcs_srs)?;
78 }
79
80 Ok(())
81}
82
83fn bench_jellyfish_plonk(
84 pcs_srs: &MultilinearUniversalParams<Bls12_381>,
85 thread: usize,
86) -> Result<(), HyperPlonkErrors> {
87 let filename = format!("jellyfish threads {}.txt", thread);
88 let mut file = File::create(filename).unwrap();
89 for nv in MIN_NUM_VARS..=MAX_NUM_VARS {
90 let jf_gate = CustomizedGates::jellyfish_turbo_plonk_gate();
91 bench_mock_circuit_zkp_helper(&mut file, nv, &jf_gate, &pcs_srs)?;
92 }
93
94 Ok(())
95}
96
97fn bench_high_degree_plonk(
98 pcs_srs: &MultilinearUniversalParams<Bls12_381>,
99 degree: usize,
100 thread: usize,
101) -> Result<(), HyperPlonkErrors> {
102 let filename = format!("high degree {} thread {}.txt", degree, thread);
103 let mut file = File::create(filename).unwrap();
104 println!("custom gate of degree {}", degree);
105 let vanilla_gate = CustomizedGates::mock_gate(2, degree);
106 bench_mock_circuit_zkp_helper(&mut file, HIGH_DEGREE_TEST_NV, &vanilla_gate, &pcs_srs)?;
107
108 Ok(())
109}
110
111fn bench_mock_circuit_zkp_helper(
112 file: &mut File,
113 nv: usize,
114 gate: &CustomizedGates,
115 pcs_srs: &MultilinearUniversalParams<Bls12_381>,
116) -> Result<(), HyperPlonkErrors> {
117 let repetition = if nv < 10 {
118 5
119 } else if nv < 20 {
120 2
121 } else {
122 1
123 };
124
125 //==========================================================
126 let circuit = MockCircuit::<Fr>::new(1 << nv, gate);
127 assert!(circuit.is_satisfied());
128 let index = circuit.index;
129 //==========================================================
130 // generate pk and vks
131 let start = Instant::now();
132 for _ in 0..repetition {
133 let (_pk, _vk) = <PolyIOP<Fr> as HyperPlonkSNARK<
134 Bls12_381,
135 MultilinearKzgPCS<Bls12_381>,
136 >>::preprocess(&index, &pcs_srs)?;
137 }
138 println!(
139 "key extraction for {} variables: {} us",
140 nv,
141 start.elapsed().as_micros() / repetition as u128
142 );
143 let (pk, vk) =
144 <PolyIOP<Fr> as HyperPlonkSNARK<Bls12_381, MultilinearKzgPCS<Bls12_381>>>::preprocess(
145 &index, &pcs_srs,
146 )?;
147 //==========================================================
148 // generate a proof
149 let start = Instant::now();
150 for _ in 0..repetition {
151 let _proof =
152 <PolyIOP<Fr> as HyperPlonkSNARK<Bls12_381, MultilinearKzgPCS<Bls12_381>>>::prove(
153 &pk,
154 &circuit.public_inputs,
155 &circuit.witnesses,
156 )?;
157 }
158 let t = start.elapsed().as_micros() / repetition as u128;
159 println!(
160 "proving for {} variables: {} us",
161 nv,
162 start.elapsed().as_micros() / repetition as u128
163 );
164 file.write_all(format!("{} {}\n", nv, t).as_ref()).unwrap();
165
166 let proof = <PolyIOP<Fr> as HyperPlonkSNARK<Bls12_381, MultilinearKzgPCS<Bls12_381>>>::prove(
167 &pk,
168 &circuit.public_inputs,
169 &circuit.witnesses,
170 )?;
171 //==========================================================
172 // verify a proof
173 let start = Instant::now();
174 for _ in 0..repetition {
175 let verify =
176 <PolyIOP<Fr> as HyperPlonkSNARK<Bls12_381, MultilinearKzgPCS<Bls12_381>>>::verify(
177 &vk,
178 &circuit.public_inputs,
179 &proof,
180 )?;
181 assert!(verify);
182 }
183 println!(
184 "verifying for {} variables: {} us",
185 nv,
186 start.elapsed().as_micros() / repetition as u128
187 );
188 Ok(())
189}