Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
api_chonk.cpp
Go to the documentation of this file.
1#include "api_chonk.hpp"
16#include <algorithm>
17#include <sstream>
18#include <stdexcept>
19
20namespace bb {
21namespace { // anonymous namespace
22
31void write_standalone_vk(std::vector<uint8_t> bytecode, const std::filesystem::path& output_path)
32{
33 auto response = bbapi::ChonkComputeStandaloneVk{
34 .circuit = { .name = "standalone_circuit", .bytecode = std::move(bytecode) }
35 }.execute();
36
37 bool is_stdout = output_path == "-";
38 if (is_stdout) {
39 write_bytes_to_stdout(response.bytes);
40 } else {
41 write_file(output_path / "vk", response.bytes);
42 }
43}
44void write_chonk_vk(std::vector<uint8_t> bytecode, const std::filesystem::path& output_dir)
45{
46 // compute the hiding kernel's vk
47 info("Chonk: computing IVC vk for hiding kernel circuit");
48 auto response = bbapi::ChonkComputeIvcVk{ .circuit{ .bytecode = std::move(bytecode) } }.execute();
49 const bool output_to_stdout = output_dir == "-";
50 if (output_to_stdout) {
51 write_bytes_to_stdout(response.bytes);
52 } else {
53 write_file(output_dir / "vk", response.bytes);
54 }
55}
56} // anonymous namespace
57
58void ChonkAPI::prove(const Flags& flags,
59 const std::filesystem::path& input_path,
60 const std::filesystem::path& output_dir)
61{
62 BB_BENCH_NAME("ChonkAPI::prove");
63 bbapi::BBApiRequest request;
66
67 bbapi::ChonkStart{ .num_circuits = raw_steps.size() }.execute(request);
68 info("Chonk: starting with ", raw_steps.size(), " circuits");
69 for (const auto& step : raw_steps) {
71 .circuit = { .name = step.function_name, .bytecode = step.bytecode, .verification_key = step.vk }
72 }.execute(request);
73
74 // NOLINTNEXTLINE(bugprone-unchecked-optional-access): we know the optional has been set here.
75 info("Chonk: accumulating " + step.function_name);
76 bbapi::ChonkAccumulate{ .witness = step.witness }.execute(request);
77 }
78
79 auto proof = bbapi::ChonkProve{}.execute(request).proof;
80
81 // We'd like to use the `write` function that UltraHonkAPI uses, but there are missing functions for creating
82 // std::string representations of vks that don't feel worth implementing
83 const bool output_to_stdout = output_dir == "-";
84
85 const auto write_proof = [&]() {
86 const auto buf = to_buffer(proof.to_field_elements());
87 if (output_to_stdout) {
88 vinfo("writing Chonk proof to stdout");
90 } else {
91 vinfo("writing Chonk proof in directory ", output_dir);
92 write_file(output_dir / "proof", buf);
93 }
94 };
95
96 write_proof();
97
98 if (flags.write_vk) {
99 vinfo("writing Chonk vk in directory ", output_dir);
100 // write CHONK vk using the bytecode of the Hiding kernel (the last step of the execution)
101 write_chonk_vk(raw_steps[raw_steps.size() - 1].bytecode, output_dir);
102 }
103}
104
105bool ChonkAPI::verify([[maybe_unused]] const Flags& flags,
106 [[maybe_unused]] const std::filesystem::path& public_inputs_path,
107 const std::filesystem::path& proof_path,
108 const std::filesystem::path& vk_path)
109{
110 BB_BENCH_NAME("ChonkAPI::verify");
111 auto proof_fields = many_from_buffer<fr>(read_file(proof_path));
112 auto proof = Chonk::Proof::from_field_elements(proof_fields);
113
114 auto vk_buffer = read_file(vk_path);
115
116 auto response = bbapi::ChonkVerify{ .proof = std::move(proof), .vk = std::move(vk_buffer) }.execute();
117 return response.valid;
118}
119
120// WORKTODO(bbapi) remove this
121bool ChonkAPI::prove_and_verify(const std::filesystem::path& input_path)
122{
125
127 // Construct the hiding kernel as the final step of the IVC
128
129 auto proof = ivc->prove();
130 const bool verified = Chonk::verify(proof, ivc->get_vk());
131 return verified;
132}
133
134void ChonkAPI::gates(const Flags& flags, const std::filesystem::path& bytecode_path)
135{
136 BB_BENCH_NAME("ChonkAPI::gates");
137 chonk_gate_count(bytecode_path, flags.include_gates_per_opcode);
138}
139
140void ChonkAPI::write_solidity_verifier([[maybe_unused]] const Flags& flags,
141 [[maybe_unused]] const std::filesystem::path& output_path,
142 [[maybe_unused]] const std::filesystem::path& vk_path)
143{
144 BB_BENCH_NAME("ChonkAPI::write_solidity_verifier");
145 throw_or_abort("API function contract not implemented");
146}
147
148bool ChonkAPI::check_precomputed_vks(const Flags& flags, const std::filesystem::path& input_path)
149{
150 BB_BENCH_NAME("ChonkAPI::check_precomputed_vks");
151 bbapi::BBApiRequest request;
153
155 bool check_failed = false;
156 for (auto& step : raw_steps) {
157 if (step.vk.empty()) {
158 info("FAIL: Expected precomputed vk for function ", step.function_name);
159 return false;
160 }
161 auto response = bbapi::ChonkCheckPrecomputedVk{
162 .circuit = { .name = step.function_name, .bytecode = step.bytecode, .verification_key = step.vk }
163 }.execute();
164
165 if (!response.valid) {
166 info("VK mismatch detected for function ", step.function_name);
167 if (vk_policy != bbapi::VkPolicy::REWRITE) {
168 info("Computed VK differs from precomputed VK in ivc-inputs.msgpack");
169 return false;
170 }
171 info("Updating VK in ivc-inputs.msgpack with computed value");
172 step.vk = response.actual_vk;
173 check_failed = true;
174 }
175 }
176 if (check_failed) {
178 return false;
179 }
180 return true;
181}
182
183void ChonkAPI::write_vk(const Flags& flags,
184 const std::filesystem::path& bytecode_path,
185 const std::filesystem::path& output_path)
186{
187 BB_BENCH_NAME("ChonkAPI::write_vk");
188 auto bytecode = get_bytecode(bytecode_path);
189 if (flags.verifier_type == "ivc") {
190 write_chonk_vk(bytecode, output_path);
191 } else if (flags.verifier_type == "standalone") {
192 write_standalone_vk(bytecode, output_path);
193 } else if (flags.verifier_type == "standalone_hiding") {
194 // write the VK for the hiding kernel which DOES NOT utilize a structured trace
195 write_standalone_vk(bytecode, output_path);
196 } else {
197 const std::string msg = std::string("Can't write vk for verifier type ") + flags.verifier_type;
198 throw_or_abort(msg);
199 }
200}
201
202bool ChonkAPI::check([[maybe_unused]] const Flags& flags,
203 [[maybe_unused]] const std::filesystem::path& bytecode_path,
204 [[maybe_unused]] const std::filesystem::path& witness_path)
205{
206 throw_or_abort("API function check_witness not implemented");
207 return false;
208}
209
210void chonk_gate_count(const std::string& bytecode_path, bool include_gates_per_opcode)
211{
212 BB_BENCH_NAME("chonk_gate_count");
213 // All circuit reports will be built into the std::string below
214 std::string functions_string = "{\"functions\": [\n ";
215
216 bbapi::BBApiRequest request;
217
218 auto bytecode = get_bytecode(bytecode_path);
219 auto response = bbapi::ChonkStats{ .circuit = { .name = "ivc_circuit", .bytecode = std::move(bytecode) },
220 .include_gates_per_opcode = include_gates_per_opcode }
221 .execute(request);
222
223 // Build the circuit report. It always has one function, corresponding to the ACIR constraint systems.
224 // NOTE: can be reconsidered
225 std::string gates_per_opcode_str;
226 if (include_gates_per_opcode && !response.gates_per_opcode.empty()) {
227 for (size_t j = 0; j < response.gates_per_opcode.size(); j++) {
228 gates_per_opcode_str += std::to_string(response.gates_per_opcode[j]);
229 if (j != response.gates_per_opcode.size() - 1) {
230 gates_per_opcode_str += ",";
231 }
232 }
233 }
234 auto result_string = format(
235 "{\n \"acir_opcodes\": ",
236 response.acir_opcodes,
237 ",\n \"circuit_size\": ",
238 response.circuit_size,
239 (include_gates_per_opcode ? format(",\n \"gates_per_opcode\": [", gates_per_opcode_str, "]") : ""),
240 "\n }");
241 functions_string = format(functions_string, result_string);
242 std::cout << format(functions_string, "\n]}");
243}
244
245} // namespace bb
void write_bytes_to_stdout(const std::vector< uint8_t > &data)
Writes raw bytes of the vector to stdout.
Definition log.hpp:21
std::shared_ptr< Napi::ThreadSafeFunction > bytecode
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:219
bool prove_and_verify(const std::filesystem::path &input_path)
bool verify(const Flags &flags, const std::filesystem::path &public_inputs_path, const std::filesystem::path &proof_path, const std::filesystem::path &vk_path) override
void write_vk(const Flags &flags, const std::filesystem::path &bytecode_path, const std::filesystem::path &output_path) override
void prove(const Flags &flags, const std::filesystem::path &input_path, const std::filesystem::path &output_dir)
Definition api_chonk.cpp:58
bool check(const Flags &flags, const std::filesystem::path &bytecode_path, const std::filesystem::path &witness_path) override
void gates(const Flags &flags, const std::filesystem::path &bytecode_path) override
bool check_precomputed_vks(const Flags &flags, const std::filesystem::path &input_path)
void write_solidity_verifier(const Flags &flags, const std::filesystem::path &output_path, const std::filesystem::path &vk_path) override
static bool verify(const Proof &proof, const VerificationKey &vk)
Definition chonk.cpp:528
std::string format(Args... args)
Definition log.hpp:22
#define vinfo(...)
Definition log.hpp:80
void info(Args... args)
Definition log.hpp:75
uint8_t const * buf
Definition data_store.hpp:9
std::vector< uint8_t > get_bytecode(const std::string &bytecodePath)
VkPolicy
Policy for handling verification keys during IVC accumulation.
VkPolicy parse_vk_policy(const std::string &policy)
Convert VK policy string to enum for internal use.
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
void chonk_gate_count(const std::string &bytecode_path, bool include_gates_per_opcode)
std::vector< uint8_t > read_file(const std::string &filename, size_t bytes=0)
Definition file_io.hpp:29
void write_file(const std::string &filename, std::vector< uint8_t > const &data)
Definition file_io.hpp:58
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
std::vector< uint8_t > to_buffer(T const &value)
bool include_gates_per_opcode
Definition api.hpp:23
bool write_vk
Definition api.hpp:22
std::string verifier_type
Definition api.hpp:20
std::string vk_policy
Definition api.hpp:26
static Proof from_field_elements(const std::vector< Chonk::FF > &fields)
Definition chonk.cpp:571
static void compress_and_save(std::vector< PrivateExecutionStepRaw > &&steps, const std::filesystem::path &output_path)
static std::vector< PrivateExecutionStepRaw > load_and_decompress(const std::filesystem::path &input_path)
std::shared_ptr< Chonk > accumulate()
void parse(std::vector< PrivateExecutionStepRaw > &&steps)
Accumulate the previously loaded circuit into the IVC proof.
std::vector< uint8_t > witness
Serialized witness data for the last loaded circuit.
Verify that a precomputed verification key matches the circuit.
CircuitInput circuit
Circuit with its precomputed verification key.
Compute IVC verification key for the complete proof.
Compute standalone verification key for a circuit.
Load a circuit into the Chonk instance for accumulation.
CircuitInput circuit
Circuit to be loaded with its bytecode and verification key.
Chonk::Proof proof
Complete IVC proof for all accumulated circuits.
Generate a proof for all accumulated circuits.
Response execute(BBApiRequest &request) &&
Initialize a new Chonk instance for incremental proof accumulation.
Get gate counts for a circuit.
CircuitInputNoVK circuit
The circuit to analyze.
Verify a Chonk proof with its verification key.
Chonk::Proof proof
The Chonk proof to verify.
std::string name
Human-readable name for the circuit.
std::string name
Human-readable name for the circuit.
std::vector< uint8_t > bytecode
Serialized bytecode representation of the circuit.
void throw_or_abort(std::string const &err)