36 template <
typename Transcript>
41 const std::shared_ptr<Transcript>& transcript,
48 const bool has_zk = (libra_polynomials[0].size() > 0);
51 const size_t virtual_log_n = multilinear_challenge.size();
54 circuit_size, polynomial_batcher, multilinear_challenge, commitment_key, transcript, has_zk);
59 const auto gemini_r = opening_claims[0].opening_pair.challenge;
66 if (!sumcheck_round_univariates.empty()) {
68 circuit_size, multilinear_challenge, sumcheck_round_univariates, sumcheck_round_evaluations);
72 commitment_key, opening_claims, transcript, libra_opening_claims, sumcheck_round_claims, virtual_log_n);
80 template <
typename Transcript>
84 const std::shared_ptr<Transcript>& transcript)
93 "Libra:concatenation_eval",
"Libra:shifted_grand_sum_eval",
"Libra:grand_sum_eval",
"Libra:quotient_eval"
96 gemini_r, gemini_r * subgroup_generator, gemini_r, gemini_r
98 for (
size_t idx = 0; idx < NUM_SMALL_IPA_EVALUATIONS; idx++) {
100 new_claim.
opening_pair.challenge = evaluation_points[idx];
102 transcript->send_to_verifier(libra_eval_labels[idx], new_claim.
opening_pair.evaluation);
103 libra_opening_claims.push_back(new_claim);
106 return libra_opening_claims;
118 const std::vector<std::array<FF, 3>>& sumcheck_round_evaluations)
124 for (
size_t idx = 0; idx < log_n; idx++) {
125 const std::vector<FF> evaluation_points = {
FF(0),
FF(1), multilinear_challenge[idx] };
129 for (
auto& eval_point : evaluation_points) {
131 new_claim.
opening_pair.evaluation = sumcheck_round_evaluations[idx][eval_idx];
132 sumcheck_round_claims.push_back(new_claim);
137 return sumcheck_round_claims;
215 template <
typename Transcript>
218 const std::vector<Fr>& multivariate_challenge,
220 const std::shared_ptr<Transcript>& transcript,
222 const std::array<Commitment, NUM_LIBRA_COMMITMENTS>& libra_commitments = {},
223 const Fr& libra_univariate_evaluation =
Fr{ 0 },
224 const std::vector<Commitment>& sumcheck_round_commitments = {},
228 const size_t virtual_log_n = multivariate_challenge.size();
230 const bool committed_sumcheck = !sumcheck_round_evaluations.empty();
232 Fr batched_evaluation =
Fr{ 0 };
235 const Fr gemini_batching_challenge = transcript->template get_challenge<Fr>(
"rho");
239 const std::vector<Commitment> fold_commitments =
243 const Fr gemini_evaluation_challenge = transcript->template get_challenge<Fr>(
"Gemini:r");
249 const std::vector<Fr> gemini_eval_challenge_powers =
254 if constexpr (HasZK) {
255 libra_evaluations[0] = transcript->template receive_from_prover<Fr>(
"Libra:concatenation_eval");
256 libra_evaluations[1] = transcript->template receive_from_prover<Fr>(
"Libra:shifted_grand_sum_eval");
257 libra_evaluations[2] = transcript->template receive_from_prover<Fr>(
"Libra:grand_sum_eval");
258 libra_evaluations[3] = transcript->template receive_from_prover<Fr>(
"Libra:quotient_eval");
263 for (
auto& eval : libra_evaluations) {
264 eval.clear_round_provenance();
271 const Fr shplonk_batching_challenge = transcript->template get_challenge<Fr>(
"Shplonk:nu");
275 const std::vector<Fr> shplonk_batching_challenge_powers = compute_shplonk_batching_challenge_powers(
276 shplonk_batching_challenge, virtual_log_n, HasZK, committed_sumcheck);
278 const auto Q_commitment = transcript->template receive_from_prover<Commitment>(
"Shplonk:Q");
282 std::vector<Commitment> commitments{ Q_commitment };
285 const Fr shplonk_evaluation_challenge = transcript->template get_challenge<Fr>(
"Shplonk:z");
291 const auto challenge_tag = shplonk_evaluation_challenge.get_origin_tag();
293 for (
auto& eval : gemini_fold_neg_evaluations) {
294 eval.set_origin_tag(challenge_tag);
299 Fr constant_term_accumulator =
Fr(0);
302 std::vector<Fr> scalars;
304 scalars.emplace_back(
Fr(1));
309 shplonk_evaluation_challenge, gemini_eval_challenge_powers);
316 inverse_vanishing_evals, shplonk_batching_challenge, gemini_evaluation_challenge);
321 commitments, scalars, batched_evaluation, gemini_batching_challenge);
326 batched_evaluation, multivariate_challenge, gemini_eval_challenge_powers, gemini_fold_neg_evaluations);
332 gemini_fold_neg_evaluations,
333 gemini_fold_pos_evaluations,
334 inverse_vanishing_evals,
335 shplonk_batching_challenge_powers,
338 constant_term_accumulator);
339 const Fr a_0_pos = gemini_fold_pos_evaluations[0];
342 constant_term_accumulator += a_0_pos * inverse_vanishing_evals[0];
344 constant_term_accumulator +=
345 gemini_fold_neg_evaluations[0] * shplonk_batching_challenge * inverse_vanishing_evals[1];
349 bool consistency_checked =
true;
352 if constexpr (HasZK) {
356 constant_term_accumulator,
359 gemini_evaluation_challenge,
360 shplonk_batching_challenge_powers,
361 shplonk_evaluation_challenge);
364 libra_evaluations, gemini_evaluation_challenge, multivariate_challenge, libra_univariate_evaluation);
369 if (committed_sumcheck) {
370 if constexpr (!HasZK) {
371 throw_or_abort(
"Shplemini: committed sumcheck requires ZK for correct nu power indexing");
375 constant_term_accumulator,
376 multivariate_challenge,
377 shplonk_batching_challenge_powers,
378 shplonk_evaluation_challenge,
379 sumcheck_round_commitments,
380 sumcheck_round_evaluations);
384 commitments.emplace_back(g1_identity);
385 scalars.emplace_back(constant_term_accumulator);
387 BatchOpeningClaim<Curve> batch_opening_claim{ commitments, scalars, shplonk_evaluation_challenge };
389 if constexpr (HasZK) {
444 std::vector<Commitment>& commitments,
445 std::vector<Fr>& scalars,
446 Fr& constant_term_accumulator)
448 const size_t virtual_log_n = gemini_neg_evaluations.size();
451 for (
size_t j = 1; j < virtual_log_n; ++j) {
453 const size_t pos_index = 2 * j;
455 const size_t neg_index = (2 * j) + 1;
458 Fr scaling_factor_pos = shplonk_batching_challenge_powers[pos_index] * inverse_vanishing_evals[pos_index];
460 Fr scaling_factor_neg = shplonk_batching_challenge_powers[neg_index] * inverse_vanishing_evals[neg_index];
464 constant_term_accumulator +=
465 scaling_factor_neg * gemini_neg_evaluations[j] + scaling_factor_pos * gemini_pos_evaluations[j];
468 scalars.emplace_back(-(scaling_factor_neg + scaling_factor_pos));
470 commitments.emplace_back(
std::move(fold_commitments[j - 1]));
485 std::vector<Fr>& scalars,
491 const size_t offset = has_zk ? 2 : 1;
493 const auto& r1 = repeated_commitments.
first;
494 const auto& r2 = repeated_commitments.
second;
496 const size_t first_duplicate_start = r1.duplicate_start +
offset;
497 const size_t second_original_start = r2.original_start +
offset;
498 const size_t second_duplicate_start = r2.duplicate_start +
offset;
501 for (
size_t i = 0; i < r1.count; i++) {
502 scalars[i + first_original_start] = scalars[i + first_original_start] + scalars[i + first_duplicate_start];
504 for (
size_t i = 0; i < r2.count; i++) {
505 scalars[i + second_original_start] =
506 scalars[i + second_original_start] + scalars[i + second_duplicate_start];
514 auto erase_range = [&](
size_t duplicate_start, [[maybe_unused]]
size_t original_start,
size_t count) {
515 for (
size_t i = 0; i < count; ++i) {
516 scalars.erase(scalars.begin() +
static_cast<std::ptrdiff_t>(duplicate_start));
517 commitments.erase(commitments.begin() +
static_cast<std::ptrdiff_t>(duplicate_start));
520 if (second_duplicate_start > first_duplicate_start) {
521 erase_range(second_duplicate_start, second_original_start, r2.count);
522 erase_range(first_duplicate_start, first_original_start, r1.count);
524 erase_range(first_duplicate_start, first_original_start, r1.count);
525 erase_range(second_duplicate_start, second_original_start, r2.count);
547 std::vector<Commitment>& commitments,
548 std::vector<Fr>& scalars,
549 Fr& constant_term_accumulator,
550 const std::array<Commitment, NUM_LIBRA_COMMITMENTS>& libra_commitments,
552 const Fr& gemini_evaluation_challenge,
553 const std::vector<Fr>& shplonk_batching_challenge_powers,
554 const Fr& shplonk_evaluation_challenge)
558 for (
size_t idx = 0; idx < libra_commitments.size(); idx++) {
559 commitments.push_back(libra_commitments[idx]);
566 denominators[0] =
Fr(1) / (shplonk_evaluation_challenge - gemini_evaluation_challenge);
569 denominators[2] = denominators[0];
570 denominators[3] = denominators[0];
574 for (
size_t idx = 0; idx < NUM_SMALL_IPA_EVALUATIONS; idx++) {
575 Fr scaling_factor = denominators[idx] * shplonk_batching_challenge_powers[2 * virtual_log_n + idx];
576 batching_scalars[idx] = -scaling_factor;
577 constant_term_accumulator += scaling_factor * libra_evaluations[idx];
581 scalars.push_back(batching_scalars[0]);
582 scalars.push_back(batching_scalars[1] + batching_scalars[2]);
583 scalars.push_back(batching_scalars[3]);
630 std::vector<Fr>& scalars,
631 Fr& constant_term_accumulator,
632 const std::vector<Fr>& multilinear_challenge,
633 const std::vector<Fr>& shplonk_batching_challenge_powers,
634 const Fr& shplonk_evaluation_challenge,
635 const std::vector<Commitment>& sumcheck_round_commitments,
636 const std::vector<std::array<Fr, 3>>& sumcheck_round_evaluations)
639 std::vector<Fr> denominators = {};
643 const size_t num_gemini_claims = 2 * multilinear_challenge.size();
648 const_denominators[0] =
Fr(1) / (shplonk_evaluation_challenge);
649 const_denominators[1] =
Fr(1) / (shplonk_evaluation_challenge -
Fr{ 1 });
653 for (
const auto& [challenge, comm] :
zip_view(multilinear_challenge, sumcheck_round_commitments)) {
654 denominators.push_back(shplonk_evaluation_challenge - challenge);
655 commitments.push_back(comm);
662 for (
auto& denominator : denominators) {
663 denominator =
Fr{ 1 } / denominator;
671 size_t power = num_gemini_claims + NUM_SMALL_IPA_EVALUATIONS;
672 for (
const auto& [eval_array, denominator] :
zip_view(sumcheck_round_evaluations, denominators)) {
674 Fr batched_scalar =
Fr(0);
675 Fr const_term_contribution =
Fr(0);
677 for (
size_t idx = 0; idx < 2; idx++) {
678 Fr current_scaling_factor = const_denominators[idx] * shplonk_batching_challenge_powers[power++];
679 batched_scalar -= current_scaling_factor;
680 const_term_contribution += current_scaling_factor * eval_array[idx];
684 Fr current_scaling_factor = denominator * shplonk_batching_challenge_powers[power++];
685 batched_scalar -= current_scaling_factor;
686 const_term_contribution += current_scaling_factor * eval_array[2];
689 constant_term_accumulator += const_term_contribution;
690 scalars.push_back(batched_scalar);
#define BB_BENCH_NAME(name)
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(const Fr &batched_evaluation, std::span< const Fr > evaluation_point, std::span< const Fr > challenge_powers, std::span< const Fr > fold_neg_evals)
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) 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 ShpleminiVerifierOutput compute_batch_opening_claim(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,...
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.
static void batch_gemini_claims_received_from_prover(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.
typename Curve::AffineElement Commitment
typename Curve::ScalarField Fr
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 and shifted polynomials in Shplemini.
void update_batch_mul_inputs_and_batched_evaluation(std::vector< Commitment > &commitments, std::vector< Fr > &scalars, Fr &batched_evaluation, const Fr &rho)
Append the commitments and scalars from each batch of claims to the Shplemini vectors which subsequen...
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...
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
Batch invert a collection of field elements using Montgomery's trick.
void throw_or_abort(std::string const &err)