34 template <
typename Transcript>
39 const std::shared_ptr<Transcript>& transcript,
45 const bool has_zk = (libra_polynomials[0].size() > 0);
48 const size_t virtual_log_n = multilinear_challenge.size();
51 circuit_size, polynomial_batcher, multilinear_challenge, commitment_key, transcript, has_zk);
56 const auto gemini_r = opening_claims[0].opening_pair.challenge;
63 if (!sumcheck_round_univariates.empty()) {
65 circuit_size, multilinear_challenge, sumcheck_round_univariates, sumcheck_round_evaluations);
69 commitment_key, opening_claims, transcript, libra_opening_claims, sumcheck_round_claims, virtual_log_n);
77 template <
typename Transcript>
81 const std::shared_ptr<Transcript>& transcript)
90 "Libra:concatenation_eval",
"Libra:shifted_grand_sum_eval",
"Libra:grand_sum_eval",
"Libra:quotient_eval"
93 gemini_r, gemini_r * subgroup_generator, gemini_r, gemini_r
95 for (
size_t idx = 0; idx < NUM_SMALL_IPA_EVALUATIONS; idx++) {
97 new_claim.
opening_pair.challenge = 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);
103 return libra_opening_claims;
112 const FF circuit_size,
115 const std::vector<std::array<FF, 3>>& sumcheck_round_evaluations)
121 for (
size_t idx = 0; idx < log_n; idx++) {
122 const std::vector<FF> evaluation_points = {
FF(0),
FF(1), multilinear_challenge[idx] };
126 for (
auto& eval_point : evaluation_points) {
128 new_claim.
opening_pair.evaluation = sumcheck_round_evaluations[idx][eval_idx];
129 sumcheck_round_claims.push_back(new_claim);
134 return sumcheck_round_claims;
204 template <
typename Transcript>
208 const std::vector<Fr>& multivariate_challenge,
210 const std::shared_ptr<Transcript>& transcript,
212 const bool has_zk =
false,
213 bool* consistency_checked =
nullptr,
216 const Fr& libra_univariate_evaluation =
Fr{ 0 },
217 const std::vector<Commitment>& sumcheck_round_commitments = {},
223 const size_t virtual_log_n = multivariate_challenge.size();
225 const bool committed_sumcheck = !sumcheck_round_evaluations.empty();
227 Fr batched_evaluation =
Fr{ 0 };
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");
238 const Fr gemini_batching_challenge = transcript->template get_challenge<Fr>(
"rho");
242 const std::vector<Commitment> fold_commitments =
245 const Fr gemini_evaluation_challenge = transcript->template get_challenge<Fr>(
"Gemini:r");
248 const std::vector<Fr> gemini_fold_neg_evaluations =
255 p_pos = transcript->template receive_from_prover<Fr>(
"Gemini:P_pos");
256 p_neg = transcript->template receive_from_prover<Fr>(
"Gemini:P_neg");
260 const std::vector<Fr> gemini_eval_challenge_powers =
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");
273 const Fr shplonk_batching_challenge = transcript->template get_challenge<Fr>(
"Shplonk:nu");
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);
280 const auto Q_commitment = transcript->template receive_from_prover<Commitment>(
"Shplonk:Q");
284 std::vector<Commitment> commitments{ Q_commitment };
287 const Fr shplonk_evaluation_challenge = transcript->template get_challenge<Fr>(
"Shplonk:z");
290 Fr constant_term_accumulator =
Fr(0);
293 std::vector<Fr> scalars;
295 scalars.emplace_back(
Fr(1));
299 const std::vector<Fr> inverse_vanishing_evals = ShplonkVerifier::compute_inverted_gemini_denominators(
300 shplonk_evaluation_challenge, gemini_eval_challenge_powers);
305 inverse_vanishing_evals, shplonk_batching_challenge, gemini_evaluation_challenge);
308 commitments.emplace_back(hiding_polynomial_commitment);
315 Fr gemini_batching_challenge_power =
Fr(1);
318 gemini_batching_challenge_power *= gemini_batching_challenge;
324 Fr shplonk_batching_pos =
Fr{ 0 };
325 Fr shplonk_batching_neg =
Fr{ 0 };
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);
340 gemini_batching_challenge,
341 gemini_batching_challenge_power,
342 shplonk_batching_pos,
343 shplonk_batching_neg);
347 const std::vector<Fr> gemini_fold_pos_evaluations =
348 GeminiVerifier_<Curve>::compute_fold_pos_evaluations(padding_indicator_array,
350 multivariate_challenge,
351 gemini_eval_challenge_powers,
352 gemini_fold_neg_evaluations,
360 gemini_fold_neg_evaluations,
361 gemini_fold_pos_evaluations,
362 inverse_vanishing_evals,
363 shplonk_batching_challenge_powers,
366 constant_term_accumulator);
367 const Fr full_a_0_pos = gemini_fold_pos_evaluations[0];
369 Fr a_0_pos = full_a_0_pos - p_pos;
372 constant_term_accumulator += a_0_pos * inverse_vanishing_evals[0];
374 constant_term_accumulator +=
375 gemini_fold_neg_evaluations[0] * shplonk_batching_challenge * inverse_vanishing_evals[1];
385 constant_term_accumulator,
388 gemini_evaluation_challenge,
389 shplonk_batching_challenge_powers,
390 shplonk_evaluation_challenge);
393 libra_evaluations, gemini_evaluation_challenge, multivariate_challenge, libra_univariate_evaluation);
397 if (committed_sumcheck) {
400 constant_term_accumulator,
401 multivariate_challenge,
402 shplonk_batching_challenge_powers,
403 shplonk_evaluation_challenge,
404 sumcheck_round_commitments,
405 sumcheck_round_evaluations);
409 commitments.emplace_back(g1_identity);
410 scalars.emplace_back(constant_term_accumulator);
412 return { commitments, scalars, shplonk_evaluation_challenge };
460 const std::vector<Commitment>& fold_commitments,
465 std::vector<Commitment>& commitments,
466 std::vector<Fr>& scalars,
467 Fr& constant_term_accumulator)
469 const size_t virtual_log_n = gemini_neg_evaluations.size();
472 for (
size_t j = 1; j < virtual_log_n; ++j) {
474 const size_t pos_index = 2 * j;
476 const size_t neg_index = 2 * j + 1;
479 Fr scaling_factor_pos = shplonk_batching_challenge_powers[pos_index] * inverse_vanishing_evals[pos_index];
481 Fr scaling_factor_neg = shplonk_batching_challenge_powers[neg_index] * inverse_vanishing_evals[neg_index];
485 constant_term_accumulator +=
486 scaling_factor_neg * gemini_neg_evaluations[j] + scaling_factor_pos * gemini_pos_evaluations[j];
489 scalars.emplace_back(-padding_indicator_array[j] * (scaling_factor_neg + scaling_factor_pos));
491 commitments.emplace_back(
std::move(fold_commitments[j - 1]));
515 std::vector<Fr>& scalars,
522 const size_t offset = has_zk ? 2 : 1;
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];
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];
548 if (second_range_shifted_start > first_range_shifted_start) {
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));
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));
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));
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));
592 std::vector<Commitment>& commitments,
593 std::vector<Fr>& scalars,
594 Fr& constant_term_accumulator,
597 const Fr& gemini_evaluation_challenge,
598 const std::vector<Fr>& shplonk_batching_challenge_powers,
599 const Fr& shplonk_evaluation_challenge)
603 for (
size_t idx = 0; idx < libra_commitments.size(); idx++) {
604 commitments.push_back(libra_commitments[idx]);
611 denominators[0] =
Fr(1) / (shplonk_evaluation_challenge - gemini_evaluation_challenge);
614 denominators[2] = denominators[0];
615 denominators[3] = denominators[0];
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];
627 scalars.push_back(batching_scalars[0]);
628 scalars.push_back(batching_scalars[1] + batching_scalars[2]);
629 scalars.push_back(batching_scalars[3]);
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)
685 std::vector<Fr> denominators = {};
689 const size_t num_gemini_claims = 2 * multilinear_challenge.size();
694 const_denominators[0] =
Fr(1) / (shplonk_evaluation_challenge);
695 const_denominators[1] =
Fr(1) / (shplonk_evaluation_challenge -
Fr{ 1 });
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);
708 for (
auto& denominator : denominators) {
709 denominator =
Fr{ 1 } / denominator;
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)) {
720 Fr batched_scalar =
Fr(0);
721 Fr const_term_contribution =
Fr(0);
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];
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];
735 constant_term_accumulator += const_term_contribution;
736 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)
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
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 &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
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(std::span< field > coeffs) noexcept