Skip to content

Commit a68c3e8

Browse files
author
notnotraju
committed
set relation audited. no degrees have been optimized.
1 parent 2f3f861 commit a68c3e8

File tree

1 file changed

+108
-67
lines changed

1 file changed

+108
-67
lines changed

barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_set_relation_impl.hpp

Lines changed: 108 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,36 @@
1212
namespace bb {
1313

1414
/**
15-
* @brief Performs list-equivalence checks for the ECCVM
15+
* @brief Performs multiset equality checks for the ECCVM. This faciliates "communication" between disjoint sets of
16+
* columns, which we view as tables: the Precomputed table, the MSM table, and the Transcript table. This used to be
17+
* called a strict lookup argument (where every element written was read _exactly_ once.)
1618
*
17-
* @details ECCVMSetRelationImpl validates the correctness of the inputs/outputs of the three main algorithms evaluated
18-
* by the ECCVM.
19+
* @details ECCVMSetRelationImpl validates the correctness of the "inputs"/"outputs" of the three main algorithms
20+
* evaluated by the ECCVM. Note that the terminology of "inputs" and "outputs" is _purely psychological_; they each just
21+
* name the multiset we are adding to.
22+
*
23+
* It will be helpful to recall that `pc` always stands for point-counter. We use the terms interchangably.
24+
*
25+
* FIRST TERM: tuple of (pc, round, wnaf_slice), computed when slicing scalar multipliers into slices, as part of
26+
* ECCVMWnafRelation.
1927
*
20-
* First term: tuple of (pc, round, wnaf_slice), computed when slicing scalar multipliers into slices,
21-
* as part of ECCVMWnafRelation
2228
* Input source: ECCVMWnafRelation
2329
* Output source: ECCVMMSMRelation
2430
*
2531
*
26-
* Second term: tuple of (point-counter, P.x, P.y, scalar-multiplier), used in ECCVMWnafRelation and
27-
* ECCVMPointTableRelation
32+
*
33+
* SECOND TERM: tuple of (pc, P.x, P.y, scalar-multiplier), used in ECCVMWnafRelation.
34+
*
2835
* Input source: ECCVMPointTableRelation
29-
* Output source: ECCVMMSMRelation
36+
* Output source: ECCVMTranscriptRelation
37+
*
38+
* Note that, from the latter table, this is only turned on when we are at an MSM transition, so we don't record the
39+
* "intermediate" `transcript_pc` values from the Transcript columns. This is compatible with the fact that the `msm_pc`
40+
* values are _constant_ on a fixed MSM.
41+
*
42+
* THIRD TERM: tuple of (pc, P.x, P.y, msm-size) from ECCVMMSMRelation, to link the output of the MSM computation from
43+
* the MSM table to the values in the Transcript tables.
3044
*
31-
* Third term: tuple of (point-counter, P.x, P.y, msm-size) from ECCVMMSMRelation
3245
* Input source: ECCVMMSMRelation
3346
* Output source: ECCVMTranscriptRelation
3447
*
@@ -57,11 +70,19 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_numerator(const AllE
5770
const auto& precompute_select = View(in.precompute_select);
5871

5972
/**
60-
* @brief First term: tuple of (pc, round, wnaf_slice), computed when slicing scalar multipliers into slices,
61-
* as part of ECCVMWnafRelation.
62-
* If precompute_select = 1, tuple entry = (wnaf-slice + point-counter * beta + msm-round * beta_sqr).
63-
* There are 4 tuple entries per row.
73+
* @brief First term: tuple of (pc, round, wnaf_slice), computed when slicing scalar multipliers into slices, as
74+
* part of ECCVMWnafRelation.
75+
*
76+
* @details
77+
* There are 4 tuple entries per row of the Precompute table. Moreover, the element that "increments" is
78+
* 4 * `precompute_round`, due to the fact that the Precompute columns contain four "digits"/slices per row.
79+
*
80+
* @note
81+
* We only add this tuple if `precompute_select == 1`. Otherwise, we add a the tuple (0, 0, 0).
6482
*/
83+
84+
// OPTIMIZE(@zac-williamson #2226) optimize degrees
85+
6586
Accumulator numerator(1); // degree-0
6687
{
6788
const auto& s0 = View(in.precompute_s1hi);
@@ -71,7 +92,6 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_numerator(const AllE
7192
wnaf_slice += wnaf_slice;
7293
wnaf_slice += s1;
7394

74-
// TODO(@zac-williamson #2226) optimize
7595
const auto wnaf_slice_input0 = wnaf_slice + gamma + precompute_pc * beta + precompute_round4 * beta_sqr;
7696
numerator *= wnaf_slice_input0; // degree-1
7797
}
@@ -83,7 +103,6 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_numerator(const AllE
83103
wnaf_slice += wnaf_slice;
84104
wnaf_slice += s1;
85105

86-
// TODO(@zac-williamson #2226) optimize
87106
const auto wnaf_slice_input1 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 1) * beta_sqr;
88107
numerator *= wnaf_slice_input1; // degree-2
89108
}
@@ -95,7 +114,6 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_numerator(const AllE
95114
wnaf_slice += wnaf_slice;
96115
wnaf_slice += s1;
97116

98-
// TODO(@zac-williamson #2226) optimize
99117
const auto wnaf_slice_input2 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 2) * beta_sqr;
100118
numerator *= wnaf_slice_input2; // degree-3
101119
}
@@ -106,7 +124,6 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_numerator(const AllE
106124
auto wnaf_slice = s0 + s0;
107125
wnaf_slice += wnaf_slice;
108126
wnaf_slice += s1;
109-
// TODO(@zac-williamson #2226) optimize
110127
const auto wnaf_slice_input3 = wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + 3) * beta_sqr;
111128
numerator *= wnaf_slice_input3; // degree-4
112129
}
@@ -121,15 +138,24 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_numerator(const AllE
121138
}
122139
{
123140
const auto& eccvm_set_permutation_delta = params.eccvm_set_permutation_delta;
141+
// if `precompute_select == 1`, don't change the numerator. if it is 0, then to get the grand product argument
142+
// to work (as we have zero-padded the rows of the MSM table), we must multiply by
143+
// `eccvm_set_permutation_delta` == (γ)·(γ + β²)·(γ + 2β²)·(γ + 3β²)
124144
numerator *= precompute_select * (-eccvm_set_permutation_delta + 1) + eccvm_set_permutation_delta; // degree-7
125145
}
126146

127147
/**
128-
* @brief Second term: tuple of (point-counter, P.x, P.y, scalar-multiplier), used in ECCVMWnafRelation and
129-
* ECCVMPointTableRelation. ECCVMWnafRelation validates the sum of the wnaf slices associated with point-counter
148+
* @brief Second term: tuple of (pc, P.x, P.y, scalar-multiplier), used in ECCVMWnafRelation and
149+
* ECCVMPointTableRelation.
150+
*
151+
* @details
152+
* ECCVMWnafRelation validates the sum of the wnaf slices associated with point-counter
130153
* equals scalar-multiplier. ECCVMPointTableRelation computes a table of muliples of [P]: { -15[P], -13[P], ...,
131-
* 15[P] }. We need to validate that scalar-multiplier and [P] = (P.x, P.y) come from MUL opcodes in the transcript
132-
* columns.
154+
* 15[P] }. We need to validate that the scalar-multiplier and [P] = (P.x, P.y) come from MUL opcodes in the
155+
* transcript columns; in other words, that the wNAF expansion of the scalar-multiplier is correct.
156+
*
157+
* @note
158+
* We only add the tuple to the multiset if `precompute_point_transition == 1`.
133159
*/
134160
{
135161
const auto& table_x = View(in.precompute_tx);
@@ -200,16 +226,19 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_numerator(const AllE
200226
numerator *= point_table_init_read; // degree-9
201227
}
202228
/**
203-
* @brief Third term: tuple of (point-counter, P.x, P.y, msm-size) from ECCVMMSMRelation.
229+
* @brief Third term: tuple of (pc, P.x, P.y, msm-size) from ECCVMMSMRelation.
204230
* (P.x, P.y) is the output of a multi-scalar-multiplication evaluated in ECCVMMSMRelation.
205231
* We need to validate that the same values (P.x, P.y) are present in the Transcript columns and describe a
206-
* multi-scalar multiplication of size `msm-size`, starting at `point-counter`.
232+
* multi-scalar multiplication of size `msm-size`, starting at `pc`.
207233
*
208-
* If msm_transition_shift = 1, this indicates the current row is the last row of a multiscalar
209-
* multiplication evaluation. The output of the MSM will be present on `(msm_accumulator_x_shift,
210-
* msm_accumulator_y_shift)`. The values of `msm_accumulator_x_shift, msm_accumulator_y_shift, msm_pc,
211-
* msm_size_of_msm` must match up with equivalent values `transcript_msm_output_x, transcript_msm_output_y,
212-
* transcript_pc, transcript_msm_count` present in the Transcript columns
234+
* If `msm_transition_shift == 1`, this indicates the current row is the last row of a multiscalar
235+
* multiplication evaluation. The output of the MSM will be present on `(msm_accumulator_x_shift,
236+
* msm_accumulator_y_shift)`. The values of `msm_accumulator_x_shift, msm_accumulator_y_shift, msm_pc,
237+
* msm_size_of_msm` must match up with equivalent values `transcript_msm_output_x, transcript_msm_output_y,
238+
* transcript_pc, transcript_msm_count` present in the Transcript columns.
239+
*
240+
* Checking `msm_size` is correct (it is tied to the `pc`) is necessary to make sure the `msm_pc` increments
241+
* correctly after it completes an MSM.
213242
*/
214243
{
215244
const auto& lagrange_first = View(in.lagrange_first);
@@ -248,8 +277,8 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_denominator(const Al
248277
{
249278
using View = typename Accumulator::View;
250279

251-
// TODO(@zac-williamson). The degree of this contribution is 17! makes overall relation degree 19.
252-
// Can optimize by refining the algebra, once we have a stable base to iterate off of.
280+
// OPTIMIZE(@zac-williamson). The degree of this contribution is 17! makes overall relation degree 19.
281+
// Can potentially optimize by refining the algebra.
253282
const auto& gamma = params.gamma;
254283
const auto& beta = params.beta;
255284
const auto& beta_sqr = params.beta_sqr;
@@ -297,43 +326,52 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_denominator(const Al
297326
}
298327

299328
/**
300-
* @brief Second term: tuple of (transcript_pc, transcript_Px, transcript_Py, z1) OR (transcript_pc, \lambda *
301-
* transcript_Px, -transcript_Py, z2) for each scalar multiplication in ECCVMTranscriptRelation columns. (the latter
302-
* term uses the curve endomorphism: \lambda = cube root of unity). These values must be equivalent to the second
329+
* @brief Second term: tuple of the form `(transcript_pc, transcript_Px, transcript_Py, z1)` OR `(transcript_pc,
330+
* \beta * transcript_Px, -transcript_Py, z2)` for each scalar multiplication in ECCVMTranscriptRelation columns.
331+
* Here \f$\beta\f$ is a cube root of unity in \f$\mathbb f_q\f$. These values must be equivalent to the second
303332
* term values in `compute_grand_product_numerator`
333+
*
334+
* @details
335+
* Recall that every element of \f$\mathbb F_r\f$ may be written as \f$z_1 + \zeta z_2 = z_1 - \beta z_2\f$, where
336+
* the \f$z_i\f$ are 128 bit numbers and \f$\zeta = -\beta\f$ is a sixth root of unity.
304337
*/
305338
{
306339
const auto& transcript_pc = View(in.transcript_pc);
307340

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);
341+
const auto& transcript_Px = View(in.transcript_Px);
342+
const auto& transcript_Py = View(in.transcript_Py);
343+
const auto& z1 = View(in.transcript_z1);
344+
const auto& z2 = View(in.transcript_z2);
345+
const auto& z1_zero = View(in.transcript_z1zero);
346+
const auto& z2_zero = View(in.transcript_z2zero);
347+
const auto& base_infinity = View(in.transcript_base_infinity);
348+
const auto& transcript_mul = View(in.transcript_mul);
316349

317-
auto lookup_first = (-z1_zero + 1);
318-
auto lookup_second = (-z2_zero + 1);
319-
FF endomorphism_base_field_shift = FF(bb::fq::cube_root_of_unity());
350+
const auto& lookup_first = (-z1_zero + 1);
351+
const auto& lookup_second = (-z2_zero + 1);
352+
FF cube_root_unity = FF(bb::fq::cube_root_of_unity());
320353

321354
auto transcript_input1 =
322355
transcript_pc + transcript_Px * beta + transcript_Py * beta_sqr + z1 * beta_cube; // degree = 1
323-
auto transcript_input2 = (transcript_pc - 1) + transcript_Px * endomorphism_base_field_shift * beta -
356+
auto transcript_input2 = (transcript_pc - 1) + transcript_Px * cube_root_unity * beta -
324357
transcript_Py * beta_sqr + z2 * beta_cube; // degree = 2
325358

326-
// | q_mul | z2_zero | z1_zero | base_infinity | lookup |
327-
// | ----- | ------- | ------- | ------------- |----------------------- |
328-
// | 0 | - | - | - | 1 |
329-
// | 1 | 0 | 0 | 0 | 1 |
330-
// | 1 | 0 | 1 | 0 | X + gamma |
331-
// | 1 | 1 | 0 | 0 | Y + gamma |
332-
// | 1 | 1 | 1 | 0 | (X + gamma)(Y + gamma) |
333-
// | 1 | 0 | 0 | 1 | 1 |
334-
// | 1 | 0 | 1 | 1 | 1 |
335-
// | 1 | 1 | 0 | 1 | 1 |
336-
// | 1 | 1 | 1 | 1 | 1 |
359+
// The following diagram expresses a fingerprint of part of the tuple. It does not include `transcript_pc` and
360+
// has not weighted the X and Y with beta and beta_sqr respectively. The point is nonetheless to show exactly
361+
// when a tuple is added to the multiset: iff it corresponds to a non-trivial (128-bit) scalar mul. If neither
362+
// z1 nor z2 are zero, then we implicitly add _two_ tuples to the multiset.
363+
//
364+
// | q_mul | z2_zero | z1_zero | base_infinity | partial lookup |
365+
// | ----- | ------- | ------- | ------------- |----------------------- |
366+
// | 0 | - | - | - | 1 |
367+
// | 1 | 0 | 0 | 0 | 1 |
368+
// | 1 | 0 | 1 | 0 | X + gamma |
369+
// | 1 | 1 | 0 | 0 | Y + gamma |
370+
// | 1 | 1 | 1 | 0 | (X + gamma)(Y + gamma) |
371+
// | 1 | 0 | 0 | 1 | 1 |
372+
// | 1 | 0 | 1 | 1 | 1 |
373+
// | 1 | 1 | 0 | 1 | 1 |
374+
// | 1 | 1 | 1 | 1 | 1 |
337375
transcript_input1 = (transcript_input1 + gamma) * lookup_first + (-lookup_first + 1); // degree 2
338376
transcript_input2 = (transcript_input2 + gamma) * lookup_second + (-lookup_second + 1); // degree 3
339377

@@ -348,19 +386,22 @@ Accumulator ECCVMSetRelationImpl<FF>::compute_grand_product_denominator(const Al
348386
* @brief Third term: tuple of (point-counter, P.x, P.y, msm-size) from ECCVMTranscriptRelation.
349387
* (P.x, P.y) is the *claimed* output of a multi-scalar-multiplication evaluated in ECCVMMSMRelation.
350388
* We need to validate that the msm output produced in ECCVMMSMRelation is equivalent to the output present
351-
* in `transcript_msm_output_x, transcript_msm_output_y`, for a given multi-scalar multiplication starting at
352-
* `transcript_pc` and has size `transcript_msm_count`
389+
* in `transcript_msm_output_x, transcript_msm_output_y`, for a given multi-scalar multiplication starting at
390+
* `transcript_pc` and has size `transcript_msm_count`.
391+
* @note In the case of an honest prover, `(transcript_msm_output_x, transcript_msm_output_y)` is the value of the
392+
* just-completed MSM + `OFFSET` (as this is what the MSM table computes with to avoid branch logic.)
393+
*
353394
*/
354395
{
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);
396+
const auto& transcript_pc_shift = View(in.transcript_pc_shift);
397+
const auto& transcript_msm_x = View(in.transcript_msm_x);
398+
const auto& transcript_msm_y = View(in.transcript_msm_y);
399+
const auto& transcript_msm_transition = View(in.transcript_msm_transition);
400+
const auto& transcript_msm_count = View(in.transcript_msm_count);
401+
const auto& z1_zero = View(in.transcript_z1zero);
402+
const auto& z2_zero = View(in.transcript_z2zero);
403+
const auto& transcript_mul = View(in.transcript_mul);
404+
const auto& base_infinity = View(in.transcript_base_infinity);
364405

365406
// do not add to count if point at infinity!
366407
auto full_msm_count =

0 commit comments

Comments
 (0)