41 const AllEntities& in,
43 const FF& scaling_factor)
46 using View =
typename Accumulator::View;
48 static const auto offset_generator = [&]() {
52 static const FF qx = result.x;
53 static const FF qy = result.y;
54 static const Accumulator ox(qx);
55 static const Accumulator oy(qy);
58 const auto z1 = View(in.transcript_z1);
59 const auto z2 = View(in.transcript_z2);
60 const auto z1_zero = View(in.transcript_z1zero);
61 const auto z2_zero = View(in.transcript_z2zero);
62 const auto op = View(in.transcript_op);
63 const auto q_add = View(in.transcript_add);
64 const auto q_mul = View(in.transcript_mul);
65 const auto q_mul_shift = View(in.transcript_mul_shift);
66 const auto q_eq = View(in.transcript_eq);
67 const auto msm_transition = View(in.transcript_msm_transition);
68 const auto msm_count = View(in.transcript_msm_count);
69 const auto msm_count_shift = View(in.transcript_msm_count_shift);
70 const auto pc = View(in.transcript_pc);
71 const auto pc_shift = View(in.transcript_pc_shift);
72 const auto transcript_accumulator_x_shift = View(in.transcript_accumulator_x_shift);
73 const auto transcript_accumulator_y_shift = View(in.transcript_accumulator_y_shift);
74 const auto transcript_accumulator_x = View(in.transcript_accumulator_x);
75 const auto transcript_accumulator_y = View(in.transcript_accumulator_y);
76 const auto msm_count_zero_at_transition = View(in.transcript_msm_count_zero_at_transition);
77 const auto msm_count_at_transition_inverse = View(in.transcript_msm_count_at_transition_inverse);
78 const auto transcript_msm_x = View(in.transcript_msm_intermediate_x);
79 const auto transcript_msm_y = View(in.transcript_msm_intermediate_y);
80 const auto transcript_Px = View(in.transcript_Px);
81 const auto transcript_Py = View(in.transcript_Py);
82 const auto is_accumulator_empty = -View(in.transcript_accumulator_not_empty) + 1;
83 const auto lagrange_first = View(in.lagrange_first);
84 const auto lagrange_last = View(in.lagrange_last);
85 const auto is_accumulator_empty_shift = -View(in.transcript_accumulator_not_empty_shift) + 1;
86 const auto q_reset_accumulator = View(in.transcript_reset_accumulator);
87 const auto lagrange_second = View(in.lagrange_second);
88 const auto lagrange_third = View(in.lagrange_third);
89 const auto transcript_Pinfinity = View(in.transcript_base_infinity);
90 const auto transcript_Px_inverse = View(in.transcript_base_x_inverse);
91 const auto transcript_Py_inverse = View(in.transcript_base_y_inverse);
92 const auto transcript_add_x_equal = View(in.transcript_add_x_equal);
93 const auto transcript_add_y_equal = View(in.transcript_add_y_equal);
94 const auto transcript_add_lambda = View(in.transcript_add_lambda);
95 const auto transcript_msm_infinity = View(in.transcript_msm_infinity);
97 const auto is_not_first_row = (-lagrange_first + 1);
98 const auto is_not_last_row = (-lagrange_last + 1);
99 const auto is_not_first_or_last_row = (-lagrange_first + -lagrange_last + 1);
100 const auto is_not_infinity = (-transcript_Pinfinity + 1);
102 const auto is_not_hiding_row = (-lagrange_second + 1);
114 std::get<0>(accumulator) += (z1 * z1_zero) * scaling_factor;
115 std::get<1>(accumulator) += (z2 * z2_zero) * scaling_factor;
122 auto tmp = q_add + q_add;
127 tmp += q_reset_accumulator;
128 std::get<2>(accumulator) += (tmp - op) * scaling_factor;
137 Accumulator pc_delta = pc - pc_shift;
138 auto num_muls_in_row = ((-z1_zero + 1) + (-z2_zero + 1)) * (-transcript_Pinfinity + 1);
141 std::get<3>(accumulator) += is_not_first_row * (pc_delta - q_mul * num_muls_in_row) * scaling_factor;
162 auto msm_transition_check = q_mul * (-q_mul_shift + 1);
163 auto msm_count_total = msm_count + num_muls_in_row;
169 auto msm_count_zero_at_transition_check = msm_count_zero_at_transition * msm_count_total;
170 msm_count_zero_at_transition_check +=
171 (msm_count_total * msm_count_at_transition_inverse - 1) * (-msm_count_zero_at_transition + 1);
176 std::get<4>(accumulator) += msm_transition_check * msm_count_zero_at_transition_check * scaling_factor;
186 (msm_transition - msm_transition_check * (-msm_count_zero_at_transition + 1)) * scaling_factor;
196 std::get<6>(accumulator) += ((-q_mul + 1) * msm_count) * scaling_factor;
203 auto msm_count_delta = msm_count_shift - msm_count;
204 std::get<7>(accumulator) += is_not_first_row * (-msm_transition + 1) * (msm_count_delta - q_mul * num_muls_in_row) *
213 auto opcode_exclusion_relation = q_mul * (q_add + q_eq + q_reset_accumulator);
214 opcode_exclusion_relation += q_add * (q_mul + q_eq + q_reset_accumulator);
215 std::get<8>(accumulator) += opcode_exclusion_relation * scaling_factor;
224 auto both_infinity = transcript_Pinfinity * is_accumulator_empty;
225 auto both_not_infinity = (-transcript_Pinfinity + 1) * (-is_accumulator_empty + 1);
226 auto infinity_exclusion_check =
227 transcript_Pinfinity + is_accumulator_empty - both_infinity - both_infinity;
228 auto eq_x_diff = transcript_Px - transcript_accumulator_x;
229 auto eq_y_diff = transcript_Py - transcript_accumulator_y;
231 auto eq_x_diff_relation =
232 q_eq * (eq_x_diff * both_not_infinity + infinity_exclusion_check) * is_not_hiding_row;
233 auto eq_y_diff_relation =
234 q_eq * (eq_y_diff * both_not_infinity + infinity_exclusion_check) * is_not_hiding_row;
235 std::get<9>(accumulator) += eq_x_diff_relation * scaling_factor;
236 std::get<10>(accumulator) += eq_y_diff_relation * scaling_factor;
248 std::get<11>(accumulator) += lagrange_third * (-is_accumulator_empty + 1) * scaling_factor;
249 std::get<12>(accumulator) += (lagrange_third * msm_count + lagrange_last * pc) * scaling_factor;
258 const auto validate_on_curve = q_add + q_mul + q_eq;
259 const auto on_curve_check =
260 transcript_Py * transcript_Py - transcript_Px * transcript_Px * transcript_Px - get_curve_b();
263 validate_on_curve * on_curve_check * is_not_infinity * is_not_hiding_row * scaling_factor;
272 Accumulator transcript_lambda_relation(0);
273 auto is_double = transcript_add_x_equal * transcript_add_y_equal;
276 auto is_add = -transcript_add_x_equal + 1;
280 auto add_result_is_infinity = transcript_add_x_equal * (-transcript_add_y_equal + 1);
281 auto rhs_x = transcript_accumulator_x;
282 auto rhs_y = transcript_accumulator_y;
283 auto out_x = transcript_accumulator_x_shift;
284 auto out_y = transcript_accumulator_y_shift;
285 auto lambda = transcript_add_lambda;
289 auto lhs_x = transcript_Px * q_add + transcript_msm_x * msm_transition;
290 auto lhs_y = transcript_Py * q_add + transcript_msm_y * msm_transition;
292 auto lhs_infinity = transcript_Pinfinity * q_add + transcript_msm_infinity * msm_transition;
293 auto rhs_infinity = is_accumulator_empty;
296 auto result_is_lhs = rhs_infinity * (-lhs_infinity + 1);
297 auto result_is_rhs = (-rhs_infinity + 1) * lhs_infinity;
300 auto result_infinity_from_inputs = lhs_infinity * rhs_infinity;
303 auto result_infinity_from_operation = transcript_add_x_equal * (-transcript_add_y_equal + 1);
307 auto result_is_infinity = result_infinity_from_inputs + result_infinity_from_operation;
308 auto any_add_is_active = q_add + msm_transition;
312 Accumulator transcript_msm_lambda_relation(0);
313 auto msm_x = transcript_msm_x;
314 auto msm_y = transcript_msm_y;
317 auto lambda_denominator = (rhs_x - msm_x);
318 auto lambda_numerator = (rhs_y - msm_y);
319 auto lambda_relation = lambda * lambda_denominator - lambda_numerator;
320 transcript_msm_lambda_relation += lambda_relation * is_add;
324 auto lambda_denominator = msm_y + msm_y;
325 auto lambda_numerator = msm_x * msm_x * 3;
326 auto lambda_relation = lambda * lambda_denominator - lambda_numerator;
327 transcript_msm_lambda_relation += lambda_relation * is_double;
329 auto transcript_add_or_dbl_from_msm_output_is_valid =
330 (-transcript_msm_infinity + 1) * (-is_accumulator_empty + 1);
334 transcript_msm_lambda_relation *= transcript_add_or_dbl_from_msm_output_is_valid;
339 auto lambda_relation_invalid =
340 (transcript_msm_infinity + is_accumulator_empty + add_result_is_infinity);
341 auto lambda_relation = lambda * lambda_relation_invalid;
342 transcript_msm_lambda_relation += lambda_relation;
345 transcript_lambda_relation = transcript_msm_lambda_relation * msm_transition;
350 Accumulator transcript_add_lambda_relation(0);
351 auto add_x = transcript_Px;
352 auto add_y = transcript_Py;
355 auto lambda_denominator = (rhs_x - add_x);
356 auto lambda_numerator = (rhs_y - add_y);
357 auto lambda_relation = lambda * lambda_denominator - lambda_numerator;
358 transcript_add_lambda_relation += lambda_relation * is_add;
362 auto lambda_denominator = add_y + add_y;
363 auto lambda_numerator = add_x * add_x * 3;
364 auto lambda_relation = lambda * lambda_denominator - lambda_numerator;
365 transcript_add_lambda_relation += lambda_relation * is_double;
367 auto transcript_add_or_dbl_from_add_output_is_valid =
368 (-transcript_Pinfinity + 1) * (-is_accumulator_empty + 1);
369 transcript_add_lambda_relation *= transcript_add_or_dbl_from_add_output_is_valid;
374 auto lambda_relation_invalid =
375 (transcript_Pinfinity + is_accumulator_empty + add_result_is_infinity);
376 auto lambda_relation = lambda * lambda_relation_invalid;
377 transcript_add_lambda_relation += lambda_relation;
380 transcript_lambda_relation += transcript_add_lambda_relation * q_add;
381 std::get<14>(accumulator) += transcript_lambda_relation * scaling_factor;
397 auto propagate_transcript_accumulator =
398 (q_mul) * (-msm_transition + 1) + (q_eq * (-q_reset_accumulator + 1));
400 auto lambda_sqr = lambda * lambda;
405 auto x3 = lambda_sqr - lhs_x - rhs_x;
406 auto y3 = lambda * (lhs_x - out_x) - lhs_y;
407 x3 += result_is_lhs * (rhs_x + lhs_x + lhs_x);
408 x3 += result_is_rhs * (lhs_x + rhs_x + rhs_x);
409 x3 += result_is_infinity * (lhs_x + rhs_x);
410 y3 += result_is_lhs * (lhs_y + lhs_y);
411 y3 += result_is_rhs * (lhs_y + rhs_y);
412 y3 += result_is_infinity * lhs_y;
416 auto add_point_x_relation = (x3 - out_x) * any_add_is_active;
417 add_point_x_relation +=
418 propagate_transcript_accumulator * is_not_last_row * (out_x - transcript_accumulator_x);
420 add_point_x_relation += (out_x * q_reset_accumulator);
421 auto add_point_y_relation = (y3 - out_y) * any_add_is_active;
422 add_point_y_relation +=
423 propagate_transcript_accumulator * is_not_last_row * (out_y - transcript_accumulator_y);
425 add_point_y_relation += (out_y * q_reset_accumulator);
426 auto opcode_is_zero =
427 (is_not_first_row) * (-q_add + 1) * (-q_mul + 1) * (-q_reset_accumulator + 1) * (-q_eq + 1);
428 add_point_x_relation += (out_x * opcode_is_zero);
429 add_point_y_relation += (out_y * opcode_is_zero);
431 std::get<15>(accumulator) += add_point_x_relation * scaling_factor;
432 std::get<16>(accumulator) += add_point_y_relation * scaling_factor;
440 const auto offset = offset_generator();
441 const auto x1 =
offset[0];
442 const auto y1 = -
offset[1];
443 const auto x2 = View(in.transcript_msm_x);
444 const auto y2 = View(in.transcript_msm_y);
445 const auto x3 = View(in.transcript_msm_intermediate_x);
446 const auto y3 = View(in.transcript_msm_intermediate_y);
447 const auto transcript_msm_infinity = View(in.transcript_msm_infinity);
451 const auto x_term = (x3 + x2 + x1) * (x2 - x1) * (x2 - x1) - (y2 - y1) * (y2 - y1);
452 const auto y_term = (x1 - x3) * (y2 - y1) - (x2 - x1) * (y1 + y3);
459 const auto transcript_offset_generator_subtract_x =
460 x_term * (-transcript_msm_infinity + 1) + transcript_msm_infinity * x3;
461 const auto transcript_offset_generator_subtract_y =
462 y_term * (-transcript_msm_infinity + 1) + transcript_msm_infinity * y3;
464 msm_transition * transcript_offset_generator_subtract_x * scaling_factor;
466 msm_transition * transcript_offset_generator_subtract_y * scaling_factor;
471 const auto x_diff = x2 - x1;
472 const auto y_sum = y2 + y1;
473 std::get<19>(accumulator) += msm_transition * transcript_msm_infinity * x_diff * scaling_factor;
474 std::get<20>(accumulator) += msm_transition * transcript_msm_infinity * y_sum * scaling_factor;
476 const auto transcript_msm_x_inverse = View(in.transcript_msm_x_inverse);
477 const auto inverse_term = (-transcript_msm_infinity + 1) * (x_diff * transcript_msm_x_inverse - 1);
478 std::get<21>(accumulator) += msm_transition * inverse_term * scaling_factor;
488 auto accumulator_infinity_preserve_flag = propagate_transcript_accumulator;
489 auto accumulator_infinity_preserve = accumulator_infinity_preserve_flag *
490 (is_accumulator_empty - is_accumulator_empty_shift) *
491 is_not_first_or_last_row;
492 auto accumulator_infinity_q_reset = q_reset_accumulator * (-is_accumulator_empty_shift + 1);
493 auto accumulator_infinity_from_add =
494 any_add_is_active * (result_is_infinity - is_accumulator_empty_shift);
495 auto accumulator_infinity_relation =
496 accumulator_infinity_preserve +
497 (accumulator_infinity_q_reset + accumulator_infinity_from_add) * is_not_first_row;
498 std::get<22>(accumulator) += accumulator_infinity_relation * scaling_factor;
505 auto x_diff = lhs_x - rhs_x;
507 auto x_product = transcript_Px_inverse * (-transcript_add_x_equal + 1) + transcript_add_x_equal;
508 auto x_constant = transcript_add_x_equal - 1;
509 auto transcript_add_x_equal_check_relation = (x_diff * x_product + x_constant) * any_add_is_active;
510 std::get<23>(accumulator) += transcript_add_x_equal_check_relation * scaling_factor;
517 auto y_diff = lhs_y - rhs_y;
518 auto y_product = transcript_Py_inverse * (-transcript_add_y_equal + 1) + transcript_add_y_equal;
519 auto y_constant = transcript_add_y_equal - 1;
520 auto transcript_add_y_equal_check_relation = (y_diff * y_product + y_constant) * any_add_is_active;
521 std::get<24>(accumulator) += transcript_add_y_equal_check_relation * scaling_factor;
530 std::get<25>(accumulator) += lagrange_second * (-q_eq + 1) * scaling_factor;
531 std::get<26>(accumulator) += lagrange_second * (-q_reset_accumulator + 1) * scaling_factor;