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) {
414 output.consistency_checked = consistency_checked;
464 const std::vector<Commitment>& fold_commitments,
469 std::vector<Commitment>& commitments,
470 std::vector<Fr>& scalars,
471 Fr& constant_term_accumulator)
473 const size_t virtual_log_n = gemini_neg_evaluations.size();
476 for (
size_t j = 1; j < virtual_log_n; ++j) {
478 const size_t pos_index = 2 * j;
480 const size_t neg_index = (2 * j) + 1;
483 Fr scaling_factor_pos = shplonk_batching_challenge_powers[pos_index] * inverse_vanishing_evals[pos_index];
485 Fr scaling_factor_neg = shplonk_batching_challenge_powers[neg_index] * inverse_vanishing_evals[neg_index];
489 constant_term_accumulator +=
490 scaling_factor_neg * gemini_neg_evaluations[j] + scaling_factor_pos * gemini_pos_evaluations[j];
493 scalars.emplace_back(-padding_indicator_array[j] * (scaling_factor_neg + scaling_factor_pos));
495 commitments.emplace_back(
std::move(fold_commitments[j - 1]));
519 std::vector<Fr>& scalars,
526 const size_t offset = has_zk ? 2 : 1;
538 for (
size_t i = 0; i < first_range_size; i++) {
539 size_t idx_to_be_shifted = i + first_range_to_be_shifted_start;
540 size_t idx_shifted = i + first_range_shifted_start;
541 scalars[idx_to_be_shifted] = scalars[idx_to_be_shifted] + scalars[idx_shifted];
546 for (
size_t i = 0; i < second_range_size; i++) {
547 size_t idx_to_be_shifted = i + second_range_to_be_shifted_start;
548 size_t idx_shifted = i + second_range_shifted_start;
549 scalars[idx_to_be_shifted] = scalars[idx_to_be_shifted] + scalars[idx_shifted];
552 if (second_range_shifted_start > first_range_shifted_start) {
554 for (
size_t i = 0; i < second_range_size; ++i) {
555 scalars.erase(scalars.begin() +
static_cast<std::ptrdiff_t>(second_range_shifted_start));
556 commitments.erase(commitments.begin() +
static_cast<std::ptrdiff_t>(second_range_shifted_start));
560 for (
size_t i = 0; i < first_range_size; ++i) {
561 scalars.erase(scalars.begin() +
static_cast<std::ptrdiff_t>(first_range_shifted_start));
562 commitments.erase(commitments.begin() +
static_cast<std::ptrdiff_t>(first_range_shifted_start));
566 for (
size_t i = 0; i < first_range_size; ++i) {
567 scalars.erase(scalars.begin() +
static_cast<std::ptrdiff_t>(first_range_shifted_start));
568 commitments.erase(commitments.begin() +
static_cast<std::ptrdiff_t>(first_range_shifted_start));
571 for (
size_t i = 0; i < second_range_size; ++i) {
572 scalars.erase(scalars.begin() +
static_cast<std::ptrdiff_t>(second_range_shifted_start));
573 commitments.erase(commitments.begin() +
static_cast<std::ptrdiff_t>(second_range_shifted_start));
596 std::vector<Commitment>& commitments,
597 std::vector<Fr>& scalars,
598 Fr& constant_term_accumulator,
601 const Fr& gemini_evaluation_challenge,
602 const std::vector<Fr>& shplonk_batching_challenge_powers,
603 const Fr& shplonk_evaluation_challenge)
607 for (
size_t idx = 0; idx < libra_commitments.size(); idx++) {
608 commitments.push_back(libra_commitments[idx]);
615 denominators[0] =
Fr(1) / (shplonk_evaluation_challenge - gemini_evaluation_challenge);
618 denominators[2] = denominators[0];
619 denominators[3] = denominators[0];
623 for (
size_t idx = 0; idx < NUM_SMALL_IPA_EVALUATIONS; idx++) {
624 Fr scaling_factor = denominators[idx] *
625 shplonk_batching_challenge_powers[2 * virtual_log_n + NUM_INTERLEAVING_CLAIMS + idx];
626 batching_scalars[idx] = -scaling_factor;
627 constant_term_accumulator += scaling_factor * libra_evaluations[idx];
631 scalars.push_back(batching_scalars[0]);
632 scalars.push_back(batching_scalars[1] + batching_scalars[2]);
633 scalars.push_back(batching_scalars[3]);
680 std::vector<Fr>& scalars,
681 Fr& constant_term_accumulator,
682 const std::vector<Fr>& multilinear_challenge,
683 const std::vector<Fr>& shplonk_batching_challenge_powers,
684 const Fr& shplonk_evaluation_challenge,
685 const std::vector<Commitment>& sumcheck_round_commitments,
686 const std::vector<std::array<Fr, 3>>& sumcheck_round_evaluations)
689 std::vector<Fr> denominators = {};
693 const size_t num_gemini_claims = 2 * multilinear_challenge.size();
698 const_denominators[0] =
Fr(1) / (shplonk_evaluation_challenge);
699 const_denominators[1] =
Fr(1) / (shplonk_evaluation_challenge -
Fr{ 1 });
703 for (
const auto& [challenge, comm] :
zip_view(multilinear_challenge, sumcheck_round_commitments)) {
704 denominators.push_back(shplonk_evaluation_challenge - challenge);
705 commitments.push_back(comm);
712 for (
auto& denominator : denominators) {
713 denominator =
Fr{ 1 } / denominator;
721 size_t power = num_gemini_claims + NUM_INTERLEAVING_CLAIMS + NUM_SMALL_IPA_EVALUATIONS;
722 for (
const auto& [eval_array, denominator] :
zip_view(sumcheck_round_evaluations, denominators)) {
724 Fr batched_scalar =
Fr(0);
725 Fr const_term_contribution =
Fr(0);
727 for (
size_t idx = 0; idx < 2; idx++) {
728 Fr current_scaling_factor = const_denominators[idx] * shplonk_batching_challenge_powers[power++];
729 batched_scalar -= current_scaling_factor;
730 const_term_contribution += current_scaling_factor * eval_array[idx];
734 Fr current_scaling_factor = denominator * shplonk_batching_challenge_powers[power++];
735 batched_scalar -= current_scaling_factor;
736 const_term_contribution += current_scaling_factor * eval_array[2];
739 constant_term_accumulator += const_term_contribution;
740 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