barretenberg
Loading...
Searching...
No Matches
compute_circuit_data.hpp
1#pragma once
2#include <fstream>
3#include <sys/stat.h>
4
5#include "../constants.hpp"
6#include "barretenberg/common/log.hpp"
7#include "barretenberg/common/timer.hpp"
8#include "barretenberg/plonk/proof_system/proving_key/serialize.hpp"
9#include "join_split/join_split.hpp"
10#include "mock/mock_circuit.hpp"
11
12#ifndef __wasm__
13#include <filesystem>
14#endif
15
16namespace join_split_example {
17namespace proofs {
18
21 : num_gates(0)
22 {}
23
24 std::shared_ptr<barretenberg::srs::factories::CrsFactory<curve::BN254>> srs;
25 std::shared_ptr<plonk::proving_key> proving_key;
26 std::shared_ptr<plonk::verification_key> verification_key;
27 size_t num_gates;
28 std::vector<uint8_t> padding_proof;
29 bool mock;
30};
31
32namespace {
33inline bool exists(std::string const& path)
34{
35 struct stat st;
36 return (stat(path.c_str(), &st) != -1);
37}
38} // namespace
39
40template <typename Composer, typename F>
41circuit_data get_circuit_data(std::string const& name,
42 std::string const& path_name,
44 std::string const& key_path,
45 bool compute,
46 bool save,
47 bool load,
48 bool pk,
49 bool vk,
50 bool padding,
51 bool mock, // TODO(#541)
52 F const& build_circuit,
53 std::string const name_suffix_for_benchmarks = "")
54{
55 using Builder = typename Composer::CircuitBuilder;
56 circuit_data data;
57 data.srs = srs;
58 data.mock = mock;
59 Composer composer;
60 Builder builder;
61 Composer mock_proof_composer;
62 Builder mock_builder;
63 BenchmarkInfoCollator benchmark_collator;
64
65 auto circuit_key_path = key_path + "/" + path_name;
66 auto pk_path = circuit_key_path + "/proving_key/proving_key";
67 auto vk_path = circuit_key_path + "/verification_key";
68 auto padding_path = circuit_key_path + "/padding_proof";
69
70 // If we're missing required data, and compute is enabled, or if
71 // compute is enabled and load is disabled, build the circuit.
72 if (((!exists(pk_path) || !exists(vk_path) || (!exists(padding_path) && padding)) && compute) ||
73 (compute && !load)) {
74 info(name, ": Building circuit...");
75 Timer timer;
76 build_circuit(builder);
77
78 benchmark_collator.benchmark_info_deferred(
79 Composer::NAME_STRING, "Core", name + name_suffix_for_benchmarks, "Build time", timer.toString());
80 benchmark_collator.benchmark_info_deferred(
81 Composer::NAME_STRING, "Core", name + name_suffix_for_benchmarks, "Gates", builder.get_num_gates());
82 info(name, ": Circuit built in: ", timer.toString(), "s");
83 info(name, ": Circuit size: ", builder.get_num_gates());
84 if (mock) {
85 auto public_inputs = builder.get_public_inputs();
86 ::join_split_example::proofs::mock::mock_circuit(mock_builder, public_inputs);
87 info(name, ": Mock circuit size: ", mock_builder.get_num_gates());
88 benchmark_collator.benchmark_info_deferred(Composer::NAME_STRING,
89 "Core",
90 name + name_suffix_for_benchmarks,
91 "Mock Gates",
92 builder.get_num_gates());
93 }
94 }
95
96#ifndef __wasm__
97 // If we're saving data, create the circuit data directory.
98 if (save) {
99 std::filesystem::create_directories(key_path.c_str());
100 std::filesystem::create_directories(circuit_key_path.c_str());
101 }
102#endif
103
104 if (pk) {
105 auto pk_dir = circuit_key_path + "/proving_key";
106 if (exists(pk_path) && load) {
107 info(name, ": Loading proving key: ", pk_path);
108 auto pk_stream = std::ifstream(pk_path);
110 read_from_file(pk_stream, pk_dir, pk_data);
111 data.proving_key =
112 std::make_shared<plonk::proving_key>(std::move(pk_data), srs->get_prover_crs(pk_data.circuit_size + 1));
113 data.num_gates = pk_data.circuit_size;
114 info(name, ": Circuit size 2^n: ", data.num_gates);
115 benchmark_collator.benchmark_info_deferred(
116 Composer::NAME_STRING, "Core", name + name_suffix_for_benchmarks, "Gates 2^n", data.num_gates);
117 } else if (compute) {
118 Timer timer;
119 info(name, ": Computing proving key...");
120
121 if (!mock) {
122 data.num_gates = builder.get_num_gates();
123 data.proving_key = composer.compute_proving_key(builder);
124 info(name, ": Circuit size 2^n: ", data.proving_key->circuit_size);
125 benchmark_collator.benchmark_info_deferred(Composer::NAME_STRING,
126 "Core",
127 name + name_suffix_for_benchmarks,
128 "Gates 2^n",
129 data.proving_key->circuit_size);
130 } else {
131 data.num_gates = mock_builder.get_num_gates();
132 data.proving_key = mock_proof_composer.compute_proving_key(mock_builder);
133 info(name, ": Mock circuit size 2^n: ", data.proving_key->circuit_size);
134 benchmark_collator.benchmark_info_deferred(Composer::NAME_STRING,
135 "Core",
136 name + name_suffix_for_benchmarks,
137 "Mock Gates 2^n",
138 data.proving_key->circuit_size);
139 }
140
141 info(name, ": Proving key computed in ", timer.toString(), "s");
142 benchmark_collator.benchmark_info_deferred(Composer::NAME_STRING,
143 "Core",
144 name + name_suffix_for_benchmarks,
145 "Proving key computed in",
146 timer.toString());
147#ifndef __wasm__
148 if (save) {
149 info(name, ": Saving proving key...");
150 std::filesystem::create_directories(pk_dir.c_str());
151 Timer write_timer;
152 std::ofstream os(pk_path);
153 write_to_file(os, pk_dir, *data.proving_key);
154 if (!os.good()) {
155 throw_or_abort(format("Failed to write: ", pk_path));
156 }
157 info(name, ": Saved in ", write_timer.toString(), "s");
158 }
159#endif
160 }
161 }
162
163 if (vk) {
164 if (exists(vk_path) && load) {
165 info(name, ": Loading verification key from: ", vk_path);
166 auto vk_stream = std::ifstream(vk_path);
168 serialize::read(vk_stream, vk_data);
169 data.verification_key =
170 std::make_shared<plonk::verification_key>(std::move(vk_data), data.srs->get_verifier_crs());
171 info(name, ": Verification key hash: ", data.verification_key->sha256_hash());
172 benchmark_collator.benchmark_info_deferred(Composer::NAME_STRING,
173 "Core",
174 name + name_suffix_for_benchmarks,
175 "Verification key hash",
176 data.verification_key->sha256_hash());
177 } else if (compute) {
178 info(name, ": Computing verification key...");
179 Timer timer;
180
181 if (!mock) {
182 data.verification_key = composer.compute_verification_key(builder);
183 } else {
184 data.verification_key = mock_proof_composer.compute_verification_key(mock_builder);
185 }
186 info(name, ": Computed verification key in ", timer.toString(), "s");
187
188 benchmark_collator.benchmark_info_deferred(Composer::NAME_STRING,
189 "Core",
190 name + name_suffix_for_benchmarks,
191 "Verification key computed in",
192 timer.toString());
193 info(name, ": Verification key hash: ", data.verification_key->sha256_hash());
194 benchmark_collator.benchmark_info_deferred(Composer::NAME_STRING,
195 "Core",
196 name + name_suffix_for_benchmarks,
197 "Verification key hash",
198 data.verification_key->sha256_hash());
199
200 if (save) {
201 std::ofstream os(vk_path);
202 write(os, *data.verification_key);
203 if (!os.good()) {
204 throw_or_abort(format("Failed to write: ", vk_path));
205 }
206 }
207 }
208 }
209
210 if (padding) {
211 if (exists(padding_path) && load) {
212 info(name, ": Loading padding proof from: ", padding_path);
213 std::ifstream is(padding_path);
214 std::vector<uint8_t> proof((std::istreambuf_iterator<char>(is)), std::istreambuf_iterator<char>());
215 data.padding_proof = proof;
216 } else if (data.proving_key) {
217 info(name, ": Computing padding proof...");
218
219 if (builder.failed()) {
220 info(name, ": Composer logic failed: ", builder.err());
221 info(name, ": Warning, padding proof can only be used to aid upstream pk construction!");
222 }
223
224 Timer timer;
225 if (!mock) {
226 auto prover = composer.create_prover(builder);
227 auto proof = prover.construct_proof();
228 data.padding_proof = proof.proof_data;
229 data.num_gates = builder.get_num_gates();
230 info(name, ": Circuit size: ", data.num_gates);
231 auto verifier = composer.create_verifier(builder);
232 info(name, ": Padding verified: ", verifier.verify_proof(proof));
233 } else {
234 auto prover = mock_proof_composer.create_prover(mock_builder);
235 auto proof = prover.construct_proof();
236 data.padding_proof = proof.proof_data;
237 data.num_gates = mock_builder.get_num_gates();
238 info(name, ": Mock circuit size: ", data.num_gates);
239 auto verifier = mock_proof_composer.create_verifier(mock_builder);
240 info(name, ": Padding verified: ", verifier.verify_proof(proof));
241 }
242 info(name, ": Padding proof computed in ", timer.toString(), "s");
243 benchmark_collator.benchmark_info_deferred(Composer::NAME_STRING,
244 "Core",
245 name + name_suffix_for_benchmarks,
246 "Padding proof computed in",
247 timer.toString());
248
249 if (save) {
250 std::ofstream os(padding_path);
251 os.write((char*)data.padding_proof.data(), (std::streamsize)data.padding_proof.size());
252 if (!os.good()) {
253 throw_or_abort(format("Failed to write: ", padding_path));
254 }
255 }
256 }
257 }
258
259 return data;
260}
261
262} // namespace proofs
263} // namespace join_split_example
A class for saving benchmarks and printing them all at once in the end of the function.
Definition: log.hpp:91
Get the execution between a block of code.
Definition: timer.hpp:12
std::string toString() const
Return the number of seconds elapsed since the start of the timer as a string.
Definition: timer.hpp:80
Definition: crs_factory.hpp:72
Definition: standard_circuit_builder.hpp:12
Definition: standard_composer.hpp:14
plonk::Prover create_prover(const CircuitBuilder &circuit_constructor)
Definition: standard_composer.cpp:145
plonk::Verifier create_verifier(const CircuitBuilder &circuit_constructor)
Definition: standard_composer.cpp:122
std::shared_ptr< plonk::proving_key > compute_proving_key(const CircuitBuilder &circuit_constructor)
Definition: standard_composer.cpp:61
std::shared_ptr< plonk::verification_key > compute_verification_key(const CircuitBuilder &circuit_constructor)
Definition: standard_composer.cpp:95
Definition: compute_circuit_data.hpp:19
Definition: proving_key.hpp:22
Definition: verification_key.hpp:14