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
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 transcript->load_proof(stdlib_proof);
96
97 // ========== Execute preamble round ==========
98
99 // Add vk hash to transcript
100 transcript->add_to_hash_buffer("avm_vk_hash", key->get_hash());
101
102 info("AVM vk hash in recursive verifier: ", key->get_hash().get_value());
103
104 // ========== Execute public inputs round ==========
105
106 // Validate number of public input columns
107 if (public_inputs.size() != AVM_NUM_PUBLIC_INPUT_COLUMNS) {
108 throw_or_abort("AvmRecursiveVerifier::verify_proof: public inputs size mismatch");
109 }
110
111 // Add public inputs to transcript. This ensures that the Sumcheck challenge depends both on the public inputs sent
112 // in the clear and on the committed columns.
113 for (size_t i = 0; i < AVM_NUM_PUBLIC_INPUT_COLUMNS; i++) {
114 if (public_inputs[i].size() != AVM_PUBLIC_INPUTS_COLUMNS_MAX_LENGTH) {
115 throw_or_abort("AvmRecursiveVerifier::verify_proof: public input size mismatch");
116 }
117 for (size_t j = 0; j < public_inputs[i].size(); j++) {
118 transcript->add_to_hash_buffer("public_input_" + std::to_string(i) + "_" + std::to_string(j),
119 public_inputs[i][j]);
120 }
121 }
122
123 // ========== Execute wire commitments round ==========
124
125 // Receive commitments to all polynomials except the logderivate ones
126 VerifierCommitments commitments{ key };
127 for (auto [comm, label] : zip_view(commitments.get_wires(), commitments.get_wires_labels())) {
128 comm = transcript->template receive_from_prover<Commitment>(label);
129 }
130
131 // ========== Execute log derivative inverse round ==========
132
133 // Generate randomness required by Lookup and Permutation relations
134 auto [beta, gamma] = transcript->template get_challenges<FF>(std::array<std::string, 2>{ "beta", "gamma" });
135 relation_parameters.beta = beta;
136 relation_parameters.gamma = gamma;
137
138 // Receive commitments to all logderivative inverse polynomials
139 for (auto [commitment, label] : zip_view(commitments.get_derived(), commitments.get_derived_labels())) {
140 commitment = transcript->template receive_from_prover<Commitment>(label);
141 }
142
143 // ========== Execute relation check rounds ==========
144
145 // Construct padding indicator array: it is a vector of constant ones as the AVM verifier performs verification of
146 // the AVM circuit, so the number of rounds is fixed.
147 std::vector<FF> padding_indicator_array(MAX_AVM_TRACE_LOG_SIZE, FF(1));
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, padding_indicator_array);
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_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 =
225 Shplemini::compute_batch_opening_claim(
226 padding_indicator_array, batched_claim_batcher, output.challenge, Commitment::one(&builder), transcript)
227 .batch_opening_claim;
228
229 PairingPoints pairing_points(PCS::reduce_verify_batch_opening_claim(std::move(opening_claim), transcript));
230
231 if (builder.failed()) {
232 info("AVM Recursive verifier builder failed with error: ", builder.err());
233 }
234
236
237 return pairing_points;
238}
239
241{
243 throw_or_abort("Transcript can only be hashed after verification is complete");
244 }
245 return Transcript::hash_avm_transcript(transcript, stdlib_proof);
246};
247
248} // namespace bb::avm2
#define AVM_NUM_PUBLIC_INPUT_COLUMNS
#define AVM_PUBLIC_INPUTS_COLUMNS_MAX_LENGTH
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:747
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:803
static stdlib::field_t< Builder > hash_avm_transcript(Builder &builder, const stdlib::Proof< Builder > &stdlib_proof, const std::vector< std::vector< stdlib::field_t< Builder > > > &public_inputs)
Construct a transcript replicating the operations performed on the AVM transcript during proof verifi...
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(const StdlibProof &stdlib_proof)
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:19
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
constexpr auto WIRES_TO_BE_SHIFTED_END_IDX
Definition columns.hpp:67
constexpr std::size_t MAX_AVM_TRACE_SIZE
Definition constants.hpp:13
constexpr std::size_t MAX_AVM_TRACE_LOG_SIZE
Definition constants.hpp:12
constexpr auto WIRES_TO_BE_SHIFTED_START_IDX
Definition columns.hpp:66
ColumnAndShifts
Definition columns.hpp:34
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_...
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)