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
23
24namespace bb::avm2 {
25
35AvmRecursiveVerifier::AvmRecursiveVerifier(Builder& builder, const std::shared_ptr<Transcript>& transcript)
37 , transcript(transcript)
38{
41}
42
56 const std::vector<FF>& challenges)
57{
58 auto coefficients = SharedShiftedVirtualZeroesArray<FF>{
59 .start_ = 0,
60 .end_ = points.size(),
61 .virtual_size_ = MAX_AVM_TRACE_SIZE,
62 .backing_memory_ = BackingMemory<FF>::allocate(points.size()),
63 };
64
65 memcpy(
66 static_cast<void*>(coefficients.data()), static_cast<const void*>(points.data()), sizeof(FF) * points.size());
67
68 return generic_evaluate_mle<FF>(challenges, coefficients);
69}
70
84 const stdlib::Proof<Builder>& stdlib_proof, const std::vector<std::vector<FF>>& public_inputs)
85{
86 using RelationParams = RelationParameters<typename Flavor::FF>;
88 using ClaimBatcher = ClaimBatcher_<Curve>;
89 using ClaimBatch = ClaimBatcher::Batch;
91
92 RelationParams relation_parameters;
93
94 transcript->load_proof(stdlib_proof);
95
96 // ========== Execute preamble round ==========
97
98 // Add vk hash to transcript
99 transcript->add_to_hash_buffer("avm_vk_hash", key->get_hash());
100
101 info("AVM vk hash in recursive verifier: ", key->get_hash().get_value());
102
103 // ========== Execute public inputs round ==========
104
105 // Validate number of public input columns
106 if (public_inputs.size() != AVM_NUM_PUBLIC_INPUT_COLUMNS) {
107 throw_or_abort("AvmRecursiveVerifier::verify_proof: public inputs size mismatch");
108 }
109
110 // Add public inputs to transcript. This ensures that the Sumcheck challenge depends both on the public inputs sent
111 // in the clear and on the committed columns.
112 for (size_t i = 0; i < AVM_NUM_PUBLIC_INPUT_COLUMNS; i++) {
113 if (public_inputs[i].size() != AVM_PUBLIC_INPUTS_COLUMNS_MAX_LENGTH) {
114 throw_or_abort("AvmRecursiveVerifier::verify_proof: public input size mismatch");
115 }
116 for (size_t j = 0; j < public_inputs[i].size(); j++) {
117 transcript->add_to_hash_buffer("public_input_" + std::to_string(i) + "_" + std::to_string(j),
118 public_inputs[i][j]);
119 }
120 }
121
122 // ========== Execute wire commitments round ==========
123
124 // Receive commitments to all polynomials except the logderivate ones
125 VerifierCommitments commitments{ key };
126 for (auto [comm, label] : zip_view(commitments.get_wires(), commitments.get_wires_labels())) {
127 comm = transcript->template receive_from_prover<Commitment>(label);
128 }
129
130 // ========== Execute log derivative inverse round ==========
131
132 // Generate randomness required by Lookup and Permutation relations
133 auto [beta, gamma] = transcript->template get_challenges<FF>(std::array<std::string, 2>{ "beta", "gamma" });
134 relation_parameters.beta = beta;
135 relation_parameters.gamma = gamma;
136
137 // Receive commitments to all logderivative inverse polynomials
138 for (auto [commitment, label] : zip_view(commitments.get_derived(), commitments.get_derived_labels())) {
139 commitment = transcript->template receive_from_prover<Commitment>(label);
140 }
141
142 // ========== Execute relation check rounds ==========
143
144 // Multiply each linearly independent subrelation contribution by `alpha^i` for i = 0, ..., NUM_SUBRELATIONS - 1.
145 const FF alpha = transcript->template get_challenge<FF>("Sumcheck:alpha");
146
148
149 std::vector<FF> gate_challenges =
150 transcript->template get_dyadic_powers_of_challenge<FF>("Sumcheck:gate_challenge", MAX_AVM_TRACE_LOG_SIZE);
151
152 SumcheckOutput<Flavor> output = sumcheck.verify(relation_parameters, gate_challenges);
153 vinfo("verified sumcheck: ", (output.verified));
154
155 // Validate that the public inputs committed in the public input columns match the public inputs sent in the clear
156 // by the Prover
157 using C = ColumnAndShifts;
159 output.claimed_evaluations.get(C::public_inputs_cols_0_),
160 output.claimed_evaluations.get(C::public_inputs_cols_1_),
161 output.claimed_evaluations.get(C::public_inputs_cols_2_),
162 output.claimed_evaluations.get(C::public_inputs_cols_3_),
163 };
164
165 // Validate public inputs match the claimed evaluations
166 for (size_t idx = 0;
167 const auto& [public_input_column, claimed_evaluation] : zip_view(public_inputs, claimed_evaluations)) {
168 FF public_input_evaluation = evaluate_public_input_column(public_input_column, output.challenge);
169 public_input_evaluation.assert_equal(claimed_evaluation,
170 format("public_input_evaluation failed at column ", idx));
171 idx++;
172 }
173
174 // ========== Execute PCS verification ==========
175
176 // Batch commitments and evaluations using short scalars to reduce ECCVM circuit size
177 auto unshifted_comms = commitments.get_unshifted();
178 auto unshifted_evals = output.claimed_evaluations.get_unshifted();
179 auto shifted_comms = commitments.get_to_be_shifted();
180 auto shifted_evals = output.claimed_evaluations.get_shifted();
181
182 // Get short batching challenges from transcript
183 Challenges challenges;
184 auto unshifted_challenges_vec = transcript->template get_challenges<FF>(challenges.get_unshifted_labels());
185 std::ranges::move(unshifted_challenges_vec, challenges.get_unshifted().begin());
186 auto unshifted_challenges = challenges.get_unshifted();
187 auto shifted_challenges = challenges.get_to_be_shifted();
188
189 // Batch to be shifted commitments
190 Commitment batched_shifted =
191 Commitment::batch_mul(std::vector<Commitment>(shifted_comms.begin(), shifted_comms.end()),
192 std::vector<FF>(shifted_challenges.begin(), shifted_challenges.end()),
193 128);
194
195 // Batch unshifted commitments: We reuse the calculation performed for shifted commitments.
196 Commitment batched_unshifted =
197 Commitment::batch_mul(
198 std::vector<Commitment>(unshifted_comms.begin(), unshifted_comms.begin() + WIRES_TO_BE_SHIFTED_START_IDX),
199 std::vector<FF>(unshifted_challenges.begin(), unshifted_challenges.begin() + WIRES_TO_BE_SHIFTED_START_IDX),
200 128) +
201 Commitment::batch_mul(
202 std::vector<Commitment>(unshifted_comms.begin() + WIRES_TO_BE_SHIFTED_END_IDX, unshifted_comms.end()),
203 std::vector<FF>(unshifted_challenges.begin() + WIRES_TO_BE_SHIFTED_END_IDX, unshifted_challenges.end()),
204 128) +
205 batched_shifted;
206
207 // Batch evaluations
208 FF batched_unshifted_eval =
209 std::inner_product(unshifted_challenges.begin(), unshifted_challenges.end(), unshifted_evals.begin(), FF(0));
210
211 FF batched_shifted_eval =
212 std::inner_product(shifted_challenges.begin(), shifted_challenges.end(), shifted_evals.begin(), FF(0));
213
214 // Execute Shplemini rounds with batched claims
215 ClaimBatcher batched_claim_batcher{ .unshifted = ClaimBatch{ .commitments = RefVector(batched_unshifted),
216 .evaluations = RefVector(batched_unshifted_eval) },
217 .shifted = ClaimBatch{ .commitments = RefVector(batched_shifted),
218 .evaluations = RefVector(batched_shifted_eval) } };
219 auto opening_claim = Shplemini::compute_batch_opening_claim(
220 batched_claim_batcher, output.challenge, Commitment::one(&builder), transcript)
221 .batch_opening_claim;
222
223 PairingPoints pairing_points(PCS::reduce_verify_batch_opening_claim(std::move(opening_claim), transcript));
224
225 if (builder.failed()) {
226 info("AVM Recursive verifier builder failed with error: ", builder.err());
227 }
228
230
231 return pairing_points;
232}
233
235{
237 throw_or_abort("Transcript can only be hashed after verification is complete");
238 }
239 return Transcript::hash_avm_transcript(transcript, stdlib_proof);
240};
241
242} // 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:804
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
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)
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)