16 const AllEntities& in,
18 const FF& scaling_factor)
33 const auto z1 = View(in.transcript_z1);
34 const auto z2 = View(in.transcript_z2);
35 const auto z1_zero = View(in.transcript_z1zero);
36 const auto z2_zero = View(in.transcript_z2zero);
37 const auto op = View(in.transcript_op);
38 const auto q_add = View(in.transcript_add);
39 const auto q_mul = View(in.transcript_mul);
40 const auto q_mul_shift = View(in.transcript_mul_shift);
41 const auto q_eq = View(in.transcript_eq);
42 const auto msm_transition = View(in.transcript_msm_transition);
43 const auto msm_count = View(in.transcript_msm_count);
44 const auto msm_count_shift = View(in.transcript_msm_count_shift);
45 const auto pc = View(in.transcript_pc);
46 const auto pc_shift = View(in.transcript_pc_shift);
47 const auto transcript_accumulator_x_shift = View(in.transcript_accumulator_x_shift);
48 const auto transcript_accumulator_y_shift = View(in.transcript_accumulator_y_shift);
49 const auto transcript_accumulator_x = View(in.transcript_accumulator_x);
50 const auto transcript_accumulator_y = View(in.transcript_accumulator_y);
51 const auto msm_count_zero_at_transition = View(in.transcript_msm_count_zero_at_transition);
52 const auto msm_count_at_transition_inverse = View(in.transcript_msm_count_at_transition_inverse);
53 const auto transcript_msm_x = View(in.transcript_msm_intermediate_x);
54 const auto transcript_msm_y = View(in.transcript_msm_intermediate_y);
55 const auto transcript_Px = View(in.transcript_Px);
56 const auto transcript_Py = View(in.transcript_Py);
57 const auto transcript_accumulator_not_empty = View(in.transcript_accumulator_not_empty);
58 const auto is_accumulator_empty = -transcript_accumulator_not_empty +
FF(1);
59 const auto lagrange_first = View(in.lagrange_first);
60 const auto lagrange_last = View(in.lagrange_last);
61 const auto is_accumulator_empty_shift = -View(in.transcript_accumulator_not_empty_shift) +
FF(1);
62 const auto q_reset_accumulator = View(in.transcript_reset_accumulator);
63 const auto lagrange_second = View(in.lagrange_second);
64 const auto lagrange_third = View(in.lagrange_third);
65 const auto transcript_Pinfinity = View(in.transcript_base_infinity);
66 const auto transcript_Px_inverse = View(in.transcript_base_x_inverse);
67 const auto transcript_Py_inverse = View(in.transcript_base_y_inverse);
68 const auto transcript_add_x_equal = View(in.transcript_add_x_equal);
69 const auto transcript_add_y_equal = View(in.transcript_add_y_equal);
70 const auto transcript_add_lambda = View(in.transcript_add_lambda);
71 const auto transcript_msm_infinity = View(in.transcript_msm_infinity);
73 const auto is_not_first_row = -lagrange_first +
FF(1);
74 const auto is_not_last_row = -lagrange_last +
FF(1);
75 const auto is_not_first_or_last_row = (-lagrange_first - lagrange_last) +
FF(1);
76 const auto is_not_infinity = -transcript_Pinfinity +
FF(1);
77 const auto is_not_hiding_row = -lagrange_second +
FF(1);
84 auto tmp = q_add + q_add;
89 tmp += q_reset_accumulator;
93 const auto pc_delta_short = pc - pc_shift;
94 const auto z1_active = -z1_zero +
FF(1);
95 const auto z2_active = -z2_zero +
FF(1);
96 const auto z_active_sum = z1_active + z2_active;
97 const auto num_muls_in_row = z_active_sum * is_not_infinity;
99 const auto first_term = Acc5((is_not_first_row * pc_delta_short) * scaling_factor);
100 const auto second_term = Acc5(is_not_first_row * q_mul) * Acc5(num_muls_in_row * scaling_factor);
105 const auto msm_transition_check = q_mul * (-q_mul_shift +
FF(1));
107 const auto msm_count_total_acc7 = Acc7(msm_count) + Acc7(num_muls_in_row);
108 const auto check_a = Acc7(msm_count_zero_at_transition) * msm_count_total_acc7;
109 const auto inv_term = msm_count_total_acc7 * Acc7(msm_count_at_transition_inverse) - Acc7(
FF(1));
110 const auto inactive = Acc7(-msm_count_zero_at_transition +
FF(1));
111 const auto zero_check = check_a + inv_term * inactive;
113 Acc7(msm_transition_check * scaling_factor) * zero_check;
118 const auto not_zero_at_transition = Acc4(-msm_count_zero_at_transition +
FF(1));
119 const auto outer = Acc4(msm_transition * scaling_factor) -
120 Acc4(msm_transition_check * scaling_factor) * not_zero_at_transition;
128 const auto msm_count_delta = msm_count_shift - msm_count;
130 const auto outer_short = is_not_first_row * (-msm_transition +
FF(1));
132 Acc6(msm_count_delta * scaling_factor) - Acc6(q_mul) * Acc6(num_muls_in_row * scaling_factor);
138 const auto mul_other = q_add + q_eq + q_reset_accumulator;
139 const auto add_other = q_mul + q_eq + q_reset_accumulator;
140 const auto sum = q_mul * mul_other + q_add * add_other;
145 const auto both_infinity_short = transcript_Pinfinity * is_accumulator_empty;
146 const auto not_pinf = -transcript_Pinfinity +
FF(1);
147 const auto not_acc_empty = -is_accumulator_empty +
FF(1);
148 const auto both_not_infinity_short = not_pinf * not_acc_empty;
149 const auto infinity_exclusion_short =
150 ((-both_infinity_short) - both_infinity_short) + (transcript_Pinfinity + is_accumulator_empty);
151 const auto q_eq_hiding_short = q_eq * is_not_hiding_row;
153 const auto eq_x_diff = transcript_Px - transcript_accumulator_x;
154 const auto inner_x = Acc6(eq_x_diff) * Acc6(both_not_infinity_short) + Acc6(infinity_exclusion_short);
158 const auto eq_y_diff = transcript_Py - transcript_accumulator_y;
159 const auto inner_y = Acc6(eq_y_diff) * Acc6(both_not_infinity_short) + Acc6(infinity_exclusion_short);
165 Acc3((lagrange_third * (-is_accumulator_empty +
FF(1))) * scaling_factor);
167 Acc3((lagrange_third * msm_count + lagrange_last * pc) * scaling_factor);
171 const auto validate_on_curve = q_add + q_mul + q_eq;
172 const auto py_sq = transcript_Py.sqr();
173 const auto px_sq = transcript_Px.sqr();
174 const auto on_curve_check =
175 Acc7(py_sq) - Acc7(px_sq) * Acc7(transcript_Px) - Acc7(Base::get_curve_b());
176 const auto gating_short = is_not_infinity * is_not_hiding_row;
177 const auto outer = Acc7(validate_on_curve) * Acc7(gating_short * scaling_factor);
183 const auto is_double_short = transcript_add_x_equal * transcript_add_y_equal;
184 const auto is_add_short = -transcript_add_x_equal +
FF(1);
185 const auto rhs_x = transcript_accumulator_x;
186 const auto rhs_y = transcript_accumulator_y;
187 const auto out_x = transcript_accumulator_x_shift;
188 const auto out_y = transcript_accumulator_y_shift;
189 const auto lambda = transcript_add_lambda;
191 const auto lhs_x_short = transcript_Px * q_add + transcript_msm_x * msm_transition;
192 const auto lhs_y_short = transcript_Py * q_add + transcript_msm_y * msm_transition;
193 const auto lhs_infinity_short =
194 transcript_Pinfinity * q_add + transcript_msm_infinity * msm_transition;
195 const auto rhs_infinity_short = is_accumulator_empty;
196 const auto neg_lhs_inf_plus_one_short = -lhs_infinity_short +
FF(1);
197 const auto neg_rhs_inf_plus_one_short = -rhs_infinity_short +
FF(1);
200 const auto result_is_lhs = Accumulator(rhs_infinity_short) * Accumulator(neg_lhs_inf_plus_one_short);
201 const auto result_is_rhs = Accumulator(neg_rhs_inf_plus_one_short) * Accumulator(lhs_infinity_short);
202 const auto result_infinity_from_inputs = Accumulator(lhs_infinity_short) * Accumulator(rhs_infinity_short);
203 const auto result_infinity_from_op_short =
204 transcript_add_x_equal * (-transcript_add_y_equal +
FF(1));
205 const auto result_is_infinity_short =
206 result_infinity_from_inputs + Accumulator(result_infinity_from_op_short);
207 const auto any_add_is_active_short = q_add + msm_transition;
209 Accumulator transcript_lambda_relation(0);
212 Accumulator transcript_msm_lambda_relation(0);
213 const auto msm_x = transcript_msm_x;
214 const auto msm_y = transcript_msm_y;
216 const auto lambda_den = rhs_x - msm_x;
217 const auto lambda_num = rhs_y - msm_y;
218 const auto lambda_rel = Accumulator(lambda * lambda_den) - Accumulator(lambda_num);
219 transcript_msm_lambda_relation += lambda_rel * Accumulator(is_add_short);
222 const auto lambda_den = msm_y + msm_y;
223 const auto lambda_num_short = msm_x.sqr() *
FF(3);
224 const auto lambda_rel = Accumulator(lambda * lambda_den) - Accumulator(lambda_num_short);
225 transcript_msm_lambda_relation += lambda_rel * Accumulator(is_double_short);
227 const auto valid_short = (-transcript_msm_infinity +
FF(1)) * (-is_accumulator_empty +
FF(1));
228 transcript_msm_lambda_relation *= Accumulator(valid_short);
230 const auto invalid_short =
231 result_infinity_from_op_short + (transcript_msm_infinity + is_accumulator_empty);
232 transcript_msm_lambda_relation += Accumulator(lambda) * Accumulator(invalid_short);
234 transcript_lambda_relation = transcript_msm_lambda_relation * Accumulator(msm_transition * scaling_factor);
238 Accumulator transcript_add_lambda_relation(0);
239 const auto add_x = transcript_Px;
240 const auto add_y = transcript_Py;
242 const auto lambda_den = rhs_x - add_x;
243 const auto lambda_num = rhs_y - add_y;
244 const auto lambda_rel = Accumulator(lambda * lambda_den) - Accumulator(lambda_num);
245 transcript_add_lambda_relation += lambda_rel * Accumulator(is_add_short);
248 const auto lambda_den = add_y + add_y;
249 const auto lambda_num_short = add_x.sqr() *
FF(3);
250 const auto lambda_rel = Accumulator(lambda * lambda_den) - Accumulator(lambda_num_short);
251 transcript_add_lambda_relation += lambda_rel * Accumulator(is_double_short);
253 const auto valid_short = (-transcript_Pinfinity +
FF(1)) * (-is_accumulator_empty +
FF(1));
254 transcript_add_lambda_relation *= Accumulator(valid_short);
256 const auto invalid_short =
257 result_infinity_from_op_short + (transcript_Pinfinity + is_accumulator_empty);
258 transcript_add_lambda_relation += Accumulator(lambda) * Accumulator(invalid_short);
260 transcript_lambda_relation += transcript_add_lambda_relation * Accumulator(q_add * scaling_factor);
265 const auto propagate_transcript_accumulator_short =
266 q_mul * (-msm_transition +
FF(1)) + q_eq * (-q_reset_accumulator +
FF(1));
267 const auto opcode_is_zero_short_part_a = is_not_first_row * (-q_add +
FF(1));
268 const auto opcode_is_zero_short_part_b = (-q_mul +
FF(1)) * (-q_reset_accumulator +
FF(1));
269 const auto opcode_is_zero_short_part_c = -q_eq +
FF(1);
270 const auto opcode_is_zero_scaled = Accumulator(opcode_is_zero_short_part_a * scaling_factor) *
271 Accumulator(opcode_is_zero_short_part_b) *
272 Accumulator(opcode_is_zero_short_part_c);
273 const auto any_add_is_active_scaled_acc = Accumulator(any_add_is_active_short * scaling_factor);
274 const auto propagate_transcript_accumulator_scaled = propagate_transcript_accumulator_short * scaling_factor;
276 const auto lambda_sqr = Accumulator(lambda.sqr());
277 const auto lhs_x_acc = Accumulator(lhs_x_short);
278 const auto lhs_y_acc = Accumulator(lhs_y_short);
279 const auto rhs_x_acc = Accumulator(rhs_x);
280 const auto rhs_y_acc = Accumulator(rhs_y);
281 auto x3 = lambda_sqr - lhs_x_acc - rhs_x_acc;
282 auto y3 = Accumulator(lambda) * (lhs_x_acc - x3) - lhs_y_acc;
283 x3 += result_is_lhs * (rhs_x_acc + lhs_x_acc + lhs_x_acc);
284 x3 += result_is_rhs * (lhs_x_acc + rhs_x_acc + rhs_x_acc);
285 x3 += result_is_infinity_short * (lhs_x_acc + rhs_x_acc);
286 y3 += result_is_lhs * (lhs_y_acc + lhs_y_acc);
287 y3 += result_is_rhs * (lhs_y_acc + rhs_y_acc);
288 y3 += result_is_infinity_short * lhs_y_acc;
290 const auto propagate_acc_x = Accumulator(propagate_transcript_accumulator_scaled) *
291 Accumulator(is_not_last_row * (out_x - transcript_accumulator_x));
292 const auto propagate_acc_y = Accumulator(propagate_transcript_accumulator_scaled) *
293 Accumulator(is_not_last_row * (out_y - transcript_accumulator_y));
294 auto add_point_x_relation = (x3 - Accumulator(out_x)) * any_add_is_active_scaled_acc + propagate_acc_x +
295 Accumulator(out_x * (q_reset_accumulator * scaling_factor)) +
296 Accumulator(out_x) * opcode_is_zero_scaled;
297 auto add_point_y_relation = (y3 - Accumulator(out_y)) * any_add_is_active_scaled_acc + propagate_acc_y +
298 Accumulator(out_y * (q_reset_accumulator * scaling_factor)) +
299 Accumulator(out_y) * opcode_is_zero_scaled;
310 const auto accumulator_infinity_preserve =
311 Accumulator(propagate_transcript_accumulator_scaled) *
312 Accumulator(is_not_first_or_last_row * (is_accumulator_empty - is_accumulator_empty_shift));
313 const auto accumulator_infinity_q_reset =
314 Accumulator((q_reset_accumulator * (-is_accumulator_empty_shift +
FF(1))) * scaling_factor);
315 const auto accumulator_infinity_from_add =
316 any_add_is_active_scaled_acc * (result_is_infinity_short - Accumulator(is_accumulator_empty_shift));
317 const auto accumulator_infinity_from_noop =
318 opcode_is_zero_scaled * Accumulator(-is_accumulator_empty_shift +
FF(1));
319 const auto accumulator_infinity_relation =
320 accumulator_infinity_preserve +
321 (accumulator_infinity_q_reset + accumulator_infinity_from_add) * Accumulator(is_not_first_row) +
322 accumulator_infinity_from_noop;
328 const auto x_diff = Acc6(lhs_x_short - rhs_x);
329 const auto x_product =
330 Acc6(transcript_Px_inverse * (-transcript_add_x_equal +
FF(1))) + Acc6(transcript_add_x_equal);
331 const auto x_constant = transcript_add_x_equal -
FF(1);
332 const auto x_relation =
333 (x_diff * x_product + Acc6(x_constant)) * Acc6(any_add_is_active_short * scaling_factor);
337 const auto y_diff = Acc6(lhs_y_short - rhs_y);
338 const auto y_product =
339 Acc6(transcript_Py_inverse * (-transcript_add_y_equal +
FF(1))) + Acc6(transcript_add_y_equal);
340 const auto y_constant = transcript_add_y_equal -
FF(1);
341 const auto y_relation =
342 (y_diff * y_product + Acc6(y_constant)) * Acc6(any_add_is_active_short * scaling_factor);
350 Acc3((lagrange_second * (-q_reset_accumulator +
FF(1))) * scaling_factor);
356 Acc3((is_accumulator_empty * transcript_accumulator_x) * scaling_factor);
358 Acc3((is_accumulator_empty * transcript_accumulator_y) * scaling_factor);
362 Acc3((lagrange_first * transcript_accumulator_not_empty) * scaling_factor);