Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
merge.test.cpp
Go to the documentation of this file.
12
13namespace bb {
14
15// Helper traits to extract Builder type from Curve
16template <typename Curve, typename = void> struct BuilderTypeHelper {
17 struct DummyBuilder {};
19};
20
21template <typename Curve> struct BuilderTypeHelper<Curve, std::enable_if_t<Curve::is_stdlib_type>> {
22 using type = typename Curve::Builder;
23};
24
30template <typename Curve> class MergeTests : public testing::Test {
31 public:
33
34 using FF = typename Curve::ScalarField;
36 using GroupElement = typename Curve::Element;
44
45 static constexpr bool IsRecursive = Curve::is_stdlib_type;
47
48 // Builder type is only available in recursive context
50
51 enum class TamperProofMode : uint8_t { None, Shift, MCommitment, LEval };
52
57 template <typename T> static auto to_native(const T& val)
58 {
59 if constexpr (IsRecursive) {
60 return val.get_value();
61 } else {
62 return val;
63 }
64 }
65
71 {
72 if constexpr (IsRecursive) {
73 auto commitment = Commitment::from_witness(&builder, native_commitment);
74 commitment.unset_free_witness_tag();
75 return commitment;
76 } else {
77 (void)builder; // Unused in native context
78 return native_commitment;
79 }
80 }
81
87 static Proof create_proof(BuilderType& builder, const std::vector<bb::fr>& native_proof)
88 {
89 if constexpr (IsRecursive) {
90 // Create stdlib::Proof, which is std::vector<stdlib::field_t<Builder>>
91 stdlib::Proof<BuilderType> stdlib_proof(builder, native_proof);
92 // It's already the right type (std::vector<FF>), just return it
93 return stdlib_proof;
94 } else {
95 (void)builder; // Unused in native context
96 return native_proof;
97 }
98 }
99
104 {
105 if constexpr (IsRecursive) {
107 } else {
108 (void)builder; // Unused in native context
109 return true;
110 }
111 }
112
116 static void tamper_with_proof(std::vector<bb::fr>& merge_proof, const TamperProofMode tampering_mode)
117 {
118 const size_t shift_idx = 0; // Index of shift_size in the merge proof
119 const size_t m_commitment_idx = 1; // Index of first commitment to merged table in merge proof
120 const size_t l_eval_idx = 22; // Index of first evaluation of l(1/kappa) in merge proof
121
122 switch (tampering_mode) {
124 // Tamper with the shift size in the proof
125 merge_proof[shift_idx] += bb::fr(1);
126 break;
128 // Tamper with the commitment in the proof
129 auto m_commitment =
130 FrCodec::deserialize_from_fields<curve::BN254::AffineElement>(std::span{ merge_proof }.subspan(
131 m_commitment_idx, FrCodec::calc_num_fields<curve::BN254::AffineElement>()));
132 m_commitment = m_commitment + curve::BN254::AffineElement::one();
133 auto m_commitment_frs = FrCodec::serialize_to_fields<curve::BN254::AffineElement>(m_commitment);
134 for (size_t idx = 0; idx < 4; ++idx) {
135 merge_proof[m_commitment_idx + idx] = m_commitment_frs[idx];
136 }
137 break;
138 }
140 // Tamper with the evaluation in the proof
141 merge_proof[l_eval_idx] -= bb::fr(1);
142 break;
143 default:
144 // Nothing to do
145 break;
146 }
147 }
148
154 const MergeSettings settings = MergeSettings::PREPEND,
155 const TamperProofMode tampering_mode = TamperProofMode::None,
156 const bool expected = true)
157 {
158 // Create native merge proof
159 MergeProver merge_prover{ op_queue, settings };
160 auto native_proof = merge_prover.construct_proof();
161 tamper_with_proof(native_proof, tampering_mode);
162
163 // Create commitments to subtables
164 auto t_current = op_queue->construct_current_ultra_ops_subtable_columns();
165 auto T_prev = op_queue->construct_previous_ultra_ops_table_columns();
166
167 // Native commitments
170 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
171 native_t_commitments[idx] = merge_prover.pcs_commitment_key.commit(t_current[idx]);
172 native_T_prev_commitments[idx] = merge_prover.pcs_commitment_key.commit(T_prev[idx]);
173 }
174
175 // Compute expected merged table commitments independently
176 // After merge, the full table is T_merged = T_prev || t_current (PREPEND) or t_current || T_prev (APPEND)
177 auto T_merged = op_queue->construct_ultra_ops_table_columns();
178 std::array<curve::BN254::AffineElement, NUM_WIRES> expected_merged_commitments;
179 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
180 expected_merged_commitments[idx] = merge_prover.pcs_commitment_key.commit(T_merged[idx]);
181 }
182
183 // Create builder (only used in recursive context)
185
186 // Create commitments and proof in the appropriate context
187 InputCommitments input_commitments;
188 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
189 input_commitments.t_commitments[idx] = create_commitment(builder, native_t_commitments[idx]);
190 input_commitments.T_prev_commitments[idx] = create_commitment(builder, native_T_prev_commitments[idx]);
191 }
192 Proof proof = create_proof(builder, native_proof);
193
194 // Verify the proof
195 auto transcript = std::make_shared<Transcript>();
196 MergeVerifierType verifier{ settings, transcript };
197 auto result = verifier.reduce_to_pairing_check(proof, input_commitments);
198
199 // Perform pairing check and verify
200 VerifierCommitmentKey pcs_verification_key;
201 bool pairing_verified = pcs_verification_key.pairing_check(to_native(result.pairing_points.P0),
202 to_native(result.pairing_points.P1));
203 bool verified = pairing_verified && result.reduction_succeeded;
204 EXPECT_EQ(verified, expected);
205
206 // If verification is expected to succeed, also check that the merged table commitments match
207 if (expected) {
208 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
209 EXPECT_EQ(to_native(result.merged_commitments[idx]), expected_merged_commitments[idx])
210 << "Merged table commitment mismatch at index " << idx;
211 }
212 }
213
214 // Check circuit validity (only relevant in recursive context)
215 if constexpr (IsRecursive) {
216 bool circuit_valid = check_circuit(builder);
217 EXPECT_EQ(circuit_valid, expected);
218 }
219 }
220
226 {
227 using InnerFlavor = MegaFlavor;
228 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
229
230 InnerBuilder builder;
232
233 // Construct a merge proof and ensure its size matches expectation
234 MergeProver merge_prover{ builder.op_queue };
235 auto merge_proof = merge_prover.construct_proof();
236
237 EXPECT_EQ(merge_proof.size(), MERGE_PROOF_SIZE);
238 }
239
243 static void test_single_merge()
244 {
245 using InnerFlavor = MegaFlavor;
246 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
247
248 auto op_queue = std::make_shared<ECCOpQueue>();
249 InnerBuilder circuit{ op_queue };
251
252 prove_and_verify_merge(op_queue);
253 }
254
259 {
260 using InnerFlavor = MegaFlavor;
261 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
262
263 auto op_queue = std::make_shared<ECCOpQueue>();
264
265 // First circuit
266 InnerBuilder circuit1{ op_queue };
268 prove_and_verify_merge(op_queue);
269
270 // Second circuit
271 InnerBuilder circuit2{ op_queue };
273 prove_and_verify_merge(op_queue);
274
275 // Third circuit
276 InnerBuilder circuit3{ op_queue };
278 prove_and_verify_merge(op_queue);
279 }
280
285 {
286 using InnerFlavor = MegaFlavor;
287 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
288
289 auto op_queue = std::make_shared<ECCOpQueue>();
290
291 // First circuit with prepend
292 InnerBuilder circuit1{ op_queue };
294 prove_and_verify_merge(op_queue);
295
296 // Second circuit with prepend
297 InnerBuilder circuit2{ op_queue };
299 prove_and_verify_merge(op_queue);
300
301 // Third circuit with append
302 InnerBuilder circuit3{ op_queue };
305 }
306
311 {
312 using InnerFlavor = MegaFlavor;
313 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
314
315 auto op_queue = std::make_shared<ECCOpQueue>();
316 InnerBuilder circuit{ op_queue };
318
319 prove_and_verify_merge(op_queue, settings, TamperProofMode::Shift, false);
320 }
321
326 {
327 using InnerFlavor = MegaFlavor;
328 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
329
330 auto op_queue = std::make_shared<ECCOpQueue>();
331 InnerBuilder circuit{ op_queue };
333
334 prove_and_verify_merge(op_queue, settings, TamperProofMode::MCommitment, false);
335 }
336
341 {
342 using InnerFlavor = MegaFlavor;
343 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
344
345 auto op_queue = std::make_shared<ECCOpQueue>();
346 InnerBuilder circuit{ op_queue };
348
349 prove_and_verify_merge(op_queue, settings, TamperProofMode::LEval, false);
350 }
351};
352
353// Define test types: native and recursive contexts
354using CurveTypes = ::testing::Types<curve::BN254, // Native
355 stdlib::bn254<MegaCircuitBuilder>, // Recursive (Mega)
356 stdlib::bn254<UltraCircuitBuilder>>; // Recursive (Ultra)
357
359
360TYPED_TEST(MergeTests, MergeProofSizeCheck)
361{
362 TestFixture::test_merge_proof_size();
363}
364
366{
367 TestFixture::test_single_merge();
368}
369
370TYPED_TEST(MergeTests, MultipleMergesPrepend)
371{
372 TestFixture::test_multiple_merges_prepend();
373}
374
375TYPED_TEST(MergeTests, MergePrependThenAppend)
376{
377 TestFixture::test_merge_prepend_then_append();
378}
379
380TYPED_TEST(MergeTests, DegreeCheckFailurePrepend)
381{
382 TestFixture::test_degree_check_failure(MergeSettings::PREPEND);
383}
384
385TYPED_TEST(MergeTests, DegreeCheckFailureAppend)
386{
387 TestFixture::test_degree_check_failure(MergeSettings::APPEND);
388}
389
390TYPED_TEST(MergeTests, MergeFailurePrepend)
391{
392 TestFixture::test_merge_failure(MergeSettings::PREPEND);
393}
394
395TYPED_TEST(MergeTests, MergeFailureAppend)
396{
397 TestFixture::test_merge_failure(MergeSettings::APPEND);
398}
399
400TYPED_TEST(MergeTests, EvalFailurePrepend)
401{
402 TestFixture::test_eval_failure(MergeSettings::PREPEND);
403}
404
405TYPED_TEST(MergeTests, EvalFailureAppend)
406{
407 TestFixture::test_eval_failure(MergeSettings::APPEND);
408}
409
423TYPED_TEST(MergeTests, DifferentTranscriptOriginTagFailure)
424{
425 if constexpr (!TestFixture::IsRecursive) {
426 GTEST_SKIP() << "OriginTag tests only apply to recursive context";
427 }
428
429 using BuilderType = typename TestFixture::BuilderType;
430 using MergeVerifierType = typename TestFixture::MergeVerifierType;
431 using Transcript = typename TestFixture::Transcript;
432 using InnerFlavor = MegaFlavor;
433 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
434 constexpr size_t NUM_WIRES = TestFixture::NUM_WIRES;
435
436 // Create single builder for both verifiers (realistic - both in same circuit)
437 BuilderType builder;
438
439 // === Generate two separate merge proofs (simulating two independent merge operations) ===
440 auto op_queue_1 = std::make_shared<ECCOpQueue>();
441 InnerBuilder circuit_1{ op_queue_1 };
443 MergeProver prover_1{ op_queue_1 };
444 auto proof_1 = prover_1.construct_proof();
445
446 auto op_queue_2 = std::make_shared<ECCOpQueue>();
447 InnerBuilder circuit_2{ op_queue_2 };
449 MergeProver prover_2{ op_queue_2 };
450 auto proof_2 = prover_2.construct_proof();
451
452 // Get native commitments for proof 1 (will be used with verifier 1's transcript)
453 auto t_1 = op_queue_1->construct_current_ultra_ops_subtable_columns();
454 auto T_prev_1 = op_queue_1->construct_previous_ultra_ops_table_columns();
456 std::array<curve::BN254::AffineElement, NUM_WIRES> native_T_prev_commitments_1;
457 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
458 native_t_commitments_1[idx] = prover_1.pcs_commitment_key.commit(t_1[idx]);
459 native_T_prev_commitments_1[idx] = prover_1.pcs_commitment_key.commit(T_prev_1[idx]);
460 }
461
462 // === Create first verifier with its own transcript instance ===
463 auto transcript_1 = std::make_shared<Transcript>();
464 [[maybe_unused]] MergeVerifierType verifier_1{ MergeSettings::PREPEND, transcript_1 };
465
466 [[maybe_unused]] auto proof_1_recursive = TestFixture::create_proof(builder, proof_1);
467
468 // Create commitments for verifier 1 - these will be "owned" by transcript_1
469 // When we read from the proof using transcript_1, those values get tagged with transcript_1's parent_tag
470 typename MergeVerifierType::InputCommitments input_commitments_1;
471 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
472 input_commitments_1.t_commitments[idx] = TestFixture::create_commitment(builder, native_t_commitments_1[idx]);
473 input_commitments_1.T_prev_commitments[idx] =
474 TestFixture::create_commitment(builder, native_T_prev_commitments_1[idx]);
475 }
476
477 // === Create second verifier with a DIFFERENT transcript instance ===
478 // This simulates having two independent merge verifiers in the same circuit
479 auto transcript_2 = std::make_shared<Transcript>();
480 MergeVerifierType verifier_2{ MergeSettings::PREPEND, transcript_2 };
481
482 auto proof_2_recursive = TestFixture::create_proof(builder, proof_2);
483
484 // Get the parent tags to show they're different
485 OriginTag tag_1 = extract_transcript_tag(*transcript_1);
486 OriginTag tag_2 = extract_transcript_tag(*transcript_2);
487
488 info("Verifier 1 transcript_index: ", tag_1.transcript_index);
489 info("Verifier 2 transcript_index: ", tag_2.transcript_index);
490 ASSERT_NE(tag_1.transcript_index, tag_2.transcript_index) << "Transcripts should have different parent tags";
491
492 // === SECURITY VIOLATION: Try to use commitments from proof 1 with verifier 2 ===
493
494 // To make this more realistic, we need to actually receive values from transcript_1 into the commitments
495 // In a real scenario, the verifier would receive_from_prover which tags values with the transcript's parent_tag
496 // For this test, we'll manually tag the commitments as if they came from transcript_1
497 OriginTag transcript_1_tag(tag_1.transcript_index, 0, /*is_submitted=*/true);
498 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
499 // Tag these commitments as if they were read from transcript_1
500 if constexpr (TestFixture::IsRecursive) {
501 input_commitments_1.t_commitments[idx].set_origin_tag(transcript_1_tag);
502 input_commitments_1.T_prev_commitments[idx].set_origin_tag(transcript_1_tag);
503 }
504 }
505
506 // Now try to verify proof_2 using verifier_2 (with transcript_2) but with commitments tagged for transcript_1
507 // When verifier_2 reads from proof_2_recursive using transcript_2, those values will have tag_2.parent_tag
508 // When it tries to mix them with input_commitments_1 (which have tag_1.parent_tag), the check should trigger
509 info("Attempting to mix transcript_1 commitments with transcript_2 proof verification...");
510
511 // Catch the exception and verify it's the expected cross-transcript error
512#ifndef NDEBUG
513 EXPECT_THROW_WITH_MESSAGE([[maybe_unused]] auto result =
514 verifier_2.verify_proof(proof_2_recursive, input_commitments_1),
515 "Tags from different transcripts were involved in the same computation");
516#endif
517}
518
523class MergeTranscriptTests : public ::testing::Test {
524 public:
526
534 {
535 TranscriptManifest manifest_expected;
536 constexpr size_t NUM_WIRES = 4;
537
538 // Size calculations
539 size_t frs_per_Fr = 1; // Native field element
540 size_t frs_per_G = FrCodec::calc_num_fields<curve::BN254::AffineElement>(); // Commitment = 4 frs
541 size_t frs_per_uint32 = 1; // shift_size
542
543 size_t round = 0;
544
545 // Round 0: Prover sends shift_size and merged table commitments
546 manifest_expected.add_entry(round, "shift_size", frs_per_uint32);
547 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
548 manifest_expected.add_entry(round, "MERGED_TABLE_" + std::to_string(idx), frs_per_G);
549 }
550 // Verifier generates degree check challenges
551 manifest_expected.add_challenge(round, "LEFT_TABLE_DEGREE_CHECK_0");
552 manifest_expected.add_challenge(round, "LEFT_TABLE_DEGREE_CHECK_1");
553 manifest_expected.add_challenge(round, "LEFT_TABLE_DEGREE_CHECK_2");
554 manifest_expected.add_challenge(round, "LEFT_TABLE_DEGREE_CHECK_3");
555
556 // Round 1: Verifier generates Shplonk batching challenges, Prover sends degree check polynomial commitment
557 round++;
558 for (size_t idx = 0; idx < 13; ++idx) {
559 manifest_expected.add_challenge(round, "SHPLONK_MERGE_BATCHING_CHALLENGE_" + std::to_string(idx));
560 }
561 manifest_expected.add_entry(round, "REVERSED_BATCHED_LEFT_TABLES", frs_per_G);
562
563 // Round 2: Verifier generates evaluation challenge kappa
564 round++;
565 manifest_expected.add_challenge(round, "kappa");
566
567 // Round 3: Verifier generates Shplonk opening challenge, Prover sends all evaluations and quotient
568 round++;
569 manifest_expected.add_challenge(round, "shplonk_opening_challenge");
570 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
571 manifest_expected.add_entry(round, "LEFT_TABLE_EVAL_" + std::to_string(idx), frs_per_Fr);
572 }
573 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
574 manifest_expected.add_entry(round, "RIGHT_TABLE_EVAL_" + std::to_string(idx), frs_per_Fr);
575 }
576 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
577 manifest_expected.add_entry(round, "MERGED_TABLE_EVAL_" + std::to_string(idx), frs_per_Fr);
578 }
579 manifest_expected.add_entry(round, "REVERSED_BATCHED_LEFT_TABLES_EVAL", frs_per_Fr);
580 manifest_expected.add_entry(round, "SHPLONK_BATCHED_QUOTIENT", frs_per_G);
581
582 // Round 4: KZG opening proof with masking challenge
583 round++;
584 manifest_expected.add_challenge(round, "KZG:masking_challenge");
585 manifest_expected.add_entry(round, "KZG:W", frs_per_G);
586
587 return manifest_expected;
588 }
589};
590
594TEST_F(MergeTranscriptTests, ProverManifestConsistency)
595{
596 using InnerFlavor = MegaFlavor;
597 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
598
599 // Construct a simple circuit to generate merge proof
600 auto op_queue = std::make_shared<ECCOpQueue>();
601 InnerBuilder circuit{ op_queue };
603
604 // Construct merge proof with manifest enabled
605 auto transcript = std::make_shared<NativeTranscript>();
606 transcript->enable_manifest();
607 CommitmentKey<curve::BN254> commitment_key;
608 MergeProver merge_prover{ op_queue, MergeSettings::PREPEND, commitment_key, transcript };
609 auto merge_proof = merge_prover.construct_proof();
610
611 // Check prover manifest matches expected manifest
612 auto manifest_expected = construct_merge_manifest();
613 auto prover_manifest = merge_prover.transcript->get_manifest();
614
615 ASSERT_GT(manifest_expected.size(), 0);
616 ASSERT_EQ(prover_manifest.size(), manifest_expected.size())
617 << "Prover manifest has " << prover_manifest.size() << " rounds, expected " << manifest_expected.size();
618
619 for (size_t round = 0; round < manifest_expected.size(); ++round) {
620 ASSERT_EQ(prover_manifest[round], manifest_expected[round]) << "Prover manifest discrepancy in round " << round;
621 }
622}
623
627TEST_F(MergeTranscriptTests, VerifierManifestConsistency)
628{
629 using InnerFlavor = MegaFlavor;
630 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
631
632 // Construct a simple circuit
633 auto op_queue = std::make_shared<ECCOpQueue>();
634 InnerBuilder circuit{ op_queue };
636
637 // Generate merge proof with prover manifest enabled
638 auto prover_transcript = std::make_shared<NativeTranscript>();
639 prover_transcript->enable_manifest();
640 CommitmentKey<curve::BN254> commitment_key;
641 MergeProver merge_prover{ op_queue, MergeSettings::PREPEND, commitment_key, prover_transcript };
642 auto merge_proof = merge_prover.construct_proof();
643
644 // Construct commitments for verifier
645 MergeVerifier::InputCommitments merge_commitments;
646 auto t_current = op_queue->construct_current_ultra_ops_subtable_columns();
647 auto T_prev = op_queue->construct_previous_ultra_ops_table_columns();
648 for (size_t idx = 0; idx < MegaFlavor::NUM_WIRES; idx++) {
649 merge_commitments.t_commitments[idx] = merge_prover.pcs_commitment_key.commit(t_current[idx]);
650 merge_commitments.T_prev_commitments[idx] = merge_prover.pcs_commitment_key.commit(T_prev[idx]);
651 }
652
653 // Verify proof with verifier manifest enabled
654 auto verifier_transcript = std::make_shared<NativeTranscript>();
655 verifier_transcript->enable_manifest();
656 MergeVerifier merge_verifier{ MergeSettings::PREPEND, verifier_transcript };
657 auto result = merge_verifier.reduce_to_pairing_check(merge_proof, merge_commitments);
658
659 // Verification should succeed
660 ASSERT_TRUE(result.pairing_points.check() && result.reduction_succeeded);
661
662 // Check prover and verifier manifests match
663 auto prover_manifest = merge_prover.transcript->get_manifest();
664 auto verifier_manifest = verifier_transcript->get_manifest();
665
666 ASSERT_GT(prover_manifest.size(), 0);
667 ASSERT_EQ(prover_manifest.size(), verifier_manifest.size())
668 << "Prover has " << prover_manifest.size() << " rounds, verifier has " << verifier_manifest.size();
669
670 for (size_t round = 0; round < prover_manifest.size(); ++round) {
671 ASSERT_EQ(prover_manifest[round], verifier_manifest[round])
672 << "Prover/Verifier manifest discrepancy in round " << round;
673 }
674}
675
676} // namespace bb
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
Definition assert.hpp:192
Common transcript class for both parties. Stores the data for the current round, as well as the manif...
CommitmentKey object over a pairing group 𝔾₁.
static void construct_simple_circuit(MegaBuilder &builder)
Generate a simple test circuit with some ECC op gates and conventional arithmetic gates.
static constexpr size_t NUM_WIRES
Prover class for the Goblin ECC op queue transcript merge protocol.
std::shared_ptr< ECCOpQueue > op_queue
BB_PROFILE MergeProof construct_proof()
Prove proper construction of the aggregate Goblin ECC op queue polynomials T_j.
Unified test fixture for native and recursive merge verification.
static void test_degree_check_failure(const MergeSettings settings=MergeSettings::PREPEND)
Test failure when degree(l) > shift_size (as read from the proof)
static bool check_circuit(BuilderType &builder)
Check circuit validity (only relevant in recursive context)
static void prove_and_verify_merge(const std::shared_ptr< ECCOpQueue > &op_queue, const MergeSettings settings=MergeSettings::PREPEND, const TamperProofMode tampering_mode=TamperProofMode::None, const bool expected=true)
Prove and verify a merge proof in both native and recursive contexts.
typename Curve::ScalarField FF
typename Curve::Element GroupElement
static Commitment create_commitment(BuilderType &builder, const curve::BN254::AffineElement &native_commitment)
Create a commitment from a native commitment value.
static void test_merge_failure(const MergeSettings settings=MergeSettings::PREPEND)
Test failure when m ≠ l + X^k r.
typename Curve::AffineElement Commitment
typename MergeVerifierType::Proof Proof
static void test_eval_failure(const MergeSettings settings=MergeSettings::PREPEND)
Test failure when g_j(kappa) ≠ kappa^{k-1} * l_j(1/kappa)
static constexpr bool IsRecursive
static void test_merge_proof_size()
Test that merge proof size matches the expected constant.
static auto to_native(const T &val)
Convert a stdlib type to its native value.
static void tamper_with_proof(std::vector< bb::fr > &merge_proof, const TamperProofMode tampering_mode)
Tamper with the merge proof for failure testing.
static Proof create_proof(BuilderType &builder, const std::vector< bb::fr > &native_proof)
Create a proof object from a vector of field elements.
typename MergeVerifierType::InputCommitments InputCommitments
typename MergeVerifierType::PairingPoints PairingPoints
static constexpr size_t NUM_WIRES
typename MergeVerifierType::Transcript Transcript
static void test_multiple_merges_prepend()
Test multiple merge proofs with prepend mode.
typename MergeVerifierType::TableCommitments TableCommitments
typename BuilderTypeHelper< Curve >::type BuilderType
static void SetUpTestSuite()
static void test_single_merge()
Test basic merge proof construction and verification.
static void test_merge_prepend_then_append()
Test merge proof with append mode.
Test class for merge protocol transcript pinning tests.
static void SetUpTestSuite()
static TranscriptManifest construct_merge_manifest()
Construct the expected manifest for a Merge protocol proof.
Unified verifier class for the Goblin ECC op queue transcript merge protocol.
std::vector< FF > Proof
TranscriptFor_t< Curve > Transcript
std::conditional_t< Curve::is_stdlib_type, stdlib::recursion::PairingPoints< Curve >, bb::PairingPoints< Curve > > PairingPoints
ReductionResult reduce_to_pairing_check(const Proof &proof, const InputCommitments &input_commitments)
Reduce the merge proof to a pairing check.
std::array< Commitment, NUM_WIRES > TableCommitments
void add_entry(size_t round, const std::string &element_label, size_t element_size)
void add_challenge(size_t round, const std::string &label)
Add a single challenge label to the manifest for the given round.
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
bool pairing_check(const GroupElement &p0, const GroupElement &p1)
verifies a pairing equation over 2 points using the verifier SRS
Representation of the Grumpkin Verifier Commitment Key inside a bn254 circuit.
typename Group::affine_element AffineElement
Definition bn254.hpp:22
typename Group::element Element
Definition grumpkin.hpp:62
static constexpr bool is_stdlib_type
Definition grumpkin.hpp:69
typename Group::affine_element AffineElement
Definition grumpkin.hpp:63
A simple wrapper around a vector of stdlib field elements representing a proof.
Definition proof.hpp:19
void info(Args... args)
Definition log.hpp:89
AluTraceBuilder builder
Definition alu.test.cpp:124
testing::Types< stdlib::secp256k1< UltraCircuitBuilder >, stdlib::secp256r1< UltraCircuitBuilder >, stdlib::secp256k1< MegaCircuitBuilder >, stdlib::secp256r1< MegaCircuitBuilder > > CurveTypes
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
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:185
TYPED_TEST_SUITE(ShpleminiTest, TestSettings)
field< Bn254FrParams > fr
Definition fr.hpp:174
::testing::Types< curve::BN254, curve::Grumpkin > CurveTypes
OriginTag extract_transcript_tag(const TranscriptType &transcript)
Extract origin tag context from a transcript.
MergeSettings
The MergeSettings define whether an current subtable will be added at the beginning (PREPEND) or at t...
TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching)
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
This file contains part of the logic for the Origin Tag mechanism that tracks the use of in-circuit p...
size_t transcript_index