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#pragma once
2
15
16namespace bb::avm2 {
17
45 public:
48
51
53
54 // The structure of the final output of the goblinized AVM2 recursive verifier. The IPA data comes from recursive
55 // verification of the ECCVM proof as part of Goblin recursive verification.
57
58 // Output of prover for inner Mega-arithmetized AVM recursive verifier circuit; input to the outer verifier
65
68 UltraFF vk_hash; // this should be a constant witness
69
73 {
74 // TODO(#15892): Set this to be the actual vk hash when vk is fixed.
75 vk_hash = UltraFF::from_witness(&builder, /* should be native hash of vk fields*/ 0);
77 }
78
89 [[nodiscard("IPA claim and Pairing points should be accumulated")]] RecursiveAvmGoblinOutput verify_proof(
90 const stdlib::Proof<UltraBuilder>& stdlib_proof, const std::vector<std::vector<UltraFF>>& public_inputs) const
91 {
92 // Construct and prove the inner Mega-arithmetized AVM recursive verifier circuit; proof is {\pi_M, \pi_G}
93 InnerProverOutput inner_output =
95
96 // Construct the outer Ultra-arithmetized Mega/Goblin recursive verifier circuit
98 construct_outer_recursive_verification_circuit(stdlib_proof, public_inputs, inner_output);
99
100 // Return ipa proof, ipa claim and output aggregation object produced from verifying the Mega + Goblin proofs
101 return result;
102 }
103
112 [[nodiscard("IPA claim and Pairing points should be accumulated")]] RecursiveAvmGoblinOutput
114 const std::vector<std::vector<UltraFF>>& public_inputs,
115 const InnerProverOutput& inner_output) const
116 {
117 // Types for MegaHonk and Goblin recursive verifiers arithmetized with Ultra
118 using MegaRecursiveFlavor = MegaRecursiveFlavor_<UltraBuilder>;
119 using MegaRecursiveVKAndHash = MegaRecursiveFlavor::VKAndHash;
121 using GoblinRecursiveVerifier = stdlib::recursion::honk::GoblinRecursiveVerifier;
122 using GoblinRecursiveVerifierOutput = stdlib::recursion::honk::GoblinRecursiveVerifierOutput;
123 using MergeCommitments = GoblinRecursiveVerifier::MergeVerifier::InputCommitments;
124 using FF = MegaRecursiveFlavor::FF;
126
127 // Construct hash buffer containing the AVM proof, public inputs, and VK
128 std::vector<FF> hash_buffer;
129 hash_buffer.insert(hash_buffer.end(), stdlib_proof.begin(), stdlib_proof.end());
130 for (const std::vector<FF>& input_vec : public_inputs) {
131 hash_buffer.insert(hash_buffer.end(), input_vec.begin(), input_vec.end());
132 }
133 // TODO(#15892): Remove vk from hash buffer when vk/hash are fixed in circuit. Keep the vk_hash in the buffer
134 hash_buffer.insert(hash_buffer.end(), outer_key_fields.begin(), outer_key_fields.end());
135 hash_buffer.emplace_back(vk_hash);
136
137 // Recursively verify the Mega proof \pi_M in the Ultra circuit
138 // All verifier components share a single transcript
140 auto mega_vk_and_hash = std::make_shared<MegaRecursiveVKAndHash>(ultra_builder, inner_output.mega_vk);
141 // Fix the inner mega vk and vk hash to be constants in the outer circuit.
142 mega_vk_and_hash->vk->fix_witness();
143 mega_vk_and_hash->hash.fix_witness();
144 // TODO(#16352): Figure out how not to add hashing gates to mega recursive verifier.
145 MegaRecursiveVerifier mega_verifier(&ultra_builder, mega_vk_and_hash, transcript);
146 stdlib::Proof<UltraBuilder> mega_proof(ultra_builder, inner_output.mega_proof);
147 auto mega_verifier_output = mega_verifier.template verify_proof<IO>(mega_proof);
148
149 // Recursively verify the goblin proof\pi_G in the Ultra circuit
150 MergeCommitments merge_commitments{
151 .t_commitments = mega_verifier.key->witness_commitments.get_ecc_op_wires().get_copy(),
153 ultra_builder) // Empty ecc op tables because there is only one layer of Goblin
154 };
155 GoblinRecursiveVerifier goblin_verifier{ &ultra_builder, inner_output.goblin_vk, transcript };
156 GoblinRecursiveVerifierOutput goblin_verifier_output =
157 goblin_verifier.verify(inner_output.goblin_proof, merge_commitments);
158 goblin_verifier_output.points_accumulator.aggregate(mega_verifier_output.points_accumulator);
159
160 // Validate the consistency of the AVM2 verifier inputs {\pi, pub_inputs, VK}_{AVM2} between the inner (Mega)
161 // circuit and the outer (Ultra) by asserting equality on the independently computed hashes of this data.
162 const FF ultra_hash = stdlib::poseidon2<UltraBuilder>::hash(ultra_builder, hash_buffer);
163 mega_verifier_output.mega_hash.assert_equal(ultra_hash);
164
165 // Return ipa proof, ipa claim and output aggregation object produced from verifying the Mega + Goblin proofs
167 output.points_accumulator = goblin_verifier_output.points_accumulator;
168 output.ipa_claim = goblin_verifier_output.opening_claim;
169 output.ipa_proof = goblin_verifier_output.ipa_proof;
170 return output;
171 }
172
181 const stdlib::Proof<UltraBuilder>& stdlib_proof, const std::vector<std::vector<UltraFF>>& public_inputs) const
182 {
183 using AvmRecursiveVerificationKey = AvmRecursiveFlavor::VerificationKey;
184 using ECCVMVK = Goblin::ECCVMVerificationKey;
185 using TranslatorVK = Goblin::TranslatorVerificationKey;
186 using MegaVerificationKey = MegaFlavor::VerificationKey;
189
190 // Instantiate Mega builder for the inner circuit (AVM2 proof recursive verifier)
191 Goblin goblin;
192 MegaBuilder mega_builder(goblin.op_queue);
193 mega_builder.queue_ecc_no_op();
194
195 // lambda to convert from Ultra to Mega stdlib field buffer and add all elements to respective hash buffers
196 std::vector<FF> mega_hash_buffer;
197 auto convert_stdlib_ultra_to_stdlib_mega = [&](const std::vector<UltraFF>& ultra_object) {
198 std::vector<FF> mega_object;
199 for (const UltraFF& ultra_element : ultra_object) {
200 FF mega_element = FF::from_witness(&mega_builder, ultra_element.get_value());
201 mega_object.emplace_back(mega_element);
202 mega_hash_buffer.emplace_back(mega_element);
203 }
204 return mega_object;
205 };
206
207 // Convert the AVM proof, public inputs, and VK to stdlib Mega representations and add them to the hash buffer.
208 stdlib::Proof<MegaBuilder> mega_stdlib_proof = convert_stdlib_ultra_to_stdlib_mega(stdlib_proof);
209 std::vector<std::vector<FF>> mega_public_inputs;
210 mega_public_inputs.reserve(public_inputs.size());
211 for (const std::vector<UltraFF>& input_vec : public_inputs) {
212 mega_public_inputs.emplace_back(convert_stdlib_ultra_to_stdlib_mega(input_vec));
213 }
214 // TODO(#15892): Remove key_fields from hash buffer when vk/hash are fixed in circuit. Keep the vk_hash in the
215 // buffer
216 std::vector<FF> key_fields = convert_stdlib_ultra_to_stdlib_mega(outer_key_fields);
217 FF mega_vk_hash = convert_stdlib_ultra_to_stdlib_mega({ vk_hash })[0];
218 // TODO(#15892): We call fix_witness on the vk hash twice here because we hash it here and also for
219 // fiat-shamiring.
220 mega_vk_hash.fix_witness(); // fix witness because vk hash should be a circuit constant
221
222 // Compute the hash and set it public
223 const FF mega_hash = stdlib::poseidon2<MegaBuilder>::hash(mega_builder, mega_hash_buffer);
224
225 // Construct a Mega-arithmetized AVM2 recursive verifier circuit
226 auto stdlib_key = std::make_shared<AvmRecursiveVerificationKey>(mega_builder, std::span<FF>(key_fields));
227 AvmRecursiveVerifier recursive_verifier{ mega_builder, stdlib_key };
228 MegaPairingPoints points_accumulator = recursive_verifier.verify_proof(mega_stdlib_proof, mega_public_inputs);
229
230 // Public inputs
231 IO inputs;
232 inputs.mega_hash = mega_hash;
233 inputs.pairing_inputs = points_accumulator;
234 inputs.set_public();
235
236 // All prover components share a single transcript
238 // Construct Mega proof \pi_M of the AVM recursive verifier circuit
239 auto mega_proving_key = std::make_shared<DeciderProvingKey_<MegaFlavor>>(mega_builder);
240 // Detect when MEGA_AVM_LOG_N needs to be bumped.
242 mega_proving_key->log_dyadic_size(),
243 MEGA_AVM_LOG_N,
244 "AVMRecursiveVerifier: circuit size exceeded current upper bound. If expected, bump MEGA_AVM_LOG_N");
245 auto mega_vk = std::make_shared<MegaVerificationKey>(mega_proving_key->get_precomputed());
246 MegaProver mega_prover(mega_proving_key, mega_vk, transcript);
247 HonkProof mega_proof = mega_prover.construct_proof();
248 goblin.transcript = transcript;
249
250 // Construct corresponding Goblin proof \pi_G (includes Merge, ECCVM, and Translator proofs)
251 GoblinProof goblin_proof = goblin.prove();
252
253 // Recursively verify the goblin proof in the Ultra circuit
255
256 return {
257 .mega_proof = mega_proof,
258 .goblin_proof = goblin_proof,
259 .mega_vk = mega_vk,
260 .goblin_vk = goblin_vk,
261 };
262 }
263};
264
265} // namespace bb::avm2
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:129
TranslatorFlavor::VerificationKey TranslatorVerificationKey
Definition goblin.hpp:38
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:50
ECCVMFlavor::VerificationKey ECCVMVerificationKey
Definition goblin.hpp:37
std::shared_ptr< Transcript > transcript
Definition goblin.hpp:55
ecc_op_tuple queue_ecc_no_op()
Logic for a no-op operation.
The verification key is responsible for storing the commitments to the precomputed (non-witness) poly...
The recursive counterpart to the "native" Mega flavor.
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
AvmGoblinRecursiveVerifier(UltraBuilder &builder, const std::vector< UltraFF > &outer_key_fields)
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
static field_t from_witness(Builder *ctx, const bb::fr &input)
Definition field.hpp:424
The data that is propagated on the public inputs of the inner GoblinAvmRecursiveVerifier circuit.
AluTraceBuilder builder
Definition alu.test.cpp:123
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
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
An object storing two EC points that represent the inputs to a pairing check.
uint32_t set_public()
Set the witness indices for the limbs of the pairing points to public.