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;
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;
213 template <
typename Transcript>
217 const std::vector<Fr>& multivariate_challenge,
219 const std::shared_ptr<Transcript>& transcript,
222 const Fr& libra_univariate_evaluation =
Fr{ 0 },
223 const std::vector<Commitment>& sumcheck_round_commitments = {},
227 const size_t virtual_log_n = multivariate_challenge.size();
229 const bool committed_sumcheck = !sumcheck_round_evaluations.empty();
231 Fr batched_evaluation =
Fr{ 0 };
234 const Fr gemini_batching_challenge = transcript->template get_challenge<Fr>(
"rho");
238 const std::vector<Commitment> fold_commitments =
242 const Fr gemini_evaluation_challenge = transcript->template get_challenge<Fr>(
"Gemini:r");
245 const std::vector<Fr> gemini_fold_neg_evaluations =
252 p_pos = transcript->template receive_from_prover<Fr>(
"Gemini:P_pos");
253 p_neg = transcript->template receive_from_prover<Fr>(
"Gemini:P_neg");
257 const std::vector<Fr> gemini_eval_challenge_powers =
262 if constexpr (HasZK) {
263 libra_evaluations[0] = transcript->template receive_from_prover<Fr>(
"Libra:concatenation_eval");
264 libra_evaluations[1] = transcript->template receive_from_prover<Fr>(
"Libra:shifted_grand_sum_eval");
265 libra_evaluations[2] = transcript->template receive_from_prover<Fr>(
"Libra:grand_sum_eval");
266 libra_evaluations[3] = transcript->template receive_from_prover<Fr>(
"Libra:quotient_eval");
271 for (
auto& eval : libra_evaluations) {
272 eval.clear_round_provenance();
279 const Fr shplonk_batching_challenge = transcript->template get_challenge<Fr>(
"Shplonk:nu");
283 const std::vector<Fr> shplonk_batching_challenge_powers = compute_shplonk_batching_challenge_powers(
284 shplonk_batching_challenge, virtual_log_n, HasZK, committed_sumcheck);
286 const auto Q_commitment = transcript->template receive_from_prover<Commitment>(
"Shplonk:Q");
290 std::vector<Commitment> commitments{ Q_commitment };
293 const Fr shplonk_evaluation_challenge = transcript->template get_challenge<Fr>(
"Shplonk:z");
296 Fr constant_term_accumulator =
Fr(0);
299 std::vector<Fr> scalars;
301 scalars.emplace_back(
Fr(1));
306 shplonk_evaluation_challenge, gemini_eval_challenge_powers);
313 inverse_vanishing_evals, shplonk_batching_challenge, gemini_evaluation_challenge);
321 Fr shplonk_interleaving_batching_pos =
Fr{ 0 };
322 Fr shplonk_interleaving_batching_neg =
Fr{ 0 };
327 const size_t interleaved_pos_index = 2 * virtual_log_n;
328 const size_t interleaved_neg_index = interleaved_pos_index + 1;
329 shplonk_interleaving_batching_pos = shplonk_batching_challenge_powers[interleaved_pos_index];
330 shplonk_interleaving_batching_neg = shplonk_batching_challenge_powers[interleaved_neg_index];
331 constant_term_accumulator +=
333 (p_pos * shplonk_interleaving_batching_pos + p_neg * shplonk_interleaving_batching_neg);
339 gemini_batching_challenge,
340 shplonk_interleaving_batching_pos,
341 shplonk_interleaving_batching_neg);
345 const std::vector<Fr> gemini_fold_pos_evaluations =
348 multivariate_challenge,
349 gemini_eval_challenge_powers,
350 gemini_fold_neg_evaluations,
358 gemini_fold_neg_evaluations,
359 gemini_fold_pos_evaluations,
360 inverse_vanishing_evals,
361 shplonk_batching_challenge_powers,
364 constant_term_accumulator);
365 const Fr full_a_0_pos = gemini_fold_pos_evaluations[0];
367 Fr a_0_pos = full_a_0_pos - p_pos;
370 constant_term_accumulator += a_0_pos * inverse_vanishing_evals[0];
372 constant_term_accumulator +=
373 gemini_fold_neg_evaluations[0] * shplonk_batching_challenge * inverse_vanishing_evals[1];
377 bool consistency_checked =
true;
380 if constexpr (HasZK) {
384 constant_term_accumulator,
387 gemini_evaluation_challenge,
388 shplonk_batching_challenge_powers,
389 shplonk_evaluation_challenge);
392 libra_evaluations, gemini_evaluation_challenge, multivariate_challenge, libra_univariate_evaluation);
396 if (committed_sumcheck) {
399 constant_term_accumulator,
400 multivariate_challenge,
401 shplonk_batching_challenge_powers,
402 shplonk_evaluation_challenge,
403 sumcheck_round_commitments,
404 sumcheck_round_evaluations);
408 commitments.emplace_back(g1_identity);
409 scalars.emplace_back(constant_term_accumulator);
411 BatchOpeningClaim<Curve> batch_opening_claim{ commitments, scalars, shplonk_evaluation_challenge };
413 if constexpr (HasZK) {
467 const std::vector<Commitment>& fold_commitments,
472 std::vector<Commitment>& commitments,
473 std::vector<Fr>& scalars,
474 Fr& constant_term_accumulator)
476 const size_t virtual_log_n = gemini_neg_evaluations.size();
479 for (
size_t j = 1; j < virtual_log_n; ++j) {
481 const size_t pos_index = 2 * j;
483 const size_t neg_index = (2 * j) + 1;
486 Fr scaling_factor_pos = shplonk_batching_challenge_powers[pos_index] * inverse_vanishing_evals[pos_index];
488 Fr scaling_factor_neg = shplonk_batching_challenge_powers[neg_index] * inverse_vanishing_evals[neg_index];
492 constant_term_accumulator +=
493 scaling_factor_neg * gemini_neg_evaluations[j] + scaling_factor_pos * gemini_pos_evaluations[j];
496 scalars.emplace_back(-padding_indicator_array[j] * (scaling_factor_neg + scaling_factor_pos));
498 commitments.emplace_back(
std::move(fold_commitments[j - 1]));
522 std::vector<Fr>& scalars,
529 const size_t offset = has_zk ? 2 : 1;
541 for (
size_t i = 0; i < first_range_size; i++) {
542 size_t idx_to_be_shifted = i + first_range_to_be_shifted_start;
543 size_t idx_shifted = i + first_range_shifted_start;
544 scalars[idx_to_be_shifted] = scalars[idx_to_be_shifted] + scalars[idx_shifted];
549 for (
size_t i = 0; i < second_range_size; i++) {
550 size_t idx_to_be_shifted = i + second_range_to_be_shifted_start;
551 size_t idx_shifted = i + second_range_shifted_start;
552 scalars[idx_to_be_shifted] = scalars[idx_to_be_shifted] + scalars[idx_shifted];
555 if (second_range_shifted_start > first_range_shifted_start) {
557 for (
size_t i = 0; i < second_range_size; ++i) {
558 scalars.erase(scalars.begin() +
static_cast<std::ptrdiff_t>(second_range_shifted_start));
559 commitments.erase(commitments.begin() +
static_cast<std::ptrdiff_t>(second_range_shifted_start));
563 for (
size_t i = 0; i < first_range_size; ++i) {
564 scalars.erase(scalars.begin() +
static_cast<std::ptrdiff_t>(first_range_shifted_start));
565 commitments.erase(commitments.begin() +
static_cast<std::ptrdiff_t>(first_range_shifted_start));
569 for (
size_t i = 0; i < first_range_size; ++i) {
570 scalars.erase(scalars.begin() +
static_cast<std::ptrdiff_t>(first_range_shifted_start));
571 commitments.erase(commitments.begin() +
static_cast<std::ptrdiff_t>(first_range_shifted_start));
574 for (
size_t i = 0; i < second_range_size; ++i) {
575 scalars.erase(scalars.begin() +
static_cast<std::ptrdiff_t>(second_range_shifted_start));
576 commitments.erase(commitments.begin() +
static_cast<std::ptrdiff_t>(second_range_shifted_start));
599 std::vector<Commitment>& commitments,
600 std::vector<Fr>& scalars,
601 Fr& constant_term_accumulator,
604 const Fr& gemini_evaluation_challenge,
605 const std::vector<Fr>& shplonk_batching_challenge_powers,
606 const Fr& shplonk_evaluation_challenge)
610 for (
size_t idx = 0; idx < libra_commitments.size(); idx++) {
611 commitments.push_back(libra_commitments[idx]);
618 denominators[0] =
Fr(1) / (shplonk_evaluation_challenge - gemini_evaluation_challenge);
621 denominators[2] = denominators[0];
622 denominators[3] = denominators[0];
626 for (
size_t idx = 0; idx < NUM_SMALL_IPA_EVALUATIONS; idx++) {
627 Fr scaling_factor = denominators[idx] *
628 shplonk_batching_challenge_powers[2 * virtual_log_n + NUM_INTERLEAVING_CLAIMS + idx];
629 batching_scalars[idx] = -scaling_factor;
630 constant_term_accumulator += scaling_factor * libra_evaluations[idx];
634 scalars.push_back(batching_scalars[0]);
635 scalars.push_back(batching_scalars[1] + batching_scalars[2]);
636 scalars.push_back(batching_scalars[3]);
683 std::vector<Fr>& scalars,
684 Fr& constant_term_accumulator,
685 const std::vector<Fr>& multilinear_challenge,
686 const std::vector<Fr>& shplonk_batching_challenge_powers,
687 const Fr& shplonk_evaluation_challenge,
688 const std::vector<Commitment>& sumcheck_round_commitments,
689 const std::vector<std::array<Fr, 3>>& sumcheck_round_evaluations)
692 std::vector<Fr> denominators = {};
696 const size_t num_gemini_claims = 2 * multilinear_challenge.size();
701 const_denominators[0] =
Fr(1) / (shplonk_evaluation_challenge);
702 const_denominators[1] =
Fr(1) / (shplonk_evaluation_challenge -
Fr{ 1 });
706 for (
const auto& [challenge, comm] :
zip_view(multilinear_challenge, sumcheck_round_commitments)) {
707 denominators.push_back(shplonk_evaluation_challenge - challenge);
708 commitments.push_back(comm);
715 for (
auto& denominator : denominators) {
716 denominator =
Fr{ 1 } / denominator;
724 size_t power = num_gemini_claims + NUM_INTERLEAVING_CLAIMS + NUM_SMALL_IPA_EVALUATIONS;
725 for (
const auto& [eval_array, denominator] :
zip_view(sumcheck_round_evaluations, denominators)) {
727 Fr batched_scalar =
Fr(0);
728 Fr const_term_contribution =
Fr(0);
730 for (
size_t idx = 0; idx < 2; idx++) {
731 Fr current_scaling_factor = const_denominators[idx] * shplonk_batching_challenge_powers[power++];
732 batched_scalar -= current_scaling_factor;
733 const_term_contribution += current_scaling_factor * eval_array[idx];
737 Fr current_scaling_factor = denominator * shplonk_batching_challenge_powers[power++];
738 batched_scalar -= current_scaling_factor;
739 const_term_contribution += current_scaling_factor * eval_array[2];
742 constant_term_accumulator += const_term_contribution;
743 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(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)
Gemini Verifier utility methods used by ShpleminiVerifier.
static std::vector< Fr > compute_fold_pos_evaluations(std::span< const Fr > padding_indicator_array, const Fr &batched_evaluation, std::span< const Fr > evaluation_point, std::span< const Fr > challenge_powers, std::span< const Fr > fold_neg_evals, Fr p_neg=Fr(0))
Compute .
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(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={})
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(size_t 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,...
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 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::ScalarField Fr
static ShpleminiVerifierOutput 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 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={})
This method receives commitments to all prover polynomials, their claimed evaluations,...
typename Curve::Element GroupElement
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...
ShpleminiVerifierOutput_< Curve, HasZK > ShpleminiVerifierOutput
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 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 std::vector< Fr > compute_inverted_gemini_denominators(const Fr &shplonk_eval_challenge, const std::vector< Fr > &gemini_eval_challenge_powers)
Computes .
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...
Representation of the Grumpkin Verifier Commitment Key inside a bn254 circuit.
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, shifted and interleaved polynomials in Shplem...
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
BatchOpeningClaim< Curve > batch_opening_claim
An efficient verifier for the evaluation proofs of multilinear polynomials and their shifts.
BatchOpeningClaim< Curve > batch_opening_claim
static void batch_invert(C &coeffs) noexcept