46 using View =
typename Accumulator::View;
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;
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);
65 Accumulator numerator(1);
67 const auto& s0 = View(in.precompute_s1hi);
68 const auto& s1 = View(in.precompute_s1lo);
70 auto wnaf_slice = s0 + s0;
71 wnaf_slice += wnaf_slice;
75 const auto wnaf_slice_input0 = wnaf_slice + gamma + precompute_pc * beta + precompute_round4 * beta_sqr;
76 numerator *= wnaf_slice_input0;
79 const auto& s0 = View(in.precompute_s2hi);
80 const auto& s1 = View(in.precompute_s2lo);
82 auto wnaf_slice = s0 + s0;
83 wnaf_slice += wnaf_slice;
87 const auto wnaf_slice_input1 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 1) * beta_sqr;
88 numerator *= wnaf_slice_input1;
91 const auto& s0 = View(in.precompute_s3hi);
92 const auto& s1 = View(in.precompute_s3lo);
94 auto wnaf_slice = s0 + s0;
95 wnaf_slice += wnaf_slice;
99 const auto wnaf_slice_input2 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 2) * beta_sqr;
100 numerator *= wnaf_slice_input2;
103 const auto& s0 = View(in.precompute_s4hi);
104 const auto& s1 = View(in.precompute_s4lo);
106 auto wnaf_slice = s0 + s0;
107 wnaf_slice += wnaf_slice;
110 const auto wnaf_slice_input3 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 3) * beta_sqr;
111 numerator *= wnaf_slice_input3;
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;
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;
135 const auto& table_x = View(in.precompute_tx);
136 const auto& table_y = View(in.precompute_ty);
138 const auto& precompute_skew = View(in.precompute_skew);
139 const auto negative_inverse_seven = []() {
141 static constexpr FF negative_inverse_seven =
FF(-7).
invert();
142 return negative_inverse_seven;
145 return negative_inverse_seven;
149 precompute_skew * negative_inverse_seven();
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));
158 row_slice += row_slice;
159 row_slice += row_slice;
160 row_slice += row_slice;
161 row_slice += row_slice;
163 row_slice += row_slice;
164 row_slice += row_slice;
165 row_slice += row_slice;
166 row_slice += row_slice;
168 row_slice += row_slice;
169 row_slice += row_slice;
170 row_slice += row_slice;
171 row_slice += row_slice;
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;
191 row_slice + adjusted_skew;
193 auto precompute_point_transition = View(in.precompute_point_transition);
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);
200 numerator *= point_table_init_read;
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);
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);
236 auto msm_result_write = msm_pc_shift + msm_x_shift * beta + msm_y_shift * beta_sqr + msm_size * beta_cube;
239 msm_result_write = msm_transition_shift * (msm_result_write + gamma) + (-msm_transition_shift + 1);
240 numerator *= msm_result_write;
249 using View =
typename Accumulator::View;
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);
266 Accumulator denominator(1);
268 const auto& add1 = View(in.msm_add1);
269 const auto& msm_slice1 = View(in.msm_slice1);
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;
276 const auto& add2 = View(in.msm_add2);
277 const auto& msm_slice2 = View(in.msm_slice2);
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;
284 const auto& add3 = View(in.msm_add3);
285 const auto& msm_slice3 = View(in.msm_slice3);
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;
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;
306 const auto& transcript_pc = View(in.transcript_pc);
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);
317 auto lookup_first = (-z1_zero + 1);
318 auto lookup_second = (-z2_zero + 1);
321 auto transcript_input1 =
322 transcript_pc + transcript_Px * beta + transcript_Py * beta_sqr + z1 * beta_cube;
323 auto transcript_input2 = (transcript_pc - 1) + transcript_Px * endomorphism_base_field_shift * beta -
324 transcript_Py * beta_sqr + z2 * beta_cube;
337 transcript_input1 = (transcript_input1 + gamma) * lookup_first + (-lookup_first + 1);
338 transcript_input2 = (transcript_input2 + gamma) * lookup_second + (-lookup_second + 1);
341 auto transcript_product = (transcript_input1 * transcript_input2) * (-base_infinity + 1) + base_infinity;
344 auto point_table_init_write = transcript_mul * transcript_product + (-transcript_mul + 1);
345 denominator *= point_table_init_write;
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);
366 auto full_msm_count =
367 transcript_msm_count + transcript_mul * ((-z1_zero + 1) + (-z2_zero + 1)) * (-base_infinity + 1);
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;
390 const AllEntities& in,
391 const Parameters& params,
392 const FF& scaling_factor)
395 using View =
typename Accumulator::View;
396 using ShortView =
typename std::tuple_element_t<1, ContainerOverSubrelations>::View;
399 Accumulator numerator_evaluation = compute_grand_product_numerator<Accumulator>(in, params);
402 Accumulator denominator_evaluation = compute_grand_product_denominator<Accumulator>(in, params);
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);
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);
414 ((z_perm + lagrange_first) * numerator_evaluation - (z_perm_shift + lagrange_last) * denominator_evaluation) *
418 std::get<1>(accumulator) += lagrange_last_short * z_perm_shift_short * scaling_factor;