19 std::lock_guard lock(
mutex_);
40 bool has_failure =
false;
42 std::lock_guard lock(
mutex_);
44 throw_or_abort(
"ChonkBatchVerifier: enqueue called while verifier is not running");
63 const size_t expected_proof_size =
static_cast<size_t>(
vks_[request.
vk_index]->vk->num_public_inputs) +
65 if (request.
proof.
size() != expected_proof_size) {
67 "proof has wrong size: expected " +
std::to_string(expected_proof_size) +
84 std::thread coordinator_thread;
86 std::unique_lock lock(
mutex_);
101 if (coordinator_thread.joinable()) {
102 coordinator_thread.join();
105 std::lock_guard lock(
mutex_);
112 info(
"ChonkBatchVerifier stopped");
117 bool should_stop =
false;
119 std::lock_guard lock(
mutex_);
129 const uint64_t request_id = result.
request_id;
135 }
catch (
const std::exception& e) {
136 info(
"ChonkBatchVerifier: result callback threw: ", e.what());
138 info(
"ChonkBatchVerifier: result callback threw unknown exception");
140 std::lock_guard lock(
mutex_);
150 std::unique_lock lock(
mutex_);
160 auto end =
queue_.begin() +
static_cast<ptrdiff_t
>(take);
180 auto reduce_start = std::chrono::steady_clock::now();
184 std::vector<size_t> passed_indices;
185 passed_indices.reserve(reduce_results.size());
186 for (
size_t i = 0; i < reduce_results.size(); ++i) {
187 auto& rr = reduce_results[i];
188 if (!rr.all_checks_passed) {
190 result.time_in_queue_ms =
ms_between(rr.enqueue_time, reduce_start);
191 result.time_in_verify_ms = rr.reduce_ms;
194 passed_indices.push_back(i);
198 if (passed_indices.empty()) {
203 auto ipa_start = std::chrono::steady_clock::now();
204 bool ok =
batch_check(reduce_results, passed_indices);
205 double ipa_ms =
ms_since(ipa_start);
206 double reduce_ms =
ms_between(reduce_start, ipa_start);
208 info(
"ChonkBatchVerifier: batch of ",
209 passed_indices.size(),
215 ok ?
"OK" :
"BISECTING");
218 emit_ok(reduce_results, passed_indices, reduce_start, ipa_ms, 0);
220 bisect(reduce_results, passed_indices, 0, reduce_start);
228 const size_t num_proofs = batch.size();
230 std::atomic<size_t> work_index{ 0 };
232 uint32_t num_workers = std::min(
num_cores_,
static_cast<uint32_t
>(num_proofs));
233 std::vector<std::thread> workers;
234 workers.reserve(num_workers);
236 for (uint32_t w = 0; w < num_workers; ++w) {
237 workers.emplace_back([&]() {
242 if (idx >= num_proofs) {
245 auto& req = batch[idx];
246 auto t0 = std::chrono::steady_clock::now();
254 .ipa_claim =
std::move(reduced.ipa_claim),
255 .ipa_proof =
std::move(reduced.ipa_proof),
256 .all_checks_passed = reduced.all_checks_passed,
257 .error_message = reduced.all_checks_passed ?
"" :
"reduction failed",
258 .enqueue_time = req.enqueue_time,
261 }
catch (
const std::exception& e) {
266 .all_checks_passed =
false,
267 .error_message = std::string(
"reduce_to_ipa_claim threw: ") + e.what(),
268 .enqueue_time = req.enqueue_time,
276 .all_checks_passed =
false,
277 .error_message =
"reduce_to_ipa_claim threw unknown exception",
278 .enqueue_time = req.enqueue_time,
285 for (
auto& t : workers) {
294 if (indices.empty()) {
304 claims.reserve(indices.size());
305 transcripts.reserve(indices.size());
306 for (
size_t idx : indices) {
307 claims.push_back(results[idx].ipa_claim);
313 }
catch (
const std::exception& e) {
314 info(
"ChonkBatchVerifier: batch_check exception: ", e.what());
320 std::vector<size_t> indices,
322 std::chrono::steady_clock::time_point reduce_start)
325 if (indices.size() == 1) {
326 auto& rr = results[indices[0]];
327 auto result =
VerifyResult::failed(rr.request_id,
"batch check failed (bisected to individual)");
328 result.time_in_queue_ms =
ms_between(rr.enqueue_time, std::chrono::steady_clock::now());
329 result.time_in_verify_ms = rr.reduce_ms;
330 result.batch_failure_count = depth + 1;
335 info(
"ChonkBatchVerifier: bisecting ", indices.size(),
" proofs at depth ", depth);
337 size_t mid = indices.size() / 2;
338 std::vector<size_t> left(indices.begin(), indices.begin() +
static_cast<ptrdiff_t
>(mid));
339 std::vector<size_t> right(indices.begin() +
static_cast<ptrdiff_t
>(mid), indices.end());
342 auto t0 = std::chrono::steady_clock::now();
347 emit_ok(results, left, reduce_start, left_ms, depth + 1);
354 auto t1 = std::chrono::steady_clock::now();
359 emit_ok(results, right, reduce_start, right_ms, depth + 1);
367 const std::vector<size_t>& indices,
368 std::chrono::steady_clock::time_point reduce_start,
372 for (
size_t idx : indices) {
373 auto& rr = results[idx];
378 .time_in_queue_ms =
ms_between(rr.enqueue_time, reduce_start),
379 .time_in_verify_ms = rr.reduce_ms + ipa_ms,
380 .batch_failure_count = depth,
std::vector< ReduceResult > parallel_reduce(const std::vector< VerifyRequest > &batch)
void bisect(std::vector< ReduceResult > &results, std::vector< size_t > indices, uint32_t depth, std::chrono::steady_clock::time_point reduce_start)
static double ms_between(std::chrono::steady_clock::time_point from, std::chrono::steady_clock::time_point to)
std::thread coordinator_thread_
std::function< void(VerifyResult)> ResultCallback
void emit_ok(const std::vector< ReduceResult > &results, const std::vector< size_t > &indices, std::chrono::steady_clock::time_point reduce_start, double ipa_ms, uint32_t depth)
void dispatch(VerifyResult result)
bool batch_check(const std::vector< ReduceResult > &results, const std::vector< size_t > &indices)
std::condition_variable stopped_cv_
static double ms_since(std::chrono::steady_clock::time_point t)
static constexpr size_t MAX_QUEUE_SIZE
std::vector< std::shared_ptr< MegaZKFlavor::VKAndHash > > vks_
std::deque< VerifyRequest > queue_
std::unordered_set< uint64_t > in_flight_ids_
void enqueue(VerifyRequest request)
Enqueue a proof for verification.
std::condition_variable cv_
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.
ResultCallback on_result_
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...
static constexpr size_t ECCVM_FIXED_SIZE
IPA (inner product argument) commitment scheme class.
Representation of the Grumpkin Verifier Commitment Key inside a bn254 circuit.
Entry point for Barretenberg command-line interface.
void set_parallel_for_concurrency(size_t num_cores)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::string to_string(bb::avm2::ValueTag tag)
Per-proof result from the reduce phase.
static constexpr size_t PROOF_LENGTH_WITHOUT_PUB_INPUTS
A request to verify a single Chonk proof.
std::chrono::steady_clock::time_point enqueue_time
Result of verifying a single proof within a batch.
static VerifyResult failed(uint64_t id, std::string msg)
void throw_or_abort(std::string const &err)