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 auto prover_transcript = std::make_shared<NativeTranscript>();
160 MergeProver merge_prover{ op_queue, prover_transcript, settings };
161 auto native_proof = merge_prover.construct_proof();
162 tamper_with_proof(native_proof, tampering_mode);
163
164 // Create commitments to subtables
165 auto t_current = op_queue->construct_current_ultra_ops_subtable_columns();
166 auto T_prev = op_queue->construct_previous_ultra_ops_table_columns();
167
168 // Native commitments
171 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
172 native_t_commitments[idx] = merge_prover.pcs_commitment_key.commit(t_current[idx]);
173 native_T_prev_commitments[idx] = merge_prover.pcs_commitment_key.commit(T_prev[idx]);
174 }
175
176 // Compute expected merged table commitments independently
177 // After merge, the full table is T_merged = T_prev || t_current (PREPEND) or t_current || T_prev (APPEND)
178 auto T_merged = op_queue->construct_ultra_ops_table_columns();
179 std::array<curve::BN254::AffineElement, NUM_WIRES> expected_merged_commitments;
180 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
181 expected_merged_commitments[idx] = merge_prover.pcs_commitment_key.commit(T_merged[idx]);
182 }
183
184 // Create builder (only used in recursive context)
186
187 // Create commitments and proof in the appropriate context
188 InputCommitments input_commitments;
189 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
190 input_commitments.t_commitments[idx] = create_commitment(builder, native_t_commitments[idx]);
191 input_commitments.T_prev_commitments[idx] = create_commitment(builder, native_T_prev_commitments[idx]);
192 }
193 Proof proof = create_proof(builder, native_proof);
194
195 // Verify the proof
196 auto transcript = std::make_shared<Transcript>();
197 MergeVerifierType verifier{ settings, transcript };
198 auto result = verifier.reduce_to_pairing_check(proof, input_commitments);
199
200 // Perform pairing check and verify
201 VerifierCommitmentKey pcs_verification_key;
202 bool pairing_verified = pcs_verification_key.pairing_check(to_native(result.pairing_points.P0),
203 to_native(result.pairing_points.P1));
204 bool verified = pairing_verified && result.reduction_succeeded;
205 EXPECT_EQ(verified, expected);
206
207 // If verification is expected to succeed, also check that the merged table commitments match
208 if (expected) {
209 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
210 EXPECT_EQ(to_native(result.merged_commitments[idx]), expected_merged_commitments[idx])
211 << "Merged table commitment mismatch at index " << idx;
212 }
213 }
214
215 // Check circuit validity (only relevant in recursive context)
216 if constexpr (IsRecursive) {
217 bool circuit_valid = check_circuit(builder);
218 EXPECT_EQ(circuit_valid, expected);
219 }
220 }
221
227 {
228 using InnerFlavor = MegaFlavor;
229 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
230
231 InnerBuilder builder;
233
234 // Construct a merge proof and ensure its size matches expectation
235 auto transcript = std::make_shared<NativeTranscript>();
236 MergeProver merge_prover{ builder.op_queue, transcript };
237 auto merge_proof = merge_prover.construct_proof();
238
239 EXPECT_EQ(merge_proof.size(), MERGE_PROOF_SIZE);
240 }
241
245 static void test_single_merge()
246 {
247 using InnerFlavor = MegaFlavor;
248 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
249
250 auto op_queue = std::make_shared<ECCOpQueue>();
251 InnerBuilder circuit{ op_queue };
253
254 prove_and_verify_merge(op_queue);
255 }
256
261 {
262 using InnerFlavor = MegaFlavor;
263 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
264
265 auto op_queue = std::make_shared<ECCOpQueue>();
266
267 // First circuit
268 InnerBuilder circuit1{ op_queue };
270 prove_and_verify_merge(op_queue);
271
272 // Second circuit
273 InnerBuilder circuit2{ op_queue };
275 prove_and_verify_merge(op_queue);
276
277 // Third circuit
278 InnerBuilder circuit3{ op_queue };
280 prove_and_verify_merge(op_queue);
281 }
282
287 {
288 using InnerFlavor = MegaFlavor;
289 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
290
291 auto op_queue = std::make_shared<ECCOpQueue>();
292
293 // First circuit with prepend
294 InnerBuilder circuit1{ op_queue };
296 prove_and_verify_merge(op_queue);
297
298 // Second circuit with prepend
299 InnerBuilder circuit2{ op_queue };
301 prove_and_verify_merge(op_queue);
302
303 // Third circuit with append
304 InnerBuilder circuit3{ op_queue };
307 }
308
313 {
314 using InnerFlavor = MegaFlavor;
315 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
316
317 auto op_queue = std::make_shared<ECCOpQueue>();
318 InnerBuilder circuit{ op_queue };
320
321 prove_and_verify_merge(op_queue, settings, TamperProofMode::Shift, false);
322 }
323
328 {
329 using InnerFlavor = MegaFlavor;
330 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
331
332 auto op_queue = std::make_shared<ECCOpQueue>();
333 InnerBuilder circuit{ op_queue };
335
336 prove_and_verify_merge(op_queue, settings, TamperProofMode::MCommitment, false);
337 }
338
343 {
344 using InnerFlavor = MegaFlavor;
345 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
346
347 auto op_queue = std::make_shared<ECCOpQueue>();
348 InnerBuilder circuit{ op_queue };
350
351 prove_and_verify_merge(op_queue, settings, TamperProofMode::LEval, false);
352 }
353};
354
355// Define test types: native and recursive contexts
356using CurveTypes = ::testing::Types<curve::BN254, // Native
357 stdlib::bn254<MegaCircuitBuilder>, // Recursive (Mega)
358 stdlib::bn254<UltraCircuitBuilder>>; // Recursive (Ultra)
359
361
362TYPED_TEST(MergeTests, MergeProofSizeCheck)
363{
364 TestFixture::test_merge_proof_size();
365}
366
368{
369 TestFixture::test_single_merge();
370}
371
372TYPED_TEST(MergeTests, MultipleMergesPrepend)
373{
374 TestFixture::test_multiple_merges_prepend();
375}
376
377TYPED_TEST(MergeTests, MergePrependThenAppend)
378{
379 TestFixture::test_merge_prepend_then_append();
380}
381
382TYPED_TEST(MergeTests, DegreeCheckFailurePrepend)
383{
384 TestFixture::test_degree_check_failure(MergeSettings::PREPEND);
385}
386
387TYPED_TEST(MergeTests, DegreeCheckFailureAppend)
388{
389 TestFixture::test_degree_check_failure(MergeSettings::APPEND);
390}
391
392TYPED_TEST(MergeTests, MergeFailurePrepend)
393{
394 TestFixture::test_merge_failure(MergeSettings::PREPEND);
395}
396
397TYPED_TEST(MergeTests, MergeFailureAppend)
398{
399 TestFixture::test_merge_failure(MergeSettings::APPEND);
400}
401
402TYPED_TEST(MergeTests, EvalFailurePrepend)
403{
404 TestFixture::test_eval_failure(MergeSettings::PREPEND);
405}
406
407TYPED_TEST(MergeTests, EvalFailureAppend)
408{
409 TestFixture::test_eval_failure(MergeSettings::APPEND);
410}
411
425TYPED_TEST(MergeTests, DifferentTranscriptOriginTagFailure)
426{
427 if constexpr (!TestFixture::IsRecursive) {
428 GTEST_SKIP() << "OriginTag tests only apply to recursive context";
429 }
430
431 using BuilderType = typename TestFixture::BuilderType;
432 using MergeVerifierType = typename TestFixture::MergeVerifierType;
433 using Transcript = typename TestFixture::Transcript;
434 using InnerFlavor = MegaFlavor;
435 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
436 constexpr size_t NUM_WIRES = TestFixture::NUM_WIRES;
437
438 // Create single builder for both verifiers (realistic - both in same circuit)
439 BuilderType builder;
440
441 // === Generate two separate merge proofs (simulating two independent merge operations) ===
442 auto op_queue_1 = std::make_shared<ECCOpQueue>();
443 InnerBuilder circuit_1{ op_queue_1 };
445 auto prover_transcript_1 = std::make_shared<NativeTranscript>();
446 MergeProver prover_1{ op_queue_1, prover_transcript_1 };
447 auto proof_1 = prover_1.construct_proof();
448
449 auto op_queue_2 = std::make_shared<ECCOpQueue>();
450 InnerBuilder circuit_2{ op_queue_2 };
452 auto prover_transcript_2 = std::make_shared<NativeTranscript>();
453 MergeProver prover_2{ op_queue_2, prover_transcript_2 };
454 auto proof_2 = prover_2.construct_proof();
455
456 // Get native commitments for proof 1 (will be used with verifier 1's transcript)
457 auto t_1 = op_queue_1->construct_current_ultra_ops_subtable_columns();
458 auto T_prev_1 = op_queue_1->construct_previous_ultra_ops_table_columns();
460 std::array<curve::BN254::AffineElement, NUM_WIRES> native_T_prev_commitments_1;
461 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
462 native_t_commitments_1[idx] = prover_1.pcs_commitment_key.commit(t_1[idx]);
463 native_T_prev_commitments_1[idx] = prover_1.pcs_commitment_key.commit(T_prev_1[idx]);
464 }
465
466 // === Create first verifier with its own transcript instance ===
467 auto transcript_1 = std::make_shared<Transcript>();
468 [[maybe_unused]] MergeVerifierType verifier_1{ MergeSettings::PREPEND, transcript_1 };
469
470 [[maybe_unused]] auto proof_1_recursive = TestFixture::create_proof(builder, proof_1);
471
472 // Create commitments for verifier 1 - these will be "owned" by transcript_1
473 // When we read from the proof using transcript_1, those values get tagged with transcript_1's parent_tag
474 typename MergeVerifierType::InputCommitments input_commitments_1;
475 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
476 input_commitments_1.t_commitments[idx] = TestFixture::create_commitment(builder, native_t_commitments_1[idx]);
477 input_commitments_1.T_prev_commitments[idx] =
478 TestFixture::create_commitment(builder, native_T_prev_commitments_1[idx]);
479 }
480
481 // === Create second verifier with a DIFFERENT transcript instance ===
482 // This simulates having two independent merge verifiers in the same circuit
483 auto transcript_2 = std::make_shared<Transcript>();
484 MergeVerifierType verifier_2{ MergeSettings::PREPEND, transcript_2 };
485
486 auto proof_2_recursive = TestFixture::create_proof(builder, proof_2);
487
488 // Get the parent tags to show they're different
489 OriginTag tag_1 = extract_transcript_tag(*transcript_1);
490 OriginTag tag_2 = extract_transcript_tag(*transcript_2);
491
492 info("Verifier 1 transcript_index: ", tag_1.transcript_index);
493 info("Verifier 2 transcript_index: ", tag_2.transcript_index);
494 ASSERT_NE(tag_1.transcript_index, tag_2.transcript_index) << "Transcripts should have different parent tags";
495
496 // === SECURITY VIOLATION: Try to use commitments from proof 1 with verifier 2 ===
497
498 // To make this more realistic, we need to actually receive values from transcript_1 into the commitments
499 // In a real scenario, the verifier would receive_from_prover which tags values with the transcript's parent_tag
500 // For this test, we'll manually tag the commitments as if they came from transcript_1
501 OriginTag transcript_1_tag(tag_1.transcript_index, 0, /*is_submitted=*/true);
502 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
503 // Tag these commitments as if they were read from transcript_1
504 if constexpr (TestFixture::IsRecursive) {
505 input_commitments_1.t_commitments[idx].set_origin_tag(transcript_1_tag);
506 input_commitments_1.T_prev_commitments[idx].set_origin_tag(transcript_1_tag);
507 }
508 }
509
510 // Now try to verify proof_2 using verifier_2 (with transcript_2) but with commitments tagged for transcript_1
511 // When verifier_2 reads from proof_2_recursive using transcript_2, those values will have tag_2.parent_tag
512 // When it tries to mix them with input_commitments_1 (which have tag_1.parent_tag), the check should trigger
513 info("Attempting to mix transcript_1 commitments with transcript_2 proof verification...");
514
515 // Catch the exception and verify it's the expected cross-transcript error
516#ifndef NDEBUG
517 EXPECT_THROW_WITH_MESSAGE([[maybe_unused]] auto result =
518 verifier_2.verify_proof(proof_2_recursive, input_commitments_1),
519 "Tags from different transcripts were involved in the same computation");
520#endif
521}
522
527class MergeTranscriptTests : public ::testing::Test {
528 public:
530
538 {
539 TranscriptManifest manifest_expected;
540 constexpr size_t NUM_WIRES = 4;
541
542 // Size calculations
543 size_t frs_per_Fr = 1; // Native field element
544 size_t frs_per_G = FrCodec::calc_num_fields<curve::BN254::AffineElement>(); // Commitment = 4 frs
545 size_t frs_per_uint32 = 1; // shift_size
546
547 size_t round = 0;
548
549 // Round 0: Prover sends shift_size and merged table commitments
550 manifest_expected.add_entry(round, "shift_size", frs_per_uint32);
551 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
552 manifest_expected.add_entry(round, "MERGED_TABLE_" + std::to_string(idx), frs_per_G);
553 }
554 // Verifier generates degree check challenges
555 manifest_expected.add_challenge(round, "LEFT_TABLE_DEGREE_CHECK_0");
556 manifest_expected.add_challenge(round, "LEFT_TABLE_DEGREE_CHECK_1");
557 manifest_expected.add_challenge(round, "LEFT_TABLE_DEGREE_CHECK_2");
558 manifest_expected.add_challenge(round, "LEFT_TABLE_DEGREE_CHECK_3");
559
560 // Round 1: Verifier generates Shplonk batching challenges, Prover sends degree check polynomial commitment
561 round++;
562 for (size_t idx = 0; idx < 13; ++idx) {
563 manifest_expected.add_challenge(round, "SHPLONK_MERGE_BATCHING_CHALLENGE_" + std::to_string(idx));
564 }
565 manifest_expected.add_entry(round, "REVERSED_BATCHED_LEFT_TABLES", frs_per_G);
566
567 // Round 2: Verifier generates evaluation challenge kappa
568 round++;
569 manifest_expected.add_challenge(round, "kappa");
570
571 // Round 3: Verifier generates Shplonk opening challenge, Prover sends all evaluations and quotient
572 round++;
573 manifest_expected.add_challenge(round, "shplonk_opening_challenge");
574 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
575 manifest_expected.add_entry(round, "LEFT_TABLE_EVAL_" + std::to_string(idx), frs_per_Fr);
576 }
577 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
578 manifest_expected.add_entry(round, "RIGHT_TABLE_EVAL_" + std::to_string(idx), frs_per_Fr);
579 }
580 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
581 manifest_expected.add_entry(round, "MERGED_TABLE_EVAL_" + std::to_string(idx), frs_per_Fr);
582 }
583 manifest_expected.add_entry(round, "REVERSED_BATCHED_LEFT_TABLES_EVAL", frs_per_Fr);
584 manifest_expected.add_entry(round, "SHPLONK_BATCHED_QUOTIENT", frs_per_G);
585
586 // Round 4: KZG opening proof with masking challenge
587 round++;
588 manifest_expected.add_challenge(round, "KZG:masking_challenge");
589 manifest_expected.add_entry(round, "KZG:W", frs_per_G);
590
591 return manifest_expected;
592 }
593};
594
598TEST_F(MergeTranscriptTests, ProverManifestConsistency)
599{
600 using InnerFlavor = MegaFlavor;
601 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
602
603 // Construct a simple circuit to generate merge proof
604 auto op_queue = std::make_shared<ECCOpQueue>();
605 InnerBuilder circuit{ op_queue };
607
608 // Construct merge proof with manifest enabled
609 auto transcript = std::make_shared<NativeTranscript>();
610 transcript->enable_manifest();
611 MergeProver merge_prover{ op_queue, transcript };
612 auto merge_proof = merge_prover.construct_proof();
613
614 // Check prover manifest matches expected manifest
615 auto manifest_expected = construct_merge_manifest();
616 auto prover_manifest = transcript->get_manifest();
617
618 ASSERT_GT(manifest_expected.size(), 0);
619 ASSERT_EQ(prover_manifest.size(), manifest_expected.size())
620 << "Prover manifest has " << prover_manifest.size() << " rounds, expected " << manifest_expected.size();
621
622 for (size_t round = 0; round < manifest_expected.size(); ++round) {
623 ASSERT_EQ(prover_manifest[round], manifest_expected[round]) << "Prover manifest discrepancy in round " << round;
624 }
625}
626
630TEST_F(MergeTranscriptTests, VerifierManifestConsistency)
631{
632 using InnerFlavor = MegaFlavor;
633 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
634
635 // Construct a simple circuit
636 auto op_queue = std::make_shared<ECCOpQueue>();
637 InnerBuilder circuit{ op_queue };
639
640 // Generate merge proof with prover manifest enabled
641 auto prover_transcript = std::make_shared<NativeTranscript>();
642 prover_transcript->enable_manifest();
643 MergeProver merge_prover{ op_queue, prover_transcript };
644 auto merge_proof = merge_prover.construct_proof();
645
646 // Construct commitments for verifier
647 MergeVerifier::InputCommitments merge_commitments;
648 auto t_current = op_queue->construct_current_ultra_ops_subtable_columns();
649 auto T_prev = op_queue->construct_previous_ultra_ops_table_columns();
650 for (size_t idx = 0; idx < MegaFlavor::NUM_WIRES; idx++) {
651 merge_commitments.t_commitments[idx] = merge_prover.pcs_commitment_key.commit(t_current[idx]);
652 merge_commitments.T_prev_commitments[idx] = merge_prover.pcs_commitment_key.commit(T_prev[idx]);
653 }
654
655 // Verify proof with verifier manifest enabled
656 auto verifier_transcript = std::make_shared<NativeTranscript>();
657 verifier_transcript->enable_manifest();
658 MergeVerifier merge_verifier{ MergeSettings::PREPEND, verifier_transcript };
659 auto result = merge_verifier.reduce_to_pairing_check(merge_proof, merge_commitments);
660
661 // Verification should succeed
662 ASSERT_TRUE(result.pairing_points.check() && result.reduction_succeeded);
663
664 // Check prover and verifier manifests match
665 auto prover_manifest = prover_transcript->get_manifest();
666 auto verifier_manifest = verifier_transcript->get_manifest();
667
668 ASSERT_GT(prover_manifest.size(), 0);
669 ASSERT_EQ(prover_manifest.size(), verifier_manifest.size())
670 << "Prover has " << prover_manifest.size() << " rounds, verifier has " << verifier_manifest.size();
671
672 for (size_t round = 0; round < prover_manifest.size(); ++round) {
673 ASSERT_EQ(prover_manifest[round], verifier_manifest[round])
674 << "Prover/Verifier manifest discrepancy in round " << round;
675 }
676}
677
678} // namespace bb
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
Definition assert.hpp:193
Common transcript class for both parties. Stores the data for the current round, as well as the manif...
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
#define info(...)
Definition log.hpp:93
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:142
TYPED_TEST_SUITE(CommitmentKeyTest, Curves)
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.
TYPED_TEST(CommitmentKeyTest, CommitToZeroPoly)
MergeSettings
The MergeSettings define whether an current subtable will be added at the beginning (PREPEND) or at t...
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