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 transcript_Pinfinity = View(in.transcript_base_infinity);
89 const auto transcript_Px_inverse = View(in.transcript_base_x_inverse);
90 const auto transcript_Py_inverse = View(in.transcript_base_y_inverse);
91 const auto transcript_add_x_equal = View(in.transcript_add_x_equal);
92 const auto transcript_add_y_equal = View(in.transcript_add_y_equal);
93 const auto transcript_add_lambda = View(in.transcript_add_lambda);
94 const auto transcript_msm_infinity = View(in.transcript_msm_infinity);
96 const auto is_not_first_row = (-lagrange_first + 1);
97 const auto is_not_last_row = (-lagrange_last + 1);
98 const auto is_not_first_or_last_row = (-lagrange_first + -lagrange_last + 1);
99 const auto is_not_infinity = (-transcript_Pinfinity + 1);
111 std::get<0>(accumulator) += (z1 * z1_zero) * scaling_factor;
112 std::get<1>(accumulator) += (z2 * z2_zero) * scaling_factor;
119 auto tmp = q_add + q_add;
124 tmp += q_reset_accumulator;
125 std::get<2>(accumulator) += (tmp - op) * scaling_factor;
134 Accumulator pc_delta = pc - pc_shift;
135 auto num_muls_in_row = ((-z1_zero + 1) + (-z2_zero + 1)) * (-transcript_Pinfinity + 1);
138 std::get<3>(accumulator) += is_not_first_row * (pc_delta - q_mul * num_muls_in_row) * scaling_factor;
159 auto msm_transition_check = q_mul * (-q_mul_shift + 1);
160 auto msm_count_total = msm_count + num_muls_in_row;
166 auto msm_count_zero_at_transition_check = msm_count_zero_at_transition * msm_count_total;
167 msm_count_zero_at_transition_check +=
168 (msm_count_total * msm_count_at_transition_inverse - 1) * (-msm_count_zero_at_transition + 1);
173 std::get<4>(accumulator) += msm_transition_check * msm_count_zero_at_transition_check * scaling_factor;
183 (msm_transition - msm_transition_check * (-msm_count_zero_at_transition + 1)) * scaling_factor;
193 std::get<6>(accumulator) += ((-q_mul + 1) * msm_count) * scaling_factor;
200 auto msm_count_delta = msm_count_shift - msm_count;
201 std::get<7>(accumulator) += is_not_first_row * (-msm_transition + 1) * (msm_count_delta - q_mul * num_muls_in_row) *
210 auto opcode_exclusion_relation = q_mul * (q_add + q_eq + q_reset_accumulator);
211 opcode_exclusion_relation += q_add * (q_mul + q_eq + q_reset_accumulator);
212 std::get<8>(accumulator) += opcode_exclusion_relation * scaling_factor;
221 auto both_infinity = transcript_Pinfinity * is_accumulator_empty;
222 auto both_not_infinity = (-transcript_Pinfinity + 1) * (-is_accumulator_empty + 1);
223 auto infinity_exclusion_check =
224 transcript_Pinfinity + is_accumulator_empty - both_infinity - both_infinity;
225 auto eq_x_diff = transcript_Px - transcript_accumulator_x;
226 auto eq_y_diff = transcript_Py - transcript_accumulator_y;
227 auto eq_x_diff_relation = q_eq * (eq_x_diff * both_not_infinity + infinity_exclusion_check);
228 auto eq_y_diff_relation = q_eq * (eq_y_diff * both_not_infinity + infinity_exclusion_check);
229 std::get<9>(accumulator) += eq_x_diff_relation * scaling_factor;
230 std::get<10>(accumulator) += eq_y_diff_relation * scaling_factor;
241 std::get<11>(accumulator) += lagrange_second * (-is_accumulator_empty + 1) * scaling_factor;
242 std::get<12>(accumulator) += (lagrange_second * msm_count + lagrange_last * pc) * scaling_factor;
250 const auto validate_on_curve = q_add + q_mul + q_eq;
251 const auto on_curve_check =
252 transcript_Py * transcript_Py - transcript_Px * transcript_Px * transcript_Px - get_curve_b();
253 std::get<13>(accumulator) += validate_on_curve * on_curve_check * is_not_infinity * scaling_factor;
262 Accumulator transcript_lambda_relation(0);
263 auto is_double = transcript_add_x_equal * transcript_add_y_equal;
266 auto is_add = -transcript_add_x_equal + 1;
270 auto add_result_is_infinity = transcript_add_x_equal * (-transcript_add_y_equal + 1);
271 auto rhs_x = transcript_accumulator_x;
272 auto rhs_y = transcript_accumulator_y;
273 auto out_x = transcript_accumulator_x_shift;
274 auto out_y = transcript_accumulator_y_shift;
275 auto lambda = transcript_add_lambda;
279 auto lhs_x = transcript_Px * q_add + transcript_msm_x * msm_transition;
280 auto lhs_y = transcript_Py * q_add + transcript_msm_y * msm_transition;
282 auto lhs_infinity = transcript_Pinfinity * q_add + transcript_msm_infinity * msm_transition;
283 auto rhs_infinity = is_accumulator_empty;
286 auto result_is_lhs = rhs_infinity * (-lhs_infinity + 1);
287 auto result_is_rhs = (-rhs_infinity + 1) * lhs_infinity;
290 auto result_infinity_from_inputs = lhs_infinity * rhs_infinity;
293 auto result_infinity_from_operation = transcript_add_x_equal * (-transcript_add_y_equal + 1);
297 auto result_is_infinity = result_infinity_from_inputs + result_infinity_from_operation;
298 auto any_add_is_active = q_add + msm_transition;
302 Accumulator transcript_msm_lambda_relation(0);
303 auto msm_x = transcript_msm_x;
304 auto msm_y = transcript_msm_y;
307 auto lambda_denominator = (rhs_x - msm_x);
308 auto lambda_numerator = (rhs_y - msm_y);
309 auto lambda_relation = lambda * lambda_denominator - lambda_numerator;
310 transcript_msm_lambda_relation += lambda_relation * is_add;
314 auto lambda_denominator = msm_y + msm_y;
315 auto lambda_numerator = msm_x * msm_x * 3;
316 auto lambda_relation = lambda * lambda_denominator - lambda_numerator;
317 transcript_msm_lambda_relation += lambda_relation * is_double;
319 auto transcript_add_or_dbl_from_msm_output_is_valid =
320 (-transcript_msm_infinity + 1) * (-is_accumulator_empty + 1);
324 transcript_msm_lambda_relation *= transcript_add_or_dbl_from_msm_output_is_valid;
329 auto lambda_relation_invalid =
330 (transcript_msm_infinity + is_accumulator_empty + add_result_is_infinity);
331 auto lambda_relation = lambda * lambda_relation_invalid;
332 transcript_msm_lambda_relation += lambda_relation;
335 transcript_lambda_relation = transcript_msm_lambda_relation * msm_transition;
340 Accumulator transcript_add_lambda_relation(0);
341 auto add_x = transcript_Px;
342 auto add_y = transcript_Py;
345 auto lambda_denominator = (rhs_x - add_x);
346 auto lambda_numerator = (rhs_y - add_y);
347 auto lambda_relation = lambda * lambda_denominator - lambda_numerator;
348 transcript_add_lambda_relation += lambda_relation * is_add;
352 auto lambda_denominator = add_y + add_y;
353 auto lambda_numerator = add_x * add_x * 3;
354 auto lambda_relation = lambda * lambda_denominator - lambda_numerator;
355 transcript_add_lambda_relation += lambda_relation * is_double;
357 auto transcript_add_or_dbl_from_add_output_is_valid =
358 (-transcript_Pinfinity + 1) * (-is_accumulator_empty + 1);
359 transcript_add_lambda_relation *= transcript_add_or_dbl_from_add_output_is_valid;
364 auto lambda_relation_invalid =
365 (transcript_Pinfinity + is_accumulator_empty + add_result_is_infinity);
366 auto lambda_relation = lambda * lambda_relation_invalid;
367 transcript_add_lambda_relation += lambda_relation;
370 transcript_lambda_relation += transcript_add_lambda_relation * q_add;
371 std::get<14>(accumulator) += transcript_lambda_relation * scaling_factor;
387 auto propagate_transcript_accumulator =
388 (q_mul) * (-msm_transition + 1) + (q_eq * (-q_reset_accumulator + 1));
390 auto lambda_sqr = lambda * lambda;
395 auto x3 = lambda_sqr - lhs_x - rhs_x;
396 auto y3 = lambda * (lhs_x - out_x) - lhs_y;
397 x3 += result_is_lhs * (rhs_x + lhs_x + lhs_x);
398 x3 += result_is_rhs * (lhs_x + rhs_x + rhs_x);
399 x3 += result_is_infinity * (lhs_x + rhs_x);
400 y3 += result_is_lhs * (lhs_y + lhs_y);
401 y3 += result_is_rhs * (lhs_y + rhs_y);
402 y3 += result_is_infinity * lhs_y;
406 auto add_point_x_relation = (x3 - out_x) * any_add_is_active;
407 add_point_x_relation +=
408 propagate_transcript_accumulator * is_not_last_row * (out_x - transcript_accumulator_x);
410 add_point_x_relation += (out_x * q_reset_accumulator);
411 auto add_point_y_relation = (y3 - out_y) * any_add_is_active;
412 add_point_y_relation +=
413 propagate_transcript_accumulator * is_not_last_row * (out_y - transcript_accumulator_y);
415 add_point_y_relation += (out_y * q_reset_accumulator);
416 auto opcode_is_zero =
417 (is_not_first_row) * (-q_add + 1) * (-q_mul + 1) * (-q_reset_accumulator + 1) * (-q_eq + 1);
418 add_point_x_relation += (out_x * opcode_is_zero);
419 add_point_y_relation += (out_y * opcode_is_zero);
421 std::get<15>(accumulator) += add_point_x_relation * scaling_factor;
422 std::get<16>(accumulator) += add_point_y_relation * scaling_factor;
430 const auto offset = offset_generator();
431 const auto x1 =
offset[0];
432 const auto y1 = -
offset[1];
433 const auto x2 = View(in.transcript_msm_x);
434 const auto y2 = View(in.transcript_msm_y);
435 const auto x3 = View(in.transcript_msm_intermediate_x);
436 const auto y3 = View(in.transcript_msm_intermediate_y);
437 const auto transcript_msm_infinity = View(in.transcript_msm_infinity);
441 const auto x_term = (x3 + x2 + x1) * (x2 - x1) * (x2 - x1) - (y2 - y1) * (y2 - y1);
442 const auto y_term = (x1 - x3) * (y2 - y1) - (x2 - x1) * (y1 + y3);
449 const auto transcript_offset_generator_subtract_x =
450 x_term * (-transcript_msm_infinity + 1) + transcript_msm_infinity * x3;
451 const auto transcript_offset_generator_subtract_y =
452 y_term * (-transcript_msm_infinity + 1) + transcript_msm_infinity * y3;
454 msm_transition * transcript_offset_generator_subtract_x * scaling_factor;
456 msm_transition * transcript_offset_generator_subtract_y * scaling_factor;
461 const auto x_diff = x2 - x1;
462 const auto y_sum = y2 + y1;
463 std::get<19>(accumulator) += msm_transition * transcript_msm_infinity * x_diff * scaling_factor;
464 std::get<20>(accumulator) += msm_transition * transcript_msm_infinity * y_sum * scaling_factor;
466 const auto transcript_msm_x_inverse = View(in.transcript_msm_x_inverse);
467 const auto inverse_term = (-transcript_msm_infinity + 1) * (x_diff * transcript_msm_x_inverse - 1);
468 std::get<21>(accumulator) += msm_transition * inverse_term * scaling_factor;
478 auto accumulator_infinity_preserve_flag = propagate_transcript_accumulator;
479 auto accumulator_infinity_preserve = accumulator_infinity_preserve_flag *
480 (is_accumulator_empty - is_accumulator_empty_shift) *
481 is_not_first_or_last_row;
482 auto accumulator_infinity_q_reset = q_reset_accumulator * (-is_accumulator_empty_shift + 1);
483 auto accumulator_infinity_from_add =
484 any_add_is_active * (result_is_infinity - is_accumulator_empty_shift);
485 auto accumulator_infinity_relation =
486 accumulator_infinity_preserve +
487 (accumulator_infinity_q_reset + accumulator_infinity_from_add) * is_not_first_row;
488 std::get<22>(accumulator) += accumulator_infinity_relation * scaling_factor;
495 auto x_diff = lhs_x - rhs_x;
497 auto x_product = transcript_Px_inverse * (-transcript_add_x_equal + 1) + transcript_add_x_equal;
498 auto x_constant = transcript_add_x_equal - 1;
499 auto transcript_add_x_equal_check_relation = (x_diff * x_product + x_constant) * any_add_is_active;
500 std::get<23>(accumulator) += transcript_add_x_equal_check_relation * scaling_factor;
507 auto y_diff = lhs_y - rhs_y;
508 auto y_product = transcript_Py_inverse * (-transcript_add_y_equal + 1) + transcript_add_y_equal;
509 auto y_constant = transcript_add_y_equal - 1;
510 auto transcript_add_y_equal_check_relation = (y_diff * y_product + y_constant) * any_add_is_active;
511 std::get<24>(accumulator) += transcript_add_y_equal_check_relation * scaling_factor;