Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
merge_verifier.test.cpp
Go to the documentation of this file.
11
13
21template <class RecursiveBuilder> class RecursiveMergeVerifierTest : public testing::Test {
22
23 // Types for recursive verifier circuit
27
28 // Define types relevant for inner circuit
32
33 // Define additional types for testing purposes
40
42
43 public:
45
46 static void tamper_with_proof(MergeProof& merge_proof, const TamperProofMode tampering_mode)
47 {
48 const size_t shift_idx = 0; // Index of shift_size in the merge proof
49 const size_t m_commitment_idx = 1; // Index of first commitment to merged table in merge proof
50 const size_t l_eval_idx = 34; // Index of first evaluation of l(1/kappa) in merge proof
51
52 switch (tampering_mode) {
54 // Tamper with the shift size in the proof
55 merge_proof[shift_idx] += 1;
56 break;
58 // Tamper with the commitment in the proof
59 Commitment m_commitment =
60 bb::field_conversion::convert_from_bn254_frs<Commitment>(std::span{ merge_proof }.subspan(
61 m_commitment_idx, bb::field_conversion::calc_num_bn254_frs<Commitment>()));
62 m_commitment = m_commitment + Commitment::one();
63 auto m_commitment_frs = bb::field_conversion::convert_to_bn254_frs<Commitment>(m_commitment);
64 for (size_t idx = 0; idx < 4; ++idx) {
65 merge_proof[m_commitment_idx + idx] = m_commitment_frs[idx];
66 }
67 break;
68 }
70 // Tamper with the evaluation in the proof
71 merge_proof[l_eval_idx] -= FF(1);
72 break;
73 default:
74 // Nothing to do
75 break;
76 }
77 }
78
81 const TamperProofMode tampering_mode = TamperProofMode::None,
82 const bool expected = true)
83 {
84 RecursiveBuilder outer_circuit;
85
86 MergeProver merge_prover{ op_queue, settings };
87 auto merge_proof = merge_prover.construct_proof();
88 tamper_with_proof(merge_proof, tampering_mode);
89
90 // Subtable values and commitments - needed for (Recursive)MergeVerifier
91 MergeCommitments merge_commitments;
92 RecursiveMergeCommitments recursive_merge_commitments;
93 auto t_current = op_queue->construct_current_ultra_ops_subtable_columns();
94 auto T_prev = op_queue->construct_previous_ultra_ops_table_columns();
95 for (size_t idx = 0; idx < InnerFlavor::NUM_WIRES; idx++) {
96 merge_commitments.t_commitments[idx] = merge_prover.pcs_commitment_key.commit(t_current[idx]);
97 merge_commitments.T_prev_commitments[idx] = merge_prover.pcs_commitment_key.commit(T_prev[idx]);
98 recursive_merge_commitments.t_commitments[idx] =
99 RecursiveMergeVerifier::Commitment::from_witness(&outer_circuit, merge_commitments.t_commitments[idx]);
100 recursive_merge_commitments.T_prev_commitments[idx] = RecursiveMergeVerifier::Commitment::from_witness(
101 &outer_circuit, merge_commitments.T_prev_commitments[idx]);
102 }
103
104 // Create a recursive merge verification circuit for the merge proof
105 RecursiveMergeVerifier verifier{ &outer_circuit, settings };
106 verifier.transcript->enable_manifest();
107 const stdlib::Proof<RecursiveBuilder> stdlib_merge_proof(outer_circuit, merge_proof);
108 auto [pairing_points, recursive_merged_table_commitments] =
109 verifier.verify_proof(stdlib_merge_proof, recursive_merge_commitments);
110
111 // Check for a failure flag in the recursive verifier circuit
112 EXPECT_EQ(outer_circuit.failed(), !expected) << outer_circuit.err();
113
114 // Check 1: Perform native merge verification then perform the pairing on the outputs of the recursive merge
115 // verifier and check that the result agrees.
116 MergeVerifier native_verifier{ settings };
117 native_verifier.transcript->enable_manifest();
118 auto [verified_native, merged_table_commitments] = native_verifier.verify_proof(merge_proof, merge_commitments);
119 VerifierCommitmentKey pcs_verification_key;
120 bool verified_recursive =
121 pcs_verification_key.pairing_check(pairing_points.P0.get_value(), pairing_points.P1.get_value());
122 EXPECT_EQ(verified_native, verified_recursive);
123 EXPECT_EQ(verified_recursive, expected);
124
125 // Check 2: Ensure that the underlying native and recursive merge verification algorithms agree by ensuring
126 // the manifests produced by each agree.
127 auto recursive_manifest = verifier.transcript->get_manifest();
128 auto native_manifest = native_verifier.transcript->get_manifest();
129 for (size_t i = 0; i < recursive_manifest.size(); ++i) {
130 EXPECT_EQ(recursive_manifest[i], native_manifest[i]);
131 }
132 }
133
138 {
139 auto op_queue = std::make_shared<ECCOpQueue>();
140
141 InnerBuilder circuit{ op_queue };
144 }
145
149 static void test_merge_failure()
150 {
151 auto op_queue = std::make_shared<ECCOpQueue>();
152
153 InnerBuilder circuit{ op_queue };
156 }
157
161 static void test_eval_failure()
162 {
163 auto op_queue = std::make_shared<ECCOpQueue>();
164
165 InnerBuilder circuit{ op_queue };
168 }
169
178 {
179 auto op_queue = std::make_shared<ECCOpQueue>();
180
181 InnerBuilder circuit{ op_queue };
183 prove_and_verify_merge(op_queue);
184
185 InnerBuilder circuit2{ op_queue };
187 prove_and_verify_merge(op_queue);
188
189 InnerBuilder circuit3{ op_queue };
192 }
193};
194
195using Builders = testing::Types<MegaCircuitBuilder, UltraCircuitBuilder>;
196
198
199TYPED_TEST(RecursiveMergeVerifierTest, SingleRecursiveVerification)
200{
201 TestFixture::test_recursive_merge_verification();
202};
203
205{
206 TestFixture::test_degree_check_failure();
207};
208
210{
211 TestFixture::test_merge_failure();
212};
213
215{
216 TestFixture::test_eval_failure();
217};
218
219} // namespace bb::stdlib::recursion::goblin
A DeciderProvingKey is normally constructed from a finalized circuit and it contains all the informat...
static void construct_simple_circuit(MegaBuilder &builder, bool last_circuit=false)
Generate a simple test circuit with some ECC op gates and conventional arithmetic gates.
Curve::ScalarField FF
static constexpr size_t NUM_WIRES
MegaCircuitBuilder CircuitBuilder
Curve::AffineElement Commitment
Prover class for the Goblin ECC op queue transcript merge protocol.
BB_PROFILE MergeProof construct_proof()
std::vector< FF > MergeProof
Verifier class for the Goblin ECC op queue transcript merge protocol.
std::array< Commitment, NUM_WIRES > TableCommitments
std::shared_ptr< Transcript > transcript
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.
A simple wrapper around a vector of stdlib field elements representing a proof.
Definition proof.hpp:19
Test suite for recursive verification of Goblin Merge proofs.
static void test_recursive_merge_verification()
Test recursive merge verification for the ops generated by several sample circuit,...
static void test_eval_failure()
Test failure g_j(kappa) = kappa^{k-1} * l_j(1/kappa)
static void tamper_with_proof(MergeProof &merge_proof, const TamperProofMode tampering_mode)
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)
static void test_merge_failure()
Test failure when m \neq l + X^k r.
MergeRecursiveVerifier_< RecursiveBuilder >::TableCommitments RecursiveTableCommitments
static void test_degree_check_failure()
Test failure when degree(l) > shift_size (as read from the proof)
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
TYPED_TEST(RecursiveMergeVerifierTest, SingleRecursiveVerification)
TYPED_TEST_SUITE(RecursiveMergeVerifierTest, Builders)
testing::Types< MegaCircuitBuilder, UltraCircuitBuilder > Builders
MergeSettings
The MergeSettings define whether an current subtable will be added at the beginning (PREPEND) or at t...
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13