Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
shplemini.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
7#pragma once
18
19namespace bb {
20
21template <typename Curve> class ShpleminiProver_ {
22 public:
23 using FF = typename Curve::ScalarField;
24 using GroupElement = typename Curve::Element;
28
33
34 template <typename Transcript>
35 static OpeningClaim prove(const FF circuit_size,
36 PolynomialBatcher& polynomial_batcher,
37 std::span<FF> multilinear_challenge,
38 const CommitmentKey<Curve>& commitment_key,
39 const std::shared_ptr<Transcript>& transcript,
40 const std::array<Polynomial, NUM_SMALL_IPA_EVALUATIONS>& libra_polynomials = {},
41 const std::vector<Polynomial>& sumcheck_round_univariates = {},
42 const std::vector<std::array<FF, 3>>& sumcheck_round_evaluations = {})
43 {
44 // While Shplemini is not templated on Flavor, we derive ZK flag this way
45 const bool has_zk = (libra_polynomials[0].size() > 0);
46
47 // When padding is enabled, the size of the multilinear challenge may be bigger than the log of `circuit_size`.
48 const size_t virtual_log_n = multilinear_challenge.size();
49
51 circuit_size, polynomial_batcher, multilinear_challenge, commitment_key, transcript, has_zk);
52 // Create opening claims for Libra masking univariates and Sumcheck Round Univariates
53 std::vector<OpeningClaim> libra_opening_claims;
54
55 if (has_zk) {
56 const auto gemini_r = opening_claims[0].opening_pair.challenge;
57 libra_opening_claims = compute_libra_opening_claims(gemini_r, libra_polynomials, transcript);
58 }
59
60 // Currently, only used in ECCVM.
61 std::vector<OpeningClaim> sumcheck_round_claims;
62
63 if (!sumcheck_round_univariates.empty()) {
64 sumcheck_round_claims = compute_sumcheck_round_claims(
65 circuit_size, multilinear_challenge, sumcheck_round_univariates, sumcheck_round_evaluations);
66 }
67
69 commitment_key, opening_claims, transcript, libra_opening_claims, sumcheck_round_claims, virtual_log_n);
70 };
71
77 template <typename Transcript>
79 const FF gemini_r,
81 const std::shared_ptr<Transcript>& transcript)
82 {
83 OpeningClaim new_claim;
84
85 std::vector<OpeningClaim> libra_opening_claims = {};
86
87 static constexpr FF subgroup_generator = Curve::subgroup_generator;
88
90 "Libra:concatenation_eval", "Libra:shifted_grand_sum_eval", "Libra:grand_sum_eval", "Libra:quotient_eval"
91 };
92 const std::array<FF, NUM_SMALL_IPA_EVALUATIONS> evaluation_points = {
93 gemini_r, gemini_r * subgroup_generator, gemini_r, gemini_r
94 };
95 for (size_t idx = 0; idx < NUM_SMALL_IPA_EVALUATIONS; idx++) {
96 new_claim.polynomial = std::move(libra_polynomials[idx]);
97 new_claim.opening_pair.challenge = evaluation_points[idx];
98 new_claim.opening_pair.evaluation = new_claim.polynomial.evaluate(evaluation_points[idx]);
99 transcript->send_to_verifier(libra_eval_labels[idx], new_claim.opening_pair.evaluation);
100 libra_opening_claims.push_back(new_claim);
101 }
102
103 return libra_opening_claims;
104 }
105
112 const FF circuit_size,
113 std::span<FF> multilinear_challenge,
114 const std::vector<Polynomial>& sumcheck_round_univariates,
115 const std::vector<std::array<FF, 3>>& sumcheck_round_evaluations)
116 {
117 OpeningClaim new_claim;
118 std::vector<OpeningClaim> sumcheck_round_claims = {};
119
120 const size_t log_n = numeric::get_msb(static_cast<uint32_t>(circuit_size));
121 for (size_t idx = 0; idx < log_n; idx++) {
122 const std::vector<FF> evaluation_points = { FF(0), FF(1), multilinear_challenge[idx] };
123 size_t eval_idx = 0;
124 new_claim.polynomial = std::move(sumcheck_round_univariates[idx]);
125
126 for (auto& eval_point : evaluation_points) {
127 new_claim.opening_pair.challenge = eval_point;
128 new_claim.opening_pair.evaluation = sumcheck_round_evaluations[idx][eval_idx];
129 sumcheck_round_claims.push_back(new_claim);
130 eval_idx++;
131 }
132 }
133
134 return sumcheck_round_claims;
135 }
136};
189template <typename Curve> class ShpleminiVerifier_ {
190 using Fr = typename Curve::ScalarField;
191 using GroupElement = typename Curve::Element;
197
198 public:
204 template <typename Transcript>
206 std::span<const Fr> padding_indicator_array,
207 ClaimBatcher& claim_batcher,
208 const std::vector<Fr>& multivariate_challenge,
209 const Commitment& g1_identity,
210 const std::shared_ptr<Transcript>& transcript,
211 const RepeatedCommitmentsData& repeated_commitments = {},
212 const bool has_zk = false,
213 bool* consistency_checked = nullptr, // TODO(https://github.com/AztecProtocol/barretenberg/issues/1191).
214 // Shplemini Refactoring: Remove bool pointer
215 const std::array<Commitment, NUM_LIBRA_COMMITMENTS>& libra_commitments = {},
216 const Fr& libra_univariate_evaluation = Fr{ 0 },
217 const std::vector<Commitment>& sumcheck_round_commitments = {},
218 const std::vector<std::array<Fr, 3>>& sumcheck_round_evaluations = {})
219
220 {
221 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1463): Investigate whether this function can be
222 // simplified using the new Shplonk api
223 const size_t virtual_log_n = multivariate_challenge.size();
224
225 const bool committed_sumcheck = !sumcheck_round_evaluations.empty();
226
227 Fr batched_evaluation = Fr{ 0 };
228
229 // While Shplemini is not templated on Flavor, we derive ZK flag this way
230 Commitment hiding_polynomial_commitment;
231 if (has_zk) {
232 hiding_polynomial_commitment =
233 transcript->template receive_from_prover<Commitment>("Gemini:masking_poly_comm");
234 batched_evaluation = transcript->template receive_from_prover<Fr>("Gemini:masking_poly_eval");
235 }
236
237 // Get the challenge ρ to batch commitments to multilinear polynomials and their shifts
238 const Fr gemini_batching_challenge = transcript->template get_challenge<Fr>("rho");
239
240 // Process Gemini transcript data:
241 // - Get Gemini commitments (com(A₁), com(A₂), … , com(Aₙ₋₁))
242 const std::vector<Commitment> fold_commitments =
243 GeminiVerifier::get_fold_commitments(virtual_log_n, transcript);
244 // - Get Gemini evaluation challenge for Aᵢ, i = 0, … , d−1
245 const Fr gemini_evaluation_challenge = transcript->template get_challenge<Fr>("Gemini:r");
246
247 // - Get evaluations (A₀(−r), A₁(−r²), ... , Aₙ₋₁(−r²⁽ⁿ⁻¹⁾))
248 const std::vector<Fr> gemini_fold_neg_evaluations =
249 GeminiVerifier::get_gemini_evaluations(virtual_log_n, transcript);
250
251 // Get evaluations of partially evaluated batched interleaved polynomials P₊(rˢ) and P₋((-r)ˢ)
252 Fr p_pos = Fr(0);
253 Fr p_neg = Fr(0);
254 if (claim_batcher.interleaved) {
255 p_pos = transcript->template receive_from_prover<Fr>("Gemini:P_pos");
256 p_neg = transcript->template receive_from_prover<Fr>("Gemini:P_neg");
257 }
258
259 // - Compute vector (r, r², ... , r^{2^{d-1}}), where d = log_n
260 const std::vector<Fr> gemini_eval_challenge_powers =
261 gemini::powers_of_evaluation_challenge(gemini_evaluation_challenge, virtual_log_n);
262
264 if (has_zk) {
265 libra_evaluations[0] = transcript->template receive_from_prover<Fr>("Libra:concatenation_eval");
266 libra_evaluations[1] = transcript->template receive_from_prover<Fr>("Libra:shifted_grand_sum_eval");
267 libra_evaluations[2] = transcript->template receive_from_prover<Fr>("Libra:grand_sum_eval");
268 libra_evaluations[3] = transcript->template receive_from_prover<Fr>("Libra:quotient_eval");
269 }
270
271 // Process Shplonk transcript data:
272 // - Get Shplonk batching challenge
273 const Fr shplonk_batching_challenge = transcript->template get_challenge<Fr>("Shplonk:nu");
274
275 // Compute the powers of ν that are required for batching Gemini, SmallSubgroupIPA, and committed sumcheck
276 // univariate opening claims.
277 const std::vector<Fr> shplonk_batching_challenge_powers = compute_shplonk_batching_challenge_powers(
278 shplonk_batching_challenge, virtual_log_n, has_zk, committed_sumcheck);
279 // - Get the quotient commitment for the Shplonk batching of Gemini opening claims
280 const auto Q_commitment = transcript->template receive_from_prover<Commitment>("Shplonk:Q");
281
282 // Start populating the vector (Q, f₀, ... , fₖ₋₁, g₀, ... , gₘ₋₁, com(A₁), ... , com(A_{d-1}), [1]₁) where fᵢ
283 // are the k commitments to unshifted polynomials and gⱼ are the m commitments to shifted polynomials
284 std::vector<Commitment> commitments{ Q_commitment };
285
286 // Get Shplonk opening point z
287 const Fr shplonk_evaluation_challenge = transcript->template get_challenge<Fr>("Shplonk:z");
288
289 // Start computing the scalar to be multiplied by [1]₁
290 Fr constant_term_accumulator = Fr(0);
291
292 // Initialize the vector of scalars placing the scalar 1 correposnding to Q_commitment
293 std::vector<Fr> scalars;
294
295 scalars.emplace_back(Fr(1));
296
297 // Compute 1/(z − r), 1/(z + r), 1/(z - r²), 1/(z + r²), … , 1/(z - r^{2^{d-1}}), 1/(z + r^{2^{d-1}})
298 // These represent the denominators of the summand terms in Shplonk partially evaluated polynomial Q_z
299 const std::vector<Fr> inverse_vanishing_evals = ShplonkVerifier::compute_inverted_gemini_denominators(
300 shplonk_evaluation_challenge, gemini_eval_challenge_powers);
301
302 // Compute the additional factors to be multiplied with unshifted and shifted commitments when lazily
303 // reconstructing the commitment of Q_z
304 claim_batcher.compute_scalars_for_each_batch(
305 inverse_vanishing_evals, shplonk_batching_challenge, gemini_evaluation_challenge);
306
307 if (has_zk) {
308 commitments.emplace_back(hiding_polynomial_commitment);
309 scalars.emplace_back(-claim_batcher.get_unshifted_batch_scalar()); // corresponds to ρ⁰
310 }
311
312 // Place the commitments to prover polynomials in the commitments vector. Compute the evaluation of the
313 // batched multilinear polynomial. Populate the vector of scalars for the final batch mul
314
315 Fr gemini_batching_challenge_power = Fr(1);
316 if (has_zk) {
317 // ρ⁰ is used to batch the hiding polynomial which has already been added to the commitments vector
318 gemini_batching_challenge_power *= gemini_batching_challenge;
319 }
320
321 // Compute the Shplonk batching power for the interleaved claims. This is \nu^{d+1} where d = log_n as the
322 // interleaved claims are sent after the rest of Gemini fold claims. Add the evaluations of (P₊(rˢ) ⋅ ν^{d+1}) /
323 // (z − r^s) and (P₋(rˢ) ⋅ ν^{d+2})/(z − r^s) to the constant term accumulator
324 Fr shplonk_batching_pos = Fr{ 0 };
325 Fr shplonk_batching_neg = Fr{ 0 };
326 if (claim_batcher.interleaved) {
327 // Currently, the prover places the Interleaving claims before the Gemini dummy claims.
328 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1293): Decouple Gemini from Interleaving.
329 const size_t interleaved_pos_index = 2 * virtual_log_n;
330 const size_t interleaved_neg_index = interleaved_pos_index + 1;
331 shplonk_batching_pos = shplonk_batching_challenge_powers[interleaved_pos_index];
332 shplonk_batching_neg = shplonk_batching_challenge_powers[interleaved_neg_index];
333 constant_term_accumulator += claim_batcher.interleaved->shplonk_denominator *
334 (p_pos * shplonk_batching_pos + p_neg * shplonk_batching_neg);
335 }
336 // Update the commitments and scalars vectors as well as the batched evaluation given the present batches
337 claim_batcher.update_batch_mul_inputs_and_batched_evaluation(commitments,
338 scalars,
339 batched_evaluation,
340 gemini_batching_challenge,
341 gemini_batching_challenge_power,
342 shplonk_batching_pos,
343 shplonk_batching_neg);
344
345 // Reconstruct Aᵢ(r²ⁱ) for i=0, ..., d - 1 from the batched evaluation of the multilinear polynomials and
346 // Aᵢ(−r²ⁱ) for i = 0, ..., d - 1. In the case of interleaving, we compute A₀(r) as A₀₊(r) + P₊(r^s).
347 const std::vector<Fr> gemini_fold_pos_evaluations =
348 GeminiVerifier_<Curve>::compute_fold_pos_evaluations(padding_indicator_array,
349 batched_evaluation,
350 multivariate_challenge,
351 gemini_eval_challenge_powers,
352 gemini_fold_neg_evaluations,
353 p_neg);
354
355 // Place the commitments to Gemini fold polynomials Aᵢ in the vector of batch_mul commitments, compute the
356 // contributions from Aᵢ(−r²ⁱ) for i=1, … , d − 1 to the constant term accumulator, add corresponding scalars
357 // for the batch mul
358 batch_gemini_claims_received_from_prover(padding_indicator_array,
359 fold_commitments,
360 gemini_fold_neg_evaluations,
361 gemini_fold_pos_evaluations,
362 inverse_vanishing_evals,
363 shplonk_batching_challenge_powers,
364 commitments,
365 scalars,
366 constant_term_accumulator);
367 const Fr full_a_0_pos = gemini_fold_pos_evaluations[0];
368 // Retrieve the contribution without P₊(r^s)
369 Fr a_0_pos = full_a_0_pos - p_pos;
370 // Add contributions from A₀₊(r) and A₀₋(-r) to constant_term_accumulator:
371 // Add A₀₊(r)/(z−r) to the constant term accumulator
372 constant_term_accumulator += a_0_pos * inverse_vanishing_evals[0];
373 // Add A₀₋(-r)/(z+r) to the constant term accumulator
374 constant_term_accumulator +=
375 gemini_fold_neg_evaluations[0] * shplonk_batching_challenge * inverse_vanishing_evals[1];
376
377 remove_repeated_commitments(commitments, scalars, repeated_commitments, has_zk);
378
379 // For ZK flavors, the sumcheck output contains the evaluations of Libra univariates that submitted to the
380 // ShpleminiVerifier, otherwise this argument is set to be empty
381 if (has_zk) {
382 add_zk_data(virtual_log_n,
383 commitments,
384 scalars,
385 constant_term_accumulator,
386 libra_commitments,
387 libra_evaluations,
388 gemini_evaluation_challenge,
389 shplonk_batching_challenge_powers,
390 shplonk_evaluation_challenge);
391
393 libra_evaluations, gemini_evaluation_challenge, multivariate_challenge, libra_univariate_evaluation);
394 }
395
396 // Currently, only used in ECCVM
397 if (committed_sumcheck) {
398 batch_sumcheck_round_claims(commitments,
399 scalars,
400 constant_term_accumulator,
401 multivariate_challenge,
402 shplonk_batching_challenge_powers,
403 shplonk_evaluation_challenge,
404 sumcheck_round_commitments,
405 sumcheck_round_evaluations);
406 }
407
408 // Finalize the batch opening claim
409 commitments.emplace_back(g1_identity);
410 scalars.emplace_back(constant_term_accumulator);
411
412 return { commitments, scalars, shplonk_evaluation_challenge };
413 };
414
460 const std::vector<Commitment>& fold_commitments,
461 std::span<const Fr> gemini_neg_evaluations,
462 std::span<const Fr> gemini_pos_evaluations,
463 std::span<const Fr> inverse_vanishing_evals,
464 std::span<const Fr> shplonk_batching_challenge_powers,
465 std::vector<Commitment>& commitments,
466 std::vector<Fr>& scalars,
467 Fr& constant_term_accumulator)
468 {
469 const size_t virtual_log_n = gemini_neg_evaluations.size();
470 // Start from 1, because the commitment to A_0 is reconstructed from the commitments to the multilinear
471 // polynomials. The corresponding evaluations are also handled separately.
472 for (size_t j = 1; j < virtual_log_n; ++j) {
473 // The index of 1/ (z - r^{2^{j}}) in the vector of inverted Gemini denominators
474 const size_t pos_index = 2 * j;
475 // The index of 1/ (z + r^{2^{j}}) in the vector of inverted Gemini denominators
476 const size_t neg_index = 2 * j + 1;
477
478 // Compute the "positive" scaling factor (ν^{2j}) / (z - r^{2^{j}})
479 Fr scaling_factor_pos = shplonk_batching_challenge_powers[pos_index] * inverse_vanishing_evals[pos_index];
480 // Compute the "negative" scaling factor (ν^{2j+1}) / (z + r^{2^{j}})
481 Fr scaling_factor_neg = shplonk_batching_challenge_powers[neg_index] * inverse_vanishing_evals[neg_index];
482
483 // Accumulate the const term contribution given by
484 // v^{2j} * A_j(r^{2^j}) /(z - r^{2^j}) + v^{2j+1} * A_j(-r^{2^j}) /(z+ r^{2^j})
485 constant_term_accumulator +=
486 scaling_factor_neg * gemini_neg_evaluations[j] + scaling_factor_pos * gemini_pos_evaluations[j];
487
488 // Place the scaling factor to the 'scalars' vector
489 scalars.emplace_back(-padding_indicator_array[j] * (scaling_factor_neg + scaling_factor_pos));
490 // Move com(Aᵢ) to the 'commitments' vector
491 commitments.emplace_back(std::move(fold_commitments[j - 1]));
492 }
493 }
494
513 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1151) Avoid erasing vector elements.
514 static void remove_repeated_commitments(std::vector<Commitment>& commitments,
515 std::vector<Fr>& scalars,
516 const RepeatedCommitmentsData& repeated_commitments,
517 bool has_zk)
518 {
519 // We started populating commitments and scalars by adding Shplonk:Q commitmment and the corresponding scalar
520 // factor 1. In the case of ZK, we also added Gemini:masking_poly_comm before populating the vector with
521 // commitments to prover polynomials
522 const size_t offset = has_zk ? 2 : 1;
523
524 // Extract the indices from the container, which is normally created in a given Flavor
525 const size_t& first_range_to_be_shifted_start = repeated_commitments.first_range_to_be_shifted_start + offset;
526 const size_t& first_range_shifted_start = repeated_commitments.first_range_shifted_start + offset;
527 const size_t& first_range_size = repeated_commitments.first_range_size;
528
529 const size_t& second_range_to_be_shifted_start = repeated_commitments.second_range_to_be_shifted_start + offset;
530 const size_t& second_range_shifted_start = repeated_commitments.second_range_shifted_start + offset;
531 const size_t& second_range_size = repeated_commitments.second_range_size;
532
533 // Iterate over the first range of to-be-shifted scalars and their shifted counterparts
534 for (size_t i = 0; i < first_range_size; i++) {
535 size_t idx_to_be_shifted = i + first_range_to_be_shifted_start;
536 size_t idx_shifted = i + first_range_shifted_start;
537 scalars[idx_to_be_shifted] = scalars[idx_to_be_shifted] + scalars[idx_shifted];
538 }
539
540 // Iterate over the second range of to-be-shifted precomputed scalars and their shifted counterparts (if
541 // provided)
542 for (size_t i = 0; i < second_range_size; i++) {
543 size_t idx_to_be_shifted = i + second_range_to_be_shifted_start;
544 size_t idx_shifted = i + second_range_shifted_start;
545 scalars[idx_to_be_shifted] = scalars[idx_to_be_shifted] + scalars[idx_shifted];
546 }
547
548 if (second_range_shifted_start > first_range_shifted_start) {
549 // Erase the shifted scalars and commitments from the second range (if provided)
550 for (size_t i = 0; i < second_range_size; ++i) {
551 scalars.erase(scalars.begin() + static_cast<std::ptrdiff_t>(second_range_shifted_start));
552 commitments.erase(commitments.begin() + static_cast<std::ptrdiff_t>(second_range_shifted_start));
553 }
554
555 // Erase the shifted scalars and commitments from the first range
556 for (size_t i = 0; i < first_range_size; ++i) {
557 scalars.erase(scalars.begin() + static_cast<std::ptrdiff_t>(first_range_shifted_start));
558 commitments.erase(commitments.begin() + static_cast<std::ptrdiff_t>(first_range_shifted_start));
559 }
560 } else {
561 // Erase the shifted scalars and commitments from the first range
562 for (size_t i = 0; i < first_range_size; ++i) {
563 scalars.erase(scalars.begin() + static_cast<std::ptrdiff_t>(first_range_shifted_start));
564 commitments.erase(commitments.begin() + static_cast<std::ptrdiff_t>(first_range_shifted_start));
565 }
566 // Erase the shifted scalars and commitments from the second range (if provided)
567 for (size_t i = 0; i < second_range_size; ++i) {
568 scalars.erase(scalars.begin() + static_cast<std::ptrdiff_t>(second_range_shifted_start));
569 commitments.erase(commitments.begin() + static_cast<std::ptrdiff_t>(second_range_shifted_start));
570 }
571 }
572 }
573
591 static void add_zk_data(const size_t virtual_log_n,
592 std::vector<Commitment>& commitments,
593 std::vector<Fr>& scalars,
594 Fr& constant_term_accumulator,
595 const std::array<Commitment, NUM_LIBRA_COMMITMENTS>& libra_commitments,
596 const std::array<Fr, NUM_SMALL_IPA_EVALUATIONS>& libra_evaluations,
597 const Fr& gemini_evaluation_challenge,
598 const std::vector<Fr>& shplonk_batching_challenge_powers,
599 const Fr& shplonk_evaluation_challenge)
600
601 {
602 // add Libra commitments to the vector of commitments
603 for (size_t idx = 0; idx < libra_commitments.size(); idx++) {
604 commitments.push_back(libra_commitments[idx]);
605 }
606
607 // compute corresponding scalars and the correction to the constant term
610 // compute Shplonk denominators and invert them
611 denominators[0] = Fr(1) / (shplonk_evaluation_challenge - gemini_evaluation_challenge);
612 denominators[1] =
613 Fr(1) / (shplonk_evaluation_challenge - Fr(Curve::subgroup_generator) * gemini_evaluation_challenge);
614 denominators[2] = denominators[0];
615 denominators[3] = denominators[0];
616
617 // compute the scalars to be multiplied against the commitments [libra_concatenated], [grand_sum], [grand_sum],
618 // and [libra_quotient]
619 for (size_t idx = 0; idx < NUM_SMALL_IPA_EVALUATIONS; idx++) {
620 Fr scaling_factor = denominators[idx] *
621 shplonk_batching_challenge_powers[2 * virtual_log_n + NUM_INTERLEAVING_CLAIMS + idx];
622 batching_scalars[idx] = -scaling_factor;
623 constant_term_accumulator += scaling_factor * libra_evaluations[idx];
624 }
625
626 // to save a scalar mul, add the sum of the batching scalars corresponding to the big sum evaluations
627 scalars.push_back(batching_scalars[0]);
628 scalars.push_back(batching_scalars[1] + batching_scalars[2]);
629 scalars.push_back(batching_scalars[3]);
630 }
631
675 static void batch_sumcheck_round_claims(std::vector<Commitment>& commitments,
676 std::vector<Fr>& scalars,
677 Fr& constant_term_accumulator,
678 const std::vector<Fr>& multilinear_challenge,
679 const std::vector<Fr>& shplonk_batching_challenge_powers,
680 const Fr& shplonk_evaluation_challenge,
681 const std::vector<Commitment>& sumcheck_round_commitments,
682 const std::vector<std::array<Fr, 3>>& sumcheck_round_evaluations)
683 {
684
685 std::vector<Fr> denominators = {};
686
687 // The number of Gemini claims is equal to `2 * log_n` and `log_n` is equal to the size of
688 // `multilinear_challenge`, as this method is never used with padding.
689 const size_t num_gemini_claims = 2 * multilinear_challenge.size();
690 // Denominators for the opening claims at 0 and 1. Need to be computed only once as opposed to the claims at the
691 // sumcheck round challenges.
692 std::array<Fr, 2> const_denominators;
693
694 const_denominators[0] = Fr(1) / (shplonk_evaluation_challenge);
695 const_denominators[1] = Fr(1) / (shplonk_evaluation_challenge - Fr{ 1 });
696
697 // Compute the denominators corresponding to the evaluation claims at the round challenges and add the
698 // commitments to the sumcheck round univariates to the vector of commitments
699 for (const auto& [challenge, comm] : zip_view(multilinear_challenge, sumcheck_round_commitments)) {
700 denominators.push_back(shplonk_evaluation_challenge - challenge);
701 commitments.push_back(comm);
702 }
703
704 // Invert denominators
705 if constexpr (!Curve::is_stdlib_type) {
706 Fr::batch_invert(denominators);
707 } else {
708 for (auto& denominator : denominators) {
709 denominator = Fr{ 1 } / denominator;
710 }
711 }
712
713 // Each commitment to a sumcheck round univariate [S_i] is multiplied by the sum of three scalars corresponding
714 // to the evaluations at 0, 1, and the round challenge u_i.
715 // Compute the power of `shplonk_batching_challenge` to add sumcheck univariate commitments and evaluations to
716 // the batch.
717 size_t power = num_gemini_claims + NUM_INTERLEAVING_CLAIMS + NUM_SMALL_IPA_EVALUATIONS;
718 for (const auto& [eval_array, denominator] : zip_view(sumcheck_round_evaluations, denominators)) {
719 // Initialize batched_scalar corresponding to 3 evaluations claims
720 Fr batched_scalar = Fr(0);
721 Fr const_term_contribution = Fr(0);
722 // Compute the contribution from the evaluations at 0 and 1
723 for (size_t idx = 0; idx < 2; idx++) {
724 Fr current_scaling_factor = const_denominators[idx] * shplonk_batching_challenge_powers[power++];
725 batched_scalar -= current_scaling_factor;
726 const_term_contribution += current_scaling_factor * eval_array[idx];
727 }
728
729 // Compute the contribution from the evaluation at the challenge u_i
730 Fr current_scaling_factor = denominator * shplonk_batching_challenge_powers[power++];
731 batched_scalar -= current_scaling_factor;
732 const_term_contribution += current_scaling_factor * eval_array[2];
733
734 // Update Shplonk constant term accumualator
735 constant_term_accumulator += const_term_contribution;
736 scalars.push_back(batched_scalar);
737 }
738 };
739};
740} // namespace bb
CommitmentKey object over a pairing group 𝔾₁.
Class responsible for computation of the batched multilinear polynomials required by the Gemini proto...
Definition gemini.hpp:123
static std::vector< Claim > prove(const Fr 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)
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:493
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:514
Fr evaluate(const Fr &z, size_t target_size) const
Polynomial p and an opening pair (r,v) such that p(r) = v.
Definition claim.hpp:34
Polynomial polynomial
Definition claim.hpp:39
OpeningPair< Curve > opening_pair
Definition claim.hpp:40
static OpeningClaim prove(const FF 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:35
typename Curve::Element GroupElement
Definition shplemini.hpp:24
typename Curve::AffineElement Commitment
Definition shplemini.hpp:25
static std::vector< OpeningClaim > compute_libra_opening_claims(const FF gemini_r, const std::array< Polynomial, NUM_SMALL_IPA_EVALUATIONS > &libra_polynomials, const std::shared_ptr< Transcript > &transcript)
For ZK Flavors: Evaluate the polynomials used in SmallSubgroupIPA argument, send the evaluations to t...
Definition shplemini.hpp:78
typename Curve::ScalarField FF
Definition shplemini.hpp:23
static std::vector< OpeningClaim > compute_sumcheck_round_claims(const FF circuit_size, std::span< FF > multilinear_challenge, const std::vector< Polynomial > &sumcheck_round_univariates, const std::vector< std::array< FF, 3 > > &sumcheck_round_evaluations)
Create a vector of 3*log_n opening claims for the evaluations of Sumcheck Round Univariates at 0,...
An efficient verifier for the evaluation proofs of multilinear polynomials and their shifts.
static void add_zk_data(const size_t virtual_log_n, std::vector< Commitment > &commitments, std::vector< Fr > &scalars, Fr &constant_term_accumulator, const std::array< Commitment, NUM_LIBRA_COMMITMENTS > &libra_commitments, const std::array< Fr, NUM_SMALL_IPA_EVALUATIONS > &libra_evaluations, const Fr &gemini_evaluation_challenge, const std::vector< Fr > &shplonk_batching_challenge_powers, const Fr &shplonk_evaluation_challenge)
Add the opening data corresponding to Libra masking univariates to the batched opening claim.
static void batch_gemini_claims_received_from_prover(std::span< const Fr > padding_indicator_array, const std::vector< Commitment > &fold_commitments, std::span< const Fr > gemini_neg_evaluations, std::span< const Fr > gemini_pos_evaluations, std::span< const Fr > inverse_vanishing_evals, std::span< const Fr > shplonk_batching_challenge_powers, std::vector< Commitment > &commitments, std::vector< Fr > &scalars, Fr &constant_term_accumulator)
Place fold polynomial commitments to commitments and compute the corresponding scalar multipliers.
static void remove_repeated_commitments(std::vector< Commitment > &commitments, std::vector< Fr > &scalars, const RepeatedCommitmentsData &repeated_commitments, bool has_zk)
Combines scalars of repeating commitments to reduce the number of scalar multiplications performed by...
static BatchOpeningClaim< Curve > compute_batch_opening_claim(std::span< const Fr > padding_indicator_array, ClaimBatcher &claim_batcher, const std::vector< Fr > &multivariate_challenge, const Commitment &g1_identity, const std::shared_ptr< Transcript > &transcript, const RepeatedCommitmentsData &repeated_commitments={}, const bool has_zk=false, bool *consistency_checked=nullptr, const std::array< Commitment, NUM_LIBRA_COMMITMENTS > &libra_commitments={}, const Fr &libra_univariate_evaluation=Fr{ 0 }, const std::vector< Commitment > &sumcheck_round_commitments={}, const std::vector< std::array< Fr, 3 > > &sumcheck_round_evaluations={})
Non-padding version of compute_batch_opening_claim. Used by all native verifiers and by recursive Tra...
typename Curve::ScalarField Fr
static void batch_sumcheck_round_claims(std::vector< Commitment > &commitments, std::vector< Fr > &scalars, Fr &constant_term_accumulator, const std::vector< Fr > &multilinear_challenge, const std::vector< Fr > &shplonk_batching_challenge_powers, const Fr &shplonk_evaluation_challenge, const std::vector< Commitment > &sumcheck_round_commitments, const std::vector< std::array< Fr, 3 > > &sumcheck_round_evaluations)
Adds the Sumcheck data into the Shplemini BatchOpeningClaim.
typename Curve::AffineElement Commitment
typename Curve::Element GroupElement
Shplonk Prover.
Definition shplonk.hpp:36
static ProverOpeningClaim< Curve > prove(const CommitmentKey< Curve > &commitment_key, std::span< ProverOpeningClaim< Curve > > opening_claims, const std::shared_ptr< Transcript > &transcript, std::span< ProverOpeningClaim< Curve > > libra_opening_claims={}, std::span< ProverOpeningClaim< Curve > > sumcheck_round_claims={}, const size_t virtual_log_n=0)
Returns a batched opening claim equivalent to a set of opening claims consisting of polynomials,...
Definition shplonk.hpp:267
Shplonk Verifier.
Definition shplonk.hpp:343
static bool check_libra_evaluations_consistency(const std::array< FF, NUM_SMALL_IPA_EVALUATIONS > &libra_evaluations, const FF &gemini_evaluation_challenge, const std::vector< FF > &multilinear_challenge, const FF &inner_product_eval_claim)
A method required by ZKSumcheck. The challenge polynomial is concatenated from the powers of the sumc...
typename Group::element Element
Definition grumpkin.hpp:55
static constexpr bool is_stdlib_type
Definition grumpkin.hpp:62
typename Group::affine_element AffineElement
Definition grumpkin.hpp:56
static constexpr ScalarField subgroup_generator
Definition grumpkin.hpp:72
ssize_t offset
Definition engine.cpp:36
std::vector< Fr > powers_of_evaluation_challenge(const Fr r, const size_t num_squares)
Compute squares of folding challenge r.
Definition gemini.hpp:92
constexpr T get_msb(const T in)
Definition get_msb.hpp:47
Entry point for Barretenberg command-line interface.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
An accumulator consisting of the Shplonk evaluation challenge and vectors of commitments and scalars.
Definition claim.hpp:169
Logic to support batching opening claims for unshifted and shifted polynomials in Shplemini.
void compute_scalars_for_each_batch(std::span< const Fr > inverted_vanishing_evals, const Fr &nu_challenge, const Fr &r_challenge)
Compute scalars used to batch each set of claims, excluding contribution from batching challenge \rho...
void update_batch_mul_inputs_and_batched_evaluation(std::vector< Commitment > &commitments, std::vector< Fr > &scalars, Fr &batched_evaluation, const Fr &rho, Fr &rho_power, Fr shplonk_batching_pos={ 0 }, Fr shplonk_batching_neg={ 0 })
Append the commitments and scalars from each batch of claims to the Shplemini, vectors which subseque...
std::optional< InterleavedBatch > interleaved
Fr get_unshifted_batch_scalar() const
static void batch_invert(std::span< field > coeffs) noexcept