Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
gemini.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Complete, auditors: [Khashayar], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#pragma once
8
14
51namespace bb {
52
67namespace gemini {
76template <class Fr> inline std::vector<Fr> powers_of_rho(const Fr& rho, const size_t num_powers)
77{
78 std::vector<Fr> rhos;
79 rhos.reserve(num_powers);
80 if (num_powers >= 1) {
81 rhos.emplace_back(Fr(1));
82 }
83 for (size_t j = 1; j < num_powers; j++) {
84 rhos.emplace_back(rhos[j - 1] * rho);
85 }
86 return rhos;
87};
88
96template <class Fr> inline std::vector<Fr> powers_of_evaluation_challenge(const Fr& r, const size_t num_squares)
97{
98 std::vector<Fr> squares = { r };
99 squares.reserve(num_squares);
100 for (size_t j = 1; j < num_squares; j++) {
101 squares.emplace_back(squares[j - 1].sqr());
102 }
103 return squares;
104};
105} // namespace gemini
106
107template <typename Curve> class GeminiProver_ {
108 using Fr = typename Curve::ScalarField;
112
113 public:
129
130 size_t full_batched_size = 0; // size of the full batched polynomial (generally the circuit size)
131 size_t actual_data_size_ = 0; // max end_index across all polynomials (actual data extent)
132
133 Polynomial batched_unshifted; // linear combination of unshifted polynomials
134 Polynomial batched_to_be_shifted_by_one; // linear combination of to-be-shifted polynomials
135
136 // Batched tails: small polynomials covering only the tail region (e.g. last NUM_MASKED_ROWS positions).
137 // Populated during compute_batched if tails are registered.
140
141 public:
142 RefVector<Polynomial> unshifted; // set of unshifted polynomials
143 RefVector<Polynomial> to_be_shifted_by_one; // set of polynomials to be left shifted by 1
144
145 // Tails: small polynomials (e.g. masking values) to be batched with the same rho scalar
146 // as their corresponding base polynomial. Pairs of (index in unshifted/shifted list, tail poly).
149
150 PolynomialBatcher(const size_t full_batched_size, const size_t actual_data_size = 0)
152 , actual_data_size_(actual_data_size == 0 ? full_batched_size : actual_data_size)
155 {}
156
157 bool has_unshifted() const { return unshifted.size() > 0; }
158 bool has_to_be_shifted_by_one() const { return to_be_shifted_by_one.size() > 0; }
159
160 // Set references to the polynomials to be batched
161 void set_unshifted(RefVector<Polynomial> polynomials) { unshifted = polynomials; }
163
164 void add_unshifted_tail(size_t batcher_index, Polynomial&& tail)
165 {
166 unshifted_tails_.emplace_back(batcher_index, std::move(tail));
167 }
168 void add_shifted_tail(size_t batcher_index, Polynomial&& tail)
169 {
170 shifted_tails_.emplace_back(batcher_index, std::move(tail));
171 }
172
181 Polynomial compute_batched(const Fr& challenge)
182 {
183 BB_BENCH_NAME("compute_batched");
184 Fr running_scalar(1);
185
186 // Batch base polynomials via a single fused parallel_for over the destination range,
187 // amortising N× parallel_for startup overhead into 1×. Updates running_scalar in place.
188 auto batch = [&](Polynomial& batched, const RefVector<Polynomial>& polynomials_to_batch) {
189 const size_t n = polynomials_to_batch.size();
191 std::vector<Fr> scalars;
192 sources.reserve(n);
193 scalars.reserve(n);
194 for (size_t i = 0; i < n; ++i) {
195 sources.emplace_back(polynomials_to_batch[i]);
196 scalars.push_back(running_scalar);
197 running_scalar *= challenge;
198 }
200 batched, std::span<const PolynomialSpan<const Fr>>(sources), std::span<const Fr>(scalars));
201 };
202
203 // Batch tails into a small accumulator with the correct rho power per tail.
204 // Tails are small (e.g. 3 elements), kept separate to avoid extending the main batched
205 // poly to full_batched_size. Each tail's scalar is base_scalar * rho^idx.
206 auto batch_tails = [&](Polynomial& batched_tail,
208 const Fr& base_scalar) {
209 for (const auto& [idx, tail] : tail_list) {
210 if (batched_tail.is_empty()) {
211 batched_tail = Polynomial(tail.size(), tail.virtual_size(), tail.start_index());
212 }
213 batched_tail.add_scaled(tail, base_scalar * challenge.pow(idx));
214 }
215 };
216
217 Polynomial full_batched(full_batched_size);
218
219 Fr unshifted_base(1);
220 if (has_unshifted()) {
222 full_batched += batched_unshifted;
223 }
224 batch_tails(batched_unshifted_tail_, unshifted_tails_, unshifted_base);
226 full_batched += batched_unshifted_tail_;
227 }
228
229 Fr shifted_base = running_scalar;
232 full_batched += batched_to_be_shifted_by_one.shifted();
233 }
234 batch_tails(batched_shifted_tail_, shifted_tails_, shifted_base);
236 full_batched += batched_shifted_tail_.shifted();
237 }
238
239 return full_batched;
240 }
241
249 {
251
252 if (has_unshifted()) {
253 A_0_pos += batched_unshifted;
254 }
256 Polynomial A_0_extended(A_0_pos, full_batched_size - A_0_pos.start_index());
257 A_0_extended += batched_unshifted_tail_;
258 A_0_pos = std::move(A_0_extended);
259 }
260
261 Polynomial A_0_neg = A_0_pos;
262
263 Fr r_inv = r_challenge.invert();
267 }
269 A_0_pos.add_scaled(batched_shifted_tail_, r_inv);
270 A_0_neg.add_scaled(batched_shifted_tail_, -r_inv);
271 }
272
273 return { A_0_pos, A_0_neg };
274 };
275 };
276
277 static std::vector<Polynomial> compute_fold_polynomials(const size_t log_n,
278 std::span<const Fr> multilinear_challenge,
279 const Polynomial& A_0);
280
282 Polynomial&& A_0_pos,
283 Polynomial&& A_0_neg,
284 std::vector<Polynomial>&& fold_polynomials,
285 const Fr& r_challenge);
286
287 template <typename Transcript>
288 static std::vector<Claim> prove(size_t circuit_size,
289 PolynomialBatcher& polynomial_batcher,
290 std::span<Fr> multilinear_challenge,
291 const CommitmentKey<Curve>& commitment_key,
292 const std::shared_ptr<Transcript>& transcript,
293 bool has_zk = false);
294
295}; // namespace bb
296
300template <typename Curve> class GeminiVerifier_ {
301 using Fr = typename Curve::ScalarField;
303
304 public:
313 static std::vector<Commitment> get_fold_commitments(const size_t virtual_log_n, auto& transcript)
314 {
315 std::vector<Commitment> fold_commitments;
316 fold_commitments.reserve(virtual_log_n - 1);
317 for (size_t i = 1; i < virtual_log_n; ++i) {
318 const Commitment commitment =
319 transcript->template receive_from_prover<Commitment>("Gemini:FOLD_" + std::to_string(i));
320 fold_commitments.emplace_back(commitment);
321 }
322 return fold_commitments;
323 }
324
334 static std::vector<Fr> get_gemini_evaluations(const size_t virtual_log_n, auto& transcript)
335 {
336 std::vector<Fr> gemini_evaluations;
337 gemini_evaluations.reserve(virtual_log_n);
338
339 for (size_t i = 1; i <= virtual_log_n; ++i) {
340 const Fr evaluation = transcript->template receive_from_prover<Fr>("Gemini:a_" + std::to_string(i));
341 gemini_evaluations.emplace_back(evaluation);
342 }
343 return gemini_evaluations;
344 }
345
369 static std::vector<Fr> compute_fold_pos_evaluations(const Fr& batched_evaluation,
370 std::span<const Fr> evaluation_point, // size = virtual_log_n
371 std::span<const Fr> challenge_powers, // size = virtual_log_n
372 std::span<const Fr> fold_neg_evals) // size = virtual_log_n
373 {
374 const size_t virtual_log_n = evaluation_point.size();
375
376 std::vector<Fr> evals(fold_neg_evals.begin(), fold_neg_evals.end());
377
378 Fr eval_pos_prev = batched_evaluation;
379
380 std::vector<Fr> fold_pos_evaluations;
381 fold_pos_evaluations.reserve(virtual_log_n);
382
383 // Solve the sequence of linear equations
384 for (size_t l = virtual_log_n; l != 0; --l) {
385 // Get r²⁽ˡ⁻¹⁾
386 const Fr& challenge_power = challenge_powers[l - 1];
387 // Get uₗ₋₁
388 const Fr& u = evaluation_point[l - 1];
389 // Get A₍ₗ₋₁₎(−r²⁽ˡ⁻¹⁾)
390 const Fr& eval_neg = evals[l - 1];
391 // Compute the numerator
392 Fr eval_pos = ((challenge_power * eval_pos_prev * 2) - eval_neg * (challenge_power * (Fr(1) - u) - u));
393 // Divide by the denominator
394 eval_pos *= (challenge_power * (Fr(1) - u) + u).invert();
395
396 eval_pos_prev = eval_pos;
397 fold_pos_evaluations.emplace_back(eval_pos_prev);
398 }
399
400 std::reverse(fold_pos_evaluations.begin(), fold_pos_evaluations.end());
401
402 return fold_pos_evaluations;
403 }
404};
405
406} // namespace bb
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:264
CommitmentKey object over a pairing group 𝔾₁.
Class responsible for computation of the batched multilinear polynomials required by the Gemini proto...
Definition gemini.hpp:128
void set_to_be_shifted_by_one(RefVector< Polynomial > polynomials)
Definition gemini.hpp:162
void add_unshifted_tail(size_t batcher_index, Polynomial &&tail)
Definition gemini.hpp:164
PolynomialBatcher(const size_t full_batched_size, const size_t actual_data_size=0)
Definition gemini.hpp:150
void set_unshifted(RefVector< Polynomial > polynomials)
Definition gemini.hpp:161
Polynomial compute_batched(const Fr &challenge)
Compute batched polynomial A₀ = F + G/X as the linear combination of all polynomials to be opened,...
Definition gemini.hpp:181
RefVector< Polynomial > to_be_shifted_by_one
Definition gemini.hpp:143
void add_shifted_tail(size_t batcher_index, Polynomial &&tail)
Definition gemini.hpp:168
std::pair< Polynomial, Polynomial > compute_partially_evaluated_batch_polynomials(const Fr &r_challenge)
Compute partially evaluated batched polynomials A₀(X, r) = A₀₊ = F + G/r, A₀(X, -r) = A₀₋ = F - G/r.
Definition gemini.hpp:248
std::vector< std::pair< size_t, Polynomial > > shifted_tails_
Definition gemini.hpp:148
RefVector< Polynomial > unshifted
Definition gemini.hpp:142
std::vector< std::pair< size_t, Polynomial > > unshifted_tails_
Definition gemini.hpp:147
static std::vector< Claim > prove(size_t circuit_size, PolynomialBatcher &polynomial_batcher, std::span< Fr > multilinear_challenge, const CommitmentKey< Curve > &commitment_key, const std::shared_ptr< Transcript > &transcript, bool has_zk=false)
bb::Polynomial< Fr > Polynomial
Definition gemini.hpp:110
static std::vector< Claim > construct_univariate_opening_claims(const size_t log_n, Polynomial &&A_0_pos, Polynomial &&A_0_neg, std::vector< Polynomial > &&fold_polynomials, const Fr &r_challenge)
Computes/aggragates d+1 univariate polynomial opening claims of the form {polynomial,...
typename Curve::ScalarField Fr
Definition gemini.hpp:108
typename Curve::AffineElement Commitment
Definition gemini.hpp:109
static std::vector< Polynomial > compute_fold_polynomials(const size_t log_n, std::span< const Fr > multilinear_challenge, const Polynomial &A_0)
Computes d-1 fold polynomials Fold_i, i = 1, ..., d-1.
Gemini Verifier utility methods used by ShpleminiVerifier.
Definition gemini.hpp:300
typename Curve::ScalarField Fr
Definition gemini.hpp:301
static std::vector< Fr > compute_fold_pos_evaluations(const Fr &batched_evaluation, std::span< const Fr > evaluation_point, std::span< const Fr > challenge_powers, std::span< const Fr > fold_neg_evals)
Compute .
Definition gemini.hpp:369
static std::vector< Commitment > get_fold_commitments(const size_t virtual_log_n, auto &transcript)
Receive the fold commitments from the prover. This method is used by Shplemini where padding may be e...
Definition gemini.hpp:313
static std::vector< Fr > get_gemini_evaluations(const size_t virtual_log_n, auto &transcript)
Receive the fold evaluations from the prover. This method is used by Shplemini where padding may be e...
Definition gemini.hpp:334
typename Curve::AffineElement Commitment
Definition gemini.hpp:302
Structured polynomial class that represents the coefficients 'a' of a_0 + a_1 x .....
Polynomial shifted() const
Returns a Polynomial the left-shift of self.
size_t start_index() const
bool is_empty() const
void add_scaled(PolynomialSpan< const Fr > other, const Fr &scaling_factor)
adds the polynomial q(X) 'other', multiplied by a scaling factor.
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.
typename Group::affine_element AffineElement
Definition grumpkin.hpp:64
std::vector< Fr > powers_of_evaluation_challenge(const Fr &r, const size_t num_squares)
Compute squares of folding challenge r.
Definition gemini.hpp:96
std::vector< Fr > powers_of_rho(const Fr &rho, const size_t num_powers)
Compute powers of challenge ρ
Definition gemini.hpp:76
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
void add_scaled_batch(Polynomial< Fr > &dst, std::span< const PolynomialSpan< const Fr > > sources, std::span< const Fr > scalars)
Fused parallel batched add: dst += sum_i scalars[i] * sources[i].
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
Curve::ScalarField Fr