Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
ecc_set_relation_impl.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
10#include <type_traits>
11
12namespace bb {
13
42template <typename FF>
43template <typename Accumulator, typename AllEntities, typename Parameters>
44Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_numerator(const AllEntities& in, const Parameters& params)
45{
46 using View = typename Accumulator::View;
47
48 const auto& precompute_round = View(in.precompute_round);
49 const auto precompute_round2 = precompute_round + precompute_round;
50 const auto precompute_round4 = precompute_round2 + precompute_round2;
51
52 const auto& gamma = params.gamma;
53 const auto& beta = params.beta;
54 const auto& beta_sqr = params.beta_sqr;
55 const auto& beta_cube = params.beta_cube;
56 const auto& precompute_pc = View(in.precompute_pc);
57 const auto& precompute_select = View(in.precompute_select);
58
65 Accumulator numerator(1); // degree-0
66 {
67 const auto& s0 = View(in.precompute_s1hi);
68 const auto& s1 = View(in.precompute_s1lo);
69
70 auto wnaf_slice = s0 + s0;
71 wnaf_slice += wnaf_slice;
72 wnaf_slice += s1;
73
74 // TODO(@zac-williamson #2226) optimize
75 const auto wnaf_slice_input0 = wnaf_slice + gamma + precompute_pc * beta + precompute_round4 * beta_sqr;
76 numerator *= wnaf_slice_input0; // degree-1
77 }
78 {
79 const auto& s0 = View(in.precompute_s2hi);
80 const auto& s1 = View(in.precompute_s2lo);
81
82 auto wnaf_slice = s0 + s0;
83 wnaf_slice += wnaf_slice;
84 wnaf_slice += s1;
85
86 // TODO(@zac-williamson #2226) optimize
87 const auto wnaf_slice_input1 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 1) * beta_sqr;
88 numerator *= wnaf_slice_input1; // degree-2
89 }
90 {
91 const auto& s0 = View(in.precompute_s3hi);
92 const auto& s1 = View(in.precompute_s3lo);
93
94 auto wnaf_slice = s0 + s0;
95 wnaf_slice += wnaf_slice;
96 wnaf_slice += s1;
97
98 // TODO(@zac-williamson #2226) optimize
99 const auto wnaf_slice_input2 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 2) * beta_sqr;
100 numerator *= wnaf_slice_input2; // degree-3
101 }
102 {
103 const auto& s0 = View(in.precompute_s4hi);
104 const auto& s1 = View(in.precompute_s4lo);
105
106 auto wnaf_slice = s0 + s0;
107 wnaf_slice += wnaf_slice;
108 wnaf_slice += s1;
109 // TODO(@zac-williamson #2226) optimize
110 const auto wnaf_slice_input3 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 3) * beta_sqr;
111 numerator *= wnaf_slice_input3; // degree-4
112 }
113 {
114 // skew product if relevant
115 const auto& skew = View(in.precompute_skew);
116 const auto& precompute_point_transition = View(in.precompute_point_transition);
117 const auto skew_input =
118 precompute_point_transition * (skew + gamma + precompute_pc * beta + (precompute_round4 + 4) * beta_sqr) +
119 (-precompute_point_transition + 1);
120 numerator *= skew_input; // degree-5
121 }
122 {
123 const auto& eccvm_set_permutation_delta = params.eccvm_set_permutation_delta;
124 numerator *= precompute_select * (-eccvm_set_permutation_delta + 1) + eccvm_set_permutation_delta; // degree-7
125 }
126
134 {
135 const auto& table_x = View(in.precompute_tx);
136 const auto& table_y = View(in.precompute_ty);
137
138 const auto& precompute_skew = View(in.precompute_skew);
139 const auto negative_inverse_seven = []() {
140 if constexpr (std::same_as<FF, grumpkin::fr>) {
141 static constexpr FF negative_inverse_seven = FF(-7).invert();
142 return negative_inverse_seven;
143 } else {
144 FF negative_inverse_seven = FF(-7).invert();
145 return negative_inverse_seven;
146 }
147 };
148 auto adjusted_skew =
149 precompute_skew * negative_inverse_seven(); // `precompute_skew` ∈ {0, 7}, `adjusted_skew`∈ {0, -1}
150
151 const auto& wnaf_scalar_sum = View(in.precompute_scalar_sum);
152 const auto w0 = convert_to_wnaf<Accumulator>(View(in.precompute_s1hi), View(in.precompute_s1lo));
153 const auto w1 = convert_to_wnaf<Accumulator>(View(in.precompute_s2hi), View(in.precompute_s2lo));
154 const auto w2 = convert_to_wnaf<Accumulator>(View(in.precompute_s3hi), View(in.precompute_s3lo));
155 const auto w3 = convert_to_wnaf<Accumulator>(View(in.precompute_s4hi), View(in.precompute_s4lo));
156
157 auto row_slice = w0;
158 row_slice += row_slice;
159 row_slice += row_slice;
160 row_slice += row_slice;
161 row_slice += row_slice;
162 row_slice += w1;
163 row_slice += row_slice;
164 row_slice += row_slice;
165 row_slice += row_slice;
166 row_slice += row_slice;
167 row_slice += w2;
168 row_slice += row_slice;
169 row_slice += row_slice;
170 row_slice += row_slice;
171 row_slice += row_slice;
172 row_slice += w3; // row_slice = 2^12 w_0 + 2^8 w_1 + 2^4 w_2 + 2^0 w_3
173
174 auto scalar_sum_full = wnaf_scalar_sum + wnaf_scalar_sum;
175 scalar_sum_full += scalar_sum_full;
176 scalar_sum_full += scalar_sum_full;
177 scalar_sum_full += scalar_sum_full;
178 scalar_sum_full += scalar_sum_full;
179 scalar_sum_full += scalar_sum_full;
180 scalar_sum_full += scalar_sum_full;
181 scalar_sum_full += scalar_sum_full;
182 scalar_sum_full += scalar_sum_full;
183 scalar_sum_full += scalar_sum_full;
184 scalar_sum_full += scalar_sum_full;
185 scalar_sum_full += scalar_sum_full;
186 scalar_sum_full += scalar_sum_full;
187 scalar_sum_full += scalar_sum_full;
188 scalar_sum_full += scalar_sum_full;
189 scalar_sum_full += scalar_sum_full;
190 scalar_sum_full +=
191 row_slice + adjusted_skew; // scalar_sum_full = 2^16 * wnaf_scalar_sum + row_slice + adjusted_skew
192
193 auto precompute_point_transition = View(in.precompute_point_transition);
194
195 auto point_table_init_read =
196 (precompute_pc + table_x * beta + table_y * beta_sqr + scalar_sum_full * beta_cube);
197 point_table_init_read =
198 precompute_point_transition * (point_table_init_read + gamma) + (-precompute_point_transition + 1);
199
200 numerator *= point_table_init_read; // degree-9
201 }
214 {
215 const auto& lagrange_first = View(in.lagrange_first);
216 const auto& partial_msm_transition_shift = View(in.msm_transition_shift);
217 const auto msm_transition_shift = (-lagrange_first + 1) * partial_msm_transition_shift;
218 const auto& msm_pc_shift = View(in.msm_pc_shift);
219
220 const auto& msm_x_shift = View(in.msm_accumulator_x_shift);
221 const auto& msm_y_shift = View(in.msm_accumulator_y_shift);
222 const auto& msm_size = View(in.msm_size_of_msm);
223
224 // msm_transition = 1 when a row BEGINS a new msm
225 //
226 // row msm tx acc.x acc.y pc msm_size
227 // i 0 no no no yes
228 // i+1 1 yes yes yes no
229 //
230 // at row i we are at the final row of the current msm
231 // at row i the value of `msm_size` = size of current msm
232 // at row i + 1 we have the final accumulated value of the msm computation
233 // at row i + 1 we have updated `pc` to be `(pc at start of msm) + msm_count`
234 // at row i + 1 q_msm_transtiion = 1
235
236 auto msm_result_write = msm_pc_shift + msm_x_shift * beta + msm_y_shift * beta_sqr + msm_size * beta_cube;
237
238 // msm_result_write = degree 2
239 msm_result_write = msm_transition_shift * (msm_result_write + gamma) + (-msm_transition_shift + 1);
240 numerator *= msm_result_write; // degree-11
241 }
242 return numerator;
243}
244
245template <typename FF>
246template <typename Accumulator, typename AllEntities, typename Parameters>
247Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_denominator(const AllEntities& in, const Parameters& params)
248{
249 using View = typename Accumulator::View;
250
251 // TODO(@zac-williamson). The degree of this contribution is 17! makes overall relation degree 19.
252 // Can optimize by refining the algebra, once we have a stable base to iterate off of.
253 const auto& gamma = params.gamma;
254 const auto& beta = params.beta;
255 const auto& beta_sqr = params.beta_sqr;
256 const auto& beta_cube = params.beta_cube;
257 const auto& msm_pc = View(in.msm_pc);
258 const auto& msm_count = View(in.msm_count);
259 const auto& msm_round = View(in.msm_round);
260
266 Accumulator denominator(1); // degree-0
267 {
268 const auto& add1 = View(in.msm_add1);
269 const auto& msm_slice1 = View(in.msm_slice1);
270
271 auto wnaf_slice_output1 =
272 add1 * (msm_slice1 + gamma + (msm_pc - msm_count) * beta + msm_round * beta_sqr) + (-add1 + 1);
273 denominator *= wnaf_slice_output1; // degree-2
274 }
275 {
276 const auto& add2 = View(in.msm_add2);
277 const auto& msm_slice2 = View(in.msm_slice2);
278
279 auto wnaf_slice_output2 =
280 add2 * (msm_slice2 + gamma + (msm_pc - msm_count - 1) * beta + msm_round * beta_sqr) + (-add2 + 1);
281 denominator *= wnaf_slice_output2; // degree-4
282 }
283 {
284 const auto& add3 = View(in.msm_add3);
285 const auto& msm_slice3 = View(in.msm_slice3);
286
287 auto wnaf_slice_output3 =
288 add3 * (msm_slice3 + gamma + (msm_pc - msm_count - 2) * beta + msm_round * beta_sqr) + (-add3 + 1);
289 denominator *= wnaf_slice_output3; // degree-6
290 }
291 {
292 const auto& add4 = View(in.msm_add4);
293 const auto& msm_slice4 = View(in.msm_slice4);
294 auto wnaf_slice_output4 =
295 add4 * (msm_slice4 + gamma + (msm_pc - msm_count - 3) * beta + msm_round * beta_sqr) + (-add4 + 1);
296 denominator *= wnaf_slice_output4; // degree-8
297 }
298
305 {
306 const auto& transcript_pc = View(in.transcript_pc);
307
308 auto transcript_Px = View(in.transcript_Px);
309 auto transcript_Py = View(in.transcript_Py);
310 auto z1 = View(in.transcript_z1);
311 auto z2 = View(in.transcript_z2);
312 auto z1_zero = View(in.transcript_z1zero);
313 auto z2_zero = View(in.transcript_z2zero);
314 auto base_infinity = View(in.transcript_base_infinity);
315 auto transcript_mul = View(in.transcript_mul);
316
317 auto lookup_first = (-z1_zero + 1);
318 auto lookup_second = (-z2_zero + 1);
319 FF endomorphism_base_field_shift = FF(bb::fq::cube_root_of_unity());
320
321 auto transcript_input1 =
322 transcript_pc + transcript_Px * beta + transcript_Py * beta_sqr + z1 * beta_cube; // degree = 1
323 auto transcript_input2 = (transcript_pc - 1) + transcript_Px * endomorphism_base_field_shift * beta -
324 transcript_Py * beta_sqr + z2 * beta_cube; // degree = 2
325
326 // | q_mul | z2_zero | z1_zero | base_infinity | lookup |
327 // | ----- | ------- | ------- | ------------- |----------------------- |
328 // | 0 | - | - | - | 1 |
329 // | 1 | 0 | 0 | 0 | 1 |
330 // | 1 | 0 | 1 | 0 | X + gamma |
331 // | 1 | 1 | 0 | 0 | Y + gamma |
332 // | 1 | 1 | 1 | 0 | (X + gamma)(Y + gamma) |
333 // | 1 | 0 | 0 | 1 | 1 |
334 // | 1 | 0 | 1 | 1 | 1 |
335 // | 1 | 1 | 0 | 1 | 1 |
336 // | 1 | 1 | 1 | 1 | 1 |
337 transcript_input1 = (transcript_input1 + gamma) * lookup_first + (-lookup_first + 1); // degree 2
338 transcript_input2 = (transcript_input2 + gamma) * lookup_second + (-lookup_second + 1); // degree 3
339
340 // transcript_product = degree 6
341 auto transcript_product = (transcript_input1 * transcript_input2) * (-base_infinity + 1) + base_infinity;
342
343 // point_table_init_write = degree 7
344 auto point_table_init_write = transcript_mul * transcript_product + (-transcript_mul + 1);
345 denominator *= point_table_init_write; // degree 17
346 }
354 {
355 auto transcript_pc_shift = View(in.transcript_pc_shift);
356 auto transcript_msm_x = View(in.transcript_msm_x);
357 auto transcript_msm_y = View(in.transcript_msm_y);
358 auto transcript_msm_transition = View(in.transcript_msm_transition);
359 auto transcript_msm_count = View(in.transcript_msm_count);
360 auto z1_zero = View(in.transcript_z1zero);
361 auto z2_zero = View(in.transcript_z2zero);
362 auto transcript_mul = View(in.transcript_mul);
363 auto base_infinity = View(in.transcript_base_infinity);
364
365 // do not add to count if point at infinity!
366 auto full_msm_count =
367 transcript_msm_count + transcript_mul * ((-z1_zero + 1) + (-z2_zero + 1)) * (-base_infinity + 1);
368 // msm_result_read = degree 2
369 auto msm_result_read =
370 transcript_pc_shift + transcript_msm_x * beta + transcript_msm_y * beta_sqr + full_msm_count * beta_cube;
371 msm_result_read = transcript_msm_transition * (msm_result_read + gamma) + (-transcript_msm_transition + 1);
372 denominator *= msm_result_read; // degree-20
373 }
374 return denominator;
375}
376
387template <typename FF>
388template <typename ContainerOverSubrelations, typename AllEntities, typename Parameters>
389void ECCVMSetRelationImpl<FF>::accumulate(ContainerOverSubrelations& accumulator,
390 const AllEntities& in,
391 const Parameters& params,
392 const FF& scaling_factor)
393{
394 using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>;
395 using View = typename Accumulator::View;
396 using ShortView = typename std::tuple_element_t<1, ContainerOverSubrelations>::View;
397
398 // degree-11
399 Accumulator numerator_evaluation = compute_grand_product_numerator<Accumulator>(in, params);
400
401 // degree-20
402 Accumulator denominator_evaluation = compute_grand_product_denominator<Accumulator>(in, params);
403
404 const auto& lagrange_first = View(in.lagrange_first);
405 const auto& lagrange_last = View(in.lagrange_last);
406 const auto& lagrange_last_short = ShortView(in.lagrange_last);
407
408 const auto& z_perm = View(in.z_perm);
409 const auto& z_perm_shift = View(in.z_perm_shift);
410 const auto& z_perm_shift_short = ShortView(in.z_perm_shift);
411
412 // degree-21
413 std::get<0>(accumulator) +=
414 ((z_perm + lagrange_first) * numerator_evaluation - (z_perm_shift + lagrange_last) * denominator_evaluation) *
415 scaling_factor;
416
417 // Contribution (2)
418 std::get<1>(accumulator) += lagrange_last_short * z_perm_shift_short * scaling_factor;
419}
420} // namespace bb
static Accumulator compute_grand_product_denominator(const AllEntities &in, const Parameters &params)
static Accumulator compute_grand_product_numerator(const AllEntities &in, const Parameters &params)
Performs list-equivalence checks for the ECCVM.
static void accumulate(ContainerOverSubrelations &accumulator, const AllEntities &in, const Parameters &params, const FF &scaling_factor)
Expression for the standard arithmetic gate. @dbetails The relation is defined as C(in(X)....
Entry point for Barretenberg command-line interface.
typename Flavor::FF FF
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static constexpr field cube_root_of_unity()
constexpr field invert() const noexcept