Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
ultra_verifier.cpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Planned, auditors: [], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
18
19namespace bb {
20
26template <typename Flavor, class IO> size_t UltraVerifier_<Flavor, IO>::compute_log_n() const
27{
28 if constexpr (Flavor::USE_PADDING) {
29 return static_cast<size_t>(Flavor::VIRTUAL_LOG_N);
30 } else {
31 // Non-padded: use actual circuit size from VK (native only)
32 return static_cast<size_t>(verifier_instance->get_vk()->log_circuit_size);
33 }
34}
35
43template <typename Flavor, class IO>
45{
46 // - Non-ZK flavors: all 1s (no masking needed)
47 // - ZK without padding: all 1s (log_n == log_circuit_size, no padded region)
48 // - ZK with padding: computed to mask padded rounds (1s for real, 0s for padding)
49 std::vector<FF> padding_indicator_array(log_n, FF{ 1 });
50 if constexpr (Flavor::HasZK && Flavor::USE_PADDING) {
51 auto vk_ptr = verifier_instance->get_vk();
52 if constexpr (IsRecursive) {
53 // Recursive: use in-circuit computation via Lagrange polynomials
54 // Note: Must be called after OinkVerifier so log_circuit_size is properly tagged
55 padding_indicator_array =
56 stdlib::compute_padding_indicator_array<Curve, Flavor::VIRTUAL_LOG_N>(vk_ptr->log_circuit_size);
57 } else {
58 // Native: simple loop comparison
59 const size_t log_circuit_size = static_cast<size_t>(vk_ptr->log_circuit_size);
60 for (size_t idx = 0; idx < log_n; idx++) {
61 padding_indicator_array[idx] = (idx < log_circuit_size) ? FF{ 1 } : FF{ 0 };
62 }
63 }
64 }
65
66 return padding_indicator_array;
67}
68
85template <typename Flavor, class IO>
87 Flavor,
88 IO>::split_rollup_proof(const Proof& combined_proof) const
89 requires(IO::HasIPA)
90{
91 // Validate combined proof is large enough to contain IPA proof
92 BB_ASSERT_GTE(combined_proof.size(),
93 IPA_PROOF_LENGTH,
94 "Combined rollup proof is too small to contain IPA proof. Expected at least " +
95 std::to_string(IPA_PROOF_LENGTH) + " elements, got " + std::to_string(combined_proof.size()));
96
97 // IPA proof is appended at the end (must match UltraProver_::export_proof())
98 const auto honk_proof_length = static_cast<std::ptrdiff_t>(combined_proof.size() - IPA_PROOF_LENGTH);
99
100 Proof honk_proof(combined_proof.begin(), combined_proof.begin() + honk_proof_length);
101 Proof ipa_proof(combined_proof.begin() + honk_proof_length, combined_proof.end());
102
103 return std::make_pair(honk_proof, ipa_proof);
104}
105
109template <typename Flavor, class IO>
110bool UltraVerifier_<Flavor, IO>::verify_ipa(const Proof& ipa_proof, const IPAClaim& ipa_claim)
111 requires(!IsRecursiveFlavor<Flavor> && IO::HasIPA)
112{
113 VerifierCommitmentKey<curve::Grumpkin> ipa_verification_key(1 << CONST_ECCVM_LOG_N);
114 ipa_transcript->load_proof(ipa_proof);
115 bool ipa_verified = IPA<curve::Grumpkin>::reduce_verify(ipa_verification_key, ipa_claim, ipa_transcript);
116 vinfo("UltraVerifier: IPA check: ", ipa_verified ? "true" : "false");
117
118 if (!ipa_verified) {
119 info("UltraVerifier: verification failed at IPA check");
120 }
121
122 return ipa_verified;
123}
124
130template <typename Flavor, class IO>
132 const typename UltraVerifier_<Flavor, IO>::Proof& proof)
133{
135 using ClaimBatcher = ClaimBatcher_<Curve>;
136 using ClaimBatch = ClaimBatcher::Batch;
137
138 transcript->load_proof(proof);
139
140 // Compute log_n first (needed for proof layout calculation)
141 const size_t log_n = compute_log_n();
142
143 // Derive num_public_inputs from proof size using centralized proof layout
144 const size_t num_public_inputs = ProofLength::Honk<Flavor>::derive_num_public_inputs(proof.size(), log_n);
145
146 OinkVerifier<Flavor> oink_verifier{ verifier_instance, transcript, num_public_inputs };
147 oink_verifier.verify();
148
149 // Compute padding indicator array AFTER OinkVerifier so VK fields are properly tagged
150 auto padding_indicator_array = compute_padding_indicator_array(log_n);
151 verifier_instance->gate_challenges =
152 transcript->template get_dyadic_powers_of_challenge<FF>("Sumcheck:gate_challenge", log_n);
153
154 // Get the witness commitments that the verifier needs to verify
155 VerifierCommitments commitments{ verifier_instance->get_vk(), verifier_instance->witness_commitments };
156 // For ZK flavors: set gemini_masking_poly commitment from accumulator
157 if constexpr (Flavor::HasZK) {
158 commitments.gemini_masking_poly = verifier_instance->gemini_masking_commitment;
159 }
160
161 // Construct the sumcheck verifier
162 SumcheckVerifier<Flavor> sumcheck(transcript, verifier_instance->alpha, log_n);
163 // Receive commitments to Libra masking polynomials for ZKFlavors
165
166 if constexpr (Flavor::HasZK) {
167 libra_commitments[0] = transcript->template receive_from_prover<Commitment>("Libra:concatenation_commitment");
168 }
169 // Run the sumcheck verifier
170 SumcheckOutput<Flavor> sumcheck_output = sumcheck.verify(
171 verifier_instance->relation_parameters, verifier_instance->gate_challenges, padding_indicator_array);
172 // Get the claimed evaluation of the Libra polynomials for ZKFlavors
173 if constexpr (Flavor::HasZK) {
174 libra_commitments[1] = transcript->template receive_from_prover<Commitment>("Libra:grand_sum_commitment");
175 libra_commitments[2] = transcript->template receive_from_prover<Commitment>("Libra:quotient_commitment");
176 }
177
178 ClaimBatcher claim_batcher{
179 .unshifted = ClaimBatch{ commitments.get_unshifted(), sumcheck_output.claimed_evaluations.get_unshifted() },
180 .shifted = ClaimBatch{ commitments.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_shifted() }
181 };
182
183 const Commitment one_commitment = [&]() {
184 if constexpr (IsRecursive) {
185 return Commitment::one(builder);
186 } else {
187 return Commitment::one();
188 }
189 }();
190
191 auto shplemini_output = Shplemini::compute_batch_opening_claim(padding_indicator_array,
192 claim_batcher,
193 sumcheck_output.challenge,
194 one_commitment,
195 transcript,
197 libra_commitments,
198 sumcheck_output.claimed_libra_evaluation);
199
200 // Build reduction result
201 ReductionResult result;
202 result.pairing_points = PCS::reduce_verify_batch_opening_claim(
203 std::move(shplemini_output.batch_opening_claim), transcript, Flavor::FINAL_PCS_MSM_SIZE(log_n));
204
205 bool consistency_checked = true;
206 if constexpr (Flavor::HasZK) {
207 consistency_checked = shplemini_output.consistency_checked;
208 vinfo("Ultra Verifier (with ZK): Libra evals consistency checked ", consistency_checked ? "true" : "false");
209 }
210 vinfo("Ultra Verifier sumcheck_verified: ", sumcheck_output.verified ? "true" : "false");
211 result.reduction_succeeded = sumcheck_output.verified && consistency_checked;
212
213 return result;
214}
215
223template <typename Flavor, class IO>
225 const typename UltraVerifier_<Flavor, IO>::Proof& proof)
226{
227 // Step 1: Split proof if needed
228 Proof honk_proof;
229 Proof ipa_proof;
230 if constexpr (IO::HasIPA) {
231 std::tie(honk_proof, ipa_proof) = split_rollup_proof(proof);
232 } else {
233 honk_proof = proof;
234 }
235
236 // Step 2: Reduce to pairing check
237 auto [pcs_pairing_points, reduction_succeeded] = reduce_to_pairing_check(honk_proof);
238 vinfo("UltraVerifier: reduced to pairing check: ", reduction_succeeded ? "true" : "false");
239
240 if constexpr (!IsRecursive) {
241 if (!reduction_succeeded) {
242 info("UltraVerifier: verification failed at reduction step");
243 return Output{};
244 }
245 }
246
247 // Step 3: Process the reduction result and public inputs
248 IO inputs;
249 inputs.reconstruct_from_public(verifier_instance->public_inputs);
250
251 // Aggregate pairing points
252 PairingPoints pi_pairing_points = inputs.pairing_inputs;
253 pi_pairing_points.aggregate(pcs_pairing_points);
254
255 // Construct output (common to both native and recursive)
256 Output output(inputs);
257
258 if constexpr (IsRecursive) {
259 // Recursive: populate output for deferred verification
260 output.points_accumulator = std::move(pi_pairing_points);
261 if constexpr (IO::HasIPA) {
262 output.ipa_proof = ipa_proof;
263 }
264 } else {
265 // Perform pairing check
266 bool pairing_verified = pi_pairing_points.check();
267 vinfo("UltraVerifier: pairing check: ", pairing_verified ? "true" : "false");
268
269 if (!pairing_verified) {
270 info("UltraVerifier: verification failed at pairing check");
271 return Output{};
272 }
273
274 // Perform IPA verification if IO requires it
275 if constexpr (IO::HasIPA) {
276 if (!verify_ipa(ipa_proof, inputs.ipa_claim)) {
277 return Output{};
278 }
279 }
280
281 output.result = true;
282 }
283
284 return output;
285}
286
287// ===== NATIVE FLAVOR INSTANTIATIONS =====
288
293template class UltraVerifier_<UltraFlavor, RollupIO>; // Rollup uses UltraFlavor + RollupIO
297
298#ifdef STARKNET_GARAGA_FLAVORS
301#endif
302
303// ===== RECURSIVE FLAVOR INSTANTIATIONS =====
304
305// UltraRecursiveFlavor with DefaultIO
310
311// UltraZKRecursiveFlavor with DefaultIO
316
317// UltraRecursiveFlavor with RollupIO (replaces UltraRollupRecursiveFlavor)
319
320// MegaRecursiveFlavor with DefaultIO
325
326// MegaZKRecursiveFlavor with DefaultIO
331
332// MegaZKRecursiveFlavor with HidingKernelIO (Chonk)
335
336// MegaRecursiveFlavor with GoblinAvmIO
339
340} // namespace bb
#define BB_ASSERT_GTE(left, right,...)
Definition assert.hpp:128
static constexpr bool HasZK
static constexpr bool USE_PADDING
static constexpr RepeatedCommitmentsData REPEATED_COMMITMENTS
IPA (inner product argument) commitment scheme class.
Definition ipa.hpp:85
Verifier class for all the presumcheck rounds, which are shared between the folding verifier and ultr...
void verify()
Oink Verifier function that runs all the rounds of the verifier.
Unverified claim (C,r,v) for some witness polynomial p(X) such that.
Definition claim.hpp:55
Implementation of the sumcheck Verifier for statements of the form for multilinear polynomials .
Definition sumcheck.hpp:721
SumcheckOutput< Flavor > verify(const bb::RelationParameters< FF > &relation_parameters, const std::vector< FF > &gate_challenges, const std::vector< FF > &padding_indicator_array)
The Sumcheck verification method. First it extracts round univariate, checks sum (the sumcheck univar...
Definition sumcheck.hpp:777
bool verify_ipa(const Proof &ipa_proof, const IPAClaim &ipa_claim)
Verify IPA proof for rollup circuits (native verifier only)
ReductionResult reduce_to_pairing_check(const Proof &proof)
Reduce ultra proof to verification claims (works for both native and recursive)
typename Transcript::Proof Proof
std::conditional_t< IsRecursive, stdlib::recursion::PairingPoints< Curve >, bb::PairingPoints< Curve > > PairingPoints
size_t compute_log_n() const
Compute log_n based on flavor.
std::vector< FF > compute_padding_indicator_array(size_t log_n) const
Compute padding indicator array based on flavor configuration.
std::conditional_t< IsRecursive, stdlib::recursion::honk::UltraRecursiveVerifierOutput< Builder >, UltraVerifierOutput< Flavor > > Output
typename Flavor::VerifierCommitments VerifierCommitments
typename Flavor::Commitment Commitment
Output verify_proof(const Proof &proof)
Perform ultra verification.
typename Flavor::FF FF
Representation of the Grumpkin Verifier Commitment Key inside a bn254 circuit.
Manages the data that is propagated on the public inputs of an application/function circuit.
The data that is propagated on the public inputs of the inner GoblinAvmRecursiveVerifier circuit.
Manages the data that is propagated on the public inputs of a hiding kernel circuit.
The data that is propagated on the public inputs of a rollup circuit.
#define info(...)
Definition log.hpp:93
#define vinfo(...)
Definition log.hpp:94
AluTraceBuilder builder
Definition alu.test.cpp:124
ECCVMFlavor Flavor
AvmProvingInputs inputs
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
For a small integer N = virtual_log_n and a given witness x = log_n, compute in-circuit an indicator_...
Logic to support batching opening claims for unshifted, shifted and interleaved polynomials in Shplem...
static constexpr size_t derive_num_public_inputs(size_t proof_size, size_t log_n)
Derive num_public_inputs from proof size.
Contains the evaluations of multilinear polynomials at the challenge point . These are computed by S...
ClaimedEvaluations claimed_evaluations
std::vector< FF > challenge
Result of reducing ultra proof to pairing points check. Contains pairing points and the aggrefate res...