66 size_t max_poly_size{ 0 };
68 for (
const auto& claim_set : { opening_claims, libra_opening_claims, sumcheck_round_claims }) {
69 for (
const auto& claim : claim_set) {
70 max_poly_size =
std::max(max_poly_size, claim.polynomial.size());
80 for (
const auto& claim : opening_claims) {
83 if (claim.gemini_fold) {
84 tmp = claim.polynomial;
85 tmp.
at(0) = tmp[0] - gemini_fold_pos_evaluations[fold_idx++];
93 tmp = claim.polynomial;
94 tmp.
at(0) = tmp[0] - claim.opening_pair.evaluation;
103 if (!libra_opening_claims.empty() || !sumcheck_round_claims.empty()) {
106 current_nu = nu.pow(2 * virtual_log_n);
109 for (
const auto& claim : libra_opening_claims) {
111 tmp = claim.polynomial;
112 tmp.
at(0) = tmp[0] - claim.opening_pair.evaluation;
120 for (
const auto& claim : sumcheck_round_claims) {
123 tmp = claim.polynomial;
124 tmp.
at(0) = tmp[0] - claim.opening_pair.evaluation;
146 const size_t virtual_log_n,
149 const Fr& nu_challenge,
150 const Fr& z_challenge,
156 const size_t num_gemini_opening_claims = 2 * opening_claims.size();
157 const size_t num_opening_claims =
158 num_gemini_opening_claims + libra_opening_claims.size() + sumcheck_opening_claims.size();
161 std::vector<Fr> inverse_vanishing_evals;
162 inverse_vanishing_evals.reserve(num_opening_claims);
163 for (
const auto& claim : opening_claims) {
164 if (claim.gemini_fold) {
165 inverse_vanishing_evals.emplace_back(z_challenge + claim.opening_pair.challenge);
167 inverse_vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge);
171 for (
const auto& claim : libra_opening_claims) {
172 inverse_vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge);
175 for (
const auto& claim : sumcheck_opening_claims) {
176 inverse_vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge);
189 for (
const auto& claim : opening_claims) {
191 if (claim.gemini_fold) {
193 Fr scaling_factor = current_nu * inverse_vanishing_evals[idx++];
194 G.add_scaled(claim.polynomial, -scaling_factor);
195 G.at(0) =
G[0] + scaling_factor * gemini_fold_pos_evaluations[fold_idx++];
197 current_nu *= nu_challenge;
200 Fr scaling_factor = current_nu * inverse_vanishing_evals[idx++];
201 G.add_scaled(claim.polynomial, -scaling_factor);
202 G.at(0) =
G[0] + scaling_factor * claim.opening_pair.evaluation;
204 current_nu *= nu_challenge;
210 if (!libra_opening_claims.empty() || !sumcheck_opening_claims.empty()) {
213 current_nu = nu_challenge.
pow(2 * virtual_log_n);
216 for (
const auto& claim : libra_opening_claims) {
218 Fr scaling_factor = current_nu * inverse_vanishing_evals[idx++];
219 G.add_scaled(claim.polynomial, -scaling_factor);
220 G.at(0) =
G[0] + scaling_factor * claim.opening_pair.evaluation;
221 current_nu *= nu_challenge;
224 for (
const auto& claim : sumcheck_opening_claims) {
225 Fr scaling_factor = current_nu * inverse_vanishing_evals[idx++];
226 G.add_scaled(claim.polynomial, -scaling_factor);
227 G.at(0) =
G[0] + scaling_factor * claim.opening_pair.evaluation;
228 current_nu *= nu_challenge;
231 return { .polynomial =
G, .opening_pair = { .challenge = z_challenge, .evaluation =
Fr::zero() } };
243 std::vector<Fr> gemini_fold_pos_evaluations;
244 gemini_fold_pos_evaluations.reserve(opening_claims.size());
246 for (
const auto& claim : opening_claims) {
247 if (claim.gemini_fold) {
249 const Fr evaluation_point = -claim.opening_pair.challenge;
251 const Fr evaluation = claim.polynomial.evaluate(evaluation_point);
252 gemini_fold_pos_evaluations.emplace_back(evaluation);
255 return gemini_fold_pos_evaluations;
267 template <
typename Transcript>
271 const std::shared_ptr<Transcript>& transcript,
274 const size_t virtual_log_n = 0)
277 BB_ASSERT(virtual_log_n > 0 || (libra_opening_claims.empty() && sumcheck_round_claims.empty()),
278 "ShplonkProver::prove: virtual_log_n must be provided when batching Libra or sumcheck claims");
279 const Fr nu = transcript->template get_challenge<Fr>(
"Shplonk:nu");
287 gemini_fold_pos_evaluations,
288 libra_opening_claims,
289 sumcheck_round_claims);
290 auto batched_quotient_commitment = commitment_key.
commit(batched_quotient);
291 transcript->send_to_verifier(
"Shplonk:Q", batched_quotient_commitment);
292 const Fr z = transcript->template get_challenge<Fr>(
"Shplonk:z");
299 gemini_fold_pos_evaluations,
300 libra_opening_claims,
301 sumcheck_round_claims),
302 batched_quotient_commitment,
306 template <
typename Transcript>
309 const std::shared_ptr<Transcript>& transcript,
312 const size_t virtual_log_n = 0)
317 libra_opening_claims,
318 sumcheck_round_claims,
397 const Fr& nu_challenge,
398 const Fr& partial_evaluation_challenge)
408 template <
typename Transcript>
410 std::shared_ptr<Transcript>& transcript,
411 const size_t num_claims)
412 :
pows_of_nu({
Fr(1), transcript->template get_challenge<Fr>(
"Shplonk:nu") })
413 ,
quotient(transcript->template receive_from_prover<Commitment>(
"Shplonk:Q"))
414 ,
z_challenge(transcript->template get_challenge<Fr>(
"Shplonk:z"))
418 BB_ASSERT_EQ(num_claims, polynomial_commitments.size());
423 void initialize(
const std::vector<Commitment>& polynomial_commitments)
425 const size_t num_claims = polynomial_commitments.size();
426 if (num_claims <= 1U) {
427 throw_or_abort(
"Using Shplonk with just one claim. Should use batch reduction.");
430 scalars.reserve(num_claims + 1);
437 for (
size_t idx = 0; idx < num_claims - 2; idx++) {
449 std::vector<Fr> inverse_vanishing_evals;
450 inverse_vanishing_evals.reserve(claims.size());
452 for (
const auto& claim : claims) {
453 inverse_vanishing_evals.emplace_back((
z_challenge - claim.opening_pair.challenge).invert());
456 for (
const auto& claim : claims) {
457 inverse_vanishing_evals.emplace_back(
z_challenge - claim.opening_pair.challenge);
464 for (
size_t idx = 0; idx < claims.size(); idx++) {
466 auto scalar_factor =
pows_of_nu[idx] * inverse_vanishing_evals[idx];
468 scalars[idx + 1] -= scalar_factor;
486 "ShplonkVerifier: finalize()/export_batch_opening_claim() are mutually exclusive and may each be "
487 "called at most once");
514 "ShplonkVerifier: finalize()/export_batch_opening_claim() are mutually exclusive and may each be "
515 "called at most once");
530 template <
typename Transcript>
532 std::shared_ptr<Transcript>& transcript)
535 const size_t num_claims = claims.size();
536 std::vector<Commitment> polynomial_commiments;
537 polynomial_commiments.reserve(num_claims);
538 for (
const auto& claim : claims) {
539 polynomial_commiments.emplace_back(claim.commitment);
550 const Fr& nu_challenge,
551 const Fr& partial_evaluation_challenge)
553 std::vector<Commitment> polynomial_commiments;
554 polynomial_commiments.reserve(claims.size());
555 for (
const auto& claim : claims) {
556 polynomial_commiments.emplace_back(claim.commitment);
559 polynomial_commiments, quotient_commitment, nu_challenge, partial_evaluation_challenge);
561 return verifier.
finalize(g1_identity);
574 template <
typename Transcript>
577 std::shared_ptr<Transcript>& transcript)
580 return verifier.finalize(g1_identity);
593 const std::vector<Fr>& gemini_eval_challenge_powers)
595 std::vector<Fr> denominators;
596 const size_t virtual_log_n = gemini_eval_challenge_powers.size();
597 const size_t num_gemini_claims = 2 * virtual_log_n;
598 denominators.reserve(num_gemini_claims);
600 for (
const auto& gemini_eval_challenge_power : gemini_eval_challenge_powers) {
602 denominators.emplace_back(shplonk_eval_challenge - gemini_eval_challenge_power);
604 denominators.emplace_back(shplonk_eval_challenge + gemini_eval_challenge_power);
610 for (
auto& denominator : denominators) {
611 denominator = denominator.invert();
623template <
typename Fr>
624static std::vector<Fr> compute_shplonk_batching_challenge_powers(
const Fr& shplonk_batching_challenge,
625 const size_t virtual_log_n,
627 bool committed_sumcheck =
false)
630 size_t num_powers = 2 * virtual_log_n;
632 static constexpr size_t NUM_COMMITTED_SUMCHECK_CLAIMS_PER_ROUND = 3;
640 if (committed_sumcheck) {
641 num_powers += NUM_COMMITTED_SUMCHECK_CLAIMS_PER_ROUND * virtual_log_n;
645 result.reserve(num_powers);
647 for (
size_t idx = 1; idx < num_powers; idx++) {
648 result.emplace_back(
result[idx - 1] * shplonk_batching_challenge);
#define BB_ASSERT(expression,...)
#define BB_ASSERT_EQ(actual, expected,...)
#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)
Unverified claim (C,r,v) for some witness polynomial p(X) such that.
void add_scaled(PolynomialSpan< const Fr > other, const Fr &scaling_factor)
adds the polynomial q(X) 'other', multiplied by a scaling factor.
Fr & at(size_t index)
Our mutable accessor, unlike operator[]. We abuse precedent a bit to differentiate at() and operator[...
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 PartiallyEvaluatedQuotient compute_partially_evaluated_quotient(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 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ⱼ )
typename Curve::AffineElement Commitment
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)
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)
bb::Polynomial< Fr > Polynomial
std::vector< Fr > pows_of_nu
typename Curve::ScalarField Fr
BatchOpeningClaim< Curve > export_batch_opening_claim(const Commitment &g1_identity)
Export a BatchOpeningClaim instead of performing final batch_mul.
ShplonkVerifier_(const std::vector< Commitment > &polynomial_commitments, const Commitment "ient_commitment, const Fr &nu_challenge, const Fr &partial_evaluation_challenge)
void accumulate_claims(std::span< const OpeningClaim< Curve > > claims)
static OpeningClaim< Curve > reduce_verification(Commitment g1_identity, std::span< const OpeningClaim< Curve > > claims, std::shared_ptr< Transcript > &transcript)
Recomputes the new claim commitment [G] given the proof and the challenge r. No verification happens ...
static OpeningClaim< Curve > compute_partially_evaluated_quotient_claim(const Commitment &g1_identity, std::span< const OpeningClaim< Curve > > claims, const Commitment "ient_commitment, const Fr &nu_challenge, const Fr &partial_evaluation_challenge)
void initialize(const std::vector< Commitment > &polynomial_commitments)
std::vector< Commitment > commitments
ShplonkVerifier_(const std::vector< Commitment > &polynomial_commitments, std::shared_ptr< Transcript > &transcript, const size_t num_claims)
Fr identity_scalar_coefficient
typename Curve::AffineElement Commitment
static std::vector< Fr > compute_inverted_gemini_denominators(const Fr &shplonk_eval_challenge, const std::vector< Fr > &gemini_eval_challenge_powers)
Computes .
static ShplonkVerifier_< Curve > reduce_verification_no_finalize(std::span< const OpeningClaim< Curve > > claims, std::shared_ptr< Transcript > &transcript)
Instantiate a Shplonk verifier and update its state with the provided claims.
typename Curve::Element GroupElement
OpeningClaim< Curve > finalize(const Commitment &g1_identity)
Finalize the Shplonk verification and return the KZG opening claim.
std::vector< Fr > scalars
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
#define G(r, i, a, b, c, d)
Entry point for Barretenberg command-line interface.
constexpr size_t NUM_SMALL_IPA_OPENING_CLAIMS
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
An accumulator consisting of the Shplonk evaluation challenge and vectors of commitments and scalars.
Commitment quotient_commitment
ProverOpeningClaim< Curve > opening_claim
static constexpr field one()
BB_INLINE constexpr field pow(const uint256_t &exponent) const noexcept
static void batch_invert(C &coeffs) noexcept
Batch invert a collection of field elements using Montgomery's trick.
static constexpr field zero()
void throw_or_abort(std::string const &err)