Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
bbapi_chonk.cpp
Go to the documentation of this file.
5#include "barretenberg/bbapi/generated/bb_types.hpp"
23
24#ifdef BBAPI_CHONK_BATCH_VERIFIER_SUPPORTED
25#include <algorithm>
26#include <cerrno>
27#include <chrono>
28#include <csignal>
29#include <cstring>
30#include <fcntl.h>
31#include <limits>
32#include <sys/stat.h>
33#include <thread>
34#include <unistd.h>
35#endif // BBAPI_CHONK_BATCH_VERIFIER_SUPPORTED
36
37#ifdef BB_NO_EXCEPTIONS
38#define try if (true)
39#define catch(...) if (false)
40#define BBAPI_CHONK_UNDEF_TRY_CATCH
41#endif
42
43namespace bb::bbapi {
44
45// BB_NO_EXCEPTIONS rewrites catch blocks away; handlers must not depend on catch bindings.
46#ifndef BB_NO_EXCEPTIONS
47#define BBAPI_CHONK_EXCEPTION_WHAT(exception) (exception).what()
48#else
49#define BBAPI_CHONK_EXCEPTION_WHAT(exception) "unknown exception"
50#endif
51
52template <typename VerificationKey> bool has_expected_vk_size(const std::vector<uint8_t>& vk_bytes, const char* label)
53{
54 const size_t expected_size = VerificationKey::calc_num_data_types() * sizeof(bb::fr);
55 if (vk_bytes.size() == expected_size) {
56 return true;
57 }
58 // Wasm builds cannot catch throw_or_abort from validate_vk_size.
59 info(label, ": verification key has wrong size: expected ", expected_size, ", got ", vk_bytes.size());
60 return false;
61}
62
63wire::ChonkStartResponse handle_chonk_start(BBApiRequest& request, wire::ChonkStart&& cmd)
64{
65 BB_BENCH_NAME("ChonkStart");
66
67 request.ivc_in_progress = std::make_shared<Chonk>(cmd.num_circuits);
68 request.ivc_stack_depth = 0;
69
70 // Clear any stale loaded-circuit state from a previous session so that
71 // ChonkAccumulate cannot silently reuse a circuit loaded before this ChonkStart.
72 request.loaded_circuit_name.clear();
73 request.loaded_circuit_constraints.reset();
74 request.loaded_circuit_vk.clear();
75
76 return {};
77}
78
79wire::ChonkLoadResponse handle_chonk_load(BBApiRequest& request, wire::ChonkLoad&& cmd)
80{
81 BB_BENCH_NAME("ChonkLoad");
82 if (!request.ivc_in_progress) {
83 throw_or_abort("Chonk not started. Call ChonkStart first.");
84 }
85
86 request.loaded_circuit_name = cmd.circuit.name;
88 request.loaded_circuit_vk = cmd.circuit.verification_key;
89
90 info("ChonkLoad - loaded circuit '", request.loaded_circuit_name, "'");
91 return {};
92}
93
94wire::ChonkAccumulateResponse handle_chonk_accumulate(BBApiRequest& request, wire::ChonkAccumulate&& cmd)
95{
96 BB_BENCH_NAME("ChonkAccumulate");
97 if (!request.ivc_in_progress) {
98 throw_or_abort("Chonk not started. Call ChonkStart first.");
99 }
100 if (!request.loaded_circuit_constraints.has_value()) {
101 throw_or_abort("No circuit loaded. Call ChonkLoad first.");
102 }
103
105 acir_format::AcirProgram program{ std::move(request.loaded_circuit_constraints.value()), std::move(witness_data) };
106
107 // Clear loaded state immediately after moving out of it. This ensures that
108 // if any subsequent step throws, the request won't appear to still have a
109 // valid circuit loaded.
110 auto loaded_vk = std::move(request.loaded_circuit_vk);
111 auto circuit_name = std::move(request.loaded_circuit_name);
112 request.loaded_circuit_constraints.reset();
113 request.loaded_circuit_vk.clear();
114 request.loaded_circuit_name.clear();
115
116 // The hiding kernel is definitionally the last circuit in the IVC stack.
118 const bool is_hiding_kernel = (request.ivc_stack_depth + 1 == chonk->get_num_circuits());
119
120 const acir_format::ProgramMetadata metadata{ .ivc = request.ivc_in_progress };
121 auto circuit = acir_format::create_circuit<IVCBase::ClientCircuit>(program, metadata);
122
124 if (request.vk_policy == VkPolicy::RECOMPUTE) {
125 precomputed_vk = nullptr;
126 } else if (request.vk_policy == VkPolicy::DEFAULT || request.vk_policy == VkPolicy::CHECK) {
127 if (!loaded_vk.empty()) {
128 validate_vk_size<Chonk::MegaVerificationKey>(loaded_vk);
129 precomputed_vk = from_buffer<std::shared_ptr<Chonk::MegaVerificationKey>>(loaded_vk);
130
131 if (request.vk_policy == VkPolicy::CHECK) {
132 // MegaZKVerificationKey and MegaVerificationKey share the same
133 // C++ type, but their contents differ between ZK and non-ZK flavors.
134 auto computed_vk = is_hiding_kernel ? std::make_shared<Chonk::MegaVerificationKey>(
135 Chonk::HidingKernelProverInstance(circuit).get_precomputed())
137 Chonk::ProverInstance(circuit).get_precomputed());
138 if (*precomputed_vk != *computed_vk) {
139 throw_or_abort("VK check failed for circuit '" + circuit_name +
140 "': provided VK does not match computed VK");
141 }
142 }
143 }
144 } else {
145 throw_or_abort("Invalid VK policy. Valid options: default, check, recompute");
146 }
147
148 info("ChonkAccumulate - accumulating circuit '", circuit_name, "'");
151 }
152 request.ivc_in_progress->accumulate(circuit, precomputed_vk);
153 request.ivc_stack_depth++;
154 return {};
155}
156
157wire::ChonkProveResponse handle_chonk_prove(BBApiRequest& request, wire::ChonkProve&& /*cmd*/)
158{
159 BB_BENCH_NAME("ChonkProve");
160 if (!request.ivc_in_progress) {
161 throw_or_abort("Chonk not started. Call ChonkStart first.");
162 }
163 if (request.ivc_stack_depth == 0) {
164 throw_or_abort("No circuits accumulated. Call ChonkAccumulate first.");
165 }
166
167 info("ChonkProve - generating proof for ", request.ivc_stack_depth, " accumulated circuits");
168
169 info("ChonkProve - using Chonk");
171 auto proof = chonk->prove();
172 auto vk_and_hash = chonk->get_hiding_kernel_vk_and_hash();
173
174 // Verify here so failures surface at proof production time rather than
175 // later in the transaction lifecycle.
176 info("ChonkProve - verifying the generated proof as a sanity check");
177 ChonkNativeVerifier verifier(vk_and_hash);
178 bool verification_passed = verifier.verify(proof);
179 if (!verification_passed) {
180 throw_or_abort("Failed to verify the generated proof!");
181 }
182
183 request.ivc_in_progress.reset();
184 request.ivc_stack_depth = 0;
185 return { .proof = chonk_proof_to_wire(proof) };
186}
187
188wire::ChonkVerifyResponse handle_chonk_verify(BBApiRequest& /*request*/, wire::ChonkVerify&& cmd)
189{
190 BB_BENCH_NAME("ChonkVerify");
191
192 try {
194 if (!has_expected_vk_size<VerificationKey>(cmd.vk, "ChonkVerify")) {
195 return { .valid = false };
196 }
197
198 auto hiding_kernel_vk = std::make_shared<VerificationKey>(from_buffer<VerificationKey>(cmd.vk));
199 auto proof = chonk_proof_from_wire(std::move(cmd.proof));
200
201 // The proof contains public inputs followed by the fixed-size proof body.
202 const size_t expected_proof_size =
203 static_cast<size_t>(hiding_kernel_vk->num_public_inputs) + ChonkProof::PROOF_LENGTH_WITHOUT_PUB_INPUTS;
204 if (proof.size() != expected_proof_size) {
205 info("ChonkVerify: proof has wrong size: expected ", expected_proof_size, ", got ", proof.size());
206 return { .valid = false };
207 }
208
209 auto vk_and_hash = std::make_shared<ChonkNativeVerifier::VKAndHash>(hiding_kernel_vk);
210 ChonkNativeVerifier verifier(vk_and_hash);
211 return { .valid = verifier.verify(proof) };
212 } catch (const std::exception& e) {
213 info("ChonkVerify: malformed input: ", BBAPI_CHONK_EXCEPTION_WHAT(e));
214 return { .valid = false };
215 } catch (...) {
216 info("ChonkVerify: malformed input: unknown exception");
217 return { .valid = false };
218 }
219}
220
221wire::ChonkVerifyFromFieldsResponse handle_chonk_verify_from_fields(BBApiRequest& /*request*/,
222 wire::ChonkVerifyFromFields&& cmd)
223{
224 BB_BENCH_NAME("ChonkVerifyFromFields");
225
226 try {
228 if (!has_expected_vk_size<VerificationKey>(cmd.vk, "ChonkVerifyFromFields")) {
229 return { .valid = false };
230 }
231
232 auto hiding_kernel_vk = std::make_shared<VerificationKey>(from_buffer<VerificationKey>(cmd.vk));
233 auto proof = fr_vec_from_wire(cmd.proof);
234
235 // The field array contains public inputs followed by the fixed-size proof body.
236 const size_t expected_field_count =
237 static_cast<size_t>(hiding_kernel_vk->num_public_inputs) + ChonkProof::PROOF_LENGTH_WITHOUT_PUB_INPUTS;
238 if (proof.size() != expected_field_count) {
239 info("ChonkVerifyFromFields: proof has wrong field count: expected ",
240 expected_field_count,
241 ", got ",
242 proof.size());
243 return { .valid = false };
244 }
245
246 // Layout knowledge stays here rather than leaking to callers.
247 auto structured = ChonkProof::from_field_elements(proof);
248
249 auto vk_and_hash = std::make_shared<ChonkNativeVerifier::VKAndHash>(hiding_kernel_vk);
250 ChonkNativeVerifier verifier(vk_and_hash);
251 return { .valid = verifier.verify(structured) };
252 } catch (const std::exception& e) {
253 info("ChonkVerifyFromFields: malformed input: ", BBAPI_CHONK_EXCEPTION_WHAT(e));
254 return { .valid = false };
255 } catch (...) {
256 info("ChonkVerifyFromFields: malformed input: unknown exception");
257 return { .valid = false };
258 }
259}
260
261wire::ChonkBatchVerifyResponse handle_chonk_batch_verify(BBApiRequest& /*request*/, wire::ChonkBatchVerify&& cmd)
262{
263 BB_BENCH_NAME("ChonkBatchVerify");
264
265 try {
266 if (cmd.proofs.size() != cmd.vks.size()) {
267 info("ChonkBatchVerify: proofs.size() (", cmd.proofs.size(), ") != vks.size() (", cmd.vks.size(), ")");
268 return { .valid = false };
269 }
270 if (cmd.proofs.empty()) {
271 info("ChonkBatchVerify: no proofs provided");
272 return { .valid = false };
273 }
274
276
279 ipa_claims.reserve(cmd.proofs.size());
280 ipa_transcripts.reserve(cmd.proofs.size());
281
282 auto proofs = chonk_proof_vec_from_wire(std::move(cmd.proofs));
283 for (size_t i = 0; i < proofs.size(); ++i) {
284 if (!has_expected_vk_size<VerificationKey>(cmd.vks[i], "ChonkBatchVerify")) {
285 return { .valid = false };
286 }
287 auto hiding_kernel_vk = std::make_shared<VerificationKey>(from_buffer<VerificationKey>(cmd.vks[i]));
288
289 const size_t expected_proof_size =
290 static_cast<size_t>(hiding_kernel_vk->num_public_inputs) + ChonkProof::PROOF_LENGTH_WITHOUT_PUB_INPUTS;
291 if (proofs[i].size() != expected_proof_size) {
292 info("ChonkBatchVerify: proof[",
293 i,
294 "] has wrong size: expected ",
295 expected_proof_size,
296 ", got ",
297 proofs[i].size());
298 return { .valid = false };
299 }
300
301 auto vk_and_hash = std::make_shared<ChonkNativeVerifier::VKAndHash>(hiding_kernel_vk);
302 ChonkNativeVerifier verifier(vk_and_hash);
303 auto result = verifier.reduce_to_ipa_claim(std::move(proofs[i]));
304 if (!result.all_checks_passed) {
305 return { .valid = false };
306 }
307 ipa_claims.push_back(std::move(result.ipa_claim));
308 ipa_transcripts.push_back(std::make_shared<NativeTranscript>(std::move(result.ipa_proof)));
309 }
310
312 return { .valid = IPA<curve::Grumpkin>::batch_reduce_verify(ipa_vk, ipa_claims, ipa_transcripts) };
313 } catch (const std::exception& e) {
314 info("ChonkBatchVerify: malformed input: ", BBAPI_CHONK_EXCEPTION_WHAT(e));
315 return { .valid = false };
316 } catch (...) {
317 info("ChonkBatchVerify: malformed input: unknown exception");
318 return { .valid = false };
319 }
320}
321
322namespace {
323std::shared_ptr<Chonk::MegaVerificationKey> compute_chonk_vk_from_program(acir_format::AcirProgram& program,
324 bool use_zk_flavor)
325{
326 Chonk::ClientCircuit builder = acir_format::create_circuit<Chonk::ClientCircuit>(program);
327 if (use_zk_flavor) {
329 Chonk::HidingKernelProverInstance(builder).get_precomputed());
330 }
332}
333} // namespace
334
335wire::ChonkComputeVkResponse handle_chonk_compute_vk(BBApiRequest& /*request*/, wire::ChonkComputeVk&& cmd)
336{
337 BB_BENCH_NAME("ChonkComputeVk");
338 info("ChonkComputeVk - deriving MegaVerificationKey for circuit '",
339 cmd.circuit.name,
340 "'",
341 cmd.use_zk_flavor ? " (MegaZK)" : "");
342
343 auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(cmd.circuit.bytecode));
344 acir_format::AcirProgram program{ constraint_system, /*witness=*/{} };
345 auto verification_key = compute_chonk_vk_from_program(program, cmd.use_zk_flavor);
346
347 info("ChonkComputeVk - VK derived, size: ", to_buffer(*verification_key).size(), " bytes");
348
349 return { .bytes = to_buffer(*verification_key), .fields = fr_vec_to_wire(verification_key->to_field_elements()) };
350}
351
352wire::ChonkCheckPrecomputedVkResponse handle_chonk_check_precomputed_vk(BBApiRequest& /*request*/,
353 wire::ChonkCheckPrecomputedVk&& cmd)
354{
355 BB_BENCH_NAME("ChonkCheckPrecomputedVk");
357 /*witness=*/{} };
358 auto computed_vk = compute_chonk_vk_from_program(program, cmd.use_zk_flavor);
359
360 if (cmd.circuit.verification_key.empty()) {
361 info("FAIL: Expected precomputed vk for function ", cmd.circuit.name);
362 throw_or_abort("Missing precomputed VK");
363 }
364
365 validate_vk_size<Chonk::MegaVerificationKey>(cmd.circuit.verification_key);
366 auto precomputed_vk = from_buffer<std::shared_ptr<Chonk::MegaVerificationKey>>(cmd.circuit.verification_key);
367
368 wire::ChonkCheckPrecomputedVkResponse response;
369 response.valid = true;
370 if (*computed_vk != *precomputed_vk) {
371 response.valid = false;
372 response.actual_vk = to_buffer(computed_vk);
373 }
374 return response;
375}
376
377wire::ChonkStatsResponse handle_chonk_stats(BBApiRequest& /*request*/, wire::ChonkStats&& cmd)
378{
379 BB_BENCH_NAME("ChonkStats");
380
381 const auto constraint_system = acir_format::circuit_buf_to_acir_format(std::move(cmd.circuit.bytecode));
382 acir_format::AcirProgram program{ constraint_system, {} };
383 const auto& ivc_constraints = constraint_system.hn_recursion_constraints;
384
386 .ivc = ivc_constraints.empty() ? nullptr : acir_format::create_mock_chonk_from_constraints(ivc_constraints),
387 .collect_gates_per_opcode = cmd.include_gates_per_opcode
388 };
389
390 auto builder = acir_format::create_circuit<MegaCircuitBuilder>(program, metadata);
391 builder.finalize_circuit();
392
393 wire::ChonkStatsResponse response;
394 response.acir_opcodes = program.constraints.num_acir_opcodes;
395 response.circuit_size = static_cast<uint32_t>(builder.num_gates());
396 if (cmd.include_gates_per_opcode) {
397 response.gates_per_opcode = std::vector<uint32_t>(program.constraints.gates_per_opcode.begin(),
398 program.constraints.gates_per_opcode.end());
399 }
400
401 info("ChonkStats - circuit: ",
402 cmd.circuit.name,
403 ", acir_opcodes: ",
404 response.acir_opcodes,
405 ", circuit_size: ",
406 response.circuit_size);
407 builder.blocks.summarize();
408 return response;
409}
410
411wire::ChonkCompressProofResponse handle_chonk_compress_proof(BBApiRequest& /*request*/, wire::ChonkCompressProof&& cmd)
412{
413 BB_BENCH_NAME("ChonkCompressProof");
414 auto proof = chonk_proof_from_wire(std::move(cmd.proof));
415 return { .compressed_proof = ProofCompressor::compress_chonk_proof(proof) };
416}
417
418wire::ChonkDecompressProofResponse handle_chonk_decompress_proof(BBApiRequest& /*request*/,
419 wire::ChonkDecompressProof&& cmd)
420{
421 BB_BENCH_NAME("ChonkDecompressProof");
422 size_t mega_num_pub = ProofCompressor::compressed_mega_num_public_inputs(cmd.compressed_proof.size());
423 auto proof = ProofCompressor::decompress_chonk_proof(cmd.compressed_proof, mega_num_pub);
424 return { .proof = chonk_proof_to_wire(proof) };
425}
426
427// ── Batch Verifier Service ──────────────────────────────────────────────────
428
429#ifdef BBAPI_CHONK_BATCH_VERIFIER_SUPPORTED
430
431namespace {
432
433bool write_all(int fd, const uint8_t* ptr, size_t len)
434{
435 while (len > 0) {
436 const auto chunk_len =
437 static_cast<unsigned int>(std::min<size_t>(len, std::numeric_limits<unsigned int>::max()));
438 const ssize_t written = ::write(fd, ptr, chunk_len);
439 if (written > 0) {
440 ptr += written;
441 len -= static_cast<size_t>(written);
442 continue;
443 }
444 if (written < 0 && errno == EINTR) {
445 continue;
446 }
447 if (written < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
448 std::this_thread::sleep_for(std::chrono::milliseconds(1));
449 continue;
450 }
451 return false;
452 }
453 return true;
454}
455
456bool write_frame(int fd, const void* data, size_t len)
457{
458 if (len > UINT32_MAX) {
459 return false;
460 }
461 auto len32 = static_cast<uint32_t>(len);
462 std::vector<uint8_t> header = {
463 static_cast<uint8_t>((len32 >> 24) & 0xFF),
464 static_cast<uint8_t>((len32 >> 16) & 0xFF),
465 static_cast<uint8_t>((len32 >> 8) & 0xFF),
466 static_cast<uint8_t>(len32 & 0xFF),
467 };
468
469 return write_all(fd, header.data(), header.size()) && write_all(fd, reinterpret_cast<const uint8_t*>(data), len);
470}
471
472} // namespace
473
475 uint32_t num_cores,
476 uint32_t batch_size,
477 const std::string& fifo_path)
478{
479 bool expected = false;
480 if (!running_.compare_exchange_strong(expected, true)) {
481 throw_or_abort("ChonkBatchVerifierService: already running");
482 }
483
484 if (num_cores == 0) {
485 num_cores = static_cast<uint32_t>(std::thread::hardware_concurrency());
486 if (num_cores == 0) {
487 num_cores = 1;
488 }
489 }
490
491#ifdef SIGPIPE
492 (void)std::signal(SIGPIPE, SIG_IGN);
493#endif
494 fifo_path_ = fifo_path;
495 fifo_failed_.store(false);
496
497 try {
499 std::move(vks), num_cores, batch_size, [this](VerifyResult result) { write_result(std::move(result)); });
500 } catch (...) {
501 running_.store(false);
502 throw;
503 }
504
505 info("ChonkBatchVerifierService started, fifo=", fifo_path);
506}
507
509{
510 if (fifo_failed_.load()) {
511 throw_or_abort("ChonkBatchVerifierService: result FIFO failed");
512 }
513 verifier_.enqueue(std::move(request));
514}
515
516void ChonkBatchVerifierService::fail_request(uint64_t request_id, std::string error_message)
517{
518 write_result(VerifyResult::failed(request_id, std::move(error_message)));
519}
520
522{
523 if (!running_.exchange(false)) {
524 return;
525 }
526
527 verifier_.stop();
528
529 {
530 std::lock_guard lock(fifo_mutex_);
532 fifo_path_.clear();
533 }
534
535 info("ChonkBatchVerifierService stopped");
536}
537
539{
540 if (running_.load()) {
541 stop();
542 }
543}
544
546{
547 if (fifo_fd_ >= 0) {
548 return true;
549 }
550 if (fifo_path_.empty()) {
551 return false;
552 }
553
554#ifndef _WIN32
555 struct stat statbuf;
556 if (lstat(fifo_path_.c_str(), &statbuf) != 0) {
557 info("ChonkBatchVerifierService: failed to stat FIFO '", fifo_path_, "': ", std::strerror(errno));
558 return false;
559 }
560 if (!S_ISFIFO(statbuf.st_mode)) {
561 info("ChonkBatchVerifierService: result path is not a FIFO: ", fifo_path_);
562 return false;
563 }
564#endif
565
566 for (size_t attempt = 0; attempt < 100; ++attempt) {
567#ifndef _WIN32
568 fifo_fd_ = open(fifo_path_.c_str(), O_WRONLY | O_NONBLOCK | O_CLOEXEC | O_NOFOLLOW);
569#else
570 fifo_fd_ = open(fifo_path_.c_str(), O_WRONLY);
571#endif
572 if (fifo_fd_ >= 0) {
573#ifndef _WIN32
574 struct stat opened_statbuf;
575 if (fstat(fifo_fd_, &opened_statbuf) != 0 || !S_ISFIFO(opened_statbuf.st_mode)) {
576 info("ChonkBatchVerifierService: opened result path is not a FIFO: ", fifo_path_);
577 close(fifo_fd_);
578 fifo_fd_ = -1;
579 return false;
580 }
581#endif
582 return true;
583 }
584 if (errno != ENXIO && errno != EINTR) {
585 info("ChonkBatchVerifierService: failed to open FIFO '", fifo_path_, "': ", std::strerror(errno));
586 return false;
587 }
588 std::this_thread::sleep_for(std::chrono::milliseconds(1));
589 }
590 info("ChonkBatchVerifierService: no FIFO reader connected for '", fifo_path_, "'");
591 return false;
592}
593
595{
596 if (fifo_fd_ >= 0) {
597 close(fifo_fd_);
598 fifo_fd_ = -1;
599 }
600}
601
602bool ChonkBatchVerifierService::fail_fifo_locked(const std::string& message)
603{
604 if (!fifo_failed_.exchange(true)) {
605 info("ChonkBatchVerifierService: ", message);
606 }
608 fifo_path_.clear();
609 return false;
610}
611
613{
614 msgpack::sbuffer buf;
615 msgpack::pack(buf, result);
616
617 std::lock_guard lock(fifo_mutex_);
618 if (fifo_failed_.load()) {
619 return false;
620 }
621 if (!ensure_fifo_open()) {
622 return fail_fifo_locked("result FIFO unavailable");
623 }
624
625 if (!write_frame(fifo_fd_, buf.data(), buf.size())) {
626 return fail_fifo_locked(std::string("FIFO write failed: ") + std::strerror(errno));
627 }
628 return true;
629}
630
631// ── Batch Verifier RPC Commands ─────────────────────────────────────────────
632
633wire::ChonkBatchVerifierStartResponse handle_chonk_batch_verifier_start(BBApiRequest& request,
634 wire::ChonkBatchVerifierStart&& cmd)
635{
636 if (request.batch_verifier_service && request.batch_verifier_service->is_running()) {
637 throw_or_abort("ChonkBatchVerifierStart: service already running. Call ChonkBatchVerifierStop first.");
638 }
639
641
643 parsed_vks.reserve(cmd.vks.size());
644
645 for (size_t i = 0; i < cmd.vks.size(); ++i) {
646 validate_vk_size<VerificationKey>(cmd.vks[i]);
647 auto vk = std::make_shared<VerificationKey>(from_buffer<VerificationKey>(cmd.vks[i]));
648 parsed_vks.push_back(std::make_shared<MegaZKFlavor::VKAndHash>(vk));
649 }
650
651 request.batch_verifier_service = std::make_shared<ChonkBatchVerifierService>();
652 request.batch_verifier_service->start(std::move(parsed_vks), cmd.num_cores, cmd.batch_size, cmd.fifo_path);
653 return {};
654}
655
656wire::ChonkBatchVerifierQueueResponse handle_chonk_batch_verifier_queue(BBApiRequest& request,
657 wire::ChonkBatchVerifierQueue&& cmd)
658{
659 if (!request.batch_verifier_service || !request.batch_verifier_service->is_running()) {
660 throw_or_abort("ChonkBatchVerifierQueue: service not running. Call ChonkBatchVerifierStart first.");
661 }
662
663 ChonkProof proof;
664 try {
665 proof = ChonkProof::from_field_elements(fr_vec_from_wire(cmd.proof_fields));
666 } catch (const std::exception& e) {
667 request.batch_verifier_service->fail_request(cmd.request_id,
668 std::string("malformed proof fields: ") + e.what());
669 return {};
670 } catch (...) {
671 request.batch_verifier_service->fail_request(cmd.request_id, "malformed proof fields: unknown exception");
672 return {};
673 }
674
675 try {
676 request.batch_verifier_service->enqueue(VerifyRequest{
677 .request_id = cmd.request_id,
678 .vk_index = cmd.vk_index,
679 .proof = std::move(proof),
680 });
681 } catch (const std::exception& e) {
682 request.batch_verifier_service->fail_request(cmd.request_id, e.what());
683 } catch (...) {
684 request.batch_verifier_service->fail_request(cmd.request_id, "failed to enqueue proof: unknown exception");
685 }
686
687 return {};
688}
689
690wire::ChonkBatchVerifierStopResponse handle_chonk_batch_verifier_stop(BBApiRequest& request,
691 wire::ChonkBatchVerifierStop&& /*cmd*/)
692{
693 if (!request.batch_verifier_service || !request.batch_verifier_service->is_running()) {
694 throw_or_abort("ChonkBatchVerifierStop: service not running.");
695 }
696
697 request.batch_verifier_service->stop();
698 request.batch_verifier_service.reset();
699 return {};
700}
701
702#else // BBAPI_CHONK_BATCH_VERIFIER_SUPPORTED
703
704wire::ChonkBatchVerifierStartResponse handle_chonk_batch_verifier_start(BBApiRequest& /*request*/,
705 wire::ChonkBatchVerifierStart&& /*cmd*/)
706{
707 throw_or_abort("ChonkBatchVerifierStart is not supported in this build");
708}
709
710wire::ChonkBatchVerifierQueueResponse handle_chonk_batch_verifier_queue(BBApiRequest& /*request*/,
711 wire::ChonkBatchVerifierQueue&& /*cmd*/)
712{
713 throw_or_abort("ChonkBatchVerifierQueue is not supported in this build");
714}
715
716wire::ChonkBatchVerifierStopResponse handle_chonk_batch_verifier_stop(BBApiRequest& /*request*/,
717 wire::ChonkBatchVerifierStop&& /*cmd*/)
718{
719 throw_or_abort("ChonkBatchVerifierStop is not supported in this build");
720}
721
722#endif // BBAPI_CHONK_BATCH_VERIFIER_SUPPORTED
723
724#undef BBAPI_CHONK_EXCEPTION_WHAT
725#ifdef BBAPI_CHONK_UNDEF_TRY_CATCH
726#undef try
727#undef catch
728#undef BBAPI_CHONK_UNDEF_TRY_CATCH
729#endif
730
731} // namespace bb::bbapi
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:264
#define BBAPI_CHONK_EXCEPTION_WHAT(exception)
Stateful Chonk batch-verifier service used by the IPC handlers.
Non-template handler declarations for the bb service.
Shared type definitions for the Barretenberg RPC API.
Wire <-> domain conversion helpers for the bbapi handlers.
void enqueue(VerifyRequest request)
Enqueue a proof for verification.
void stop()
Stop the processor, flushing remaining proofs.
void start(std::vector< std::shared_ptr< MegaZKFlavor::VKAndHash > > vks, uint32_t num_cores, uint32_t batch_size, ResultCallback on_result)
Start the coordinator thread.
Flavor::VerificationKey MegaVerificationKey
Definition chonk.hpp:44
Verifier for Chonk IVC proofs (both native and recursive).
IPAReductionResult reduce_to_ipa_claim(const Proof &proof)
Run Chonk verification up to but not including IPA, returning the IPA claim for deferred verification...
Output verify(const Proof &proof)
Verify a Chonk proof.
static constexpr size_t ECCVM_FIXED_SIZE
IPA (inner product argument) commitment scheme class.
Definition ipa.hpp:86
Base Native verification key class.
Definition flavor.hpp:137
static constexpr size_t calc_num_data_types()
Calculate the number of field elements needed for serialization.
Definition flavor.hpp:202
static std::vector< uint8_t > compress_chonk_proof(const ChonkProof &proof)
static ChonkProof decompress_chonk_proof(const std::vector< uint8_t > &compressed, size_t mega_num_public_inputs)
static size_t compressed_mega_num_public_inputs(size_t compressed_bytes)
Derive mega_num_public_inputs from compressed proof size.
Contains all the information required by a Honk prover to create a proof, constructed from a finalize...
Representation of the Grumpkin Verifier Commitment Key inside a bn254 circuit.
void enqueue(VerifyRequest request)
void fail_request(uint64_t request_id, std::string error_message)
bool write_result(VerifyResult result)
void start(std::vector< std::shared_ptr< MegaZKFlavor::VKAndHash > > vks, uint32_t num_cores, uint32_t batch_size, const std::string &fifo_path)
bool fail_fifo_locked(const std::string &message)
#define info(...)
Definition log.hpp:93
AluTraceBuilder builder
Definition alu.test.cpp:124
WitnessVector witness_buf_to_witness_vector(std::vector< uint8_t > &&buf)
Convert a buffer representing a witness vector into Barretenberg's internal WitnessVector format.
std::shared_ptr< Chonk > create_mock_chonk_from_constraints(const std::vector< RecursionConstraint > &constraints)
Create a Chonk instance with mocked state corresponding to a set of IVC recursion constraints.
std::vector< bb::fr > WitnessVector
AcirFormat circuit_buf_to_acir_format(std::vector< uint8_t > &&buf)
Convert a buffer representing a circuit into Barretenberg's internal AcirFormat representation.
wire::ChonkBatchVerifierStartResponse handle_chonk_batch_verifier_start(BBApiRequest &, wire::ChonkBatchVerifierStart &&)
bool has_expected_vk_size(const std::vector< uint8_t > &vk_bytes, const char *label)
wire::ChonkBatchVerifyResponse handle_chonk_batch_verify(BBApiRequest &, wire::ChonkBatchVerify &&cmd)
wire::ChonkVerifyResponse handle_chonk_verify(BBApiRequest &, wire::ChonkVerify &&cmd)
wire::ChonkProveResponse handle_chonk_prove(BBApiRequest &request, wire::ChonkProve &&)
wire::ChonkDecompressProofResponse handle_chonk_decompress_proof(BBApiRequest &, wire::ChonkDecompressProof &&cmd)
wire::ChonkProof chonk_proof_to_wire(const ChonkProof &d)
wire::ChonkCompressProofResponse handle_chonk_compress_proof(BBApiRequest &, wire::ChonkCompressProof &&cmd)
wire::ChonkAccumulateResponse handle_chonk_accumulate(BBApiRequest &request, wire::ChonkAccumulate &&cmd)
wire::ChonkLoadResponse handle_chonk_load(BBApiRequest &request, wire::ChonkLoad &&cmd)
ChonkProof chonk_proof_from_wire(wire::ChonkProof &&w)
wire::ChonkStartResponse handle_chonk_start(BBApiRequest &request, wire::ChonkStart &&cmd)
wire::ChonkBatchVerifierStopResponse handle_chonk_batch_verifier_stop(BBApiRequest &, wire::ChonkBatchVerifierStop &&)
std::vector< Fr > fr_vec_to_wire(const std::vector< bb::fr > &d)
wire::ChonkComputeVkResponse handle_chonk_compute_vk(BBApiRequest &, wire::ChonkComputeVk &&cmd)
wire::ChonkVerifyFromFieldsResponse handle_chonk_verify_from_fields(BBApiRequest &, wire::ChonkVerifyFromFields &&cmd)
wire::ChonkCheckPrecomputedVkResponse handle_chonk_check_precomputed_vk(BBApiRequest &, wire::ChonkCheckPrecomputedVk &&cmd)
std::vector< ChonkProof > chonk_proof_vec_from_wire(std::vector< wire::ChonkProof > &&w)
wire::ChonkBatchVerifierQueueResponse handle_chonk_batch_verifier_queue(BBApiRequest &, wire::ChonkBatchVerifierQueue &&)
std::vector< bb::fr > fr_vec_from_wire(const std::vector< Fr > &w)
wire::ChonkStatsResponse handle_chonk_stats(BBApiRequest &, wire::ChonkStats &&cmd)
bool use_memory_profile
MemoryProfile GLOBAL_MEMORY_PROFILE
field< Bn254FrParams > fr
Definition fr.hpp:155
void write(B &buf, field2< base_field, Params > const &value)
VerifierCommitmentKey< Curve > vk
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
uint8_t len
std::byte * data
std::vector< uint8_t > to_buffer(T const &value)
std::vector< size_t > gates_per_opcode
Struct containing both the constraints to be added to the circuit and the witness vector.
Metadata required to create a circuit.
std::shared_ptr< bb::IVCBase > ivc
static constexpr size_t PROOF_LENGTH_WITHOUT_PUB_INPUTS
static ChonkProof_ from_field_elements(const std::vector< FF > &fields)
Reconstruct proof from field elements.
A request to verify a single Chonk proof.
Result of verifying a single proof within a batch.
static VerifyResult failed(uint64_t id, std::string msg)
std::string loaded_circuit_name
std::shared_ptr< IVCBase > ivc_in_progress
std::vector< uint8_t > loaded_circuit_vk
std::optional< acir_format::AcirFormat > loaded_circuit_constraints
void set_circuit_name(const std::string &name)
void throw_or_abort(std::string const &err)