1
1
#pragma once
2
2
3
3
#include " barretenberg/commitment_schemes/claim.hpp"
4
+ #include " barretenberg/commitment_schemes/claim_batcher.hpp"
4
5
#include " barretenberg/polynomials/polynomial.hpp"
5
6
#include " barretenberg/transcript/transcript.hpp"
6
7
@@ -104,11 +105,12 @@ template <typename Curve> class GeminiProver_ {
104
105
* @brief Class responsible for computation of the batched multilinear polynomials required by the Gemini protocol
105
106
* @details Opening multivariate polynomials using Gemini requires the computation of three batched polynomials. The
106
107
* first, here denoted A₀, is a linear combination of all polynomials to be opened. If we denote the linear
107
- * combinations (based on challenge rho) of the unshifted and the to-be-shited-by-1 polynomials by F and G,
108
- * respectively, then A₀ = F + G/X. This polynomial is "folded" in Gemini to produce d-1 univariate polynomials
109
- * Fold_i, i = 1, ..., d-1. The second and third are the partially evaluated batched polynomials A₀₊ = F + G/r, and
110
- * A₀₋ = F - G/r. These are required in order to prove the opening of shifted polynomials G_i/X from the commitments
111
- * to their unshifted counterparts G_i.
108
+ * combinations (based on challenge rho) of the unshifted, to-be-shifted-by-1, and to-be-right-shifted-by-k
109
+ * polynomials by F, G, and H respectively, then A₀ = F + G/X + X^k*H. (Note: 'k' is assumed even and thus a factor
110
+ * (-1)^k in not needed for the evaluation at -r). This polynomial is "folded" in Gemini to produce d-1 univariate
111
+ * polynomials Fold_i, i = 1, ..., d-1. The second and third are the partially evaluated batched polynomials A₀₊ = F
112
+ * + G/r + r^K*H, and A₀₋ = F - G/r + r^K*H. These are required in order to prove the opening of shifted polynomials
113
+ * G_i/X, X^k*H_i and from the commitments to their unshifted counterparts G_i and H_i.
112
114
* @note TODO(https://github.com/AztecProtocol/barretenberg/issues/1223): There are certain operations herein that
113
115
* could be made more efficient by e.g. reusing already initialized polynomials, possibly at the expense of clarity.
114
116
*/
@@ -122,9 +124,13 @@ template <typename Curve> class GeminiProver_ {
122
124
123
125
RefVector<Polynomial> unshifted; // set of unshifted polynomials
124
126
RefVector<Polynomial> to_be_shifted_by_one; // set of polynomials to be left shifted by 1
127
+ RefVector<Polynomial> to_be_shifted_by_k; // set of polynomials to be right shifted by k
128
+
129
+ size_t k_shift_magnitude = 0 ; // magnitude of right-shift-by-k (assumed even)
125
130
126
131
Polynomial batched_unshifted; // linear combination of unshifted polynomials
127
132
Polynomial batched_to_be_shifted_by_one; // linear combination of to-be-shifted polynomials
133
+ Polynomial batched_to_be_shifted_by_k; // linear combination of to-be-shifted-by-k polynomials
128
134
129
135
public:
130
136
PolynomialBatcher (const size_t full_batched_size)
@@ -135,10 +141,17 @@ template <typename Curve> class GeminiProver_ {
135
141
136
142
bool has_unshifted () const { return unshifted.size () > 0 ; }
137
143
bool has_to_be_shifted_by_one () const { return to_be_shifted_by_one.size () > 0 ; }
144
+ bool has_to_be_shifted_by_k () const { return to_be_shifted_by_k.size () > 0 ; }
138
145
139
146
// Set references to the polynomials to be batched
140
147
void set_unshifted (RefVector<Polynomial> polynomials) { unshifted = polynomials; }
141
148
void set_to_be_shifted_by_one (RefVector<Polynomial> polynomials) { to_be_shifted_by_one = polynomials; }
149
+ void set_to_be_shifted_by_k (RefVector<Polynomial> polynomials, const size_t shift_magnitude)
150
+ {
151
+ ASSERT (k_shift_magnitude % 2 == 0 ); // k must be even for the formulas herein to be valid
152
+ to_be_shifted_by_k = polynomials;
153
+ k_shift_magnitude = shift_magnitude;
154
+ }
142
155
143
156
// Initialize the random polynomial used to add randomness to the batched polynomials for ZK
144
157
void set_random_polynomial (Polynomial&& random)
@@ -169,19 +182,26 @@ template <typename Curve> class GeminiProver_ {
169
182
170
183
// if necessary, add randomness to the full batched polynomial for ZK
171
184
if (has_random_polynomial) {
172
- full_batched += random_polynomial;
185
+ full_batched += random_polynomial; // A₀ += rand
173
186
}
174
187
175
188
// compute the linear combination F of the unshifted polynomials
176
189
if (has_unshifted ()) {
177
190
batch (batched_unshifted, unshifted);
178
- full_batched += batched_unshifted; // A₀ = F
191
+ full_batched += batched_unshifted; // A₀ + = F
179
192
}
180
193
181
194
// compute the linear combination G of the to-be-shifted polynomials
182
195
if (has_to_be_shifted_by_one ()) {
183
196
batch (batched_to_be_shifted_by_one, to_be_shifted_by_one);
184
- full_batched += batched_to_be_shifted_by_one.shifted (); // A₀ = F + G/X
197
+ full_batched += batched_to_be_shifted_by_one.shifted (); // A₀ += G/X
198
+ }
199
+
200
+ // compute the linear combination H of the to-be-shifted-by-k polynomials
201
+ if (has_to_be_shifted_by_k ()) {
202
+ batched_to_be_shifted_by_k = Polynomial (full_batched_size - k_shift_magnitude, full_batched_size, 0 );
203
+ batch (batched_to_be_shifted_by_k, to_be_shifted_by_k);
204
+ full_batched += batched_to_be_shifted_by_k.right_shifted (k_shift_magnitude); // A₀ += X^k * H
185
205
}
186
206
187
207
return full_batched;
@@ -206,14 +226,20 @@ template <typename Curve> class GeminiProver_ {
206
226
A_0_pos += batched_unshifted; // A₀₊ += F
207
227
}
208
228
229
+ if (has_to_be_shifted_by_k ()) {
230
+ Fr r_pow_k = r_challenge.pow (k_shift_magnitude); // r^k
231
+ batched_to_be_shifted_by_k *= r_pow_k;
232
+ A_0_pos += batched_to_be_shifted_by_k; // A₀₊ += r^k * H
233
+ }
234
+
209
235
Polynomial A_0_neg = A_0_pos;
210
236
211
237
if (has_to_be_shifted_by_one ()) {
212
238
Fr r_inv = r_challenge.invert (); // r⁻¹
213
239
batched_to_be_shifted_by_one *= r_inv; // G = G/r
214
240
215
- A_0_pos += batched_to_be_shifted_by_one; // A₀₊ = F + G/r
216
- A_0_neg -= batched_to_be_shifted_by_one; // A₀₋ = F - G/r
241
+ A_0_pos += batched_to_be_shifted_by_one; // A₀₊ += G/r
242
+ A_0_neg -= batched_to_be_shifted_by_one; // A₀₋ -= G/r
217
243
}
218
244
219
245
return { A_0_pos, A_0_neg };
@@ -252,6 +278,7 @@ template <typename Curve> class GeminiVerifier_ {
252
278
using Fr = typename Curve::ScalarField;
253
279
using GroupElement = typename Curve::Element;
254
280
using Commitment = typename Curve::AffineElement;
281
+ using ClaimBatcher = ClaimBatcher_<Curve>;
255
282
256
283
public:
257
284
/* *
@@ -268,10 +295,7 @@ template <typename Curve> class GeminiVerifier_ {
268
295
*/
269
296
static std::vector<OpeningClaim<Curve>> reduce_verification (
270
297
std::span<Fr> multilinear_challenge,
271
- RefSpan<Fr> unshifted_evaluations,
272
- RefSpan<Fr> shifted_evaluations,
273
- RefSpan<Commitment> unshifted_commitments,
274
- RefSpan<Commitment> to_be_shifted_commitments,
298
+ ClaimBatcher& claim_batcher,
275
299
auto & transcript,
276
300
const std::vector<RefVector<Commitment>>& concatenation_group_commitments = {},
277
301
RefSpan<Fr> concatenated_evaluations = {})
@@ -288,13 +312,15 @@ template <typename Curve> class GeminiVerifier_ {
288
312
289
313
Fr batched_evaluation = Fr (0 );
290
314
Fr batching_scalar = Fr (1 );
291
- for (auto [eval, comm] : zip_view (unshifted_evaluations, unshifted_commitments)) {
315
+ for (auto [eval, comm] :
316
+ zip_view (claim_batcher.get_unshifted ().evaluations , claim_batcher.get_unshifted ().commitments )) {
292
317
batched_evaluation += eval * batching_scalar;
293
318
batched_commitment_unshifted += comm * batching_scalar;
294
319
batching_scalar *= rho;
295
320
}
296
321
297
- for (auto [eval, comm] : zip_view (shifted_evaluations, to_be_shifted_commitments)) {
322
+ for (auto [eval, comm] :
323
+ zip_view (claim_batcher.get_shifted ().evaluations , claim_batcher.get_shifted ().commitments )) {
298
324
batched_evaluation += eval * batching_scalar;
299
325
batched_commitment_to_be_shifted += comm * batching_scalar;
300
326
batching_scalar *= rho;
0 commit comments