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,
221 const std::array<Commitment, NUM_LIBRA_COMMITMENTS>& libra_commitments = {},
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 =
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 : const_cast<
std::vector<
Fr>&>(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);
325 const std::vector<Fr> gemini_fold_pos_evaluations =
328 multivariate_challenge,
329 gemini_eval_challenge_powers,
330 gemini_fold_neg_evaluations);
337 gemini_fold_neg_evaluations,
338 gemini_fold_pos_evaluations,
339 inverse_vanishing_evals,
340 shplonk_batching_challenge_powers,
343 constant_term_accumulator);
344 const Fr a_0_pos = gemini_fold_pos_evaluations[0];
347 constant_term_accumulator += a_0_pos * inverse_vanishing_evals[0];
349 constant_term_accumulator +=
350 gemini_fold_neg_evaluations[0] * shplonk_batching_challenge * inverse_vanishing_evals[1];
354 bool consistency_checked =
true;
357 if constexpr (HasZK) {
361 constant_term_accumulator,
364 gemini_evaluation_challenge,
365 shplonk_batching_challenge_powers,
366 shplonk_evaluation_challenge);
369 libra_evaluations, gemini_evaluation_challenge, multivariate_challenge, libra_univariate_evaluation);
373 if (committed_sumcheck) {
376 constant_term_accumulator,
377 multivariate_challenge,
378 shplonk_batching_challenge_powers,
379 shplonk_evaluation_challenge,
380 sumcheck_round_commitments,
381 sumcheck_round_evaluations);
385 commitments.emplace_back(g1_identity);
386 scalars.emplace_back(constant_term_accumulator);
388 BatchOpeningClaim<Curve> batch_opening_claim{ commitments, scalars, shplonk_evaluation_challenge };
390 if constexpr (HasZK) {
444 const std::vector<Commitment>& fold_commitments,
449 std::vector<Commitment>& commitments,
450 std::vector<Fr>& scalars,
451 Fr& constant_term_accumulator)
453 const size_t virtual_log_n = gemini_neg_evaluations.size();
456 for (
size_t j = 1; j < virtual_log_n; ++j) {
458 const size_t pos_index = 2 * j;
460 const size_t neg_index = (2 * j) + 1;
463 Fr scaling_factor_pos = shplonk_batching_challenge_powers[pos_index] * inverse_vanishing_evals[pos_index];
465 Fr scaling_factor_neg = shplonk_batching_challenge_powers[neg_index] * inverse_vanishing_evals[neg_index];
469 constant_term_accumulator +=
470 scaling_factor_neg * gemini_neg_evaluations[j] + scaling_factor_pos * gemini_pos_evaluations[j];
473 scalars.emplace_back(-padding_indicator_array[j] * (scaling_factor_neg + scaling_factor_pos));
475 commitments.emplace_back(
std::move(fold_commitments[j - 1]));
490 std::vector<Fr>& scalars,
496 const size_t offset = has_zk ? 2 : 1;
498 const auto& r1 = repeated_commitments.
first;
499 const auto& r2 = repeated_commitments.
second;
501 const size_t first_duplicate_start = r1.duplicate_start +
offset;
502 const size_t second_original_start = r2.original_start +
offset;
503 const size_t second_duplicate_start = r2.duplicate_start +
offset;
506 for (
size_t i = 0; i < r1.count; i++) {
507 scalars[i + first_original_start] = scalars[i + first_original_start] + scalars[i + first_duplicate_start];
509 for (
size_t i = 0; i < r2.count; i++) {
510 scalars[i + second_original_start] =
511 scalars[i + second_original_start] + scalars[i + second_duplicate_start];
515 auto erase_range = [&](
size_t start,
size_t count) {
516 for (
size_t i = 0; i < count; ++i) {
517 scalars.erase(scalars.begin() +
static_cast<std::ptrdiff_t>(start));
518 commitments.erase(commitments.begin() +
static_cast<std::ptrdiff_t>(start));
521 if (second_duplicate_start > first_duplicate_start) {
522 erase_range(second_duplicate_start, r2.count);
523 erase_range(first_duplicate_start, r1.count);
525 erase_range(first_duplicate_start, r1.count);
526 erase_range(second_duplicate_start, r2.count);
548 std::vector<Commitment>& commitments,
549 std::vector<Fr>& scalars,
550 Fr& constant_term_accumulator,
551 const std::array<Commitment, NUM_LIBRA_COMMITMENTS>& libra_commitments,
553 const Fr& gemini_evaluation_challenge,
554 const std::vector<Fr>& shplonk_batching_challenge_powers,
555 const Fr& shplonk_evaluation_challenge)
559 for (
size_t idx = 0; idx < libra_commitments.size(); idx++) {
560 commitments.push_back(libra_commitments[idx]);
567 denominators[0] =
Fr(1) / (shplonk_evaluation_challenge - gemini_evaluation_challenge);
570 denominators[2] = denominators[0];
571 denominators[3] = denominators[0];
575 for (
size_t idx = 0; idx < NUM_SMALL_IPA_EVALUATIONS; idx++) {
576 Fr scaling_factor = denominators[idx] * shplonk_batching_challenge_powers[2 * virtual_log_n + idx];
577 batching_scalars[idx] = -scaling_factor;
578 constant_term_accumulator += scaling_factor * libra_evaluations[idx];
582 scalars.push_back(batching_scalars[0]);
583 scalars.push_back(batching_scalars[1] + batching_scalars[2]);
584 scalars.push_back(batching_scalars[3]);
631 std::vector<Fr>& scalars,
632 Fr& constant_term_accumulator,
633 const std::vector<Fr>& multilinear_challenge,
634 const std::vector<Fr>& shplonk_batching_challenge_powers,
635 const Fr& shplonk_evaluation_challenge,
636 const std::vector<Commitment>& sumcheck_round_commitments,
637 const std::vector<std::array<Fr, 3>>& sumcheck_round_evaluations)
640 std::vector<Fr> denominators = {};
644 const size_t num_gemini_claims = 2 * multilinear_challenge.size();
649 const_denominators[0] =
Fr(1) / (shplonk_evaluation_challenge);
650 const_denominators[1] =
Fr(1) / (shplonk_evaluation_challenge -
Fr{ 1 });
654 for (
const auto& [challenge, comm] :
zip_view(multilinear_challenge, sumcheck_round_commitments)) {
655 denominators.push_back(shplonk_evaluation_challenge - challenge);
656 commitments.push_back(comm);
663 for (
auto& denominator : denominators) {
664 denominator =
Fr{ 1 } / denominator;
672 size_t power = num_gemini_claims + NUM_SMALL_IPA_EVALUATIONS;
673 for (
const auto& [eval_array, denominator] :
zip_view(sumcheck_round_evaluations, denominators)) {
675 Fr batched_scalar =
Fr(0);
676 Fr const_term_contribution =
Fr(0);
678 for (
size_t idx = 0; idx < 2; idx++) {
679 Fr current_scaling_factor = const_denominators[idx] * shplonk_batching_challenge_powers[power++];
680 batched_scalar -= current_scaling_factor;
681 const_term_contribution += current_scaling_factor * eval_array[idx];
685 Fr current_scaling_factor = denominator * shplonk_batching_challenge_powers[power++];
686 batched_scalar -= current_scaling_factor;
687 const_term_contribution += current_scaling_factor * eval_array[2];
690 constant_term_accumulator += const_term_contribution;
691 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)
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 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 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.