50template <
typename Curve>
51template <
typename Transcript>
57 const std::shared_ptr<Transcript>& transcript,
62 const size_t virtual_log_n = multilinear_challenge.size();
66 const Fr rho = transcript->template get_challenge<Fr>(
"rho");
76 for (
size_t l = 0; l < virtual_log_n - 1; l++) {
78 transcript->send_to_verifier(
label, commitment_key.
commit(fold_polynomials[l]));
80 const Fr r_challenge = transcript->template get_challenge<Fr>(
"Gemini:r");
82 const bool gemini_challenge_in_small_subgroup = (has_zk) && (r_challenge.pow(
Curve::SUBGROUP_SIZE) ==
Fr(1));
87 if (gemini_challenge_in_small_subgroup) {
88 throw_or_abort(
"Gemini evaluation challenge is in the SmallSubgroup.");
97 for (
size_t l = 1; l <= virtual_log_n; l++) {
99 transcript->send_to_verifier(
label, claims[l].opening_pair.evaluation);
112template <
typename Curve>
117 BB_ASSERT_GTE(log_n,
size_t(2),
"Gemini folding requires at least 4-element polynomials");
118 const size_t virtual_log_n = multilinear_challenge.size();
121 constexpr size_t fold_iteration_cost =
127 size_t actual_size =
std::max(A_0.
end_index(),
static_cast<size_t>(NUM_DISABLED_ROWS_IN_SUMCHECK));
131 fold_polynomials.reserve(virtual_log_n - 1);
132 for (
size_t l = 0; l < log_n - 1; ++l) {
133 const size_t fold_size = (actual_size + 1) / 2;
136 fold_polynomials.emplace_back(
Polynomial(fold_size));
137 actual_size = fold_size;
144 for (
size_t l = 0; l < log_n - 1; ++l) {
145 const size_t fold_size = (actual_size + 1) / 2;
146 const size_t num_pairs = actual_size / 2;
149 const Fr u_l = l < virtual_log_n ? multilinear_challenge[l] :
Fr(0);
160 auto chunk_range = chunk.
range(num_pairs);
161 if (chunk_range.empty()) {
164 const size_t lo = *chunk_range.begin();
165 const size_t hi = lo + chunk_range.size();
168 fold_iteration_cost);
170 if (actual_size & 1) {
171 A_l_fold.
at(num_pairs) = source[actual_size - 1] * (
Fr(1) - u_l);
175 actual_size = fold_size;
182 const auto& last = fold_polynomials.back();
183 const Fr u_last = (log_n - 1) < virtual_log_n ? multilinear_challenge[log_n - 1] :
Fr(0);
184 const Fr final_eval = last.at(0) + u_last * (last.at(1) - last.at(0));
186 const_fold.at(0) = final_eval;
187 fold_polynomials.emplace_back(
std::move(const_fold));
191 for (
size_t k = log_n; k < virtual_log_n - 1; ++k) {
192 tail *= (
Fr(1) - multilinear_challenge[k]);
194 next_const.
at(0) = final_eval * tail;
195 fold_polynomials.emplace_back(
std::move(next_const));
198 return fold_polynomials;
222template <
typename Curve>
228 const Fr& r_challenge)
231 claims.reserve(log_n + 1);
234 Fr a_0_pos = A_0_pos.evaluate(r_challenge);
235 claims.emplace_back(
Claim{
std::move(A_0_pos), { r_challenge, a_0_pos } });
237 Fr a_0_neg = A_0_neg.evaluate(-r_challenge);
238 claims.emplace_back(
Claim{
std::move(A_0_neg), { -r_challenge, a_0_neg } });
245 const bool gemini_fold =
true;
248 for (
size_t l = 0; l < log_n - 1; ++l) {
249 Fr evaluation = fold_polynomials[l].evaluate(-r_squares[l + 1]);
250 claims.emplace_back(
Claim{
std::move(fold_polynomials[l]), { -r_squares[l + 1], evaluation }, gemini_fold });
#define BB_ASSERT_GTE(left, right,...)
#define BB_BENCH_NAME(name)
CommitmentKey object over a pairing group 𝔾₁.
Commitment commit(PolynomialSpan< const Fr > polynomial, bool has_duplicates_hint=false) const
Uses the ProverSRS to create a commitment to p(X)
Class responsible for computation of the batched multilinear polynomials required by the Gemini proto...
Polynomial compute_batched(const Fr &challenge)
Compute batched polynomial A₀ = F + G/X as the linear combination of all polynomials to be opened,...
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.
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)
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< Polynomial > compute_fold_polynomials(const size_t log_n, std::span< const Fr > multilinear_challenge, const Polynomial &A_0)
Computes d-1 fold polynomials Fold_i, i = 1, ..., d-1.
Fr & at(size_t index)
Our mutable accessor, unlike operator[]. We abuse precedent a bit to differentiate at() and operator[...
Polynomial p and an opening pair (r,v) such that p(r) = v.
static constexpr size_t SUBGROUP_SIZE
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)
constexpr size_t FF_ADDITION_COST
constexpr size_t FF_MULTIPLICATION_COST
Entry point for Barretenberg command-line interface.
void fold_stride2(const Polynomial< Fr > &src, Polynomial< Fr > &dst, const size_t begin, const size_t end, const Fr &challenge)
Stride-2 linear-interpolation fold: dst[k] = src[2k] + challenge * (src[2k+1] - src[2k]) for every ou...
void parallel_for_heuristic(size_t num_points, const std::function< void(size_t, size_t, size_t)> &func, size_t heuristic_cost)
Split a loop into several loops running in parallel based on operations in 1 iteration.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::string to_string(bb::avm2::ValueTag tag)
auto range(size_t size, size_t offset=0) const
void throw_or_abort(std::string const &err)