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 [pairing_points, merged_table_commitments, degree_check_passed, concatenation_check_passed] =
198 verifier.verify_proof(proof, input_commitments);
199
200 // Perform pairing check and verify
201 VerifierCommitmentKey pcs_verification_key;
202 bool pairing_verified =
203 pcs_verification_key.pairing_check(to_native(pairing_points.P0), to_native(pairing_points.P1));
204 bool verified = pairing_verified && degree_check_passed && concatenation_check_passed;
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(merged_table_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 MergeProver merge_prover{ builder.op_queue };
236 auto merge_proof = merge_prover.construct_proof();
237
238 EXPECT_EQ(merge_proof.size(), MERGE_PROOF_SIZE);
239 }
240
244 static void test_single_merge()
245 {
246 using InnerFlavor = MegaFlavor;
247 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
248
249 auto op_queue = std::make_shared<ECCOpQueue>();
250 InnerBuilder circuit{ op_queue };
252
253 prove_and_verify_merge(op_queue);
254 }
255
260 {
261 using InnerFlavor = MegaFlavor;
262 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
263
264 auto op_queue = std::make_shared<ECCOpQueue>();
265
266 // First circuit
267 InnerBuilder circuit1{ op_queue };
269 prove_and_verify_merge(op_queue);
270
271 // Second circuit
272 InnerBuilder circuit2{ op_queue };
274 prove_and_verify_merge(op_queue);
275
276 // Third circuit
277 InnerBuilder circuit3{ op_queue };
279 prove_and_verify_merge(op_queue);
280 }
281
286 {
287 using InnerFlavor = MegaFlavor;
288 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
289
290 auto op_queue = std::make_shared<ECCOpQueue>();
291
292 // First circuit with prepend
293 InnerBuilder circuit1{ op_queue };
295 prove_and_verify_merge(op_queue);
296
297 // Second circuit with prepend
298 InnerBuilder circuit2{ op_queue };
300 prove_and_verify_merge(op_queue);
301
302 // Third circuit with append
303 InnerBuilder circuit3{ op_queue };
306 }
307
312 {
313 using InnerFlavor = MegaFlavor;
314 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
315
316 auto op_queue = std::make_shared<ECCOpQueue>();
317 InnerBuilder circuit{ op_queue };
319
320 prove_and_verify_merge(op_queue, settings, TamperProofMode::Shift, false);
321 }
322
327 {
328 using InnerFlavor = MegaFlavor;
329 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
330
331 auto op_queue = std::make_shared<ECCOpQueue>();
332 InnerBuilder circuit{ op_queue };
334
335 prove_and_verify_merge(op_queue, settings, TamperProofMode::MCommitment, false);
336 }
337
342 {
343 using InnerFlavor = MegaFlavor;
344 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
345
346 auto op_queue = std::make_shared<ECCOpQueue>();
347 InnerBuilder circuit{ op_queue };
349
350 prove_and_verify_merge(op_queue, settings, TamperProofMode::LEval, false);
351 }
352};
353
354// Define test types: native and recursive contexts
355using CurveTypes = ::testing::Types<curve::BN254, // Native
356 stdlib::bn254<MegaCircuitBuilder>, // Recursive (Mega)
357 stdlib::bn254<UltraCircuitBuilder>>; // Recursive (Ultra)
358
360
361TYPED_TEST(MergeTests, MergeProofSizeCheck)
362{
363 TestFixture::test_merge_proof_size();
364}
365
367{
368 TestFixture::test_single_merge();
369}
370
371TYPED_TEST(MergeTests, MultipleMergesPrepend)
372{
373 TestFixture::test_multiple_merges_prepend();
374}
375
376TYPED_TEST(MergeTests, MergePrependThenAppend)
377{
378 TestFixture::test_merge_prepend_then_append();
379}
380
381TYPED_TEST(MergeTests, DegreeCheckFailurePrepend)
382{
383 TestFixture::test_degree_check_failure(MergeSettings::PREPEND);
384}
385
386TYPED_TEST(MergeTests, DegreeCheckFailureAppend)
387{
388 TestFixture::test_degree_check_failure(MergeSettings::APPEND);
389}
390
391TYPED_TEST(MergeTests, MergeFailurePrepend)
392{
393 TestFixture::test_merge_failure(MergeSettings::PREPEND);
394}
395
396TYPED_TEST(MergeTests, MergeFailureAppend)
397{
398 TestFixture::test_merge_failure(MergeSettings::APPEND);
399}
400
401TYPED_TEST(MergeTests, EvalFailurePrepend)
402{
403 TestFixture::test_eval_failure(MergeSettings::PREPEND);
404}
405
406TYPED_TEST(MergeTests, EvalFailureAppend)
407{
408 TestFixture::test_eval_failure(MergeSettings::APPEND);
409}
410
424TYPED_TEST(MergeTests, DifferentTranscriptOriginTagFailure)
425{
426 if constexpr (!TestFixture::IsRecursive) {
427 GTEST_SKIP() << "OriginTag tests only apply to recursive context";
428 }
429
430 using BuilderType = typename TestFixture::BuilderType;
431 using MergeVerifierType = typename TestFixture::MergeVerifierType;
432 using Transcript = typename TestFixture::Transcript;
433 using InnerFlavor = MegaFlavor;
434 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
435 constexpr size_t NUM_WIRES = TestFixture::NUM_WIRES;
436
437 // Create single builder for both verifiers (realistic - both in same circuit)
438 BuilderType builder;
439
440 // === Generate two separate merge proofs (simulating two independent merge operations) ===
441 auto op_queue_1 = std::make_shared<ECCOpQueue>();
442 InnerBuilder circuit_1{ op_queue_1 };
444 MergeProver prover_1{ op_queue_1 };
445 auto proof_1 = prover_1.construct_proof();
446
447 auto op_queue_2 = std::make_shared<ECCOpQueue>();
448 InnerBuilder circuit_2{ op_queue_2 };
450 MergeProver prover_2{ op_queue_2 };
451 auto proof_2 = prover_2.construct_proof();
452
453 // Get native commitments for proof 1 (will be used with verifier 1's transcript)
454 auto t_1 = op_queue_1->construct_current_ultra_ops_subtable_columns();
455 auto T_prev_1 = op_queue_1->construct_previous_ultra_ops_table_columns();
457 std::array<curve::BN254::AffineElement, NUM_WIRES> native_T_prev_commitments_1;
458 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
459 native_t_commitments_1[idx] = prover_1.pcs_commitment_key.commit(t_1[idx]);
460 native_T_prev_commitments_1[idx] = prover_1.pcs_commitment_key.commit(T_prev_1[idx]);
461 }
462
463 // === Create first verifier with its own transcript instance ===
464 auto transcript_1 = std::make_shared<Transcript>();
465 [[maybe_unused]] MergeVerifierType verifier_1{ MergeSettings::PREPEND, transcript_1 };
466
467 [[maybe_unused]] auto proof_1_recursive = TestFixture::create_proof(builder, proof_1);
468
469 // Create commitments for verifier 1 - these will be "owned" by transcript_1
470 // When we read from the proof using transcript_1, those values get tagged with transcript_1's parent_tag
471 typename MergeVerifierType::InputCommitments input_commitments_1;
472 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
473 input_commitments_1.t_commitments[idx] = TestFixture::create_commitment(builder, native_t_commitments_1[idx]);
474 input_commitments_1.T_prev_commitments[idx] =
475 TestFixture::create_commitment(builder, native_T_prev_commitments_1[idx]);
476 }
477
478 // === Create second verifier with a DIFFERENT transcript instance ===
479 // This simulates having two independent merge verifiers in the same circuit
480 auto transcript_2 = std::make_shared<Transcript>();
481 MergeVerifierType verifier_2{ MergeSettings::PREPEND, transcript_2 };
482
483 auto proof_2_recursive = TestFixture::create_proof(builder, proof_2);
484
485 // Get the parent tags to show they're different
486 OriginTag tag_1 = extract_transcript_tag(*transcript_1);
487 OriginTag tag_2 = extract_transcript_tag(*transcript_2);
488
489 info("Verifier 1 transcript_index: ", tag_1.transcript_index);
490 info("Verifier 2 transcript_index: ", tag_2.transcript_index);
491 ASSERT_NE(tag_1.transcript_index, tag_2.transcript_index) << "Transcripts should have different parent tags";
492
493 // === SECURITY VIOLATION: Try to use commitments from proof 1 with verifier 2 ===
494
495 // To make this more realistic, we need to actually receive values from transcript_1 into the commitments
496 // In a real scenario, the verifier would receive_from_prover which tags values with the transcript's parent_tag
497 // For this test, we'll manually tag the commitments as if they came from transcript_1
498 OriginTag transcript_1_tag(tag_1.transcript_index, 0, /*is_submitted=*/true);
499 for (size_t idx = 0; idx < NUM_WIRES; idx++) {
500 // Tag these commitments as if they were read from transcript_1
501 if constexpr (TestFixture::IsRecursive) {
502 input_commitments_1.t_commitments[idx].set_origin_tag(transcript_1_tag);
503 input_commitments_1.T_prev_commitments[idx].set_origin_tag(transcript_1_tag);
504 }
505 }
506
507 // Now try to verify proof_2 using verifier_2 (with transcript_2) but with commitments tagged for transcript_1
508 // When verifier_2 reads from proof_2_recursive using transcript_2, those values will have tag_2.parent_tag
509 // When it tries to mix them with input_commitments_1 (which have tag_1.parent_tag), the check should trigger
510 info("Attempting to mix transcript_1 commitments with transcript_2 proof verification...");
511
512 // Catch the exception and verify it's the expected cross-transcript error
513#ifndef NDEBUG
514 EXPECT_THROW_OR_ABORT([[maybe_unused]] auto result =
515 verifier_2.verify_proof(proof_2_recursive, input_commitments_1),
516 "Tags from different transcripts were involved in the same computation");
517#endif
518}
519
524class MergeTranscriptTests : public ::testing::Test {
525 public:
527
535 {
536 TranscriptManifest manifest_expected;
537 constexpr size_t NUM_WIRES = 4;
538
539 // Size calculations
540 size_t frs_per_Fr = 1; // Native field element
541 size_t frs_per_G = FrCodec::calc_num_fields<curve::BN254::AffineElement>(); // Commitment = 4 frs
542 size_t frs_per_uint32 = 1; // shift_size
543
544 size_t round = 0;
545
546 // Round 0: Prover sends shift_size and merged table commitments
547 manifest_expected.add_entry(round, "shift_size", frs_per_uint32);
548 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
549 manifest_expected.add_entry(round, "MERGED_TABLE_" + std::to_string(idx), frs_per_G);
550 }
551 // Verifier generates degree check challenges
552 manifest_expected.add_challenge(round, "LEFT_TABLE_DEGREE_CHECK_0");
553 manifest_expected.add_challenge(round, "LEFT_TABLE_DEGREE_CHECK_1");
554 manifest_expected.add_challenge(round, "LEFT_TABLE_DEGREE_CHECK_2");
555 manifest_expected.add_challenge(round, "LEFT_TABLE_DEGREE_CHECK_3");
556
557 // Round 1: Verifier generates Shplonk batching challenges, Prover sends degree check polynomial commitment
558 round++;
559 for (size_t idx = 0; idx < 13; ++idx) {
560 manifest_expected.add_challenge(round, "SHPLONK_MERGE_BATCHING_CHALLENGE_" + std::to_string(idx));
561 }
562 manifest_expected.add_entry(round, "REVERSED_BATCHED_LEFT_TABLES", frs_per_G);
563
564 // Round 2: Verifier generates evaluation challenge kappa
565 round++;
566 manifest_expected.add_challenge(round, "kappa");
567
568 // Round 3: Verifier generates Shplonk opening challenge, Prover sends all evaluations and quotient
569 round++;
570 manifest_expected.add_challenge(round, "shplonk_opening_challenge");
571 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
572 manifest_expected.add_entry(round, "LEFT_TABLE_EVAL_" + std::to_string(idx), frs_per_Fr);
573 }
574 for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
575 manifest_expected.add_entry(round, "RIGHT_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, "MERGED_TABLE_EVAL_" + std::to_string(idx), frs_per_Fr);
579 }
580 manifest_expected.add_entry(round, "REVERSED_BATCHED_LEFT_TABLES_EVAL", frs_per_Fr);
581 manifest_expected.add_entry(round, "SHPLONK_BATCHED_QUOTIENT", frs_per_G);
582
583 // Round 4: KZG opening proof with masking challenge
584 round++;
585 manifest_expected.add_challenge(round, "KZG:masking_challenge");
586 manifest_expected.add_entry(round, "KZG:W", frs_per_G);
587
588 return manifest_expected;
589 }
590};
591
595TEST_F(MergeTranscriptTests, ProverManifestConsistency)
596{
597 using InnerFlavor = MegaFlavor;
598 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
599
600 // Construct a simple circuit to generate merge proof
601 auto op_queue = std::make_shared<ECCOpQueue>();
602 InnerBuilder circuit{ op_queue };
604
605 // Construct merge proof with manifest enabled
606 auto transcript = std::make_shared<NativeTranscript>();
607 transcript->enable_manifest();
608 CommitmentKey<curve::BN254> commitment_key;
609 MergeProver merge_prover{ op_queue, MergeSettings::PREPEND, commitment_key, transcript };
610 auto merge_proof = merge_prover.construct_proof();
611
612 // Check prover manifest matches expected manifest
613 auto manifest_expected = construct_merge_manifest();
614 auto prover_manifest = merge_prover.transcript->get_manifest();
615
616 ASSERT_GT(manifest_expected.size(), 0);
617 ASSERT_EQ(prover_manifest.size(), manifest_expected.size())
618 << "Prover manifest has " << prover_manifest.size() << " rounds, expected " << manifest_expected.size();
619
620 for (size_t round = 0; round < manifest_expected.size(); ++round) {
621 ASSERT_EQ(prover_manifest[round], manifest_expected[round]) << "Prover manifest discrepancy in round " << round;
622 }
623}
624
628TEST_F(MergeTranscriptTests, VerifierManifestConsistency)
629{
630 using InnerFlavor = MegaFlavor;
631 using InnerBuilder = typename InnerFlavor::CircuitBuilder;
632
633 // Construct a simple circuit
634 auto op_queue = std::make_shared<ECCOpQueue>();
635 InnerBuilder circuit{ op_queue };
637
638 // Generate merge proof with prover manifest enabled
639 auto prover_transcript = std::make_shared<NativeTranscript>();
640 prover_transcript->enable_manifest();
641 CommitmentKey<curve::BN254> commitment_key;
642 MergeProver merge_prover{ op_queue, MergeSettings::PREPEND, commitment_key, prover_transcript };
643 auto merge_proof = merge_prover.construct_proof();
644
645 // Construct commitments for verifier
646 MergeVerifier::InputCommitments merge_commitments;
647 auto t_current = op_queue->construct_current_ultra_ops_subtable_columns();
648 auto T_prev = op_queue->construct_previous_ultra_ops_table_columns();
649 for (size_t idx = 0; idx < MegaFlavor::NUM_WIRES; idx++) {
650 merge_commitments.t_commitments[idx] = merge_prover.pcs_commitment_key.commit(t_current[idx]);
651 merge_commitments.T_prev_commitments[idx] = merge_prover.pcs_commitment_key.commit(T_prev[idx]);
652 }
653
654 // Verify proof with verifier manifest enabled
655 auto verifier_transcript = std::make_shared<NativeTranscript>();
656 verifier_transcript->enable_manifest();
657 MergeVerifier merge_verifier{ MergeSettings::PREPEND, verifier_transcript };
658 auto [pairing_points, _, degree_check_passed, concatenation_check_passed] =
659 merge_verifier.verify_proof(merge_proof, merge_commitments);
660
661 // Verification should succeed
662 ASSERT_TRUE(pairing_points.check() && degree_check_passed && concatenation_check_passed);
663
664 // Check prover and verifier manifests match
665 auto prover_manifest = merge_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_OR_ABORT(statement, matcher)
Definition assert.hpp:174
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
Defines the circuit block types for the Mega arithmetization.
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
VerificationResult verify_proof(const Proof &proof, const InputCommitments &input_commitments)
Verify the merge proof.
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:75
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