Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
prover.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// =====================
7
8#include <algorithm>
9#include <cstdlib>
10
24
25namespace bb::avm2 {
26
27// Maximum number of polynomials to batch commit at once.
29 getenv("AVM_MAX_MSM_BATCH_SIZE") != nullptr ? std::stoul(getenv("AVM_MAX_MSM_BATCH_SIZE")) : 32;
30
32using FF = Flavor::FF;
33
44 const PCSCommitmentKey& commitment_key)
45 : proving_key(std::move(input_proving_key))
46 , vk(std::move(vk))
47 , prover_polynomials(*proving_key)
48 , commitment_key(commitment_key)
49{}
50
56{
57 FF vk_hash = vk->get_hash();
58 transcript->add_to_hash_buffer("avm_vk_hash", vk_hash);
59 vinfo("AVM vk hash in prover: ", vk_hash);
60}
61
70{
71 BB_BENCH_NAME("AvmProver::execute_public_inputs_round");
72
73 using C = ColumnAndShifts;
74 // Add the public inputs to the transcript so that the Sumcheck challenge depends both on the public inputs sent in
75 // the clear and the commitments to the columns that are purtported to contain them.
77 C::public_inputs_cols_0_,
78 C::public_inputs_cols_1_,
79 C::public_inputs_cols_2_,
80 C::public_inputs_cols_3_,
81 };
82
83 for (size_t i = 0; i < public_input_columns.size(); ++i) {
84 const Polynomial& public_input_col = prover_polynomials.get(public_input_columns[i]);
85 size_t public_input_col_size = public_input_col.size();
86 for (size_t j = 0; j < AVM_PUBLIC_INPUTS_COLUMNS_MAX_LENGTH; ++j) {
87 // The public inputs are added to the hash buffer, but do not increase the size of the proof
88 transcript->add_to_hash_buffer("public_input_" + std::to_string(i) + "_" + std::to_string(j),
89 j < public_input_col_size ? public_input_col.at(j) : FF(0));
90 }
91 }
92}
98{
99 BB_BENCH_NAME("AvmProver::execute_wire_commitments_round");
100 // Commit to all polynomials (apart from logderivative inverse polynomials, which are committed to in the later
101 // logderivative phase)
102 auto batch = commitment_key.start_batch();
103 for (const auto& [poly, label] : zip_view(prover_polynomials.get_wires(), prover_polynomials.get_wires_labels())) {
104 batch.add_to_batch(poly, label, /*mask=*/false);
105 }
106 batch.commit_and_send_to_verifier(transcript, AVM_MAX_MSM_BATCH_SIZE);
107}
108
110{
111 BB_BENCH_NAME("AvmProver::execute_log_derivative_inverse_round");
112
113 auto [beta, gamma] = transcript->template get_challenges<FF>(std::array<std::string, 2>{ "beta", "gamma" });
116 std::vector<std::function<void()>> tasks;
117
118 // Iterate over all LookupRelations and for each relation create a task that:
119 // 1. Resizes the inverse polynomial based on the max end_index() of the source and destination selector
120 // 2. Computes the logderivative inverse
121 bb::constexpr_for<0, std::tuple_size_v<Flavor::LookupRelations>, 1>([&]<size_t relation_idx>() {
123 tasks.push_back([&]() {
124 // We need to resize the inverse polynomials for the relation, now that the selectors have been computed.
126 Relation::Settings::INVERSES,
127 Relation::Settings::SRC_SELECTOR,
128 Relation::Settings::DST_SELECTOR);
129
130 AVM_TRACK_TIME(std::string("prove/log_derivative_inverse_round/") + std::string(Relation::NAME),
131 (compute_logderivative_inverse<FF, Relation, Flavor::ProverPolynomials, false>(
133 });
134 });
135
136 // Execute all the tasks in parallel
137 bb::parallel_for(tasks.size(), [&](size_t i) { tasks[i](); });
138}
139
141{
142 BB_BENCH_NAME("AvmProver::execute_log_derivative_inverse_commitments_round");
143 auto batch = commitment_key.start_batch();
144 // Commit to all logderivative inverse polynomials and send to verifier
145 for (auto [derived_poly, label] :
146 zip_view(prover_polynomials.get_derived(), prover_polynomials.get_derived_labels())) {
147
148 batch.add_to_batch(derived_poly, label, /*mask=*/false);
149 }
150 batch.commit_and_send_to_verifier(transcript, AVM_MAX_MSM_BATCH_SIZE);
151}
152
158{
159 BB_BENCH_NAME("AvmProver::execute_relation_check_rounds");
160 using Sumcheck = SumcheckProver<Flavor>;
161
162 // Multiply each linearly independent subrelation contribution by `alpha^i` for i = 0, ..., NUM_SUBRELATIONS - 1.
163 const FF alpha = transcript->template get_challenge<FF>("Sumcheck:alpha");
164
165 // Generate gate challenges
166 std::vector<FF> gate_challenges = transcript->template get_dyadic_powers_of_challenge<FF>(
167 "Sumcheck:gate_challenge", ProvingKey::log_circuit_size);
168
169 Sumcheck sumcheck(ProvingKey::circuit_size,
172 alpha,
173 gate_challenges,
176
177 sumcheck_output = sumcheck.prove();
178}
179
192{
193 BB_BENCH_NAME("AvmProver::execute_pcs_rounds");
194
196 using PolynomialBatcher = GeminiProver_<Curve>::PolynomialBatcher;
197 using Challenges = Flavor::AllEntities<FF>;
198
199 // Batch polynomials using short scalars to reduce ECCVM circuit size
200 auto unshifted_polys = prover_polynomials.get_unshifted();
201 auto shifted_polys = prover_polynomials.get_to_be_shifted();
202
203 // Get short batching challenges from transcript
204 Challenges challenges;
205 auto unshifted_challenges_vec = transcript->template get_challenges<FF>(challenges.get_unshifted_labels());
206 std::ranges::move(unshifted_challenges_vec, challenges.get_unshifted().begin());
207 auto unshifted_challenges = challenges.get_unshifted();
208 auto shifted_challenges = challenges.get_to_be_shifted();
209
210 auto index_of_max_end_index = [](const auto& polys) {
211 // this assumes non-empty, returns an iterator
212 auto it = std::ranges::max_element(
213 polys.begin(), polys.end(), [](const auto& a, const auto& b) { return a.end_index() < b.end_index(); });
214
215 // retrieves the index of the max element
216 return static_cast<size_t>(std::distance(polys.begin(), it));
217 };
218
219 // Batch to be shifted polys in their to_be_shifted form
220 // Search for poly with largest end index to avoid allocating a zero polynomial of circuit size
221 size_t max_idx = index_of_max_end_index(shifted_polys);
222
223 Polynomial batched_shifted = std::move(shifted_polys[max_idx]);
224 batched_shifted *= shifted_challenges[max_idx];
225 for (size_t idx = 0; const auto [poly, challenge] : zip_view(shifted_polys, shifted_challenges)) {
226 if (idx != max_idx) {
227 batched_shifted.add_scaled(poly, challenge);
228 }
229 idx++;
230 }
231
232 // Batch unshifted polys (to avoid allocating a zero polynomial of circuit size, we initialize the batched
233 // polynomial with the polynomial of the largest size)
234 max_idx = index_of_max_end_index(unshifted_polys);
235
236 Polynomial batched_unshifted = std::move(unshifted_polys[max_idx]);
237 batched_unshifted *= unshifted_challenges[max_idx];
238 batched_unshifted += batched_shifted;
239 for (size_t idx = 0; const auto [poly, challenge] : zip_view(unshifted_polys, unshifted_challenges)) {
240 // Only operate in the range of not to be shifted polys, as the contribution for those has already been added
241 if (idx < WIRES_TO_BE_SHIFTED_START_IDX || idx >= WIRES_TO_BE_SHIFTED_END_IDX) {
242 if (idx != max_idx) {
243 batched_unshifted.add_scaled(poly, challenge);
244 }
245 }
246 idx++;
247 }
248
249 const size_t circuit_dyadic_size = numeric::round_up_power_2(batched_unshifted.end_index());
250
251 PolynomialBatcher polynomial_batcher(circuit_dyadic_size);
252 polynomial_batcher.set_unshifted(RefVector{ batched_unshifted });
253 polynomial_batcher.set_to_be_shifted_by_one(RefVector{ batched_shifted });
254
255 const OpeningClaim prover_opening_claim = ShpleminiProver_<Curve>::prove(
256 circuit_dyadic_size, polynomial_batcher, sumcheck_output.challenge, commitment_key, transcript);
257
259}
260
262{
263 return transcript->export_proof();
264}
265
267{
268 // Add vk hash to transcript.
270
271 // Add public inputs to transcript.
272 AVM_TRACK_TIME("prove/public_inputs_round", execute_public_inputs_round());
273
274 // Compute wire commitments.
275 AVM_TRACK_TIME("prove/wire_commitments_round", execute_wire_commitments_round());
276
277 // Compute log derivative inverses.
278 AVM_TRACK_TIME("prove/log_derivative_inverse_round", execute_log_derivative_inverse_round());
279
280 // Compute commitments to logderivative inverse polynomials.
281 AVM_TRACK_TIME("prove/log_derivative_inverse_commitments_round",
283
284 // Run sumcheck subprotocol.
286
287 // Execute PCS.
288 AVM_TRACK_TIME("prove/pcs_rounds", execute_pcs_rounds());
289
290 return export_proof();
291}
292
293} // namespace bb::avm2
#define AVM_PUBLIC_INPUTS_COLUMNS_MAX_LENGTH
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:225
CommitmentKey object over a pairing group 𝔾₁.
CommitBatch start_batch()
Class responsible for computation of the batched multilinear polynomials required by the Gemini proto...
Definition gemini.hpp:125
static void compute_opening_proof(const CK &ck, const ProverOpeningClaim< Curve > &opening_claim, const std::shared_ptr< Transcript > &prover_trancript)
Computes the KZG commitment to an opening proof polynomial at a single evaluation point.
Definition kzg.hpp:42
Unverified claim (C,r,v) for some witness polynomial p(X) such that.
Definition claim.hpp:55
void add_scaled(PolynomialSpan< const Fr > other, const Fr &scaling_factor)
adds the polynomial q(X) 'other', multiplied by a scaling factor.
size_t end_index() const
Fr & at(size_t index)
Our mutable accessor, unlike operator[]. We abuse precedent a bit to differentiate at() and operator[...
std::size_t size() const
Polynomial p and an opening pair (r,v) such that p(r) = v.
Definition claim.hpp:36
A template class for a reference vector. Behaves as if std::vector<T&> was possible.
A wrapper for Relations to expose methods used by the Sumcheck prover or verifier to add the contribu...
static OpeningClaim prove(size_t circuit_size, PolynomialBatcher &polynomial_batcher, std::span< FF > multilinear_challenge, const CommitmentKey< Curve > &commitment_key, const std::shared_ptr< Transcript > &transcript, const std::array< Polynomial, NUM_SMALL_IPA_EVALUATIONS > &libra_polynomials={}, const std::vector< Polynomial > &sumcheck_round_univariates={}, const std::vector< std::array< FF, 3 > > &sumcheck_round_evaluations={})
Definition shplemini.hpp:36
The implementation of the sumcheck Prover for statements of the form for multilinear polynomials .
Definition sumcheck.hpp:298
DataType & get(ColumnAndShifts c)
Definition flavor.hpp:145
static constexpr size_t log_circuit_size
Definition flavor.hpp:206
static constexpr size_t circuit_size
Definition flavor.hpp:205
AvmFlavorSettings::FF FF
Definition flavor.hpp:43
void execute_pcs_rounds()
Run the PCS to prove that the claimed evaluations are correct.
Definition prover.cpp:191
std::shared_ptr< Transcript > transcript
Definition prover.hpp:46
SumcheckOutput< Flavor > sumcheck_output
Definition prover.hpp:58
PCSCommitmentKey commitment_key
Definition prover.hpp:60
std::shared_ptr< VerificationKey > vk
Definition prover.hpp:53
void execute_relation_check_rounds()
Run Sumcheck resulting in u = (u_1,...,u_d) challenges and all evaluations at u being calculated.
Definition prover.cpp:157
void execute_preamble_round()
Add vk hash to transcript.
Definition prover.cpp:55
ProverPolynomials prover_polynomials
Definition prover.hpp:56
void execute_log_derivative_inverse_commitments_round()
Definition prover.cpp:140
void execute_log_derivative_inverse_round()
Definition prover.cpp:109
bb::RelationParameters< FF > relation_parameters
Definition prover.hpp:50
Flavor::FF FF
Definition prover.hpp:18
AvmProver(std::shared_ptr< ProvingKey > input_proving_key, std::shared_ptr< VerificationKey > vk, const PCSCommitmentKey &commitment_key)
Definition prover.cpp:42
HonkProof construct_proof()
Definition prover.cpp:266
void execute_public_inputs_round()
Add public inputs to transcript.
Definition prover.cpp:69
void execute_wire_commitments_round()
Compute commitments to all of the witness wires (apart from the logderivative inverse wires)
Definition prover.cpp:97
HonkProof export_proof()
Definition prover.cpp:261
#define vinfo(...)
Definition log.hpp:94
FF a
FF b
void resize_inverses(AvmFlavor::ProverPolynomials &prover_polynomials, Column inverses_col, Column src_selector_col, Column dst_selector_col)
constexpr auto WIRES_TO_BE_SHIFTED_END_IDX
Definition columns.hpp:67
const size_t AVM_MAX_MSM_BATCH_SIZE
Definition prover.cpp:28
AvmFlavorSettings::FF FF
Definition field.hpp:10
ColumnAndShifts
Definition columns.hpp:34
constexpr T round_up_power_2(const T in)
Definition get_msb.hpp:75
std::vector< fr > HonkProof
Definition proof.hpp:15
void parallel_for(size_t num_iterations, const std::function< void(size_t)> &func)
Definition thread.cpp:111
VerifierCommitmentKey< Curve > vk
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
#define AVM_TRACK_TIME(key, body)
Definition stats.hpp:16
void add_to_batch(Polynomial< Fr > &poly, const std::string &label, bool mask)