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: Completed, auditors: [Sergei], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
20
21namespace bb {
22
28template <typename Flavor, class IO> size_t UltraVerifier_<Flavor, IO>::compute_log_n() const
29{
30 if constexpr (Flavor::USE_PADDING) {
31 return static_cast<size_t>(Flavor::VIRTUAL_LOG_N);
32 } else {
33 // Non-padded: use actual circuit size from VK (native only)
34 const size_t log_circuit_size = static_cast<size_t>(verifier_instance->get_vk()->log_circuit_size);
36 log_circuit_size, static_cast<size_t>(1), "VK log_circuit_size is 0, which is invalid for any circuit");
37 return log_circuit_size;
38 }
39}
40
57template <typename Flavor, class IO>
59 Flavor,
60 IO>::split_rollup_proof(const Proof& combined_proof) const
61 requires(IO::HasIPA)
62{
63 // Validate combined proof is large enough to contain IPA proof
64 BB_ASSERT_GTE(combined_proof.size(),
65 IPA_PROOF_LENGTH,
66 "Combined rollup proof is too small to contain IPA proof. Expected at least " +
67 std::to_string(IPA_PROOF_LENGTH) + " elements, got " + std::to_string(combined_proof.size()));
68
69 // IPA proof is appended at the end (must match UltraProver_::export_proof())
70 const auto honk_proof_length = static_cast<std::ptrdiff_t>(combined_proof.size() - IPA_PROOF_LENGTH);
71
72 Proof honk_proof(combined_proof.begin(), combined_proof.begin() + honk_proof_length);
73 Proof ipa_proof(combined_proof.begin() + honk_proof_length, combined_proof.end());
74
75 return std::make_pair(honk_proof, ipa_proof);
76}
77
81template <typename Flavor, class IO>
82bool UltraVerifier_<Flavor, IO>::verify_ipa(const Proof& ipa_proof, const IPAClaim& ipa_claim)
83 requires(!IsRecursiveFlavor<Flavor> && IO::HasIPA)
84{
85 VerifierCommitmentKey<curve::Grumpkin> ipa_verification_key(1 << CONST_ECCVM_LOG_N);
86 ipa_transcript->load_proof(ipa_proof);
87 bool ipa_verified = IPA<curve::Grumpkin>::reduce_verify(ipa_verification_key, ipa_claim, ipa_transcript);
88 vinfo("UltraVerifier: IPA check: ", ipa_verified ? "true" : "false");
89
90 if (!ipa_verified) {
91 info("UltraVerifier: verification failed at IPA check");
92 }
93
94 return ipa_verified;
95}
96
102template <typename Flavor, class IO>
104 const typename UltraVerifier_<Flavor, IO>::Proof& proof)
105{
107 using ClaimBatcher = ClaimBatcher_<Curve>;
108 using ClaimBatch = ClaimBatcher::Batch;
109
110 transcript->load_proof(proof);
111
112 // Compute log_n first (needed for proof layout calculation)
113 const size_t log_n = compute_log_n();
114
115 // Guard against proof size underflow before deriving num_public_inputs
116 const size_t min_proof_size = ProofLength::Honk<Flavor>::LENGTH_WITHOUT_PUB_INPUTS(log_n);
117 BB_ASSERT_GTE(proof.size(),
118 min_proof_size,
119 "Proof size too small. Got " + std::to_string(proof.size()) + " field elements, but need at least " +
120 std::to_string(min_proof_size) + " (excluding public inputs) for log_n=" + std::to_string(log_n));
121
122 // Derive num_public_inputs from proof size using centralized proof layout
123 const size_t num_public_inputs = ProofLength::Honk<Flavor>::derive_num_public_inputs(proof.size(), log_n);
124
125 OinkVerifier<Flavor> oink_verifier{ verifier_instance, transcript, num_public_inputs };
126 oink_verifier.verify();
127
128 verifier_instance->gate_challenges =
129 transcript->template get_dyadic_powers_of_challenge<FF>("Sumcheck:gate_challenge", log_n);
130
131 auto commitments = VerifierCommitmentsConstructor<Flavor>::construct(verifier_instance->get_vk(),
132 verifier_instance->witness_commitments,
133 verifier_instance->gemini_masking_commitment);
134
135 // Construct the sumcheck verifier
136 SumcheckVerifier<Flavor> sumcheck(transcript, verifier_instance->alpha, log_n);
137 // Receive commitments to Libra masking polynomials for ZKFlavors
138 std::array<Commitment, NUM_SMALL_IPA_COMMITMENTS> libra_commitments = {};
139
140 if constexpr (Flavor::HasZK) {
141 libra_commitments[0] = transcript->template receive_from_prover<Commitment>("Libra:concatenation_commitment");
142 }
143 // Run the sumcheck verifier
144 SumcheckOutput<Flavor> sumcheck_output =
145 sumcheck.verify(verifier_instance->relation_parameters, verifier_instance->gate_challenges);
146 // Get the claimed evaluation of the Libra polynomials for ZKFlavors
147 if constexpr (Flavor::HasZK) {
148 libra_commitments[1] = transcript->template receive_from_prover<Commitment>("Libra:grand_sum_commitment");
149 libra_commitments[2] = transcript->template receive_from_prover<Commitment>("Libra:quotient_commitment");
150 }
151
152 ClaimBatcher claim_batcher{
153 .unshifted = ClaimBatch{ commitments.get_unshifted(), sumcheck_output.claimed_evaluations.get_unshifted() },
154 .shifted = ClaimBatch{ commitments.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_shifted() }
155 };
156
157 const Commitment one_commitment = [&]() {
158 if constexpr (IsRecursive) {
159 return Commitment::one(builder);
160 } else {
161 return Commitment::one();
162 }
163 }();
164
165 auto shplemini_output = Shplemini::compute_batch_opening_claim(claim_batcher,
166 sumcheck_output.challenge,
167 one_commitment,
168 transcript,
169 Flavor::REPEATED_COMMITMENTS,
170 libra_commitments,
171 sumcheck_output.claimed_libra_evaluation);
172
173 // Build reduction result
175 result.pairing_points = PCS::reduce_verify_batch_opening_claim(
176 std::move(shplemini_output.batch_opening_claim), transcript, Flavor::FINAL_PCS_MSM_SIZE(log_n));
177
178 bool consistency_checked = true;
179 if constexpr (Flavor::HasZK) {
180 consistency_checked = shplemini_output.consistency_checked;
181 vinfo("Ultra Verifier (with ZK): Libra evals consistency checked ", consistency_checked ? "true" : "false");
182 }
183 vinfo("Ultra Verifier sumcheck_verified: ", sumcheck_output.verified ? "true" : "false");
184 result.reduction_succeeded = sumcheck_output.verified && consistency_checked;
185
186 return result;
187}
188
196template <typename Flavor, class IO>
198 const typename UltraVerifier_<Flavor, IO>::Proof& proof)
199{
200 BB_BENCH_NAME("UltraVerifier::verify_proof");
201 // Step 1: Split proof if needed
202 Proof honk_proof;
203 Proof ipa_proof;
204 if constexpr (IO::HasIPA) {
205 std::tie(honk_proof, ipa_proof) = split_rollup_proof(proof);
206 } else {
207 honk_proof = proof;
208 }
209
210 // Step 2: Reduce to pairing check
211 auto [pcs_pairing_points, reduction_succeeded] = reduce_to_pairing_check(honk_proof);
212 vinfo("UltraVerifier: reduced to pairing check: ", reduction_succeeded ? "true" : "false");
213
214 if constexpr (!IsRecursive) {
215 if (!reduction_succeeded) {
216 info("UltraVerifier: verification failed at reduction step");
217 return Output{};
218 }
219 }
220
221 // Step 3: Process the reduction result and public inputs
222 IO inputs;
223 inputs.reconstruct_from_public(verifier_instance->public_inputs);
224
225 // Aggregate pairing points
226 PairingPoints pi_pairing_points = inputs.pairing_inputs;
227 pi_pairing_points.aggregate(pcs_pairing_points);
228
229 // Construct output (common to both native and recursive)
230 Output output(inputs);
231
232 if constexpr (IsRecursive) {
233 // Recursive: populate output for deferred verification
234 output.points_accumulator = std::move(pi_pairing_points);
235 if constexpr (IO::HasIPA) {
236 output.ipa_proof = ipa_proof;
237 }
238 } else {
239 // Perform pairing check
240 bool pairing_verified = pi_pairing_points.check();
241 vinfo("UltraVerifier: pairing check: ", pairing_verified ? "true" : "false");
242
243 if (!pairing_verified) {
244 info("UltraVerifier: verification failed at pairing check");
245 return Output{};
246 }
247
248 // Perform IPA verification if IO requires it
249 if constexpr (IO::HasIPA) {
250 if (!verify_ipa(ipa_proof, inputs.ipa_claim)) {
251 return Output{};
252 }
253 }
254
255 output.result = true;
256 }
257
258 return output;
259}
260
261// ===== NATIVE FLAVOR INSTANTIATIONS =====
262
267template class UltraVerifier_<UltraFlavor, RollupIO>; // Rollup uses UltraFlavor + RollupIO
271
272#ifdef STARKNET_GARAGA_FLAVORS
275#endif
276
277// ===== RECURSIVE FLAVOR INSTANTIATIONS =====
278
279// UltraRecursiveFlavor with DefaultIO
284
285// UltraZKRecursiveFlavor with DefaultIO
290
291// UltraRecursiveFlavor with RollupIO (replaces UltraRollupRecursiveFlavor)
293
294// MegaRecursiveFlavor with DefaultIO
299
300// MegaZKRecursiveFlavor with DefaultIO
305
306// MegaZKRecursiveFlavor with HidingKernelIO (Chonk)
309
310// MegaRecursiveFlavor with GoblinAvmIO
313
314} // namespace bb
#define BB_ASSERT_GTE(left, right,...)
Definition assert.hpp:128
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:264
static constexpr bool HasZK
static constexpr bool USE_PADDING
IPA (inner product argument) commitment scheme class.
Definition ipa.hpp:87
Verifier counterpart to OinkProver: receives witness commitments, computes relation parameters,...
void verify(bool emit_alpha=true)
Receive witness commitments, compute relation parameters, and prepare for Sumcheck.
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:802
SumcheckOutput< Flavor > verify(const bb::RelationParameters< FF > &relation_parameters, const std::vector< FF > &gate_challenges)
The Sumcheck verification method. First it extracts round univariate, checks sum (the sumcheck univar...
Definition sumcheck.hpp:859
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::conditional_t< IsRecursive, stdlib::recursion::honk::UltraRecursiveVerifierOutput< Builder >, UltraVerifierOutput< Flavor > > Output
typename Flavor::Commitment Commitment
Output verify_proof(const Proof &proof)
Perform ultra verification.
Representation of the Grumpkin Verifier Commitment Key inside a bn254 circuit.
static Commitments construct(const std::shared_ptr< VerificationKey > &verification_key)
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)
Logic to support batching opening claims for unshifted and shifted polynomials in Shplemini.
static constexpr size_t LENGTH_WITHOUT_PUB_INPUTS(size_t log_n)
static 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 aggregate res...
VectorField result