30 std::lock_guard lock(
mutex_);
40 std::lock_guard lock(
mutex_);
47 info(
"ChonkBatchVerifier stopped");
63 std::unique_lock lock(
mutex_);
73 auto end =
queue_.begin() +
static_cast<ptrdiff_t
>(take);
86 auto it = batch.begin();
87 while (it != batch.end()) {
88 if (it->vk_index >=
vks_.size()) {
103 auto reduce_start = std::chrono::steady_clock::now();
107 std::vector<size_t> passed_indices;
108 passed_indices.reserve(reduce_results.size());
109 for (
size_t i = 0; i < reduce_results.size(); ++i) {
110 auto& rr = reduce_results[i];
111 if (!rr.all_checks_passed) {
113 result.time_in_queue_ms =
ms_between(rr.enqueue_time, reduce_start);
114 result.time_in_verify_ms = rr.reduce_ms;
117 passed_indices.push_back(i);
121 if (passed_indices.empty()) {
126 auto ipa_start = std::chrono::steady_clock::now();
127 bool ok =
batch_check(reduce_results, passed_indices);
128 double ipa_ms =
ms_since(ipa_start);
129 double reduce_ms =
ms_between(reduce_start, ipa_start);
131 info(
"ChonkBatchVerifier: batch of ",
132 passed_indices.size(),
138 ok ?
"OK" :
"BISECTING");
141 emit_ok(reduce_results, passed_indices, reduce_start, ipa_ms, 0);
143 bisect(reduce_results, passed_indices, 0, reduce_start);
151 const size_t num_proofs = batch.size();
153 std::atomic<size_t> work_index{ 0 };
155 uint32_t num_workers = std::min(
num_cores_,
static_cast<uint32_t
>(num_proofs));
156 std::vector<std::thread> workers;
157 workers.reserve(num_workers);
159 for (uint32_t w = 0; w < num_workers; ++w) {
160 workers.emplace_back([&]() {
165 if (idx >= num_proofs) {
168 auto& req = batch[idx];
169 auto t0 = std::chrono::steady_clock::now();
177 .ipa_claim =
std::move(reduced.ipa_claim),
178 .ipa_proof =
std::move(reduced.ipa_proof),
179 .all_checks_passed = reduced.all_checks_passed,
180 .error_message = reduced.all_checks_passed ?
"" :
"reduction failed",
181 .enqueue_time = req.enqueue_time,
184 }
catch (
const std::exception& e) {
187 .all_checks_passed =
false,
188 .error_message = std::string(
"reduce_to_ipa_claim threw: ") + e.what(),
189 .enqueue_time = req.enqueue_time,
195 .all_checks_passed =
false,
196 .error_message =
"reduce_to_ipa_claim threw unknown exception",
197 .enqueue_time = req.enqueue_time,
204 for (
auto& t : workers) {
213 if (indices.empty()) {
223 claims.reserve(indices.size());
224 transcripts.reserve(indices.size());
225 for (
size_t idx : indices) {
226 claims.push_back(results[idx].ipa_claim);
232 }
catch (
const std::exception& e) {
233 info(
"ChonkBatchVerifier: batch_check exception: ", e.what());
239 std::vector<size_t> indices,
241 std::chrono::steady_clock::time_point reduce_start)
244 if (indices.size() == 1) {
245 auto& rr = results[indices[0]];
246 auto result =
VerifyResult::failed(rr.request_id,
"batch check failed (bisected to individual)");
247 result.time_in_queue_ms =
ms_between(rr.enqueue_time, std::chrono::steady_clock::now());
248 result.time_in_verify_ms = rr.reduce_ms;
249 result.batch_failure_count = depth + 1;
254 info(
"ChonkBatchVerifier: bisecting ", indices.size(),
" proofs at depth ", depth);
256 size_t mid = indices.size() / 2;
257 std::vector<size_t> left(indices.begin(), indices.begin() +
static_cast<ptrdiff_t
>(mid));
258 std::vector<size_t> right(indices.begin() +
static_cast<ptrdiff_t
>(mid), indices.end());
261 auto t0 = std::chrono::steady_clock::now();
266 emit_ok(results, left, reduce_start, left_ms, depth + 1);
273 auto t1 = std::chrono::steady_clock::now();
278 emit_ok(results, right, reduce_start, right_ms, depth + 1);
286 const std::vector<size_t>& indices,
287 std::chrono::steady_clock::time_point reduce_start,
291 for (
size_t idx : indices) {
292 auto& rr = results[idx];
296 .time_in_queue_ms =
ms_between(rr.enqueue_time, reduce_start),
297 .time_in_verify_ms = rr.reduce_ms + ipa_ms,
298 .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)
bool batch_check(const std::vector< ReduceResult > &results, const std::vector< size_t > &indices)
static double ms_since(std::chrono::steady_clock::time_point t)
std::vector< std::shared_ptr< MegaZKFlavor::VKAndHash > > vks_
std::deque< VerifyRequest > queue_
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.
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)