Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
goblin_avm_recursive_verifier.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Planned, auditors: [Federico], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#pragma once
8
22
23namespace bb::avm2 {
24
52 public:
55
58
60
61 // The structure of the final output of the goblinized AVM2 recursive verifier. The IPA data comes from recursive
62 // verification of the ECCVM proof as part of Goblin recursive verification.
64
65 // Output of prover for inner Mega-arithmetized AVM recursive verifier circuit; input to the outer verifier
69 std::shared_ptr<MegaAvmFlavor::VerificationKey> mega_vk; // VK_M
70 };
71
73
77
88 [[nodiscard("IPA claim and Pairing points should be accumulated")]] RecursiveAvmGoblinOutput verify_proof(
89 const stdlib::Proof<UltraBuilder>& stdlib_proof, const std::vector<std::vector<UltraFF>>& public_inputs) const
90 {
91 // Construct and prove the inner Mega-arithmetized AVM recursive verifier circuit; proof is {\pi_M, \pi_G}
92 InnerProverOutput inner_output =
94
95 // Construct the outer Ultra-arithmetized Mega/Goblin recursive verifier circuit
97 construct_outer_recursive_verification_circuit(stdlib_proof, public_inputs, inner_output);
98
99 // Return ipa proof, ipa claim and output aggregation object produced from verifying the Mega + Goblin proofs
100 return result;
101 }
102
111 [[nodiscard("IPA claim and Pairing points should be accumulated")]] RecursiveAvmGoblinOutput
113 const std::vector<std::vector<UltraFF>>& public_inputs,
114 const InnerProverOutput& inner_output) const
115 {
116 // Types for MegaHonk and Goblin recursive verifiers arithmetized with Ultra
117 using MegaAvmRecursiveFlavor = MegaAvmRecursiveFlavor_<UltraBuilder>;
118 using MegaRecursiveVKAndHash = MegaAvmRecursiveFlavor::VKAndHash;
120 using MergeCommitments = GoblinRecursiveVerifier::MergeCommitments;
121 using FF = MegaAvmRecursiveFlavor::FF;
123 using MegaRecursiveVerifier = UltraVerifier_<MegaAvmRecursiveFlavor, IO>;
124
125 // Construct hash buffer containing the AVM proof and public inputs
126 std::vector<FF> hash_buffer;
127 hash_buffer.insert(hash_buffer.end(), stdlib_proof.begin(), stdlib_proof.end());
128 for (const std::vector<FF>& input_vec : public_inputs) {
129 hash_buffer.insert(hash_buffer.end(), input_vec.begin(), input_vec.end());
130 }
131
132 // Recursively verify the Mega proof \pi_M in the Ultra circuit
133 // All verifier components share a single transcript
135 auto mega_vk_and_hash = std::make_shared<MegaRecursiveVKAndHash>(ultra_builder, inner_output.mega_vk);
136 // Fix the inner mega vk and vk hash to be constants in the outer circuit.
137 mega_vk_and_hash->vk->fix_witness();
138 mega_vk_and_hash->hash.fix_witness();
139
140 MegaRecursiveVerifier mega_verifier(mega_vk_and_hash, transcript);
141 stdlib::Proof<UltraBuilder> mega_proof(ultra_builder, inner_output.mega_proof);
142 auto mega_verifier_output = mega_verifier.verify_proof(mega_proof);
143
144 // Recursively verify the goblin proof\pi_G in the Ultra circuit
145 MergeCommitments merge_commitments{
146 .t_commitments = mega_verifier.get_verifier_instance()->witness_commitments.get_ecc_op_wires().get_copy(),
148 ultra_builder) // Empty ecc op tables because there is only one layer of Goblin
149 };
150 GoblinStdlibProof stdlib_goblin_proof(ultra_builder, inner_output.goblin_proof);
151 GoblinRecursiveVerifier goblin_verifier{
152 transcript, stdlib_goblin_proof, merge_commitments, MergeSettings::PREPEND
153 };
154 GoblinRecursiveVerifier::ReductionResult goblin_verifier_output =
155 goblin_verifier.reduce_to_pairing_check_and_ipa_opening();
156
157 // Batch aggregate all pairing points: Mega + Merge + Translator
158 // Edge case handling disabled: Safe because all points are verifier-computed (deterministic, won't collide)
159 // and the random challenges maintain binding. Saves significant circuit gates.
160 std::vector<PairingPoints> all_pairing_points;
161 all_pairing_points.reserve(3);
162 all_pairing_points.push_back(mega_verifier_output.points_accumulator);
163 all_pairing_points.push_back(std::move(goblin_verifier_output.merge_pairing_points));
164 all_pairing_points.push_back(std::move(goblin_verifier_output.translator_pairing_points));
165
166 constexpr bool handle_edge_cases = false;
167 PairingPoints aggregated_pairing_points =
168 PairingPoints::aggregate_multiple(all_pairing_points, handle_edge_cases);
169
170 // Validate the consistency of the AVM2 verifier inputs {\pi, pub_inputs, VK}_{AVM2} between the inner (Mega)
171 // circuit and the outer (Ultra) by asserting equality on the independently computed hashes of this data.
172 const FF ultra_hash = stdlib::poseidon2<UltraBuilder>::hash(hash_buffer);
173 mega_verifier_output.mega_hash.assert_equal(ultra_hash);
174
175 // Return ipa proof, ipa claim and output aggregation object produced from verifying the Mega + Goblin proofs
177 output.points_accumulator = std::move(aggregated_pairing_points);
178 output.ipa_claim = goblin_verifier_output.ipa_claim;
179 output.ipa_proof = goblin_verifier_output.ipa_proof;
180 return output;
181 }
182
191 const stdlib::Proof<UltraBuilder>& stdlib_proof, const std::vector<std::vector<UltraFF>>& public_inputs) const
192 {
195 using MegaAvmProverInstance = ProverInstance_<MegaAvmFlavor>;
196 using MegaAvmVerificationKey = MegaAvmFlavor::VerificationKey;
197 using MegaAvmProver = UltraProver_<MegaAvmFlavor>;
198
199 // Instantiate Mega builder for the inner circuit (AVM2 proof recursive verifier)
200 Goblin goblin;
201 goblin.avm_mode = true;
202 MegaBuilder mega_builder(goblin.op_queue);
203 goblin.ensure_well_formed_op_queue_for_avm(mega_builder);
204 // lambda to convert from Ultra to Mega stdlib field buffer and add all elements to respective hash buffers
205 std::vector<FF> mega_hash_buffer;
206 auto convert_stdlib_ultra_to_stdlib_mega = [&](const std::vector<UltraFF>& ultra_object) {
207 std::vector<FF> mega_object;
208 for (const UltraFF& ultra_element : ultra_object) {
209 FF mega_element = FF::from_witness(&mega_builder, ultra_element.get_value());
210 mega_object.emplace_back(mega_element);
211 mega_hash_buffer.emplace_back(mega_element);
212 }
213 return mega_object;
214 };
215
216 // Convert the AVM proof, public inputs, and VK to stdlib Mega representations and add them to the hash buffer.
217 stdlib::Proof<MegaBuilder> mega_stdlib_proof = convert_stdlib_ultra_to_stdlib_mega(stdlib_proof);
218 std::vector<std::vector<FF>> mega_public_inputs;
219 mega_public_inputs.reserve(public_inputs.size());
220 for (const std::vector<UltraFF>& input_vec : public_inputs) {
221 mega_public_inputs.emplace_back(convert_stdlib_ultra_to_stdlib_mega(input_vec));
222 }
223
224 // Compute the hash and set it public
225 const FF mega_hash = stdlib::poseidon2<MegaBuilder>::hash(mega_hash_buffer);
226
227 // Construct a Mega-arithmetized AVM2 recursive verifier circuit
228 AvmRecursiveVerifier recursive_verifier{ mega_builder };
229 MegaPairingPoints points_accumulator = recursive_verifier.verify_proof(mega_stdlib_proof, mega_public_inputs);
230
231 // Public inputs
232 IO inputs;
233 inputs.mega_hash = mega_hash;
234 inputs.pairing_inputs = points_accumulator;
236
237 // All prover components share a single transcript
239 // Construct Mega proof \pi_M of the AVM recursive verifier circuit
240 auto mega_proving_key = std::make_shared<MegaAvmProverInstance>(mega_builder);
241 // Detect when MEGA_AVM_LOG_N needs to be bumped.
243 mega_proving_key->log_dyadic_size(),
244 MEGA_AVM_LOG_N,
245 "AVMRecursiveVerifier: circuit size exceeded current upper bound. If expected, bump MEGA_AVM_LOG_N");
246 auto mega_vk = std::make_shared<MegaAvmVerificationKey>(mega_proving_key->get_precomputed());
247 MegaAvmProver mega_prover(mega_proving_key, mega_vk, transcript);
248 HonkProof mega_proof = mega_prover.construct_proof();
249 goblin.transcript = transcript;
250 goblin.avm_mode = true;
251
252 // Construct corresponding Goblin proof \pi_G (includes Merge, ECCVM, and Translator proofs)
253 GoblinProof goblin_proof = goblin.prove();
254
255 return {
256 .mega_proof = mega_proof,
257 .goblin_proof = goblin_proof,
258 .mega_vk = mega_vk,
259 };
260 }
261};
262
263} // namespace bb::avm2
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:168
void ensure_well_formed_op_queue_for_avm(MegaBuilder &builder) const
Add required initial ops to the op queue for AVM mode.
Definition goblin.cpp:109
std::shared_ptr< OpQueue > op_queue
Definition goblin.hpp:48
GoblinProof prove(const MergeSettings merge_settings=MergeSettings::PREPEND)
Constuct a full Goblin proof (ECCVM, Translator, merge)
Definition goblin.cpp:62
bool avm_mode
Definition goblin.hpp:62
std::shared_ptr< Transcript > transcript
Definition goblin.hpp:55
Unified Goblin verifier for both native and recursive verification.
typename MergeVerifier::InputCommitments MergeCommitments
Recursive flavor for verifying proofs produced with MegaAvmFlavor.
NativeVerificationKey_< PrecomputedEntities< Commitment >, Codec, HashFunction, CommitmentKey > VerificationKey
The verification key is responsible for storing the commitments to the precomputed (non-witness) poly...
A ProverInstance is normally constructed from a finalized circuit and it contains all the information...
Recursive verifier of AVM2 proofs that utilizes the Goblin mechanism for efficient EC operations.
InnerProverOutput construct_and_prove_inner_recursive_verification_circuit(const stdlib::Proof< UltraBuilder > &stdlib_proof, const std::vector< std::vector< UltraFF > > &public_inputs) const
Construct and prove the inner Mega-arithmetized AVM recursive verifier circuit.
stdlib::recursion::honk::UltraRecursiveVerifierOutput< UltraBuilder > RecursiveAvmGoblinOutput
RecursiveAvmGoblinOutput construct_outer_recursive_verification_circuit(const stdlib::Proof< UltraBuilder > &stdlib_proof, const std::vector< std::vector< UltraFF > > &public_inputs, const InnerProverOutput &inner_output) const
Construct the outer circuit which recursively verifies a Mega proof and a Goblin proof.
RecursiveAvmGoblinOutput verify_proof(const stdlib::Proof< UltraBuilder > &stdlib_proof, const std::vector< std::vector< UltraFF > > &public_inputs) const
Recursively verify an AVM proof using Goblin and two layers of recursive verification.
AvmRecursiveFlavorSettings::FF FF
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
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 the inner GoblinAvmRecursiveVerifier circuit.
AluTraceBuilder builder
Definition alu.test.cpp:124
AvmProvingInputs inputs
AvmFlavorSettings::FF FF
Definition field.hpp:10
std::array< typename bn254< Builder >::Group, Builder::NUM_WIRES > empty_ecc_op_tables(Builder &builder)
Construct commitments to empty subtables.
std::vector< fr > HonkProof
Definition proof.hpp:15
UltraCircuitBuilder_< UltraExecutionTraceBlocks > UltraCircuitBuilder
MegaCircuitBuilder_< field< Bn254FrParams > > MegaCircuitBuilder
GoblinVerifier_< stdlib::bn254< UltraCircuitBuilder > > GoblinRecursiveVerifier
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Result of Goblin verification with mode-specific semantics.
std::shared_ptr< MegaAvmFlavor::VerificationKey > mega_vk
An object storing two EC points that represent the inputs to a pairing check.
static PairingPoints aggregate_multiple(std::vector< PairingPoints > &pairing_points, bool handle_edge_cases=true)
Aggregate multiple PairingPoints using random linear combination.
uint32_t set_public()
Set the witness indices for the limbs of the pairing points to public.
Output type for recursive ultra verification.