Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
batch_merge.test.cpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
19
20namespace bb {
21
24
25static constexpr size_t NUM_WIRES = MegaExecutionTraceBlocks::NUM_WIRES;
26static constexpr size_t NUM_FRS_COMM = NativeTranscript::Codec::template calc_num_fields<NativeG1>();
27
28template <typename Curve, typename = void> struct BuilderTypeHelper {
29 struct DummyBuilder {};
31};
32
33template <typename Curve> struct BuilderTypeHelper<Curve, std::enable_if_t<Curve::is_stdlib_type>> {
34 using type = typename Curve::Builder;
35};
36
37enum class FaultMode : uint8_t {
38 NONE,
39 WRONG_MERGED_TABLE, // merged table commitment/evals/opening are self-consistent but table is wrong
40 BAD_DEGREE_CHECK_POLY, // degree-check commitment/eval/opening are self-consistent but polynomial is wrong
41 PADDING_NOT_INFINITY, // padded slot sends non-zero shift size and non-zero commitment/eval
42 SHIFT_SIZE_MINUS_ONE, // send k-1 as shift size for a subtable polynomial of size k
43 ZK_TABLE_DEGREE_TOO_HIGH, // zk table has degree above verifier hard-coded ZK shift
44 ZERO_SUBTABLES_CLAIM, // send 0 as number of subtables,
45 TOO_MANY_SUBTABLES, // send a number of subtables above the max that the verifier is configured for
46};
47
48void populate_subtable(const std::shared_ptr<ECCOpQueue>& op_queue, size_t num_ops)
49{
50 for (size_t i = 0; i < num_ops; ++i) {
51 op_queue->add_accumulate(NativeG1::random_element());
52 op_queue->mul_accumulate(NativeG1::random_element(), bb::fr::random_element());
53 op_queue->eq_and_reset();
54 }
55}
56
58{
59 const size_t max_op_queue_ops = 10;
60 auto op_queue = std::make_shared<ECCOpQueue>();
61 for (size_t i = 0; i < n; ++i) {
62 if (i > 0) {
63 op_queue->initialize_new_subtable();
64 }
65 populate_subtable(op_queue, ((1 + i) % max_op_queue_ops) + 1); // +1 to avoid empty subtables
66 op_queue->merge();
67 }
68 return op_queue;
69}
70
76bb::fr compute_running_hash(const std::vector<bb::fr>& proof, size_t N)
77{
78 std::vector<bb::fr> round_inputs;
79 bb::fr previous_challenge(0);
80 bool is_first_challenge = true;
81
82 for (size_t subtable_idx = 0; subtable_idx < N; ++subtable_idx) {
83 round_inputs.clear();
84 if (!is_first_challenge) {
85 round_inputs.push_back(previous_challenge);
86 }
87 for (size_t col = 0; col < NUM_WIRES; ++col) {
88 const size_t global_col_idx = (subtable_idx * NUM_WIRES) + col;
89 const size_t base = (global_col_idx * NUM_FRS_COMM);
90 for (size_t j = 0; j < NUM_FRS_COMM; ++j) {
91 round_inputs.push_back(proof[base + j]);
92 }
93 }
94
95 // Transcript logic: hash full round buffer, then split into two challenge parts; get_challenge uses part[0].
97 previous_challenge = full_hash;
98 is_first_challenge = false;
99 }
100
101 return previous_challenge;
102}
103
115
116 public:
123
125 {
126 const size_t M = max_subtables;
127
128 // Step 1
129 std::vector<std::array<Polynomial, NUM_WIRES>> subtable_cols = op_queue->construct_subtable_columns();
130
131 size_t N = subtable_cols.size();
132
133 std::vector<size_t> shift_sizes(N);
134 size_t max_shift_size = 0;
135 for (size_t i = 0; i < N; ++i) {
136 shift_sizes[i] = subtable_cols[i][0].size();
137 max_shift_size = std::max(max_shift_size, shift_sizes[i]);
138 }
139
140 // Step 2: commit subtable columns
141 Polynomial zero_poly(0);
142 for (size_t idx = 0; idx < N; ++idx) {
143 for (size_t col = 0; col < NUM_WIRES; ++col) {
144 const Polynomial& col_to_commit =
145 (fault_mode == FaultMode::ZERO_SUBTABLES_CLAIM) ? zero_poly : subtable_cols[idx][col];
146 transcript->send_to_verifier("COLUMN_" + std::to_string(col) + "_" + std::to_string(idx),
147 pcs_commitment_key.commit(col_to_commit));
148 }
149 [[maybe_unused]] FF _ = transcript->template get_challenge<FF>("HASH_" + std::to_string(idx));
150 }
151
152 Polynomial one_poly(1);
153 one_poly.at(0) = 1;
154 for (size_t idx = N; idx < M; ++idx) {
155 for (size_t col = 0; col < NUM_WIRES; ++col) {
156 const bool non_infinity_padding =
157 (fault_mode == FaultMode::PADDING_NOT_INFINITY && idx == N && col == 0);
158 transcript->send_to_verifier("COLUMN_" + std::to_string(col) + "_" + std::to_string(idx),
159 pcs_commitment_key.commit(non_infinity_padding ? one_poly : zero_poly));
160 }
161 [[maybe_unused]] FF _ = transcript->template get_challenge<FF>("HASH_" + std::to_string(idx));
162 }
163
164 // Step 2.b: Send the masking table
165 std::array<Polynomial, NUM_WIRES> zk_columns = op_queue->construct_zk_columns();
166
168 for (size_t col = 0; col < NUM_WIRES; ++col) {
169 // Make zk column degree exceed verifier's hard-coded ZK shift (= ZK_ULTRA_OPS).
170 Polynomial larger_zk_col(zk_columns[col], zk_columns[col].size() + 1);
171 larger_zk_col.at(larger_zk_col.size() - 1) = FF(1);
172 zk_columns[col] = std::move(larger_zk_col);
173 }
174 }
175
176 for (size_t col = 0; col < NUM_WIRES; ++col) {
177 transcript->send_to_verifier("ZK_COLUMN_" + std::to_string(col),
178 pcs_commitment_key.commit(zk_columns[col]));
179 }
180 max_shift_size = std::max(max_shift_size, zk_columns[0].size());
181
182 // Step 2.c: Flatten the columns for easier utilisation
183 std::vector<Polynomial> flattened_cols;
184 flattened_cols.reserve((subtable_cols.size() * NUM_WIRES) + NUM_WIRES);
185 for (size_t col = 0; col < NUM_WIRES; ++col) {
186 flattened_cols.push_back(std::move(zk_columns[col]));
187 }
188 for (auto& subtable_col : subtable_cols) {
189 for (size_t col = 0; col < NUM_WIRES; ++col) {
191 flattened_cols.push_back(Polynomial(1));
192 } else {
193 flattened_cols.push_back(std::move(subtable_col[col]));
194 }
195 }
196 }
197
198 // Step 3
199 uint32_t sent_num_subtables = static_cast<uint32_t>(N);
201 sent_num_subtables = 0;
202 }
203 transcript->send_to_verifier("NUM_SUBTABLES", sent_num_subtables);
204 for (size_t i = 0; i < M; ++i) {
205 uint32_t sent_shift_size = static_cast<uint32_t>(i < N ? shift_sizes[i] : 0);
206 if (fault_mode == FaultMode::PADDING_NOT_INFINITY && i == N && N < M) {
207 sent_shift_size = 1;
208 }
209 if (fault_mode == FaultMode::SHIFT_SIZE_MINUS_ONE && i == 0 && N > 0) {
210 BB_ASSERT_GT(shift_sizes[0], 0U);
211 sent_shift_size = static_cast<uint32_t>(shift_sizes[0] - 1);
212 }
213 if (fault_mode == FaultMode::ZERO_SUBTABLES_CLAIM && i == N && N < M) {
214 sent_shift_size = 0;
215 }
216 transcript->send_to_verifier("SHIFT_SIZE_" + std::to_string(i), sent_shift_size);
217 }
218
219 // Step 4: merged table
220 std::array<Polynomial, NUM_WIRES> merged_table(op_queue->construct_ultra_ops_table_columns());
221 if (fault_mode == FaultMode::WRONG_MERGED_TABLE && !merged_table[0].is_empty()) {
222 merged_table[0].at(0) += FF(1);
224 for (size_t col = 0; col < NUM_WIRES; ++col) {
225 merged_table[col] = Polynomial(1);
226 }
227 }
228 for (size_t col = 0; col < NUM_WIRES; ++col) {
229 transcript->send_to_verifier("MERGED_COLUMN_" + std::to_string(col),
230 pcs_commitment_key.commit(merged_table[col]));
231 }
232
233 // Step 5
234 const FF degree_check_challenge = transcript->template get_challenge<FF>("DEGREE_CHECK_CHALLENGE");
235 const size_t num_degree_check_challenges = (M * NUM_WIRES) + NUM_WIRES;
236 std::vector<FF> degree_check_challenges = { FF(1), degree_check_challenge };
237 for (size_t idx = 2; idx < num_degree_check_challenges; ++idx) {
238 degree_check_challenges.push_back(degree_check_challenges.back() * degree_check_challenge);
239 }
240
241 // Step 6: degree-check poly
243 // This is the case in which we test that if the prover sends more columns than the max number of tables
244 // then the verifier rejects
245 size_t diff = flattened_cols.size() - num_degree_check_challenges;
246 for (size_t idx = 0; idx < diff * NUM_WIRES; ++idx) {
247 // Add challenges for the extra columns sent by the prover
248 degree_check_challenges.push_back(degree_check_challenges.back() * degree_check_challenge);
249 }
250 }
251
252 Polynomial degree_check_poly =
253 compute_degree_check_polynomial(flattened_cols, degree_check_challenges, max_shift_size);
254
256 // Remove the extra challenge added above to keep the degree check poly consistent with the rest of the
257 // proof
258 degree_check_challenges.pop_back();
259 }
260
261 if (fault_mode == FaultMode::BAD_DEGREE_CHECK_POLY && !degree_check_poly.is_empty()) {
262 degree_check_poly.at(0) += FF(1);
263 }
264
265 transcript->send_to_verifier("DEGREE_CHECK_POLY", pcs_commitment_key.commit(degree_check_poly));
266
267 // Step 7
268 const FF kappa = transcript->template get_challenge<FF>("KAPPA");
269 const FF kappa_inv = kappa.invert();
270
271 // Step 8: evals
272 std::vector<FF> evals;
273 const size_t num_actual_flattened_cols = (N * NUM_WIRES) + NUM_WIRES;
274 const size_t num_flattened_col_evals = (M * NUM_WIRES) + NUM_WIRES;
275 for (size_t flat_idx = 0; flat_idx < num_flattened_col_evals; ++flat_idx) {
276 FF eval = FF(0);
277 if (flat_idx < num_actual_flattened_cols) {
278 eval = flattened_cols[flat_idx].evaluate(kappa);
279 } else if (fault_mode == FaultMode::PADDING_NOT_INFINITY && flat_idx == num_actual_flattened_cols) {
280 eval = FF(1); // matches one_poly commitment at the first padded slot
281 }
282 evals.push_back(eval);
283 transcript->send_to_verifier("C_EVAL_" + std::to_string(flat_idx), eval);
284 }
285
286 for (size_t col = 0; col < NUM_WIRES; ++col) {
287 evals.push_back(merged_table[col].evaluate(kappa));
288 transcript->send_to_verifier("MERGED_EVAL_" + std::to_string(col), evals.back());
289 }
290
291 evals.push_back(degree_check_poly.evaluate(kappa_inv));
292 transcript->send_to_verifier("DEGREE_CHECK_EVAL", evals.back());
293
294 // Step 9
295 const size_t num_opening_claims = ((M + 1) * NUM_WIRES) + 1 + NUM_WIRES;
296 std::vector<OpeningClaim> opening_claims;
297 opening_claims.reserve(num_opening_claims);
298
299 for (size_t idx = 0; idx < num_flattened_col_evals; ++idx) {
300 if (idx < num_actual_flattened_cols) {
301 opening_claims.push_back({ std::move(flattened_cols[idx]), { kappa, evals[idx] } });
302 } else {
303 opening_claims.push_back({ Polynomial(1), { kappa, FF(0) } });
304 }
305 }
306
307 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
308 opening_claims.push_back(
309 { std::move(merged_table[idx]), { kappa, evals[(M * NUM_WIRES) + NUM_WIRES + idx] } });
310 }
311
312 opening_claims.push_back({ std::move(degree_check_poly), { kappa_inv, evals.back() } });
313
314 auto shplonk_opening_claim = ShplonkProver::prove(pcs_commitment_key, opening_claims, transcript);
315
317 return transcript->export_proof();
318 }
319
320 private:
322};
323
324// Custom parameter struct to hold both Curve type and NumSubtables value
325template <typename Curve, size_t N> struct TestParam {
327 static constexpr size_t NumSubtables = N;
328};
329
330// Specialize the fixture to extract both template parameters from TypeParam
331template <typename Param> class BatchMergeTests : public testing::Test {
332 public:
333 using Curve = typename Param::CurveType;
334 static constexpr size_t NumSubtables = Param::NumSubtables;
335 using FF = typename Curve::ScalarField;
337 using Proof = typename Verifier::Proof;
339 static constexpr bool IsRecursive = Curve::is_stdlib_type;
341
342 static constexpr size_t VERIFIER_NUM_GATES = NumSubtables == 9 ? 6362 : 22624;
343 static constexpr size_t ZK_OFFSET = NumSubtables == 9 ? 666 : 520;
344
350
352
353 static Proof create_proof(BuilderType& builder, const std::vector<bb::fr>& native_proof)
354 {
355 if constexpr (IsRecursive) {
356 stdlib::Proof<BuilderType> stdlib_proof(builder, native_proof);
357 return stdlib_proof;
358 } else {
359 (void)builder;
360 return native_proof;
361 }
362 }
363
364 static FF create_hash(BuilderType& builder, const bb::fr& native_hash)
365 {
366 if constexpr (IsRecursive) {
367 auto hash = FF::from_witness(&builder, native_hash);
368 hash.unset_free_witness_tag();
369 return hash;
370 } else {
371 (void)builder;
372 return native_hash;
373 }
374 }
375
377 {
378 if constexpr (IsRecursive) {
380 } else {
381 (void)builder;
382 return true;
383 }
384 }
385
387 FaultMode fault_mode = FaultMode::NONE,
388 bool wrong_hash = false,
389 bool check_manifest = false)
390 {
391 TranscriptManifest prover_manifest;
392 std::vector<bb::fr> native_proof;
393 if (fault_mode == FaultMode::NONE) {
394 BatchMergeProver prover{ op_queue, NumSubtables };
395 if (check_manifest) {
396 prover.transcript->enable_manifest();
397 }
398
399 native_proof = prover.construct_proof();
400 if (check_manifest) {
401 prover_manifest = prover.transcript->get_manifest();
402 }
403 } else {
404 TweakableBatchMergeProver prover{ op_queue, NumSubtables, fault_mode };
405 if (check_manifest) {
406 prover.transcript->enable_manifest();
407 }
408
409 native_proof = prover.construct_proof();
410 if (check_manifest) {
411 prover_manifest = prover.transcript->get_manifest();
412 }
413 }
414
415 bb::fr native_hash = compute_running_hash(native_proof, op_queue->num_subtables());
416 if (wrong_hash) {
417 native_hash += bb::fr(1);
418 }
419
421 Proof proof = create_proof(builder, native_proof);
422 FF hash = create_hash(builder, native_hash);
423
424 Verifier verifier;
425 if (check_manifest) {
426 verifier.transcript->enable_manifest();
427 }
428 auto result = verifier.reduce_to_pairing_check(proof, hash);
429
430 if (check_manifest) {
431 // Check consistency of manifests
432 auto verifier_manifest = verifier.transcript->get_manifest();
433 EXPECT_EQ(prover_manifest.size(), verifier_manifest.size());
434 for (size_t i = 0; i < prover_manifest.size(); ++i) {
435 EXPECT_EQ(prover_manifest[i], verifier_manifest[i]);
436 }
437 }
438
439 if constexpr (Curve::is_stdlib_type) {
440 EXPECT_EQ(builder.get_num_finalized_gates_inefficient(), VERIFIER_NUM_GATES + ZK_OFFSET);
441 }
442
443 return { result.reduction_succeeded, result.pairing_points.check(), check_circuit(builder) };
444 }
445};
446
447using TestParams = ::testing::Types<TestParam<curve::BN254, 9>,
450 TestParam<stdlib::bn254<MegaCircuitBuilder>, CHONK_MAX_NUM_CIRCUITS>>;
452
453// Completeness
454
455TYPED_TEST(BatchMergeTests, ValidProofPassesWithPadding)
456{
457 auto op_queue = make_op_queue_with_n_subtables(3);
458 auto res = TestFixture::prove_and_verify(op_queue, FaultMode::NONE, false, /*check_manifest*/ true);
459 EXPECT_TRUE(res.reduction_ok);
460 EXPECT_TRUE(res.pairing_ok);
461 EXPECT_TRUE(res.circuit_ok);
462}
463
464TYPED_TEST(BatchMergeTests, ValidProofMaxSizePasses)
465{
466 auto op_queue = make_op_queue_with_n_subtables(TestFixture::NumSubtables);
467 auto res = TestFixture::prove_and_verify(op_queue);
468 EXPECT_TRUE(res.reduction_ok);
469 EXPECT_TRUE(res.pairing_ok);
470 EXPECT_TRUE(res.circuit_ok);
471}
472
473// Soundness
474
475TYPED_TEST(BatchMergeTests, ZeroSubtablesFails)
476{
478 auto op_queue = make_op_queue_with_n_subtables(3);
479 auto res = TestFixture::prove_and_verify(op_queue, FaultMode::ZERO_SUBTABLES_CLAIM);
480 EXPECT_FALSE(res.reduction_ok); // Caught by product check
481 EXPECT_TRUE(res.pairing_ok);
482 if constexpr (TestFixture::IsRecursive) {
483 EXPECT_FALSE(res.circuit_ok);
484 }
485}
486
487TYPED_TEST(BatchMergeTests, TooManySubtablesFails)
488{
489 if constexpr (!TestFixture::Curve::is_stdlib_type) {
490 GTEST_SKIP() << "This test in native setting fails due to a deserialization failure. The verifier path in the "
491 "same for native and recursive code, so it's enough to test the recursive code.";
492 } else {
494 auto op_queue = make_op_queue_with_n_subtables(TestFixture::NumSubtables + 1);
495 auto res = TestFixture::prove_and_verify(op_queue, FaultMode::TOO_MANY_SUBTABLES);
496 EXPECT_FALSE(res.reduction_ok); // Caught by product check
497 EXPECT_FALSE(res.pairing_ok); // Verifier uses fewer commitments than the one sent
498 if constexpr (TestFixture::IsRecursive) {
499 EXPECT_FALSE(res.circuit_ok); // Assertions fail
500 }
501 }
502}
503
504TYPED_TEST(BatchMergeTests, WrongMergedTableFails)
505{
506 auto op_queue = make_op_queue_with_n_subtables(2);
507 auto res = TestFixture::prove_and_verify(op_queue, FaultMode::WRONG_MERGED_TABLE);
508 EXPECT_FALSE(res.reduction_ok); // Caught by the concatenation check
509 EXPECT_TRUE(res.pairing_ok);
510 if constexpr (TestFixture::IsRecursive) {
511 EXPECT_FALSE(res.circuit_ok);
512 }
513}
514
516{
517 auto op_queue = make_op_queue_with_n_subtables(4);
518 auto res = TestFixture::prove_and_verify(op_queue, FaultMode::NONE, true);
519 EXPECT_FALSE(res.reduction_ok); // Caught by the hash check
520 EXPECT_TRUE(res.pairing_ok);
521 if constexpr (TestFixture::IsRecursive) {
522 EXPECT_FALSE(res.circuit_ok);
523 }
524}
525
526TYPED_TEST(BatchMergeTests, BadSubtableDegreeCheckFails)
527{
528 auto op_queue = make_op_queue_with_n_subtables(6);
529 auto res = TestFixture::prove_and_verify(op_queue, FaultMode::BAD_DEGREE_CHECK_POLY);
530 EXPECT_FALSE(res.reduction_ok); // Caught by the degree check
531 EXPECT_TRUE(res.pairing_ok);
532 if constexpr (TestFixture::IsRecursive) {
533 EXPECT_FALSE(res.circuit_ok);
534 }
535}
536
537TYPED_TEST(BatchMergeTests, PaddingTableNotInfinityFails)
538{
539 auto op_queue = make_op_queue_with_n_subtables(3);
540 auto res = TestFixture::prove_and_verify(op_queue, FaultMode::PADDING_NOT_INFINITY);
541 EXPECT_FALSE(res.reduction_ok); // Caught by the degree check: shift sizes are zeroed out >= N
542 EXPECT_TRUE(res.pairing_ok); // PCS is consistent
543 if constexpr (TestFixture::IsRecursive) {
544 EXPECT_FALSE(res.circuit_ok); // Caught by the degree check: shift sizes are zeroed out >= N
545 }
546}
547
548TYPED_TEST(BatchMergeTests, ShiftSizeMinusOneFailsReductionOnly)
549{
550 auto op_queue = make_op_queue_with_n_subtables(7);
551 auto res = TestFixture::prove_and_verify(op_queue, FaultMode::SHIFT_SIZE_MINUS_ONE);
552 EXPECT_FALSE(res.reduction_ok); // Caught by the degree check
553 EXPECT_TRUE(res.pairing_ok);
554 if constexpr (TestFixture::IsRecursive) {
555 EXPECT_FALSE(res.circuit_ok);
556 }
557}
558
559TYPED_TEST(BatchMergeTests, ZKTableDegreeTooHighFailsReductionOnly)
560{
561 auto op_queue = make_op_queue_with_n_subtables(5);
562 auto res = TestFixture::prove_and_verify(op_queue, FaultMode::ZK_TABLE_DEGREE_TOO_HIGH);
563 EXPECT_FALSE(res.reduction_ok); // Caught by degree/concatenation reductions via hard-coded ZK shift.
564 EXPECT_TRUE(res.pairing_ok); // PCS opening remains self-consistent with sent commitments/evals.
565 if constexpr (TestFixture::IsRecursive) {
566 EXPECT_FALSE(res.circuit_ok);
567 }
568}
569
570// Static analysis of the recursive verifier circuit: every variable must belong to a single connected
571// component (no disjoint subgraphs) and there must be no variables that participate in only one gate
572// (i.e. no unconstrained witnesses).
573TYPED_TEST(BatchMergeTests, GraphDescription)
574{
575 if constexpr (!TestFixture::IsRecursive) {
576 GTEST_SKIP() << "Graph description analysis only applies to stdlib (recursive) verifier circuits.";
577 } else {
578 using BuilderType = typename TestFixture::BuilderType;
579 using FF = typename TestFixture::FF;
580 using Proof = typename TestFixture::Proof;
581 using Verifier = typename TestFixture::Verifier;
582
583 auto op_queue = make_op_queue_with_n_subtables(5);
584 BatchMergeProver prover{ op_queue, TestFixture::NumSubtables };
585 auto native_proof = prover.construct_proof();
586 const bb::fr native_hash = compute_running_hash(native_proof, op_queue->num_subtables());
587
588 BuilderType builder;
589 Proof proof = TestFixture::create_proof(builder, native_proof);
590 FF hash = TestFixture::create_hash(builder, native_hash);
591 // The hash is consumed only via split_challenge, which yields a low/high pair via a single arithmetic
592 // gate: hash = lo + 2^127 * hi. The verifier subsequently uses only the low half, so hash itself
593 // appears in only that one gate. Pin it so the StaticAnalyzer doesn't flag it as unconstrained.
594 hash.fix_witness();
595
596 Verifier verifier;
597 auto result = verifier.reduce_to_pairing_check(proof, hash);
598
599 // The pairing points are public outputs from the recursive verifier that will be verified externally via a
600 // pairing check. Their output coordinates may not appear in multiple constraint gates; fix_witness() pins
601 // them so the StaticAnalyzer doesn't flag the coordinate limbs as unconstrained.
602 result.pairing_points.fix_witness();
603
604 builder.finalize_circuit();
605
606 using Analyzer =
608 auto graph = Analyzer(builder);
609 auto [cc, variables_in_one_gate] = graph.analyze_circuit(/*filter_cc=*/true);
610
611 EXPECT_EQ(cc.size(), 1);
612 EXPECT_EQ(variables_in_one_gate.size(), 0);
613 }
614}
615
616} // namespace bb
#define BB_ASSERT_GT(left, right,...)
Definition assert.hpp:113
#define BB_DISABLE_ASSERTS()
Definition assert.hpp:33
Common transcript class for both parties. Stores the data for the current round, as well as the manif...
Batch merge prover.
static constexpr size_t NUM_WIRES
std::shared_ptr< Transcript > transcript
std::shared_ptr< ECCOpQueue > op_queue
std::vector< FF > MergeProof
MergeProof construct_proof()
Construct the batch merge proof.
static Polynomial compute_degree_check_polynomial(const std::vector< Polynomial > &flattened_columns, const std::vector< FF > &degree_check_challenges, const size_t max_size)
static constexpr size_t ZK_OFFSET
typename Verifier::Transcript Transcript
typename Param::CurveType Curve
static Proof create_proof(BuilderType &builder, const std::vector< bb::fr > &native_proof)
static constexpr bool IsRecursive
static constexpr size_t NumSubtables
typename Verifier::Proof Proof
static bool check_circuit(BuilderType &builder)
static FF create_hash(BuilderType &builder, const bb::fr &native_hash)
typename BuilderTypeHelper< Curve >::type BuilderType
static constexpr size_t VERIFIER_NUM_GATES
static VerifyResult prove_and_verify(const std::shared_ptr< ECCOpQueue > &op_queue, FaultMode fault_mode=FaultMode::NONE, bool wrong_hash=false, bool check_manifest=false)
typename Curve::ScalarField FF
Unified batch verifier for the batch Goblin ECC op queue merge protocol.
std::shared_ptr< Transcript > transcript
ReductionResult reduce_to_pairing_check(const Proof &proof, const FF hash)
Reduce the batch merge proof to a pairing check.
TranscriptFor_t< Curve > Transcript
Commitment commit(PolynomialSpan< const Fr > polynomial) const
Uses the ProverSRS to create a commitment to p(X)
static void compute_opening_proof(const CK &ck, const ProverOpeningClaim< Curve > &opening_claim, const std::shared_ptr< Transcript > &prover_trancript)
Computes the KZG commitment to an opening proof polynomial at a single evaluation point.
Definition kzg.hpp:43
bool is_empty() const
Fr evaluate(const Fr &z) const
Fr & at(size_t index)
Our mutable accessor, unlike operator[]. We abuse precedent a bit to differentiate at() and operator[...
std::size_t size() const
Polynomial p and an opening pair (r,v) such that p(r) = v.
Definition claim.hpp:36
static ProverOpeningClaim< Curve > prove(const CommitmentKey< Curve > &commitment_key, std::span< ProverOpeningClaim< Curve > > opening_claims, const std::shared_ptr< Transcript > &transcript, std::span< ProverOpeningClaim< Curve > > libra_opening_claims={}, std::span< ProverOpeningClaim< Curve > > sumcheck_round_claims={}, const size_t virtual_log_n=0)
Returns a batched opening claim equivalent to a set of opening claims consisting of polynomials,...
Definition shplonk.hpp:254
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
TweakableBatchMergeProver(const std::shared_ptr< ECCOpQueue > &op_queue, size_t max_subtables, FaultMode mode=FaultMode::NONE)
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
typename Group::affine_element AffineElement
Definition bn254.hpp:22
bb::fr ScalarField
Definition bn254.hpp:18
static constexpr bool is_stdlib_type
Definition grumpkin.hpp:67
A simple wrapper around a vector of stdlib field elements representing a proof.
Definition proof.hpp:19
AluTraceBuilder builder
Definition alu.test.cpp:124
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
@ ZK_TABLE_DEGREE_TOO_HIGH
TYPED_TEST_SUITE(CommitmentKeyTest, Curves)
field< Bn254FrParams > fr
Definition fr.hpp:155
bb::fr compute_running_hash(const std::vector< bb::fr > &proof, size_t N)
void populate_subtable(const std::shared_ptr< ECCOpQueue > &op_queue, size_t num_ops)
TYPED_TEST(CommitmentKeyTest, CommitToZeroPoly)
curve::Grumpkin Curve
NativeCurve::AffineElement NativeG1
std::shared_ptr< ECCOpQueue > make_op_queue_with_n_subtables(size_t n)
::testing::Types< TestParam< curve::BN254, 9 >, TestParam< curve::BN254, CHONK_MAX_NUM_CIRCUITS >, TestParam< stdlib::bn254< MegaCircuitBuilder >, 9 >, TestParam< stdlib::bn254< MegaCircuitBuilder >, CHONK_MAX_NUM_CIRCUITS > > TestParams
BaseTranscript< FrCodec, bb::crypto::Poseidon2< bb::crypto::Poseidon2Bn254ScalarFieldParams > > NativeTranscript
StaticAnalyzer_< bb::fr, bb::MegaCircuitBuilder > MegaStaticAnalyzer
Definition graph.hpp:189
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
static constexpr size_t NumSubtables
constexpr field invert() const noexcept
static field random_element(numeric::RNG *engine=nullptr) noexcept