Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
claim_batcher.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Complete, auditors: [Khashayar], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#pragma once
12#include <algorithm>
13#include <cstddef>
14#include <optional>
15#include <span>
16#include <utility>
17#include <vector>
18
19namespace bb {
20
21template <typename Curve> struct ProverOpeningClaimBatcher {
25
28
29 void add(ProverClaim prover_claim, Commitment commitment)
30 {
31 verifier_claims.push_back({ prover_claim.opening_pair, commitment });
32 prover_claims.push_back(std::move(prover_claim));
33 }
34};
35
36template <typename Fr> inline std::vector<Fr> batching_scalars(const Fr& challenge, const size_t count)
37{
38 std::vector<Fr> scalars;
39 scalars.reserve(count);
40 Fr scalar = Fr::one();
41 for (size_t idx = 0; idx < count; ++idx) {
42 scalars.emplace_back(scalar);
43 scalar *= challenge;
44 }
45 return scalars;
46}
47
48template <typename Curve>
51{
52 using Fr = typename Curve::ScalarField;
53 BB_ASSERT_EQ(evaluations.size(), scalars.size());
54 if (evaluations.empty()) {
55 return Fr::zero();
56 }
57 if constexpr (Curve::is_stdlib_type) {
58 constexpr size_t max_products = 16;
59 Fr result;
60 for (size_t start = 0; start < evaluations.size(); start += max_products) {
61 const size_t len = std::min(max_products, evaluations.size() - start);
62 std::vector<Fr> scalar_chunk(scalars.begin() + static_cast<std::ptrdiff_t>(start),
63 scalars.begin() + static_cast<std::ptrdiff_t>(start + len));
64 std::vector<Fr> evaluation_chunk(evaluations.begin() + static_cast<std::ptrdiff_t>(start),
65 evaluations.begin() + static_cast<std::ptrdiff_t>(start + len));
66 result = (start == 0) ? Fr::mult_madd(scalar_chunk, evaluation_chunk, {})
67 : Fr::mult_madd(scalar_chunk, evaluation_chunk, { result });
68 }
69 return result;
70 } else {
71 Fr result = Fr::zero();
72 for (size_t idx = 0; idx < evaluations.size(); ++idx) {
73 result += scalars[idx] * evaluations[idx];
74 }
75 return result;
76 }
77}
78
79template <typename Curve>
82{
83 using Fr = typename Curve::ScalarField;
84 using Commitment = typename Curve::AffineElement;
85 using GroupElement = typename Curve::Element;
86 BB_ASSERT_EQ(commitments.size(), scalars.size());
87 BB_ASSERT_GT(commitments.size(), 0UL);
88
89 std::vector<Fr> scalars_copy(scalars.begin(), scalars.end());
90 if constexpr (Curve::is_stdlib_type) {
91 return GroupElement::batch_mul(std::vector<Commitment>(commitments.begin(), commitments.end()), scalars_copy);
92 } else {
93 return Commitment::batch_mul(commitments, std::span<Fr>(scalars_copy));
94 }
95}
96
109template <typename Curve> struct ClaimBatcher_ {
110 using Fr = typename Curve::ScalarField;
112
113 struct Batch {
116 // scalar used for batching the claims, excluding the power of batching challenge \rho
118 };
119
120 std::optional<Batch> unshifted; // commitments and evaluations of unshifted polynomials
121 std::optional<Batch> shifted; // commitments of to-be-shifted-by-1 polys, evals of their shifts
122
124 Batch get_shifted() { return (shifted) ? *shifted : Batch{}; }
125
126 Fr get_unshifted_batch_scalar() const { return unshifted ? unshifted->scalar : Fr{ 0 }; }
127
152 const Fr& nu_challenge,
153 const Fr& r_challenge)
154 {
155 const Fr& inverse_vanishing_eval_pos = inverted_vanishing_evals[0];
156 const Fr& inverse_vanishing_eval_neg = inverted_vanishing_evals[1];
157
158 if (unshifted) {
159 // (1/(z−r) + ν/(z+r))
160 unshifted->scalar = inverse_vanishing_eval_pos + nu_challenge * inverse_vanishing_eval_neg;
161 }
162 if (shifted) {
163 // r⁻¹ ⋅ (1/(z−r) − ν/(z+r))
164 //
165 // This scalar is the verifier-side to-be-shifted-by-one PCS contract: every commitment in
166 // `shifted.commitments` is required to be a commitment to a polynomial with constant term zero.
167 // A commitment to a polynomial with poly[0] != 0 opens to G(r)/r = poly[0]/r + G_shift(r) on
168 // the commitment side, whereas the claimed MLE evaluation poly_shift(u) reconstructs to
169 // G_shift(r) at the Gemini challenge. The two sides differ by poly[0]/r, the Shplonk quotient
170 // is then not a polynomial, and the KZG pairing check rejects with overwhelming probability
171 // over the FS challenges.
172 // Regression: commitment_schemes/shplonk/shplemini.test.cpp::ToBeShiftedNonZeroConstantTermRejected.
173 shifted->scalar =
174 r_challenge.invert() * (inverse_vanishing_eval_pos - nu_challenge * inverse_vanishing_eval_neg);
175 }
176 }
187 void update_batch_mul_inputs_and_batched_evaluation(std::vector<Commitment>& commitments,
188 std::vector<Fr>& scalars,
189 Fr& batched_evaluation,
190 const Fr& rho)
191 {
192 size_t num_powers = 0;
193 num_powers += unshifted.has_value() ? unshifted->commitments.size() : 0;
194 num_powers += shifted.has_value() ? shifted->commitments.size() : 0;
195
196 Fr rho_power = Fr(1);
197 size_t power_idx = 0;
198
199 // Append the commitments/scalars from a given batch to the corresponding containers; update the batched
200 // evaluation and the running batching challenge in place
201 auto aggregate_claim_data_and_update_batched_evaluation = [&](const Batch& batch) {
202 for (auto [commitment, evaluation] : zip_view(batch.commitments, batch.evaluations)) {
203 commitments.emplace_back(std::move(commitment));
204 scalars.emplace_back(-batch.scalar * rho_power);
205 batched_evaluation += evaluation * rho_power;
206 power_idx++;
207 if (power_idx < num_powers) {
208 rho_power *= rho;
209 }
210 }
211 };
212
213 // Incorporate the claim data from each batch of claims that is present in the vectors of commitments and
214 // scalars for the batch mul
215 if (unshifted) {
216 // i-th Unshifted commitment will be multiplied by ρ^i and (1/(z−r) + ν/(z+r))
217 aggregate_claim_data_and_update_batched_evaluation(*unshifted);
218 }
219 if (shifted) {
220 // i-th shifted commitments will be multiplied by ρ^{num_unshifted + i} and r⁻¹ ⋅ (1/(z−r) − ν/(z+r))
221 aggregate_claim_data_and_update_batched_evaluation(*shifted);
222 }
223
224 BB_ASSERT_EQ(power_idx, num_powers);
225 }
226};
227
228} // namespace bb
#define BB_ASSERT_GT(left, right,...)
Definition assert.hpp:113
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:83
Unverified claim (C,r,v) for some witness polynomial p(X) such that.
Definition claim.hpp:55
Polynomial p and an opening pair (r,v) such that p(r) = v.
Definition claim.hpp:36
OpeningPair< Curve > opening_pair
Definition claim.hpp:42
A template class for a reference vector. Behaves as if std::vector<T&> was possible.
typename Group::element Element
Definition grumpkin.hpp:63
static constexpr bool is_stdlib_type
Definition grumpkin.hpp:67
typename Group::affine_element AffineElement
Definition grumpkin.hpp:64
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
Curve::AffineElement batch_commitments(std::span< const typename Curve::AffineElement > commitments, std::span< const typename Curve::ScalarField > scalars)
Curve::ScalarField batch_evaluations(std::span< const typename Curve::ScalarField > evaluations, std::span< const typename Curve::ScalarField > scalars)
std::vector< Fr > batching_scalars(const Fr &challenge, const size_t count)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
uint8_t len
RefVector< Commitment > commitments
Logic to support batching opening claims for unshifted and shifted polynomials in Shplemini.
std::optional< Batch > unshifted
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...
std::optional< Batch > shifted
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...
typename Curve::ScalarField Fr
Fr get_unshifted_batch_scalar() const
typename Curve::AffineElement Commitment
std::vector< VerifierClaim > verifier_claims
void add(ProverClaim prover_claim, Commitment commitment)
typename Curve::AffineElement Commitment
std::vector< ProverClaim > prover_claims
static constexpr field one()
static constexpr field zero()
VectorField result