Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
ecc_transcript_relation_impl.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Complete, auditors: [Raju], commit: 2a49eb6 }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#pragma once
8#include <array>
9#include <tuple>
10
14
15namespace bb {
38template <typename FF>
39template <typename ContainerOverSubrelations, typename AllEntities, typename Parameters>
40void ECCVMTranscriptRelationImpl<FF>::accumulate(ContainerOverSubrelations& accumulator,
41 const AllEntities& in,
42 const Parameters& /*unused*/,
43 const FF& scaling_factor)
44{
45 using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>;
46 using View = typename Accumulator::View;
47
48 static const auto offset_generator = [&]() {
49 static constexpr auto offset_generator_base = get_precomputed_generators<g1, "ECCVM_OFFSET_GENERATOR", 1>()[0];
50 static bb::g1::affine_element result =
51 bb::g1::affine_element(bb::g1::element(offset_generator_base) * grumpkin::fq(uint256_t(1) << 124));
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);
56 return std::array<Accumulator, 2>{ ox, oy };
57 };
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);
96
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);
101 // Row 1 (lagrange_second = 1) is the hiding op row - skip on-curve check and eq constraints there
102 const auto is_not_hiding_row = (-lagrange_second + 1);
114 std::get<Z1_ZERO_CHECK>(accumulator) += (z1 * z1_zero) * scaling_factor; // if z1_zero = 1, z1 must be 0. degree 2
115 std::get<Z2_ZERO_CHECK>(accumulator) += (z2 * z2_zero) * scaling_factor; // degree 2
116
122 auto tmp = q_add + q_add;
123 tmp += q_mul;
124 tmp += tmp;
125 tmp += q_eq;
126 tmp += tmp;
127 tmp += q_reset_accumulator;
128 std::get<OPCODE_WELL_FORMED>(accumulator) += (tmp - op) * scaling_factor; // degree 1
129
137 Accumulator pc_delta = pc - pc_shift;
138 auto num_muls_in_row = ((-z1_zero + 1) + (-z2_zero + 1)) * (-transcript_Pinfinity + 1);
139 // note that the value of `pc` in the first row is 0 because `pc` is shiftable. It is the second row where it starts
140 // out at its maximum value.
141 std::get<PC_UPDATE>(accumulator) +=
142 is_not_first_row * (pc_delta - q_mul * num_muls_in_row) * scaling_factor; // degree 4
143
160 // `msm_transition_check` is a _syntactic_ check that we could be in a transition.
161 // `msm_count_total` is the total number of (short) multiplications, _including_ the multiplications to be processed
162 // in this row.
163 auto msm_transition_check = q_mul * (-q_mul_shift + 1); // degree 2
164 auto msm_count_total = msm_count + num_muls_in_row; // degree 2
165
166 // `msm_count_at_transition_check` witnesses the claim that if `msm_count_zero_at_transition == 1`, then
167 // `msm_count_total == 0` and if `msm_count_zero_at_transition == 0` and we are at a syntactic transition, then
168 // `msm_count_total is invertible`. The way it does this is `msm_count_at_transition_inverse` is supposed to vanish
169 // *except* possibly at a syntactic transition.
170 auto msm_count_zero_at_transition_check = msm_count_zero_at_transition * msm_count_total;
171 msm_count_zero_at_transition_check +=
172 (msm_count_total * msm_count_at_transition_inverse - 1) * (-msm_count_zero_at_transition + 1); // degree 4
173 // forces `msm_count_zero_at_transition` to have the following property at a syntactic transition: if
174 // `msm_count_zero_at_transition == 1`, then `msm_count_total == 0`. else if `msm_count_zero_at_transition == 0`,
175 // then `msm_count_total != 0` and is in fact the inverse of `msm_count_at_transition_inverse` (which is a witness
176 // column).
178 msm_transition_check * msm_count_zero_at_transition_check * scaling_factor; // degree 6
179
187 std::get<MSM_TRANSITION>(accumulator) +=
188 (msm_transition - msm_transition_check * (-msm_count_zero_at_transition + 1)) * scaling_factor; // degree 3
189
198 std::get<MSM_COUNT_ZERO_WHEN_NOT_MUL>(accumulator) += ((-q_mul + 1) * msm_count) * scaling_factor; // degree 2
199
205 auto msm_count_delta = msm_count_shift - msm_count;
206 std::get<MSM_COUNT_INCREMENT_ACROSS_ROWS>(accumulator) += is_not_first_row * (-msm_transition + 1) *
207 (msm_count_delta - q_mul * num_muls_in_row) *
208 scaling_factor; // degree 5
209
216 auto opcode_exclusion_relation = q_mul * (q_add + q_eq + q_reset_accumulator);
217 opcode_exclusion_relation += q_add * (q_mul + q_eq + q_reset_accumulator);
218 std::get<OPCODE_EXCLUSION>(accumulator) += opcode_exclusion_relation * scaling_factor; // degree 2
219
227 auto both_infinity = transcript_Pinfinity * is_accumulator_empty; // degree 2
228 auto both_not_infinity = (-transcript_Pinfinity + 1) * (-is_accumulator_empty + 1); // degree 2
229 auto infinity_exclusion_check =
230 transcript_Pinfinity + is_accumulator_empty - both_infinity - both_infinity; // degree 2
231 auto eq_x_diff = transcript_Px - transcript_accumulator_x; // degree 1
232 auto eq_y_diff = transcript_Py - transcript_accumulator_y; // degree 1
233 // Gate eq constraints with is_not_hiding_row to skip at row 1 (hiding op row)
234 auto eq_x_diff_relation =
235 q_eq * (eq_x_diff * both_not_infinity + infinity_exclusion_check) * is_not_hiding_row; // degree 5
236 auto eq_y_diff_relation =
237 q_eq * (eq_y_diff * both_not_infinity + infinity_exclusion_check) * is_not_hiding_row; // degree 5
238 std::get<EQ_X_DIFF>(accumulator) += eq_x_diff_relation * scaling_factor; // degree 5
239 std::get<EQ_Y_DIFF>(accumulator) += eq_y_diff_relation * scaling_factor; // degree 5
240
252 lagrange_third * (-is_accumulator_empty + 1) * scaling_factor; // degree 2
254 (lagrange_third * msm_count + lagrange_last * pc) * scaling_factor; // degree 2
255
263 const auto validate_on_curve = q_add + q_mul + q_eq;
264 const auto on_curve_check =
265 transcript_Py * transcript_Py - transcript_Px * transcript_Px * transcript_Px - get_curve_b();
266 // Gate on-curve check with is_not_hiding_row to skip at row 1 (hiding op row with potentially off-curve Px, Py)
267 std::get<ON_CURVE_CHECK>(accumulator) +=
268 validate_on_curve * on_curve_check * is_not_infinity * is_not_hiding_row * scaling_factor; // degree 6
269
274 {
275 // in the following, LHS is the new elliptic curve point and RHS is the accumulator. LHS can either be the
276 // explicit point in an `add` op or the result of an MSM at the end of an MSM. RHS is often referred to as A.
277 Accumulator transcript_lambda_relation(0);
278 auto is_double = transcript_add_x_equal * transcript_add_y_equal; // degree 2
279 // `is_add == 1` iff the x-values of the point-to-add and the accumulator are _not_ equal. this ensures that
280 // it is not a double and that the result is not the point-at-infinity. Used for both `add` and MSM operations.
281 auto is_add = -transcript_add_x_equal + 1; // degree 1
282 auto rhs_x = transcript_accumulator_x; // degree 1
283 auto rhs_y = transcript_accumulator_y; // degree 1
284 auto out_x = transcript_accumulator_x_shift; // degree 1
285 auto out_y = transcript_accumulator_y_shift; // degree 1
286 auto lambda = transcript_add_lambda; // degree 1
287 // note that `msm_transition` and `q_add` are mutually exclusive booleans. (they can also both be off.)
288 // therefore `(lhs_x, lhs_y)` is either the point in the `add` VM instruction _or_ the output of the
289 // just-completed MSM.
290 auto lhs_x = transcript_Px * q_add + transcript_msm_x * msm_transition; // degree 2
291 auto lhs_y = transcript_Py * q_add + transcript_msm_y * msm_transition; // degree 2
292 // `lhs_infinity == 1` iff the point being added to the accumulator is the point-at-infinity.
293 auto lhs_infinity = transcript_Pinfinity * q_add + transcript_msm_infinity * msm_transition; // degree 2
294 auto rhs_infinity = is_accumulator_empty; // degree 1
295 // `result_is_lhs == 1` iff the output of the operation is the LHS and is _not_ the point-at-infinity.
296 // `result_is_rhs == 1` iff the output of the operation is the RHS and is _not_ the point-at-infinity.
297 auto result_is_lhs = rhs_infinity * (-lhs_infinity + 1); // degree 2
298 auto result_is_rhs = (-rhs_infinity + 1) * lhs_infinity; // degree 2
299 // `result_infinity_from_inputs` checks if both the LHS && RHS are the point-at-infinity. this means that the
300 // result is the point-at-infinity from "pure-thought" reasons from the inputs.
301 auto result_infinity_from_inputs = lhs_infinity * rhs_infinity; // degree 2
302 // `result_infinity_from_operation` tests if the operation is non-trivial and the output is the
303 // point-at-infinity. note we are using that our EC has no non-trivial rational 2-torsion.
304 auto result_infinity_from_operation = transcript_add_x_equal * (-transcript_add_y_equal + 1); // degree 2
305 // `result_infinity_from_inputs` and `result_infinity_from_operation` are mutually exclusive (i.e., cannot both
306 // be 1), so we can perform an OR by adding. (they are mutually exclusive because if
307 // `result_infinity_from_inputs` then `transcript_add_y_equal == 1`.)
308 auto result_is_infinity = result_infinity_from_inputs + result_infinity_from_operation; // degree 2
309 auto any_add_is_active = q_add + msm_transition; // degree 1
310
311 // Validate `transcript_msm_lambda` is well formed if we are adding MSM output into accumulator
312 {
313 Accumulator transcript_msm_lambda_relation(0);
314 auto msm_x = transcript_msm_x;
315 auto msm_y = transcript_msm_y;
316 // Group operation is point addition
317 {
318 auto lambda_denominator = (rhs_x - msm_x);
319 auto lambda_numerator = (rhs_y - msm_y);
320 auto lambda_relation = lambda * lambda_denominator - lambda_numerator; // degree 2
321 transcript_msm_lambda_relation += lambda_relation * is_add; // degree 3
322 }
323 // Group operation is point doubling
324 {
325 auto lambda_denominator = msm_y + msm_y;
326 auto lambda_numerator = msm_x * msm_x * 3;
327 auto lambda_relation = lambda * lambda_denominator - lambda_numerator; // degree 2
328 transcript_msm_lambda_relation += lambda_relation * is_double; // degree 4
329 }
330 auto transcript_add_or_dbl_from_msm_output_is_valid =
331 (-transcript_msm_infinity + 1) * (-is_accumulator_empty + 1); // degree 2
332 // zero-out the value of `transcript_msm_lambda_relation` if output of MSM is point-at-infinity or the
333 // accumulator is point-at-infinity. (this case cannot be handled uniformly and will be handled by the
334 // following logic.)
335 transcript_msm_lambda_relation *= transcript_add_or_dbl_from_msm_output_is_valid; // degree 6
336 // No group operation because of points at infinity
337 {
338 // `lambda_relation_invalid != 0` means that lambda does not enter into our calculation for
339 // point-at-infinity reasons. in this case, `lambda` is constrained to be 0.
340 auto lambda_relation_invalid =
341 (transcript_msm_infinity + is_accumulator_empty + result_infinity_from_operation); // degree 2
342 auto lambda_relation = lambda * lambda_relation_invalid; // degree 4
343 transcript_msm_lambda_relation += lambda_relation; // degree 6
344 }
345 // relation is only touched if we are at an msm_transition
346 transcript_lambda_relation = transcript_msm_lambda_relation * msm_transition; // degree 7
347 }
348 // Valdiate `transcript_add_lambda` is well formed if we are adding base point into accumulator
349 // very similar to the above code for adding an MSM output.
350 {
351 Accumulator transcript_add_lambda_relation(0);
352 auto add_x = transcript_Px;
353 auto add_y = transcript_Py;
354 // Group operation is point addition
355 {
356 auto lambda_denominator = (rhs_x - add_x);
357 auto lambda_numerator = (rhs_y - add_y);
358 auto lambda_relation = lambda * lambda_denominator - lambda_numerator; // degree 2
359 transcript_add_lambda_relation += lambda_relation * is_add; // degree 3
360 }
361 // Group operation is point doubling
362 {
363 auto lambda_denominator = add_y + add_y;
364 auto lambda_numerator = add_x * add_x * 3;
365 auto lambda_relation = lambda * lambda_denominator - lambda_numerator; // degree 2
366 transcript_add_lambda_relation += lambda_relation * is_double; // degree 4
367 }
368 auto transcript_add_or_dbl_from_add_output_is_valid =
369 (-transcript_Pinfinity + 1) * (-is_accumulator_empty + 1); // degree 2
370 transcript_add_lambda_relation *= transcript_add_or_dbl_from_add_output_is_valid; // degree 6
371 // No group operation because of points at infinity
372 {
373 // `lambda_relation_invalid != 0` means that lambda does not enter into our calculation for
374 // point-at-infinity reasons. in this case, `lambda` is constrained to be 0.
375 auto lambda_relation_invalid =
376 (transcript_Pinfinity + is_accumulator_empty + result_infinity_from_operation); // degree 2
377 auto lambda_relation = lambda * lambda_relation_invalid; // degree 4
378 transcript_add_lambda_relation += lambda_relation; // degree 6
379 }
380 // relation is only touched if we are at an `add` instruction.
381 transcript_lambda_relation += transcript_add_lambda_relation * q_add;
382 std::get<LAMBDA_RELATION>(accumulator) += transcript_lambda_relation * scaling_factor; // degree 7
383 }
395 // accumulator is propagated if we are at a `mul` and _not_ at an `msm_transition` OR we are at an `eq` and we
396 // don't reset the accumulator. note that if `msm_transition_check == 1` (i.e., we are at a syntactic
397 // transition) but the total number of muls is 0, then the accumulator should indeed be propagated.
398 auto propagate_transcript_accumulator =
399 (q_mul) * (-msm_transition + 1) + (q_eq * (-q_reset_accumulator + 1)); // degree 2
400 {
401 auto lambda_sqr = lambda * lambda;
402
403 // N.B. these relations rely on the fact that `lambda = 0` if we are not evaluating add/double formula
404 // (i.e. one or both outputs are points at infinity, or produce a point at infinity)
405 // This should be validated by the lambda_relation
406 auto x3 = lambda_sqr - lhs_x - rhs_x; // degree 2
407 auto y3 = lambda * (lhs_x - x3) - lhs_y; // degree 3
408 x3 += result_is_lhs * (rhs_x + lhs_x + lhs_x); // degree 4
409 x3 += result_is_rhs * (lhs_x + rhs_x + rhs_x); // degree 4
410 x3 += result_is_infinity * (lhs_x + rhs_x); // degree 4
411 y3 += result_is_lhs * (lhs_y + lhs_y); // degree 4
412 y3 += result_is_rhs * (lhs_y + rhs_y); // degree 4
413 y3 += result_is_infinity * lhs_y; // degree 4
414 // internal to the Transcript columns, the point-at-infinity is encoded as `(0, 0)`.
415 // this is implicit in the subsequent computations: e.g. if `result_is_infinity`, then `(x3, y3) == (0, 0)`,
416 // or if `q_reset_accumulator == 1`, then `(out_x, out_y) == (0, 0)`.
417 auto add_point_x_relation = (x3 - out_x) * any_add_is_active; // degree 5
418 add_point_x_relation +=
419 propagate_transcript_accumulator * is_not_last_row * (out_x - transcript_accumulator_x); // degree 4
420 // validate out_x = 0 if q_reset_accumulator = 1
421 add_point_x_relation += (out_x * q_reset_accumulator);
422 auto add_point_y_relation = (y3 - out_y) * any_add_is_active; // degree 5
423 add_point_y_relation +=
424 propagate_transcript_accumulator * is_not_last_row * (out_y - transcript_accumulator_y);
425 // validate out_y = 0 if q_reset_accumulator = 1
426 add_point_y_relation += (out_y * q_reset_accumulator);
427 auto opcode_is_zero =
428 (is_not_first_row) * (-q_add + 1) * (-q_mul + 1) * (-q_reset_accumulator + 1) * (-q_eq + 1); // degree 5
429 add_point_x_relation += (out_x * opcode_is_zero); // degree 6
430 add_point_y_relation += (out_y * opcode_is_zero); // degree 6
431
432 std::get<ACCUMULATOR_X_UPDATE>(accumulator) += add_point_x_relation * scaling_factor; // degree 6
433 std::get<ACCUMULATOR_Y_UPDATE>(accumulator) += add_point_y_relation * scaling_factor; // degree 6
434 }
435
436 // subtract offset generator from msm_accumulator. this might produce a point at infinity
437 {
438 // the fundamental relation is: `(transcript_msm_x, transcript_msm_y) - offset ==
439 // `(transcript_msm_intermediate_x, transcript_msm_intermediate_y)`. in other words, `(transcript_msm_x,
440 // transcript_msm_y)` is the _shifted_ value of the MSM.
441 const auto offset = offset_generator();
442 const auto x1 = offset[0];
443 const auto y1 = -offset[1];
444 const auto x2 = View(in.transcript_msm_x);
445 const auto y2 = View(in.transcript_msm_y);
446 const auto x3 = View(in.transcript_msm_intermediate_x);
447 const auto y3 = View(in.transcript_msm_intermediate_y);
448 const auto transcript_msm_infinity = View(in.transcript_msm_infinity);
449 // cases:
450 // x2 == x1, y2 == y1
451 // x2 != x1
452 const auto x_term = (x3 + x2 + x1) * (x2 - x1) * (x2 - x1) - (y2 - y1) * (y2 - y1); // degree 3
453 const auto y_term = (x1 - x3) * (y2 - y1) - (x2 - x1) * (y1 + y3); // degree 2
454 // If `transcript_msm_infinity == 0`, then `(transcript_msm_intermediate_x, transcript_msm_intermediate_y)`
455 // is the result of subtracting offset generator from `(transcript_msm_x, transcript_msm_y)`. If
456 // `transcript_msm_infinity == 1`, then both `transcript_msm_intermediate_x ==0` and
457 // `transcript_msm_intermediate_y == 0`.
458 //
459 // again, point-at-infinity is represented internally in the Transcript columns by `(0, 0)`.
460 const auto transcript_offset_generator_subtract_x =
461 x_term * (-transcript_msm_infinity + 1) + transcript_msm_infinity * x3; // degree 4
462 const auto transcript_offset_generator_subtract_y =
463 y_term * (-transcript_msm_infinity + 1) + transcript_msm_infinity * y3; // degree 3
464 std::get<OFFSET_GENERATOR_X>(accumulator) +=
465 msm_transition * transcript_offset_generator_subtract_x * scaling_factor; // degree 5
466 std::get<OFFSET_GENERATOR_Y>(accumulator) +=
467 msm_transition * transcript_offset_generator_subtract_y * scaling_factor; // degree 5
468
469 // validate `transcript_msm_infinity` is correct
470 // if `transcript_msm_infinity == 1`, then both `x2 == x1` and `y2 + y1 == 0`. (this is because `(x1, y1)`
471 // is the negative of the offset.)
472 const auto x_diff = x2 - x1;
473 const auto y_sum = y2 + y1;
474 std::get<MSM_INFINITY_X_DIFF>(accumulator) +=
475 msm_transition * transcript_msm_infinity * x_diff * scaling_factor; // degree 3
476 std::get<MSM_INFINITY_Y_SUM>(accumulator) +=
477 msm_transition * transcript_msm_infinity * y_sum * scaling_factor; // degree 3
478 // if `transcript_msm_infinity == 0`, then `x_diff` must have an inverse
479 const auto transcript_msm_x_inverse = View(in.transcript_msm_x_inverse);
480 const auto inverse_term = (-transcript_msm_infinity + 1) * (x_diff * transcript_msm_x_inverse - 1);
481 std::get<MSM_INFINITY_INVERSE>(accumulator) += msm_transition * inverse_term * scaling_factor; // degree 3
482 }
483
500 auto accumulator_infinity_preserve_flag = propagate_transcript_accumulator; // degree 1
501 auto accumulator_infinity_preserve = accumulator_infinity_preserve_flag *
502 (is_accumulator_empty - is_accumulator_empty_shift) *
503 is_not_first_or_last_row; // degree 3
504 auto accumulator_infinity_q_reset = q_reset_accumulator * (-is_accumulator_empty_shift + 1); // degree 2
505 auto accumulator_infinity_from_add =
506 any_add_is_active * (result_is_infinity - is_accumulator_empty_shift); // degree 3
507 // When opcode_is_zero (no-op row), the accumulator output is forced to (0,0) by subrelations 15 and 16.
508 // We must also force is_accumulator_empty_shift = 1 so that the emptiness flag is consistent
509 // with the (0,0) accumulator coordinates. Without this, a malicious prover could set
510 // accumulator_not_empty = 1 on the next row while the accumulator is (0,0), creating an
511 // inconsistency that bypasses on-curve checks (which are only performed on input coordinates).
512 auto opcode_is_zero =
513 (is_not_first_row) * (-q_add + 1) * (-q_mul + 1) * (-q_reset_accumulator + 1) * (-q_eq + 1); // degree 5
514 auto accumulator_infinity_from_noop = opcode_is_zero * (-is_accumulator_empty_shift + 1); // degree 6
515 auto accumulator_infinity_relation =
516 accumulator_infinity_preserve +
517 (accumulator_infinity_q_reset + accumulator_infinity_from_add) * is_not_first_row +
518 accumulator_infinity_from_noop; // degree 6
519 std::get<ACCUMULATOR_EMPTY_UPDATE>(accumulator) += accumulator_infinity_relation * scaling_factor; // degree 6
520
526 auto x_diff = lhs_x - rhs_x; // degree 2
527 // recall that transcript_Px_inverse is the claimed inverse of `x_diff`.
528 auto x_product = transcript_Px_inverse * (-transcript_add_x_equal + 1) + transcript_add_x_equal; // degree 2
529 auto x_constant = transcript_add_x_equal - 1; // degree 1
530 auto transcript_add_x_equal_check_relation = (x_diff * x_product + x_constant) * any_add_is_active; // degree 5
531 std::get<ADD_X_EQUAL_CHECK>(accumulator) += transcript_add_x_equal_check_relation * scaling_factor; // degree 5
532
538 auto y_diff = lhs_y - rhs_y;
539 auto y_product = transcript_Py_inverse * (-transcript_add_y_equal + 1) + transcript_add_y_equal;
540 auto y_constant = transcript_add_y_equal - 1;
541 auto transcript_add_y_equal_check_relation = (y_diff * y_product + y_constant) * any_add_is_active;
542 std::get<ADD_Y_EQUAL_CHECK>(accumulator) += transcript_add_y_equal_check_relation * scaling_factor; // degree 5
543 }
544
551 std::get<HIDING_ROW_EQ>(accumulator) += lagrange_second * (-q_eq + 1) * scaling_factor; // degree 2
552 std::get<HIDING_ROW_RESET>(accumulator) +=
553 lagrange_second * (-q_reset_accumulator + 1) * scaling_factor; // degree 2
554
561 // Base point coordinates must be zero when transcript_Pinfinity is set
562 std::get<INFINITY_BASE_PX>(accumulator) += transcript_Pinfinity * transcript_Px * scaling_factor; // degree 2
563 std::get<INFINITY_BASE_PY>(accumulator) += transcript_Pinfinity * transcript_Py * scaling_factor; // degree 2
564 // Accumulator coordinates must be zero when is_accumulator_empty is set
565 std::get<INFINITY_ACC_X>(accumulator) +=
566 is_accumulator_empty * transcript_accumulator_x * scaling_factor; // degree 2
567 std::get<INFINITY_ACC_Y>(accumulator) +=
568 is_accumulator_empty * transcript_accumulator_y * scaling_factor; // degree 2
569
577 lagrange_first * View(in.transcript_accumulator_not_empty) * scaling_factor; // degree 2
578}
579} // namespace bb
static void accumulate(ContainerOverSubrelations &accumulator, const AllEntities &in, const Parameters &, const FF &scaling_factor)
ECCVMTranscriptRelationImpl evaluates the correctness of the ECCVM transcript columns.
element class. Implements ecc group arithmetic using Jacobian coordinates See https://hyperelliptic....
Definition element.hpp:35
group_elements::affine_element< Fq, Fr, Params > affine_element
Definition group.hpp:44
ssize_t offset
Definition engine.cpp:62
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
group< fq, fr, Bn254G1Params > g1
Definition g1.hpp:34
constexpr std::span< const typename Group::affine_element > get_precomputed_generators()
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13