Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
commitment_key.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
7#pragma once
8
26
27#include <cstddef>
28#include <memory>
29#include <string_view>
30
31namespace bb {
40template <class Curve> class CommitmentKey {
41
42 using Fr = typename Curve::ScalarField;
44 using G1 = typename Curve::AffineElement;
45 static constexpr size_t EXTRA_SRS_POINTS_FOR_ECCVM_IPA = 1;
46
47 static size_t get_num_needed_srs_points(size_t num_points)
48 {
49 // NOTE 1: Currently we must round up internal space for points as our pippenger algorithm (specifically,
50 // pippenger_unsafe_optimized_for_non_dyadic_polys) will use next power of 2. This is used to simplify the
51 // recursive halving scheme. We do, however allow the polynomial to not be fully formed. Pippenger internally
52 // will pad 0s into the runtime state.
53 // NOTE 2: We then add one for ECCVM to provide for IPA verification
55 }
56
57 public:
60
61 CommitmentKey() = default;
62
70 CommitmentKey(const size_t num_points)
71 : srs(srs::get_crs_factory<Curve>()->get_crs(get_num_needed_srs_points(num_points)))
73 {}
79 bool initialized() const { return srs != nullptr; }
80
88 {
89 // Note: this fn used to expand polynomials to the dyadic size,
90 // due to a quirk in how our pippenger algo used to function.
91 // The pippenger algo has been refactored and this is no longer an issue
92 PROFILE_THIS_NAME("commit");
93 std::span<const G1> point_table = srs->get_monomial_points();
94 size_t consumed_srs = polynomial.start_index + polynomial.size();
95 if (consumed_srs > srs->get_monomial_size()) {
96 throw_or_abort(format("Attempting to commit to a polynomial that needs ",
97 consumed_srs,
98 " points with an SRS of size ",
99 srs->get_monomial_size()));
100 }
101
102 G1 r = scalar_multiplication::pippenger_unsafe<Curve>(polynomial, point_table);
103 Commitment point(r);
104 return point;
105 };
106
122 const std::vector<std::pair<size_t, size_t>>& active_ranges,
123 size_t final_active_wire_idx = 0)
124 {
125 PROFILE_THIS_NAME("commit");
126 BB_ASSERT_LTE(polynomial.end_index(), srs->get_monomial_size(), "Polynomial size exceeds commitment key size.");
127 BB_ASSERT_LTE(polynomial.end_index(), dyadic_size, "Polynomial size exceeds commitment key size.");
128
129 // Percentage of nonzero coefficients beyond which we resort to the conventional commit method
130 constexpr size_t NONZERO_THRESHOLD = 75;
131
132 // Compute the number of non-zero coefficients in the polynomial
133 size_t total_num_scalars = 0;
134 for (const auto& [first, second] : active_ranges) {
135 total_num_scalars += second - first;
136 }
137
138 // Compute "active" percentage of polynomial; resort to standard commit if appropriate
139 size_t polynomial_size = final_active_wire_idx != 0 ? final_active_wire_idx : polynomial.size();
140 size_t percentage_nonzero = total_num_scalars * 100 / polynomial_size;
141 if (percentage_nonzero > NONZERO_THRESHOLD) {
142 return commit(polynomial);
143 }
144
145 // Extract the precomputed point table (contains raw SRS points at even indices and the corresponding
146 // endomorphism point (\beta*x, -y) at odd indices).
147 std::span<G1> point_table = srs->get_monomial_points();
148
149 std::vector<Fr> scalars;
150 scalars.reserve(total_num_scalars);
151 std::vector<G1> points;
152 points.reserve(total_num_scalars);
153 for (const auto& [first, second] : active_ranges) {
154 auto poly_start = &polynomial[first];
155 // Pointer to the first element past the active range. Accessing `&polynomial[second]` directly can trigger
156 // an assertion when `second == polynomial_size`, so we compute the pointer using `polynomial.data()`
157 // to ensure safe range handling.
158 auto poly_end = polynomial.data() + (second - polynomial.start_index);
159 scalars.insert(scalars.end(), poly_start, poly_end);
160
161 auto pts_start = &point_table[first];
162 auto pts_end = &point_table[second];
163 points.insert(points.end(), pts_start, pts_end);
164 }
165
166 // Call the version of pippenger which assumes all points are distinct
167 G1 r = scalar_multiplication::pippenger_unsafe<Curve>({ 0, scalars }, points);
168 return Commitment(r);
169 }
170
184 const std::vector<std::pair<size_t, size_t>>& active_ranges,
185 size_t final_active_wire_idx = 0)
186 {
187 PROFILE_THIS_NAME("commit");
188 BB_ASSERT_LTE(polynomial.end_index(), srs->get_monomial_size(), "Polynomial size exceeds commitment key size.");
189
190 using BatchedAddition = BatchedAffineAddition<Curve>;
191
192 // Percentage of constant coefficients below which we resort to the conventional commit method
193 constexpr size_t CONSTANT_THRESHOLD = 50;
194
195 // Compute the active range complement over which the polynomial is assumed to be constant within each range.
196 // Note: the range from the end of the last active range to the end of the polynomial is excluded from the
197 // complement since the polynomial is assumed to be zero there.
198 std::vector<std::pair<size_t, size_t>> active_ranges_complement;
199 // Also compute total number of scalars in the constant regions
200 size_t total_num_complement_scalars = 0;
201 for (size_t i = 0; i < active_ranges.size() - 1; ++i) {
202 const size_t start = active_ranges[i].second;
203 const size_t end = active_ranges[i + 1].first;
204 if (end > start) {
205 active_ranges_complement.emplace_back(start, end);
206 total_num_complement_scalars += end - start;
207 }
208 }
209
210 size_t polynomial_size = final_active_wire_idx != 0 ? final_active_wire_idx : polynomial.size();
211 // Compute percentage of polynomial comprised of constant blocks; resort to standard commit if appropriate
212 size_t percentage_constant = total_num_complement_scalars * 100 / polynomial_size;
213
214 if (percentage_constant < CONSTANT_THRESHOLD) {
215 return commit(polynomial);
216 }
217
218 // Extract the precomputed point table (contains raw SRS points at even indices and the corresponding
219 // endomorphism point (\beta*x, -y) at odd indices).
220 std::span<G1> point_table = srs->get_monomial_points();
221
222 // Copy the raw SRS points (no endo points) corresponding to the constant regions into contiguous memory
223 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1131): Peak memory usage could be improved by
224 // performing this copy and the subsequent summation as a precomputation prior to constructing the point table.
225 std::vector<G1> points;
226
227 points.reserve(total_num_complement_scalars);
228 for (const auto& [start, end] : active_ranges_complement) {
229 for (size_t i = start; i < end; i++) {
230 points.emplace_back(point_table[i]);
231 }
232 }
233
234 // Populate the set of unique scalars with first coeff from each range (values assumed constant over each
235 // range). Also store the number of points in each sequence to be summed
236 std::vector<Fr> unique_scalars;
237 std::vector<size_t> sequence_counts;
238 for (const auto& range : active_ranges_complement) {
239 unique_scalars.emplace_back(polynomial.span[range.first]);
240 sequence_counts.emplace_back(range.second - range.first);
241 }
242
243 // Reduce each sequence to a single point
244 auto reduced_points = BatchedAddition::add_in_place(points, sequence_counts);
245
246 // Compute the full commitment as the sum of the "active" region commitment and the constant region contribution
247 Commitment result = commit_structured(polynomial, active_ranges, final_active_wire_idx);
248
249 for (auto [scalar, point] : zip_view(unique_scalars, reduced_points)) {
250 result = result + point * scalar;
251 }
252
253 return result;
254 }
255
257
259 CommitType type,
260 const std::vector<std::pair<size_t, size_t>>& active_ranges = {},
261 size_t final_active_wire_idx = 0)
262 {
263 switch (type) {
266 return commit(poly);
268 return commit_structured_with_nonzero_complement(poly, active_ranges, final_active_wire_idx);
270 default:
271 return commit(poly);
272 }
273 }
274};
275
276} // namespace bb
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:129
Class for handling fast batched affine addition of large sets of EC points.
CommitmentKey object over a pairing group 𝔾₁.
CommitmentKey()=default
typename Curve::AffineElement G1
typename Curve::ScalarField Fr
static constexpr size_t EXTRA_SRS_POINTS_FOR_ECCVM_IPA
typename Curve::AffineElement Commitment
CommitmentKey(const size_t num_points)
Construct a new Kate Commitment Key object from existing SRS.
Commitment commit_structured(PolynomialSpan< const Fr > polynomial, const std::vector< std::pair< size_t, size_t > > &active_ranges, size_t final_active_wire_idx=0)
Efficiently commit to a polynomial whose nonzero elements are arranged in discrete blocks.
Commitment commit(PolynomialSpan< const Fr > polynomial) const
Uses the ProverSRS to create a commitment to p(X)
bool initialized() const
Checks the commitment key is properly initialized.
std::shared_ptr< srs::factories::Crs< Curve > > srs
Commitment commit_structured_with_nonzero_complement(PolynomialSpan< const Fr > polynomial, const std::vector< std::pair< size_t, size_t > > &active_ranges, size_t final_active_wire_idx=0)
Efficiently commit to a polynomial with discrete blocks of arbitrary elements and constant elements.
Commitment commit_with_type(PolynomialSpan< const Fr > poly, CommitType type, const std::vector< std::pair< size_t, size_t > > &active_ranges={}, size_t final_active_wire_idx=0)
static size_t get_num_needed_srs_points(size_t num_points)
typename Group::affine_element AffineElement
Definition grumpkin.hpp:56
std::string format(Args... args)
Definition log.hpp:20
constexpr T round_up_power_2(const T in)
Definition get_msb.hpp:52
Entry point for Barretenberg command-line interface.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
#define PROFILE_THIS_NAME(name)
Definition op_count.hpp:16
size_t size() const
std::span< Fr > span
size_t end_index() const
void throw_or_abort(std::string const &err)