35 template <
typename Transcript>
40 const std::shared_ptr<Transcript>& transcript,
46 const bool has_zk = (libra_polynomials[0].size() > 0);
49 const size_t virtual_log_n = multilinear_challenge.size();
52 circuit_size, polynomial_batcher, multilinear_challenge, commitment_key, transcript, has_zk);
57 const auto gemini_r = opening_claims[0].opening_pair.challenge;
64 if (!sumcheck_round_univariates.empty()) {
66 circuit_size, multilinear_challenge, sumcheck_round_univariates, sumcheck_round_evaluations);
70 commitment_key, opening_claims, transcript, libra_opening_claims, sumcheck_round_claims, virtual_log_n);
78 template <
typename Transcript>
82 const std::shared_ptr<Transcript>& transcript)
91 "Libra:concatenation_eval",
"Libra:shifted_grand_sum_eval",
"Libra:grand_sum_eval",
"Libra:quotient_eval"
94 gemini_r, gemini_r * subgroup_generator, gemini_r, gemini_r
96 for (
size_t idx = 0; idx < NUM_SMALL_IPA_EVALUATIONS; idx++) {
98 new_claim.
opening_pair.challenge = evaluation_points[idx];
100 transcript->send_to_verifier(libra_eval_labels[idx], new_claim.
opening_pair.evaluation);
101 libra_opening_claims.push_back(new_claim);
104 return libra_opening_claims;
113 const FF circuit_size,
116 const std::vector<std::array<FF, 3>>& sumcheck_round_evaluations)
122 for (
size_t idx = 0; idx < log_n; idx++) {
123 const std::vector<FF> evaluation_points = {
FF(0),
FF(1), multilinear_challenge[idx] };
127 for (
auto& eval_point : evaluation_points) {
129 new_claim.
opening_pair.evaluation = sumcheck_round_evaluations[idx][eval_idx];
130 sumcheck_round_claims.push_back(new_claim);
135 return sumcheck_round_claims;
205 template <
typename Transcript>
209 const std::vector<Fr>& multivariate_challenge,
211 const std::shared_ptr<Transcript>& transcript,
213 const bool has_zk =
false,
214 bool* consistency_checked =
nullptr,
217 const Fr& libra_univariate_evaluation =
Fr{ 0 },
218 const std::vector<Commitment>& sumcheck_round_commitments = {},
224 const size_t virtual_log_n = multivariate_challenge.size();
226 const bool committed_sumcheck = !sumcheck_round_evaluations.empty();
228 Fr batched_evaluation =
Fr{ 0 };
231 const Fr gemini_batching_challenge = transcript->template get_challenge<Fr>(
"rho");
235 const std::vector<Commitment> fold_commitments =
238 const Fr gemini_evaluation_challenge = transcript->template get_challenge<Fr>(
"Gemini:r");
241 const std::vector<Fr> gemini_fold_neg_evaluations =
248 p_pos = transcript->template receive_from_prover<Fr>(
"Gemini:P_pos");
249 p_neg = transcript->template receive_from_prover<Fr>(
"Gemini:P_neg");
253 const std::vector<Fr> gemini_eval_challenge_powers =
258 libra_evaluations[0] = transcript->template receive_from_prover<Fr>(
"Libra:concatenation_eval");
259 libra_evaluations[1] = transcript->template receive_from_prover<Fr>(
"Libra:shifted_grand_sum_eval");
260 libra_evaluations[2] = transcript->template receive_from_prover<Fr>(
"Libra:grand_sum_eval");
261 libra_evaluations[3] = transcript->template receive_from_prover<Fr>(
"Libra:quotient_eval");
266 for (
auto& eval : libra_evaluations) {
267 eval.clear_round_provenance();
274 const Fr shplonk_batching_challenge = transcript->template get_challenge<Fr>(
"Shplonk:nu");
278 const std::vector<Fr> shplonk_batching_challenge_powers = compute_shplonk_batching_challenge_powers(
279 shplonk_batching_challenge, virtual_log_n, has_zk, committed_sumcheck);
281 const auto Q_commitment = transcript->template receive_from_prover<Commitment>(
"Shplonk:Q");
285 std::vector<Commitment> commitments{ Q_commitment };
288 const Fr shplonk_evaluation_challenge = transcript->template get_challenge<Fr>(
"Shplonk:z");
291 Fr constant_term_accumulator =
Fr(0);
294 std::vector<Fr> scalars;
296 scalars.emplace_back(
Fr(1));
300 const std::vector<Fr> inverse_vanishing_evals = ShplonkVerifier::compute_inverted_gemini_denominators(
301 shplonk_evaluation_challenge, gemini_eval_challenge_powers);
306 inverse_vanishing_evals, shplonk_batching_challenge, gemini_evaluation_challenge);
314 Fr shplonk_batching_pos =
Fr{ 0 };
315 Fr shplonk_batching_neg =
Fr{ 0 };
319 const size_t interleaved_pos_index = 2 * virtual_log_n;
320 const size_t interleaved_neg_index = interleaved_pos_index + 1;
321 shplonk_batching_pos = shplonk_batching_challenge_powers[interleaved_pos_index];
322 shplonk_batching_neg = shplonk_batching_challenge_powers[interleaved_neg_index];
323 constant_term_accumulator += claim_batcher.
interleaved->shplonk_denominator *
324 (p_pos * shplonk_batching_pos + p_neg * shplonk_batching_neg);
330 gemini_batching_challenge,
331 shplonk_batching_pos,
332 shplonk_batching_neg);
336 const std::vector<Fr> gemini_fold_pos_evaluations =
337 GeminiVerifier_<Curve>::compute_fold_pos_evaluations(padding_indicator_array,
339 multivariate_challenge,
340 gemini_eval_challenge_powers,
341 gemini_fold_neg_evaluations,
349 gemini_fold_neg_evaluations,
350 gemini_fold_pos_evaluations,
351 inverse_vanishing_evals,
352 shplonk_batching_challenge_powers,
355 constant_term_accumulator);
356 const Fr full_a_0_pos = gemini_fold_pos_evaluations[0];
358 Fr a_0_pos = full_a_0_pos - p_pos;
361 constant_term_accumulator += a_0_pos * inverse_vanishing_evals[0];
363 constant_term_accumulator +=
364 gemini_fold_neg_evaluations[0] * shplonk_batching_challenge * inverse_vanishing_evals[1];
374 constant_term_accumulator,
377 gemini_evaluation_challenge,
378 shplonk_batching_challenge_powers,
379 shplonk_evaluation_challenge);
382 libra_evaluations, gemini_evaluation_challenge, multivariate_challenge, libra_univariate_evaluation);
386 if (committed_sumcheck) {
389 constant_term_accumulator,
390 multivariate_challenge,
391 shplonk_batching_challenge_powers,
392 shplonk_evaluation_challenge,
393 sumcheck_round_commitments,
394 sumcheck_round_evaluations);
398 commitments.emplace_back(g1_identity);
399 scalars.emplace_back(constant_term_accumulator);
401 return { commitments, scalars, shplonk_evaluation_challenge };
449 const std::vector<Commitment>& fold_commitments,
454 std::vector<Commitment>& commitments,
455 std::vector<Fr>& scalars,
456 Fr& constant_term_accumulator)
458 const size_t virtual_log_n = gemini_neg_evaluations.size();
461 for (
size_t j = 1; j < virtual_log_n; ++j) {
463 const size_t pos_index = 2 * j;
465 const size_t neg_index = 2 * j + 1;
468 Fr scaling_factor_pos = shplonk_batching_challenge_powers[pos_index] * inverse_vanishing_evals[pos_index];
470 Fr scaling_factor_neg = shplonk_batching_challenge_powers[neg_index] * inverse_vanishing_evals[neg_index];
474 constant_term_accumulator +=
475 scaling_factor_neg * gemini_neg_evaluations[j] + scaling_factor_pos * gemini_pos_evaluations[j];
478 scalars.emplace_back(-padding_indicator_array[j] * (scaling_factor_neg + scaling_factor_pos));
480 commitments.emplace_back(
std::move(fold_commitments[j - 1]));
504 std::vector<Fr>& scalars,
511 const size_t offset = has_zk ? 2 : 1;
523 for (
size_t i = 0; i < first_range_size; i++) {
524 size_t idx_to_be_shifted = i + first_range_to_be_shifted_start;
525 size_t idx_shifted = i + first_range_shifted_start;
526 scalars[idx_to_be_shifted] = scalars[idx_to_be_shifted] + scalars[idx_shifted];
531 for (
size_t i = 0; i < second_range_size; i++) {
532 size_t idx_to_be_shifted = i + second_range_to_be_shifted_start;
533 size_t idx_shifted = i + second_range_shifted_start;
534 scalars[idx_to_be_shifted] = scalars[idx_to_be_shifted] + scalars[idx_shifted];
537 if (second_range_shifted_start > first_range_shifted_start) {
539 for (
size_t i = 0; i < second_range_size; ++i) {
540 scalars.erase(scalars.begin() +
static_cast<std::ptrdiff_t>(second_range_shifted_start));
541 commitments.erase(commitments.begin() +
static_cast<std::ptrdiff_t>(second_range_shifted_start));
545 for (
size_t i = 0; i < first_range_size; ++i) {
546 scalars.erase(scalars.begin() +
static_cast<std::ptrdiff_t>(first_range_shifted_start));
547 commitments.erase(commitments.begin() +
static_cast<std::ptrdiff_t>(first_range_shifted_start));
551 for (
size_t i = 0; i < first_range_size; ++i) {
552 scalars.erase(scalars.begin() +
static_cast<std::ptrdiff_t>(first_range_shifted_start));
553 commitments.erase(commitments.begin() +
static_cast<std::ptrdiff_t>(first_range_shifted_start));
556 for (
size_t i = 0; i < second_range_size; ++i) {
557 scalars.erase(scalars.begin() +
static_cast<std::ptrdiff_t>(second_range_shifted_start));
558 commitments.erase(commitments.begin() +
static_cast<std::ptrdiff_t>(second_range_shifted_start));
581 std::vector<Commitment>& commitments,
582 std::vector<Fr>& scalars,
583 Fr& constant_term_accumulator,
586 const Fr& gemini_evaluation_challenge,
587 const std::vector<Fr>& shplonk_batching_challenge_powers,
588 const Fr& shplonk_evaluation_challenge)
592 for (
size_t idx = 0; idx < libra_commitments.size(); idx++) {
593 commitments.push_back(libra_commitments[idx]);
600 denominators[0] =
Fr(1) / (shplonk_evaluation_challenge - gemini_evaluation_challenge);
603 denominators[2] = denominators[0];
604 denominators[3] = denominators[0];
608 for (
size_t idx = 0; idx < NUM_SMALL_IPA_EVALUATIONS; idx++) {
609 Fr scaling_factor = denominators[idx] *
610 shplonk_batching_challenge_powers[2 * virtual_log_n + NUM_INTERLEAVING_CLAIMS + idx];
611 batching_scalars[idx] = -scaling_factor;
612 constant_term_accumulator += scaling_factor * libra_evaluations[idx];
616 scalars.push_back(batching_scalars[0]);
617 scalars.push_back(batching_scalars[1] + batching_scalars[2]);
618 scalars.push_back(batching_scalars[3]);
665 std::vector<Fr>& scalars,
666 Fr& constant_term_accumulator,
667 const std::vector<Fr>& multilinear_challenge,
668 const std::vector<Fr>& shplonk_batching_challenge_powers,
669 const Fr& shplonk_evaluation_challenge,
670 const std::vector<Commitment>& sumcheck_round_commitments,
671 const std::vector<std::array<Fr, 3>>& sumcheck_round_evaluations)
674 std::vector<Fr> denominators = {};
678 const size_t num_gemini_claims = 2 * multilinear_challenge.size();
683 const_denominators[0] =
Fr(1) / (shplonk_evaluation_challenge);
684 const_denominators[1] =
Fr(1) / (shplonk_evaluation_challenge -
Fr{ 1 });
688 for (
const auto& [challenge, comm] :
zip_view(multilinear_challenge, sumcheck_round_commitments)) {
689 denominators.push_back(shplonk_evaluation_challenge - challenge);
690 commitments.push_back(comm);
697 for (
auto& denominator : denominators) {
698 denominator =
Fr{ 1 } / denominator;
706 size_t power = num_gemini_claims + NUM_INTERLEAVING_CLAIMS + NUM_SMALL_IPA_EVALUATIONS;
707 for (
const auto& [eval_array, denominator] :
zip_view(sumcheck_round_evaluations, denominators)) {
709 Fr batched_scalar =
Fr(0);
710 Fr const_term_contribution =
Fr(0);
712 for (
size_t idx = 0; idx < 2; idx++) {
713 Fr current_scaling_factor = const_denominators[idx] * shplonk_batching_challenge_powers[power++];
714 batched_scalar -= current_scaling_factor;
715 const_term_contribution += current_scaling_factor * eval_array[idx];
719 Fr current_scaling_factor = denominator * shplonk_batching_challenge_powers[power++];
720 batched_scalar -= current_scaling_factor;
721 const_term_contribution += current_scaling_factor * eval_array[2];
724 constant_term_accumulator += const_term_contribution;
725 scalars.push_back(batched_scalar);
CommitmentKey object over a pairing group 𝔾₁.
Class responsible for computation of the batched multilinear polynomials required by the Gemini proto...
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)
Gemini Verifier utility methods used by ShpleminiVerifier.
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...
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...
Fr evaluate(const Fr &z, size_t target_size) const
Polynomial p and an opening pair (r,v) such that p(r) = v.
OpeningPair< Curve > opening_pair
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={})
typename Curve::Element GroupElement
typename Curve::AffineElement Commitment
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...
typename Curve::ScalarField FF
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
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,...
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
static constexpr bool is_stdlib_type
typename Group::affine_element AffineElement
static constexpr ScalarField subgroup_generator
std::vector< Fr > powers_of_evaluation_challenge(const Fr r, const size_t num_squares)
Compute squares of folding challenge r.
constexpr T get_msb(const T in)
Entry point for Barretenberg command-line interface.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
This file contains part of the logic for the Origin Tag mechanism that tracks the use of in-circuit p...
An accumulator consisting of the Shplonk evaluation challenge and vectors of commitments and scalars.
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 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
size_t second_range_shifted_start
size_t first_range_shifted_start
size_t second_range_to_be_shifted_start
size_t first_range_to_be_shifted_start
static void batch_invert(C &coeffs) noexcept