Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
recursive_verifier.cpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Completed, auditors: [Federico], commit: 0e37cb8}
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
8
9#include <algorithm>
10#include <cstddef>
11#include <memory>
12#include <numeric>
13
14#include "barretenberg/aztec/aztec_constants.hpp"
24
25namespace bb::avm2 {
26
36AvmRecursiveVerifier::AvmRecursiveVerifier(Builder& builder, const std::shared_ptr<Transcript>& transcript)
38 , transcript(transcript)
39{
42}
43
57 const std::vector<FF>& challenges)
58{
59 auto coefficients = SharedShiftedVirtualZeroesArray<FF>{
60 .start_ = 0,
61 .end_ = points.size(),
62 .virtual_size_ = MAX_AVM_TRACE_SIZE,
63 .backing_memory_ = BackingMemory<FF>::allocate(points.size()),
64 };
65
66 memcpy(
67 static_cast<void*>(coefficients.data()), static_cast<const void*>(points.data()), sizeof(FF) * points.size());
68
69 return generic_evaluate_mle<FF>(challenges, coefficients);
70}
71
85 const stdlib::Proof<Builder>& stdlib_proof, const std::vector<std::vector<FF>>& public_inputs)
86{
87 using RelationParams = RelationParameters<typename Flavor::FF>;
89 using ClaimBatcher = ClaimBatcher_<Curve>;
90 using ClaimBatch = ClaimBatcher::Batch;
92
93 RelationParams relation_parameters;
94
95 BB_ASSERT_EQ(stdlib_proof.size(),
96 static_cast<size_t>(AVM_V2_PROOF_LENGTH_IN_FIELDS),
97 "AVM recursive verifier proof length mismatch");
98
99 transcript->load_proof(stdlib_proof);
100
101 // ========== Execute preamble round ==========
102
103 // Add vk hash to transcript
104 transcript->add_to_hash_buffer("avm_vk_hash", key->get_hash());
105
106 info("AVM vk hash in recursive verifier: ", key->get_hash().get_value());
107
108 // ========== Execute public inputs round ==========
109
110 // Validate number of public input columns
111 if (public_inputs.size() != AVM_NUM_PUBLIC_INPUT_COLUMNS) {
112 throw_or_abort("AvmRecursiveVerifier::verify_proof: public inputs size mismatch");
113 }
114
115 // Add public inputs to transcript. This ensures that the Sumcheck challenge depends both on the public inputs sent
116 // in the clear and on the committed columns.
117 for (size_t i = 0; i < AVM_NUM_PUBLIC_INPUT_COLUMNS; i++) {
118 if (public_inputs[i].size() != AVM_PUBLIC_INPUTS_COLUMN_LENGTHS[i]) {
119 throw_or_abort("AvmRecursiveVerifier::verify_proof: public input size mismatch");
120 }
121 for (size_t j = 0; j < public_inputs[i].size(); j++) {
122 transcript->add_to_hash_buffer("public_input_" + std::to_string(i) + "_" + std::to_string(j),
123 public_inputs[i][j]);
124 }
125 }
126
127 // ========== Execute wire commitments round ==========
128
129 // Receive commitments to all polynomials except the logderivate ones
130 VerifierCommitments commitments{ key };
131 for (auto [comm, label] : zip_view(commitments.get_wires(), commitments.get_wires_labels())) {
132 comm = transcript->template receive_from_prover<Commitment>(label);
133 }
134
135 // ========== Execute log derivative inverse round ==========
136
137 // Generate randomness required by Lookup and Permutation relations
138 auto [beta, gamma] = transcript->template get_challenges<FF>(std::array<std::string, 2>{ "beta", "gamma" });
139 relation_parameters.beta = beta;
140 relation_parameters.gamma = gamma;
141
142 // Receive commitments to all logderivative inverse polynomials
143 for (auto [commitment, label] : zip_view(commitments.get_derived(), commitments.get_derived_labels())) {
144 commitment = transcript->template receive_from_prover<Commitment>(label);
145 }
146
147 // ========== Execute relation check rounds ==========
148
149 // Multiply each linearly independent subrelation contribution by `alpha^i` for i = 0, ..., NUM_SUBRELATIONS - 1.
150 const FF alpha = transcript->template get_challenge<FF>("Sumcheck:alpha");
151
153
154 std::vector<FF> gate_challenges =
155 transcript->template get_dyadic_powers_of_challenge<FF>("Sumcheck:gate_challenge", MAX_AVM_TRACE_LOG_SIZE);
156
157 SumcheckOutput<Flavor> output = sumcheck.verify(relation_parameters, gate_challenges);
158 vinfo("verified sumcheck: ", (output.verified));
159
160 // Validate that the public inputs committed in the public input columns match the public inputs sent in the clear
161 // by the Prover
162 using C = ColumnAndShifts;
164 output.claimed_evaluations.get(C::public_inputs_cols_0_),
165 output.claimed_evaluations.get(C::public_inputs_cols_1_),
166 output.claimed_evaluations.get(C::public_inputs_cols_2_),
167 output.claimed_evaluations.get(C::public_inputs_cols_3_),
168 };
169
170 // Validate public inputs match the claimed evaluations
171 for (size_t idx = 0;
172 const auto& [public_input_column, claimed_evaluation] : zip_view(public_inputs, claimed_evaluations)) {
173 FF public_input_evaluation = evaluate_public_input_column(public_input_column, output.challenge);
174 public_input_evaluation.assert_equal(claimed_evaluation,
175 format("public_input_evaluation failed at column ", idx));
176 idx++;
177 }
178
179 // ========== Execute PCS verification ==========
180
181 // Batch commitments and evaluations using short scalars to reduce ECCVM circuit size
182 auto unshifted_comms = commitments.get_unshifted();
183 auto unshifted_evals = output.claimed_evaluations.get_unshifted();
184 auto shifted_comms = commitments.get_to_be_shifted();
185 auto shifted_evals = output.claimed_evaluations.get_shifted();
186
187 // Get short batching challenges from transcript
188 Challenges challenges;
189 auto unshifted_challenges_vec = transcript->template get_short_challenges<FF>(challenges.get_unshifted_labels());
190 std::ranges::move(unshifted_challenges_vec, challenges.get_unshifted().begin());
191 auto unshifted_challenges = challenges.get_unshifted();
192 auto shifted_challenges = challenges.get_to_be_shifted();
193
194 // Batch to be shifted commitments
195 Commitment batched_shifted =
196 Commitment::batch_mul(std::vector<Commitment>(shifted_comms.begin(), shifted_comms.end()),
197 std::vector<FF>(shifted_challenges.begin(), shifted_challenges.end()),
198 128);
199
200 // Batch unshifted commitments: We reuse the calculation performed for shifted commitments.
201 Commitment batched_unshifted =
202 Commitment::batch_mul(
203 std::vector<Commitment>(unshifted_comms.begin(), unshifted_comms.begin() + WIRES_TO_BE_SHIFTED_START_IDX),
204 std::vector<FF>(unshifted_challenges.begin(), unshifted_challenges.begin() + WIRES_TO_BE_SHIFTED_START_IDX),
205 128) +
206 Commitment::batch_mul(
207 std::vector<Commitment>(unshifted_comms.begin() + WIRES_TO_BE_SHIFTED_END_IDX, unshifted_comms.end()),
208 std::vector<FF>(unshifted_challenges.begin() + WIRES_TO_BE_SHIFTED_END_IDX, unshifted_challenges.end()),
209 128) +
210 batched_shifted;
211
212 // Batch evaluations
213 FF batched_unshifted_eval =
214 std::inner_product(unshifted_challenges.begin(), unshifted_challenges.end(), unshifted_evals.begin(), FF(0));
215
216 FF batched_shifted_eval =
217 std::inner_product(shifted_challenges.begin(), shifted_challenges.end(), shifted_evals.begin(), FF(0));
218
219 // Execute Shplemini rounds with batched claims
220 ClaimBatcher batched_claim_batcher{ .unshifted = ClaimBatch{ .commitments = RefVector(batched_unshifted),
221 .evaluations = RefVector(batched_unshifted_eval) },
222 .shifted = ClaimBatch{ .commitments = RefVector(batched_shifted),
223 .evaluations = RefVector(batched_shifted_eval) } };
224 auto opening_claim = Shplemini::compute_batch_opening_claim(
225 batched_claim_batcher, output.challenge, Commitment::one(&builder), transcript)
226 .batch_opening_claim;
227
228 PairingPoints pairing_points(PCS::reduce_verify_batch_opening_claim(std::move(opening_claim), transcript));
229
230 if (builder.failed()) {
231 info("AVM Recursive verifier builder failed with error: ", builder.err());
232 }
233
235
236 return pairing_points;
237}
238
240{
242 throw_or_abort("Transcript can only be hashed after verification is complete");
243 }
244 // Finalise AVM transcript
245 return transcript->template get_challenge<FF>("final_transcript_state");
246};
247
248} // namespace bb::avm2
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:83
A template class for a reference vector. Behaves as if std::vector<T&> was possible.
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
AvmRecursiveVerifier(Builder &builder, const std::shared_ptr< Transcript > &transcript=std::make_shared< Transcript >())
Construct a new AvmRecursiveVerifier.
std::shared_ptr< Transcript > transcript
typename Flavor::VerifierCommitments VerifierCommitments
FF hash_avm_transcript()
Hash the transcript after verification is complete to produce a hash of the public inputs and proofs ...
std::shared_ptr< VerificationKey > key
PairingPoints verify_proof(const StdlibProof &stdlib_proof, const std::vector< std::vector< typename Flavor::FF > > &public_inputs)
Verify an AVM proof and return PairingPoints whose validity bears witness to successful verification ...
static FF evaluate_public_input_column(const std::vector< FF > &points, const std::vector< FF > &challenges)
Evaluate the given public input column over the multivariate challenge points.
typename Flavor::CircuitBuilder Builder
typename Flavor::Commitment Commitment
A simple wrapper around a vector of stdlib field elements representing a proof.
Definition proof.hpp:20
std::string format(Args... args)
Definition log.hpp:23
#define info(...)
Definition log.hpp:93
#define vinfo(...)
Definition log.hpp:94
AluTraceBuilder builder
Definition alu.test.cpp:124
std::string label
constexpr auto WIRES_TO_BE_SHIFTED_END_IDX
Definition columns.hpp:68
constexpr std::size_t MAX_AVM_TRACE_SIZE
Definition constants.hpp:14
constexpr std::size_t MAX_AVM_TRACE_LOG_SIZE
Definition constants.hpp:13
ColumnAndShifts
Definition columns.hpp:35
constexpr auto WIRES_TO_BE_SHIFTED_START_IDX
Definition columns.hpp:67
constexpr std::array< std::size_t, AVM_NUM_PUBLIC_INPUT_COLUMNS > AVM_PUBLIC_INPUTS_COLUMN_LENGTHS
Definition constants.hpp:19
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
static BackingMemory allocate(size_t size)
A shared pointer array template that represents a virtual array filled with zeros up to virtual_size_...
size_t start_
The starting index of the memory-backed range.
Logic to support batching opening claims for unshifted and shifted polynomials in Shplemini.
Container for parameters used by the grand product (permutation, lookup) Honk relations.
Contains the evaluations of multilinear polynomials at the challenge point . These are computed by S...
ClaimedEvaluations claimed_evaluations
std::vector< FF > challenge
An object storing two EC points that represent the inputs to a pairing check.
void throw_or_abort(std::string const &err)