62 using View =
typename Accumulator::View;
64 const auto& precompute_round = View(in.precompute_round);
65 const auto precompute_round2 = precompute_round + precompute_round;
66 const auto precompute_round4 = precompute_round2 + precompute_round2;
68 const auto& gamma = params.gamma;
69 const auto& beta = params.beta;
70 const auto& beta_sqr = params.beta_sqr;
71 const auto& beta_cube = params.beta_cube;
72 const auto& precompute_pc = View(in.precompute_pc);
73 const auto& precompute_select = View(in.precompute_select);
89 Accumulator numerator(1);
91 const auto& s0 = View(in.precompute_s1hi);
92 const auto& s1 = View(in.precompute_s1lo);
94 auto wnaf_slice = s0 + s0;
95 wnaf_slice += wnaf_slice;
98 const auto wnaf_slice_input0 = wnaf_slice + gamma + precompute_pc * beta + precompute_round4 * beta_sqr;
99 numerator *= wnaf_slice_input0;
102 const auto& s0 = View(in.precompute_s2hi);
103 const auto& s1 = View(in.precompute_s2lo);
105 auto wnaf_slice = s0 + s0;
106 wnaf_slice += wnaf_slice;
109 const auto wnaf_slice_input1 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 1) * beta_sqr;
110 numerator *= wnaf_slice_input1;
113 const auto& s0 = View(in.precompute_s3hi);
114 const auto& s1 = View(in.precompute_s3lo);
116 auto wnaf_slice = s0 + s0;
117 wnaf_slice += wnaf_slice;
120 const auto wnaf_slice_input2 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 2) * beta_sqr;
121 numerator *= wnaf_slice_input2;
124 const auto& s0 = View(in.precompute_s4hi);
125 const auto& s1 = View(in.precompute_s4lo);
127 auto wnaf_slice = s0 + s0;
128 wnaf_slice += wnaf_slice;
130 const auto wnaf_slice_input3 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 3) * beta_sqr;
131 numerator *= wnaf_slice_input3;
135 const auto& skew = View(in.precompute_skew);
136 const auto& precompute_point_transition = View(in.precompute_point_transition);
137 const auto skew_input =
138 precompute_point_transition * (skew + gamma + precompute_pc * beta + (precompute_round4 + 4) * beta_sqr) +
139 (-precompute_point_transition + 1);
140 numerator *= skew_input;
143 const auto& eccvm_set_permutation_delta = params.eccvm_set_permutation_delta;
147 numerator *= precompute_select * (-eccvm_set_permutation_delta + 1) + eccvm_set_permutation_delta;
164 const auto& table_x = View(in.precompute_tx);
165 const auto& table_y = View(in.precompute_ty);
167 const auto& precompute_skew = View(in.precompute_skew);
168 const auto negative_inverse_seven = []() {
170 static constexpr FF negative_inverse_seven =
FF(-7).
invert();
171 return negative_inverse_seven;
174 return negative_inverse_seven;
178 precompute_skew * negative_inverse_seven();
180 const auto& wnaf_scalar_sum = View(in.precompute_scalar_sum);
181 const auto w0 = convert_to_wnaf<Accumulator>(View(in.precompute_s1hi), View(in.precompute_s1lo));
182 const auto w1 = convert_to_wnaf<Accumulator>(View(in.precompute_s2hi), View(in.precompute_s2lo));
183 const auto w2 = convert_to_wnaf<Accumulator>(View(in.precompute_s3hi), View(in.precompute_s3lo));
184 const auto w3 = convert_to_wnaf<Accumulator>(View(in.precompute_s4hi), View(in.precompute_s4lo));
187 row_slice += row_slice;
188 row_slice += row_slice;
189 row_slice += row_slice;
190 row_slice += row_slice;
192 row_slice += row_slice;
193 row_slice += row_slice;
194 row_slice += row_slice;
195 row_slice += row_slice;
197 row_slice += row_slice;
198 row_slice += row_slice;
199 row_slice += row_slice;
200 row_slice += row_slice;
203 auto scalar_sum_full = wnaf_scalar_sum + wnaf_scalar_sum;
204 scalar_sum_full += scalar_sum_full;
205 scalar_sum_full += scalar_sum_full;
206 scalar_sum_full += scalar_sum_full;
207 scalar_sum_full += scalar_sum_full;
208 scalar_sum_full += scalar_sum_full;
209 scalar_sum_full += scalar_sum_full;
210 scalar_sum_full += scalar_sum_full;
211 scalar_sum_full += scalar_sum_full;
212 scalar_sum_full += scalar_sum_full;
213 scalar_sum_full += scalar_sum_full;
214 scalar_sum_full += scalar_sum_full;
215 scalar_sum_full += scalar_sum_full;
216 scalar_sum_full += scalar_sum_full;
217 scalar_sum_full += scalar_sum_full;
218 scalar_sum_full += scalar_sum_full;
220 row_slice + adjusted_skew;
222 auto precompute_point_transition = View(in.precompute_point_transition);
224 auto point_table_init_read =
225 (precompute_pc + table_x * beta + table_y * beta_sqr + scalar_sum_full * beta_cube);
226 point_table_init_read =
227 precompute_point_transition * (point_table_init_read + gamma) + (-precompute_point_transition + 1);
229 numerator *= point_table_init_read;
249 const auto& lagrange_first = View(in.lagrange_first);
250 const auto& partial_msm_transition_shift = View(in.msm_transition_shift);
251 const auto msm_transition_shift = (-lagrange_first + 1) * partial_msm_transition_shift;
252 const auto& msm_pc_shift = View(in.msm_pc_shift);
254 const auto& msm_x_shift = View(in.msm_accumulator_x_shift);
255 const auto& msm_y_shift = View(in.msm_accumulator_y_shift);
256 const auto& msm_size = View(in.msm_size_of_msm);
270 auto msm_result_write = msm_pc_shift + msm_x_shift * beta + msm_y_shift * beta_sqr + msm_size * beta_cube;
273 msm_result_write = msm_transition_shift * (msm_result_write + gamma) + (-msm_transition_shift + 1);
274 numerator *= msm_result_write;
283 using View =
typename Accumulator::View;
287 const auto& gamma = params.gamma;
288 const auto& beta = params.beta;
289 const auto& beta_sqr = params.beta_sqr;
290 const auto& beta_cube = params.beta_cube;
291 const auto& msm_pc = View(in.msm_pc);
292 const auto& msm_count = View(in.msm_count);
293 const auto& msm_round = View(in.msm_round);
300 Accumulator denominator(1);
302 const auto& add1 = View(in.msm_add1);
303 const auto& msm_slice1 = View(in.msm_slice1);
305 auto wnaf_slice_output1 =
306 add1 * (msm_slice1 + gamma + (msm_pc - msm_count) * beta + msm_round * beta_sqr) + (-add1 + 1);
307 denominator *= wnaf_slice_output1;
310 const auto& add2 = View(in.msm_add2);
311 const auto& msm_slice2 = View(in.msm_slice2);
313 auto wnaf_slice_output2 =
314 add2 * (msm_slice2 + gamma + (msm_pc - msm_count - 1) * beta + msm_round * beta_sqr) + (-add2 + 1);
315 denominator *= wnaf_slice_output2;
318 const auto& add3 = View(in.msm_add3);
319 const auto& msm_slice3 = View(in.msm_slice3);
321 auto wnaf_slice_output3 =
322 add3 * (msm_slice3 + gamma + (msm_pc - msm_count - 2) * beta + msm_round * beta_sqr) + (-add3 + 1);
323 denominator *= wnaf_slice_output3;
326 const auto& add4 = View(in.msm_add4);
327 const auto& msm_slice4 = View(in.msm_slice4);
328 auto wnaf_slice_output4 =
329 add4 * (msm_slice4 + gamma + (msm_pc - msm_count - 3) * beta + msm_round * beta_sqr) + (-add4 + 1);
330 denominator *= wnaf_slice_output4;
344 const auto& transcript_pc = View(in.transcript_pc);
346 const auto& transcript_Px = View(in.transcript_Px);
347 const auto& transcript_Py = View(in.transcript_Py);
348 const auto& z1 = View(in.transcript_z1);
349 const auto& z2 = View(in.transcript_z2);
350 const auto& z1_zero = View(in.transcript_z1zero);
351 const auto& z2_zero = View(in.transcript_z2zero);
352 const auto& base_infinity = View(in.transcript_base_infinity);
353 const auto& transcript_mul = View(in.transcript_mul);
355 const auto& lookup_first = (-z1_zero + 1);
356 const auto& lookup_second = (-z2_zero + 1);
359 auto transcript_input1 =
360 transcript_pc + transcript_Px * beta + transcript_Py * beta_sqr + z1 * beta_cube;
361 auto transcript_input2 = (transcript_pc - 1) + transcript_Px * cube_root_unity * beta -
362 transcript_Py * beta_sqr + z2 * beta_cube;
380 transcript_input1 = (transcript_input1 + gamma) * lookup_first + (-lookup_first + 1);
381 transcript_input2 = (transcript_input2 + gamma) * lookup_second + (-lookup_second + 1);
384 auto transcript_product = (transcript_input1 * transcript_input2) * (-base_infinity + 1) + base_infinity;
387 auto point_table_init_write = transcript_mul * transcript_product + (-transcript_mul + 1);
388 denominator *= point_table_init_write;
406 const auto& transcript_pc_shift = View(in.transcript_pc_shift);
407 const auto& transcript_msm_x = View(in.transcript_msm_x);
408 const auto& transcript_msm_y = View(in.transcript_msm_y);
409 const auto& transcript_msm_transition = View(in.transcript_msm_transition);
410 const auto& transcript_msm_count = View(in.transcript_msm_count);
411 const auto& z1_zero = View(in.transcript_z1zero);
412 const auto& z2_zero = View(in.transcript_z2zero);
413 const auto& transcript_mul = View(in.transcript_mul);
414 const auto& base_infinity = View(in.transcript_base_infinity);
417 auto full_msm_count =
418 transcript_msm_count + transcript_mul * ((-z1_zero + 1) + (-z2_zero + 1)) * (-base_infinity + 1);
420 auto msm_result_read =
421 transcript_pc_shift + transcript_msm_x * beta + transcript_msm_y * beta_sqr + full_msm_count * beta_cube;
422 msm_result_read = transcript_msm_transition * (msm_result_read + gamma) + (-transcript_msm_transition + 1);
423 denominator *= msm_result_read;
441 const AllEntities& in,
442 const Parameters& params,
443 const FF& scaling_factor)
446 using View =
typename Accumulator::View;
447 using ShortView =
typename std::tuple_element_t<1, ContainerOverSubrelations>::View;
450 Accumulator numerator_evaluation = compute_grand_product_numerator<Accumulator>(in, params);
453 Accumulator denominator_evaluation = compute_grand_product_denominator<Accumulator>(in, params);
455 const auto& lagrange_first = View(in.lagrange_first);
456 const auto& lagrange_last = View(in.lagrange_last);
457 const auto& lagrange_last_short = ShortView(in.lagrange_last);
459 const auto& z_perm = View(in.z_perm);
460 const auto& z_perm_shift = View(in.z_perm_shift);
461 const auto& z_perm_shift_short = ShortView(in.z_perm_shift);
465 ((z_perm + lagrange_first) * numerator_evaluation - (z_perm_shift + lagrange_last) * denominator_evaluation) *
469 std::get<1>(accumulator) += lagrange_last_short * z_perm_shift_short * scaling_factor;