77template <
class Fr>
inline std::vector<Fr>
powers_of_rho(
const Fr rho,
const size_t num_powers)
79 std::vector<Fr> rhos = {
Fr(1), rho };
80 rhos.reserve(num_powers);
81 for (
size_t j = 2; j < num_powers; j++) {
82 rhos.emplace_back(rhos[j - 1] * rho);
96 std::vector<Fr> squares = { r };
97 squares.reserve(num_squares);
98 for (
size_t j = 1; j < num_squares; j++) {
99 squares.emplace_back(squares[j - 1].sqr());
171 k_shift_magnitude % 2,
static_cast<size_t>(0),
"k must be even for the formulas herein to be valid");
186 if (groups[0].size() % 2 != 0) {
206 for (
auto& poly : polynomials_to_batch) {
208 running_scalar *= challenge;
253 running_scalar *= challenge;
269 const bool shift =
false)
273 size_t challenge_idx = 0;
277 for (
auto& poly : polynomials_to_batch) {
278 full_batched.add_scaled(poly, challenges[challenge_idx]);
285 for (
auto& poly : polynomials_to_batch) {
286 full_batched.
add_scaled(poly, challenges[challenge_idx]);
322 Fr r_inv = r_challenge.invert();
329 return { A_0_pos, A_0_neg };
347 Fr current_r_shift_pos = r_challenge;
348 Fr current_r_shift_neg = -r_challenge;
352 current_r_shift_pos *= r_challenge;
353 current_r_shift_neg *= -r_challenge;
356 return { P_pos, P_neg };
365 const bool& has_zk =
false);
370 const Fr& r_challenge,
377 const Fr& r_challenge);
379 template <
typename Transcript>
384 const std::shared_ptr<Transcript>& transcript,
385 bool has_zk =
false);
413 const size_t log_n = multilinear_challenge.size();
414 const bool has_interleaved = claim_batcher.
interleaved.has_value();
416 const Fr rho = transcript->template get_challenge<Fr>(
"rho");
418 GroupElement batched_commitment_unshifted = GroupElement::zero();
419 GroupElement batched_commitment_to_be_shifted = GroupElement::zero();
421 Fr batched_evaluation =
Fr(0);
422 Fr batching_scalar =
Fr(1);
423 for (
auto [eval, comm] :
425 batched_evaluation += eval * batching_scalar;
426 batched_commitment_unshifted += comm * batching_scalar;
427 batching_scalar *= rho;
430 for (
auto [eval, comm] :
432 batched_evaluation += eval * batching_scalar;
433 batched_commitment_to_be_shifted += comm * batching_scalar;
434 batching_scalar *= rho;
441 const Fr r = transcript->template get_challenge<Fr>(
"Gemini:r");
452 Fr r_inv = r.invert();
453 if (!batched_commitment_to_be_shifted.is_point_at_infinity()) {
454 batched_commitment_to_be_shifted = batched_commitment_to_be_shifted * r_inv;
455 C0_r_pos += batched_commitment_to_be_shifted;
456 C0_r_neg -= batched_commitment_to_be_shifted;
463 if (has_interleaved) {
465 Fr current_r_shift_pos =
Fr(1);
466 Fr current_r_shift_neg =
Fr(1);
467 std::vector<Fr> r_shifts_pos;
468 std::vector<Fr> r_shifts_neg;
469 for (
size_t i = 0; i < interleaved_group_size; ++i) {
470 r_shifts_pos.emplace_back(current_r_shift_pos);
471 r_shifts_neg.emplace_back(current_r_shift_neg);
472 current_r_shift_pos *= r;
473 current_r_shift_neg *= (-r);
476 for (
auto [group_commitments, interleaved_evaluation] :
zip_view(
480 for (
size_t i = 0; i < interleaved_group_size; ++i) {
481 C_P_pos += group_commitments[i] * batching_scalar * r_shifts_pos[i];
482 C_P_neg += group_commitments[i] * batching_scalar * r_shifts_neg[i];
484 batched_evaluation += interleaved_evaluation * batching_scalar;
485 batching_scalar *= rho;
491 if (has_interleaved) {
492 p_pos = transcript->template receive_from_prover<Fr>(
"Gemini:P_0_pos");
493 p_neg = transcript->template receive_from_prover<Fr>(
"Gemini:P_0_neg");
495 std::vector<Fr> padding_indicator_array(log_n,
Fr{ 1 });
498 std::vector<Fr> gemini_fold_pos_evaluations = compute_fold_pos_evaluations(
499 padding_indicator_array, batched_evaluation, multilinear_challenge, r_squares, evaluations, p_neg);
501 auto full_a_0_pos = gemini_fold_pos_evaluations[0];
503 fold_polynomial_opening_claims.reserve(2 * log_n + 2);
506 fold_polynomial_opening_claims.emplace_back(
OpeningClaim<Curve>{ { r, full_a_0_pos - p_pos }, C0_r_pos });
508 fold_polynomial_opening_claims.emplace_back(
OpeningClaim<Curve>{ { -r, evaluations[0] }, C0_r_neg });
509 for (
size_t l = 0; l < log_n - 1; ++l) {
511 fold_polynomial_opening_claims.emplace_back(
512 OpeningClaim<Curve>{ { r_squares[l + 1], gemini_fold_pos_evaluations[l + 1] }, commitments[l] });
514 fold_polynomial_opening_claims.emplace_back(
517 if (has_interleaved) {
519 Fr r_pow = r.pow(interleaved_group_size);
520 fold_polynomial_opening_claims.emplace_back(
OpeningClaim<Curve>{ { r_pow, p_pos }, C_P_pos });
521 fold_polynomial_opening_claims.emplace_back(
OpeningClaim<Curve>{ { r_pow, p_neg }, C_P_neg });
524 return fold_polynomial_opening_claims;
535 static std::vector<Commitment>
get_fold_commitments([[maybe_unused]]
const size_t virtual_log_n,
auto& transcript)
537 std::vector<Commitment> fold_commitments;
538 fold_commitments.reserve(virtual_log_n - 1);
539 for (
size_t i = 0; i < virtual_log_n - 1; ++i) {
541 transcript->template receive_from_prover<Commitment>(
"Gemini:FOLD_" +
std::to_string(i + 1));
542 fold_commitments.emplace_back(commitment);
544 return fold_commitments;
558 std::vector<Fr> gemini_evaluations;
559 gemini_evaluations.reserve(virtual_log_n);
561 for (
size_t i = 1; i <= virtual_log_n; ++i) {
562 const Fr evaluation = transcript->template receive_from_prover<Fr>(
"Gemini:a_" +
std::to_string(i));
563 gemini_evaluations.emplace_back(evaluation);
565 return gemini_evaluations;
602 static std::vector<Fr> compute_fold_pos_evaluations(
std::span<const Fr> padding_indicator_array,
603 const Fr& batched_evaluation,
609 const size_t virtual_log_n = evaluation_point.size();
611 std::vector<Fr> evals(fold_neg_evals.begin(), fold_neg_evals.end());
613 Fr eval_pos_prev = batched_evaluation;
617 zero.convert_constant_to_fixed_witness(fold_neg_evals[0].get_context());
620 std::vector<Fr> fold_pos_evaluations;
621 fold_pos_evaluations.reserve(virtual_log_n);
626 for (
size_t l = virtual_log_n; l != 0; --l) {
628 const Fr& challenge_power = challenge_powers[l - 1];
630 const Fr& u = evaluation_point[l - 1];
631 const Fr& eval_neg = evals[l - 1];
634 Fr eval_pos = ((challenge_power * eval_pos_prev * 2) - eval_neg * (challenge_power * (
Fr(1) - u) - u));
636 eval_pos *= (challenge_power * (
Fr(1) - u) + u).
invert();
641 padding_indicator_array[l - 1] * eval_pos + (
Fr{ 1 } - padding_indicator_array[l - 1]) * eval_pos_prev;
644 fold_pos_evaluations.emplace_back(padding_indicator_array[l - 1] * eval_pos_prev);
647 std::reverse(fold_pos_evaluations.begin(), fold_pos_evaluations.end());
649 return fold_pos_evaluations;
#define BB_ASSERT_EQ(actual, expected,...)
#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...
std::pair< Polynomial, Polynomial > compute_partially_evaluated_interleaved_polynomial(const Fr &r_challenge)
Compute the partially evaluated polynomials P₊(X, r) and P₋(X, -r)
void set_to_be_shifted_by_one(RefVector< Polynomial > polynomials)
bool has_random_polynomial
bool batched_unshifted_initialized
bool has_to_be_shifted_by_one() const
void set_interleaved(RefVector< Polynomial > results, std::vector< RefVector< Polynomial > > groups)
void set_random_polynomial(Polynomial &&random)
RefVector< Polynomial > interleaved
std::vector< RefVector< Polynomial > > groups_to_be_interleaved
Polynomial batched_to_be_shifted_by_k
bool has_to_be_shifted_by_k() const
Polynomial random_polynomial
RefVector< Polynomial > to_be_shifted_by_k
void set_to_be_shifted_by_k(RefVector< Polynomial > polynomials, const size_t shift_magnitude)
Polynomial compute_batched(const Fr &challenge, Fr &running_scalar)
Compute batched polynomial A₀ = F + G/X as the linear combination of all polynomials to be opened.
void set_unshifted(RefVector< Polynomial > polynomials)
Polynomial batched_interleaved
std::vector< Polynomial > batched_group
Polynomial batched_unshifted
static Polynomial compute_batched(RefArray< Polynomial, N > &polynomials_to_batch, const size_t full_batched_size, const std::array< Fr, N > &challenges, const bool shift=false)
Compute batched polynomial.
RefVector< Polynomial > to_be_shifted_by_one
std::pair< Polynomial, Polynomial > compute_partially_evaluated_batch_polynomials(const Fr &r_challenge)
Compute partially evaluated batched polynomials A₀(X, r) = A₀₊ = F + G/r, A₀(X, -r) = A₀₋ = F - G/r.
bool has_interleaved() const
RefVector< Polynomial > unshifted
bool has_unshifted() const
Polynomial batched_to_be_shifted_by_one
PolynomialBatcher(const size_t full_batched_size)
bb::Polynomial< Fr > Polynomial
static std::vector< Claim > construct_univariate_opening_claims(const size_t log_n, Polynomial &&A_0_pos, Polynomial &&A_0_neg, std::vector< Polynomial > &&fold_polynomials, const Fr &r_challenge)
Computes/aggragates d+1 univariate polynomial opening claims of the form {polynomial,...
typename Curve::ScalarField Fr
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::pair< Polynomial, Polynomial > compute_partially_evaluated_batch_polynomials(const size_t log_n, PolynomialBatcher &polynomial_batcher, const Fr &r_challenge, const std::vector< Polynomial > &batched_groups_to_be_concatenated={})
typename Curve::AffineElement Commitment
static std::vector< Polynomial > compute_fold_polynomials(const size_t log_n, std::span< const Fr > multilinear_challenge, const Polynomial &A_0, const bool &has_zk=false)
Computes d-1 fold polynomials Fold_i, i = 1, ..., d-1.
static std::vector< OpeningClaim< Curve > > reduce_verification(std::span< Fr > multilinear_challenge, ClaimBatcher &claim_batcher, auto &transcript)
Returns univariate opening claims for the Fold polynomials to be checked later.
typename Curve::ScalarField Fr
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...
typename Curve::Element GroupElement
typename Curve::AffineElement Commitment
Unverified claim (C,r,v) for some witness polynomial p(X) such that.
Structured polynomial class that represents the coefficients 'a' of a_0 + a_1 x .....
Polynomial shifted() const
Returns a Polynomial the left-shift of self.
Polynomial right_shifted(const size_t magnitude) const
Returns a Polynomial equal to the right-shift-by-magnitude of self.
void add_scaled(PolynomialSpan< const Fr > other, Fr scaling_factor) &
adds the polynomial q(X) 'other', multiplied by a scaling factor.
static Polynomial shiftable(size_t virtual_size)
Utility to create a shiftable polynomial of given virtual size.
Polynomial p and an opening pair (r,v) such that p(r) = v.
A template class for a reference array. Behaves as if std::array<T&, N> was possible.
A template class for a reference vector. Behaves as if std::vector<T&> was possible.
typename Group::element Element
static constexpr bool is_stdlib_type
typename Group::affine_element AffineElement
std::vector< Fr > powers_of_evaluation_challenge(const Fr r, const size_t num_squares)
Compute squares of folding challenge r.
std::vector< Fr > powers_of_rho(const Fr rho, const size_t num_powers)
Compute powers of challenge ρ
Entry point for Barretenberg command-line interface.
void parallel_for(size_t num_iterations, const std::function< void(size_t)> &func)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::string to_string(bb::avm2::ValueTag tag)
RefVector< Commitment > commitments
RefVector< Fr > evaluations
RefVector< Fr > evaluations
std::vector< RefVector< Commitment > > commitments_groups
Logic to support batching opening claims for unshifted and shifted polynomials in Shplemini.
uint32_t get_groups_to_be_interleaved_size()
InterleavedBatch get_interleaved()
std::optional< InterleavedBatch > interleaved
constexpr field invert() const noexcept
void throw_or_abort(std::string const &err)