Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
recursive_verifier.test.cpp
Go to the documentation of this file.
16
17#include <gtest/gtest.h>
18
19namespace bb::avm2::constraining {
20
21class AvmRecursiveTests : public ::testing::Test {
22 public:
27
29
30 // Helper function to create and verify native proof
35
36 // Helper function to create and verify native proof. Due to the way ASSERT_TRUE
37 // works, this routine needs to return void and therefore we feed proof_result
38 // by reference.
40 {
41 static auto [cached_verified, cached_proof_result] = []() {
42 auto [trace, public_inputs] = testing::get_minimal_trace_with_pi();
43
44 const auto public_inputs_cols = public_inputs.to_columns();
45
46 InnerProver prover;
47 const auto proof = prover.prove(std::move(trace));
48 const auto verification_key = InnerProver::create_verification_key(InnerProver().get_verification_key());
49 InnerVerifier verifier(verification_key);
50
51 const bool verified = verifier.verify_proof(proof, public_inputs_cols);
52
53 return std::pair<bool, NativeProofResult>{ verified, NativeProofResult{ proof, public_inputs_cols } };
54 }();
55
56 ASSERT_TRUE(cached_verified) << "native proof verification failed";
57 proof_result = cached_proof_result;
58 }
59};
60
61// Parameterized test class for testing with and without proof padding
62class AvmRecursiveTestsParameterized : public AvmRecursiveTests, public ::testing::WithParamInterface<bool> {};
63
74{
76 GTEST_SKIP() << "Skipping slow test";
77 }
78
79 const bool pad_proof = GetParam();
80
81 // Type aliases specific to GoblinRecursion test
83 using OuterBuilder = typename UltraRollupFlavor::CircuitBuilder;
85 using UltraRollupProver = UltraProver_<UltraRollupFlavor>;
86 using NativeVerifierCommitmentKey = typename AvmFlavor::VerifierCommitmentKey;
87
88 NativeProofResult proof_result;
89 std::cout << "Creating and verifying native proof..." << std::endl;
90 std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
91 ASSERT_NO_FATAL_FAILURE({ create_and_verify_native_proof(proof_result); });
92 std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
93 std::cout << "Time taken (native proof): " << std::chrono::duration_cast<std::chrono::seconds>(end - start).count()
94 << "s" << std::endl;
95
96 auto [proof, public_inputs_cols] = proof_result;
97
98 // Optionally pad the proof to match production behavior
99 if (pad_proof) {
100 std::cout << "Padding proof from " << proof.size() << " to " << AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED
101 << " fields" << std::endl;
102 ASSERT_LE(proof.size(), AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED) << "Proof exceeds padded length";
104 }
105
106 // Construct stdlib representations of the proof, public inputs and verification key
107 OuterBuilder outer_circuit;
108 stdlib::Proof<OuterBuilder> stdlib_proof(outer_circuit, proof);
109
110 std::vector<std::vector<UltraFF>> public_inputs_ct;
111 public_inputs_ct.reserve(public_inputs_cols.size());
112 for (const auto& vec : public_inputs_cols) {
114 vec_ct.reserve(vec.size());
115 for (const auto& val : vec) {
116 vec_ct.push_back(UltraFF::from_witness(&outer_circuit, val));
117 }
118 public_inputs_ct.push_back(vec_ct);
119 }
120
121 // Construct the AVM recursive verifier and verify the proof
122 // Scoped to free memory of AvmRecursiveVerifier.
123 auto verifier_output = [&]() {
124 std::cout << "Constructing AvmRecursiveVerifier and verifying " << (pad_proof ? "padded " : "") << "proof..."
125 << std::endl;
126 std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
127 AvmRecursiveVerifier avm_rec_verifier(outer_circuit);
128 auto result = avm_rec_verifier.verify_proof(stdlib_proof, public_inputs_ct);
129 std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
130 std::cout << "Time taken (recursive verification): "
131 << std::chrono::duration_cast<std::chrono::seconds>(end - start).count() << "s" << std::endl;
132 return result;
133 }();
134
136 inputs.pairing_inputs = verifier_output.points_accumulator;
137 inputs.ipa_claim = verifier_output.ipa_claim;
138 inputs.set_public();
139 outer_circuit.ipa_proof = verifier_output.ipa_proof.get_value();
140
141 // Ensure that the pairing check is satisfied on the outputs of the recursive verifier
142 NativeVerifierCommitmentKey pcs_vkey{};
143 bool agg_output_valid = pcs_vkey.pairing_check(verifier_output.points_accumulator.P0.get_value(),
144 verifier_output.points_accumulator.P1.get_value());
145 ASSERT_TRUE(agg_output_valid) << "Pairing points (aggregation state) are not valid.";
146 ASSERT_FALSE(outer_circuit.failed()) << "Outer circuit has failed.";
147
148 vinfo("Recursive verifier",
149 (pad_proof ? " (padded proof)" : ""),
150 ": finalized num gates = ",
151 outer_circuit.num_gates());
152
153 // Construct and verify an Ultra Rollup proof of the AVM recursive verifier circuit. This proof carries an IPA claim
154 // from ECCVM recursive verification in its public inputs that will be verified as part of the UltraRollupVerifier.
155 auto outer_proving_key = std::make_shared<ProverInstance_<UltraRollupFlavor>>(outer_circuit);
156
157 // Scoped to free memory of UltraRollupProver.
158 auto outer_proof = [&]() {
159 auto verification_key =
160 std::make_shared<UltraRollupFlavor::VerificationKey>(outer_proving_key->get_precomputed());
161 UltraRollupProver outer_prover(outer_proving_key, verification_key);
162 return outer_prover.construct_proof();
163 }();
164
165 // Verify the proof of the Ultra circuit that verified the AVM recursive verifier circuit
166 auto outer_verification_key =
167 std::make_shared<UltraRollupFlavor::VerificationKey>(outer_proving_key->get_precomputed());
168 auto outer_vk_and_hash = std::make_shared<UltraRollupFlavor::VKAndHash>(outer_verification_key);
169 UltraRollupVerifier final_verifier(outer_vk_and_hash);
170
171 bool result = final_verifier.verify_proof(outer_proof).result;
172 EXPECT_TRUE(result);
173}
174
177 ::testing::Values(false, true),
178 [](const auto& info) { return info.param ? "Padded" : "Unpadded"; });
179
180// Ensures that the recursive verifier fails with wrong PIs.
181TEST_F(AvmRecursiveTests, GoblinRecursionFailsWithWrongPIs)
182{
184 GTEST_SKIP() << "Skipping slow test";
185 }
186
187 // Type aliases specific to GoblinRecursion test
189 using OuterBuilder = typename UltraRollupFlavor::CircuitBuilder;
191
192 NativeProofResult proof_result;
193 std::cout << "Creating and verifying native proof..." << std::endl;
194 std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
195 ASSERT_NO_FATAL_FAILURE({ create_and_verify_native_proof(proof_result); });
196 std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
197 std::cout << "Time taken (native proof): " << std::chrono::duration_cast<std::chrono::seconds>(end - start).count()
198 << "s" << std::endl;
199
200 auto [proof, public_inputs_cols] = proof_result;
201
202 // Construct stdlib representations of the proof, public inputs and verification key
203 OuterBuilder outer_circuit;
204 stdlib::Proof<OuterBuilder> stdlib_proof(outer_circuit, proof);
205
206 std::vector<std::vector<UltraFF>> public_inputs_ct;
207 public_inputs_ct.reserve(public_inputs_cols.size());
208 for (const auto& vec : public_inputs_cols) {
210 vec_ct.reserve(vec.size());
211 for (const auto& val : vec) {
212 vec_ct.push_back(UltraFF::from_witness(&outer_circuit, val));
213 }
214 public_inputs_ct.push_back(vec_ct);
215 }
216 // Mutate a PI entry to verify that validation correctly fails with incorrect public inputs
217 public_inputs_ct[1][5] += 1;
218
219 // Construct the AVM recursive verifier and verify the proof
220 // Scoped to free memory of AvmRecursiveVerifier.
221 {
222 std::cout << "Constructing AvmRecursiveVerifier and verifying proof..." << std::endl;
223 std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
224 AvmRecursiveVerifier avm_rec_verifier(outer_circuit);
225 auto result = avm_rec_verifier.verify_proof(stdlib_proof, public_inputs_ct);
226 std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
227 std::cout << "Time taken (recursive verification): "
228 << std::chrono::duration_cast<std::chrono::seconds>(end - start).count() << "s" << std::endl;
229 };
230
231 ASSERT_TRUE(outer_circuit.failed()) << "Outer circuit SHOULD fail with bad PIs.";
232}
233
234} // namespace bb::avm2::constraining
#define AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED
UltraCircuitBuilder CircuitBuilder
typename Curve::ScalarField FF
Output verify_proof(const Proof &proof)
Perform ultra verification.
AvmFlavorSettings::VerifierCommitmentKey VerifierCommitmentKey
Definition flavor.hpp:43
Recursive verifier of AVM2 proofs that utilizes the Goblin mechanism for efficient EC operations.
Proof prove(tracegen::TraceContainer &&trace)
static std::shared_ptr< AvmVerifier::VerificationKey > create_verification_key(const VkData &vk_data)
AvmRecursiveFlavorSettings::CircuitBuilder CircuitBuilder
PairingPoints verify_proof(const HonkProof &proof, const std::vector< std::vector< fr > > &public_inputs_vec_nt)
virtual bool verify_proof(const HonkProof &proof, const std::vector< std::vector< FF > > &public_inputs)
This function verifies an Avm Honk proof for given program settings.
Definition verifier.cpp:42
typename RecursiveFlavor::CircuitBuilder OuterBuilder
static void create_and_verify_native_proof(NativeProofResult &proof_result)
A simple wrapper around a vector of stdlib field elements representing a proof.
Definition proof.hpp:19
The data that is propagated on the public inputs of a rollup circuit.
#define vinfo(...)
Definition log.hpp:94
void info(Args... args)
Definition log.hpp:89
TestTraceContainer trace
AvmProvingInputs inputs
INSTANTIATE_TEST_SUITE_P(PaddingVariants, AvmRecursiveTestsParameterized, ::testing::Values(false, true), [](const auto &info) { return info.param ? "Padded" :"Unpadded";})
TEST_F(AvmRecursiveTests, GoblinRecursionFailsWithWrongPIs)
TEST_P(AvmRecursiveTestsParameterized, GoblinRecursion)
A test of the Goblinized AVM recursive verifier.
bool skip_slow_tests()
Check if slow tests should be skipped.
Definition fixtures.cpp:199
std::pair< tracegen::TraceContainer, PublicInputs > get_minimal_trace_with_pi()
Definition fixtures.cpp:183
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13