57 size_t max_poly_size{ 0 };
59 for (
const auto& claim_set : { opening_claims, libra_opening_claims, sumcheck_round_claims }) {
60 for (
const auto& claim : claim_set) {
61 max_poly_size =
std::max(max_poly_size, claim.polynomial.size());
75 for (
const auto& claim : opening_claims) {
78 if (claim.gemini_fold) {
79 tmp = claim.polynomial;
80 tmp.
at(0) = tmp[0] - gemini_fold_pos_evaluations[fold_idx++];
88 tmp = claim.polynomial;
89 tmp.
at(0) = tmp[0] - claim.opening_pair.evaluation;
99 if (!libra_opening_claims.empty()) {
100 current_nu = nu.pow(2 * virtual_log_n + NUM_INTERLEAVING_CLAIMS);
103 for (
const auto& claim : libra_opening_claims) {
105 tmp = claim.polynomial;
106 tmp.
at(0) = tmp[0] - claim.opening_pair.evaluation;
114 for (
const auto& claim : sumcheck_round_claims) {
117 tmp = claim.polynomial;
118 tmp.
at(0) = tmp[0] - claim.opening_pair.evaluation;
140 const size_t virtual_log_n,
143 const Fr& nu_challenge,
144 const Fr& z_challenge,
150 const size_t num_gemini_opening_claims = 2 * opening_claims.size();
151 const size_t num_opening_claims =
152 num_gemini_opening_claims + libra_opening_claims.size() + sumcheck_opening_claims.size();
155 std::vector<Fr> inverse_vanishing_evals;
156 inverse_vanishing_evals.reserve(num_opening_claims);
157 for (
const auto& claim : opening_claims) {
158 if (claim.gemini_fold) {
159 inverse_vanishing_evals.emplace_back(z_challenge + claim.opening_pair.challenge);
161 inverse_vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge);
165 for (
const auto& claim : libra_opening_claims) {
166 inverse_vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge);
169 for (
const auto& claim : sumcheck_opening_claims) {
170 inverse_vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge);
185 for (
auto& claim : opening_claims) {
187 if (claim.gemini_fold) {
188 tmp = claim.polynomial;
189 tmp.at(0) = tmp[0] - gemini_fold_pos_evaluations[fold_idx++];
190 Fr scaling_factor = current_nu * inverse_vanishing_evals[idx++];
192 G.add_scaled(tmp, -scaling_factor);
194 current_nu *= nu_challenge;
197 claim.polynomial.at(0) = claim.polynomial[0] - claim.opening_pair.evaluation;
198 Fr scaling_factor = current_nu * inverse_vanishing_evals[idx++];
201 G.add_scaled(claim.polynomial, -scaling_factor);
203 current_nu *= nu_challenge;
207 if (!libra_opening_claims.empty()) {
208 current_nu = nu_challenge.
pow(2 * virtual_log_n + NUM_INTERLEAVING_CLAIMS);
211 for (
auto& claim : libra_opening_claims) {
213 claim.polynomial.at(0) = claim.polynomial[0] - claim.opening_pair.evaluation;
214 Fr scaling_factor = current_nu * inverse_vanishing_evals[idx++];
217 G.add_scaled(claim.polynomial, -scaling_factor);
218 current_nu *= nu_challenge;
221 for (
auto& claim : sumcheck_opening_claims) {
222 claim.polynomial.at(0) = claim.polynomial[0] - claim.opening_pair.evaluation;
223 Fr scaling_factor = current_nu * inverse_vanishing_evals[idx++];
226 G.add_scaled(claim.polynomial, -scaling_factor);
227 current_nu *= nu_challenge;
230 return { .polynomial =
G, .opening_pair = { .challenge = z_challenge, .evaluation =
Fr::zero() } };
242 std::vector<Fr> gemini_fold_pos_evaluations;
243 gemini_fold_pos_evaluations.reserve(opening_claims.size());
245 for (
const auto& claim : opening_claims) {
246 if (claim.gemini_fold) {
248 const Fr evaluation_point = -claim.opening_pair.challenge;
250 const Fr evaluation = claim.polynomial.evaluate(evaluation_point);
251 gemini_fold_pos_evaluations.emplace_back(evaluation);
254 return gemini_fold_pos_evaluations;
266 template <
typename Transcript>
269 const std::shared_ptr<Transcript>& transcript,
272 const size_t virtual_log_n = 0)
274 const Fr nu = transcript->template get_challenge<Fr>(
"Shplonk:nu");
282 gemini_fold_pos_evaluations,
283 libra_opening_claims,
284 sumcheck_round_claims);
285 auto batched_quotient_commitment = commitment_key.
commit(batched_quotient);
286 transcript->send_to_verifier(
"Shplonk:Q", batched_quotient_commitment);
287 const Fr z = transcript->template get_challenge<Fr>(
"Shplonk:z");
294 gemini_fold_pos_evaluations,
295 libra_opening_claims,
296 sumcheck_round_claims);
367 template <
typename Transcript>
369 std::shared_ptr<Transcript>& transcript,
370 const size_t num_claims)
371 :
pows_of_nu({
Fr(1), transcript->template get_challenge<Fr>(
"Shplonk:nu") })
372 ,
quotient(transcript->template receive_from_prover<Commitment>(
"Shplonk:Q"))
373 ,
z_challenge(transcript->template get_challenge<Fr>(
"Shplonk:z"))
377 BB_ASSERT_GT(num_claims, 1U,
"Using Shplonk with just one claim. Should use batch reduction.");
380 scalars.reserve(num_commitments);
387 for (
size_t idx = 0; idx < num_claims - 2; idx++) {
436 auto scaling_factor = scalar_factor * coefficient;
438 scalars[index + 1] -= scaling_factor;
456 OpeningClaim<Curve> finalize(
const Commitment& g1_identity)
464 result = GroupElement::zero();
466 result += commitment * scalar;
488 BatchOpeningClaim<Curve> export_batch_opening_claim(
const Commitment& g1_identity)
503 template <
typename Transcript>
504 static ShplonkVerifier_<Curve> reduce_verification_no_finalize(std::span<
const OpeningClaim<Curve>> claims,
505 std::shared_ptr<Transcript>& transcript)
508 const size_t num_claims = claims.size();
509 std::vector<Commitment> polynomial_commiments;
510 polynomial_commiments.reserve(num_claims);
511 for (
const auto& claim : claims) {
512 polynomial_commiments.emplace_back(claim.commitment);
514 ShplonkVerifier_<Curve> verifier(polynomial_commiments, transcript, num_claims);
517 std::vector<Fr> inverse_vanishing_evals;
518 inverse_vanishing_evals.reserve(num_claims);
520 for (
const auto& claim : claims) {
521 inverse_vanishing_evals.emplace_back((verifier.z_challenge - claim.opening_pair.challenge).invert());
524 for (
const auto& claim : claims) {
525 inverse_vanishing_evals.emplace_back(verifier.z_challenge - claim.opening_pair.challenge);
530 for (
size_t idx = 0; idx < claims.size(); idx++) {
531 verifier.update({ { idx }, {
Fr(1) }, claims[idx].opening_pair }, inverse_vanishing_evals[idx]);
547 const size_t num_claims = claims.size();
550 std::vector<Fr> inverse_vanishing_evals;
551 inverse_vanishing_evals.reserve(num_claims);
553 for (
const auto& claim : claims) {
554 inverse_vanishing_evals.emplace_back((this->z_challenge - claim.opening_pair.challenge).invert());
557 for (
const auto& claim : claims) {
558 inverse_vanishing_evals.emplace_back(this->z_challenge - claim.opening_pair.challenge);
563 for (
const auto& [claim, inv] :
zip_view(claims, inverse_vanishing_evals)) {
564 this->update(claim, inv);
578 OpeningClaim<Curve> reduce_verification_vector_claims(
Commitment g1_identity,
581 this->reduce_verification_vector_claims_no_finalize(claims);
582 return this->finalize(g1_identity);
595 template <
typename Transcript>
596 static OpeningClaim<Curve> reduce_verification(
Commitment g1_identity,
597 std::span<
const OpeningClaim<Curve>> claims,
598 std::shared_ptr<Transcript>& transcript)
600 auto verifier = ShplonkVerifier_::reduce_verification_no_finalize(claims, transcript);
601 return verifier.finalize(g1_identity);
613 static std::vector<Fr> compute_inverted_gemini_denominators(
const Fr& shplonk_eval_challenge,
614 const std::vector<Fr>& gemini_eval_challenge_powers)
616 std::vector<Fr> denominators;
617 const size_t virtual_log_n = gemini_eval_challenge_powers.size();
618 const size_t num_gemini_claims = 2 * virtual_log_n;
619 denominators.reserve(num_gemini_claims);
621 for (
const auto& gemini_eval_challenge_power : gemini_eval_challenge_powers) {
623 denominators.emplace_back(shplonk_eval_challenge - gemini_eval_challenge_power);
625 denominators.emplace_back(shplonk_eval_challenge + gemini_eval_challenge_power);
631 for (
auto& denominator : denominators) {
632 denominator = denominator.invert();
644template <
typename Fr>
645static std::vector<Fr> compute_shplonk_batching_challenge_powers(
const Fr& shplonk_batching_challenge,
646 const size_t virtual_log_n,
648 bool committed_sumcheck =
false)
651 size_t num_powers = 2 * virtual_log_n + NUM_INTERLEAVING_CLAIMS;
653 static constexpr size_t NUM_COMMITTED_SUMCHECK_CLAIMS_PER_ROUND = 3;
657 num_powers += NUM_SMALL_IPA_EVALUATIONS;
661 if (committed_sumcheck) {
662 num_powers += NUM_COMMITTED_SUMCHECK_CLAIMS_PER_ROUND * virtual_log_n;
665 std::vector<Fr> result;
666 result.reserve(num_powers);
667 result.emplace_back(
Fr{ 1 });
668 for (
size_t idx = 1; idx < num_powers; idx++) {
669 result.emplace_back(result[idx - 1] * shplonk_batching_challenge);
#define BB_ASSERT_GT(left, right,...)
CommitmentKey object over a pairing group 𝔾₁.
Commitment commit(PolynomialSpan< const Fr > polynomial) const
Uses the ProverSRS to create a commitment to p(X)
Opening pair (r,v) for some witness polynomial p(X) such that p(r) = v.
Structured polynomial class that represents the coefficients 'a' of a_0 + a_1 x .....
Fr & at(size_t index)
Our mutable accessor, unlike operator[]. We abuse precedent a bit to differentiate at() and operator[...
void add_scaled(PolynomialSpan< const Fr > other, Fr scaling_factor) &
adds the polynomial q(X) 'other', multiplied by a scaling factor.
void factor_roots(const Fr &root)
Divides p(X) by (X-r) in-place. Assumes that p(rⱼ)=0 for all j.
Polynomial p and an opening pair (r,v) such that p(r) = v.
static std::vector< Fr > compute_gemini_fold_pos_evaluations(std::span< const ProverOpeningClaim< Curve > > opening_claims)
Compute evaluations of fold polynomials Fold_i at r^{2^i} for i>0. TODO(https://github....
static Polynomial compute_batched_quotient(const size_t virtual_log_n, std::span< const ProverOpeningClaim< Curve > > opening_claims, const Fr &nu, std::span< Fr > gemini_fold_pos_evaluations, std::span< const ProverOpeningClaim< Curve > > libra_opening_claims, std::span< const ProverOpeningClaim< Curve > > sumcheck_round_claims)
Compute batched quotient polynomial Q(X) = ∑ⱼ νʲ ⋅ ( fⱼ(X) − vⱼ) / ( X − xⱼ )
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,...
typename Curve::ScalarField Fr
static ProverOpeningClaim< Curve > compute_partially_evaluated_batched_quotient(const size_t virtual_log_n, std::span< ProverOpeningClaim< Curve > > opening_claims, Polynomial &batched_quotient_Q, const Fr &nu_challenge, const Fr &z_challenge, std::span< Fr > gemini_fold_pos_evaluations, std::span< ProverOpeningClaim< Curve > > libra_opening_claims={}, std::span< ProverOpeningClaim< Curve > > sumcheck_opening_claims={})
Compute partially evaluated batched quotient polynomial difference Q(X) - Q_z(X)
std::vector< Fr > pows_of_nu
typename Curve::ScalarField Fr
ShplonkVerifier_(std::vector< Commitment > &polynomial_commitments, std::shared_ptr< Transcript > &transcript, const size_t num_claims)
std::vector< Commitment > commitments
Fr identity_scalar_coefficient
typename Curve::AffineElement Commitment
typename Curve::Element GroupElement
std::vector< Fr > scalars
typename Group::element Element
static constexpr bool is_stdlib_type
typename Group::affine_element AffineElement
typename Flavor::Polynomial Polynomial
#define G(r, i, a, b, c, d)
constexpr T round_up_power_2(const T in)
Entry point for Barretenberg command-line interface.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::vector< Fr > scalars
std::vector< size_t > indices
OpeningPair< Curve > opening_pair
static constexpr field one()
BB_INLINE constexpr field pow(const uint256_t &exponent) const noexcept
static void batch_invert(std::span< field > coeffs) noexcept
static constexpr field zero()