Skip to content

Commit 1a0e853

Browse files
committed
feat: WIP quick pil changes exploring removing is inf (no opcode changes yet)
1 parent 898f85b commit 1a0e853

20 files changed

Lines changed: 178 additions & 267 deletions

barretenberg/cpp/pil/vm2/bytecode/address_derivation.pil

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ namespace address_derivation;
307307

308308
// Enforces address_point = preaddress_public_key + incoming_viewing_key on Grumpkin, and that
309309
// address = address_point.x.
310+
// TODO(MW): Remove result_infinity?
310311
#[ADDRESS_ECADD]
311312
sel {
312313
preaddress_public_key_x, preaddress_public_key_y, precomputed.zero,
@@ -315,7 +316,7 @@ namespace address_derivation;
315316
} in ecc.sel {
316317
ecc.p_x, ecc.p_y, ecc.p_is_inf,
317318
ecc.q_x, ecc.q_y, ecc.q_is_inf,
318-
ecc.r_x, ecc.r_y, ecc.r_is_inf
319+
ecc.r_x, ecc.r_y, ecc.result_infinity
319320
};
320321

321322
// Note: We can safely assume the address point is not infinity since that would imply either

barretenberg/cpp/pil/vm2/ecc.pil

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,32 @@
66
* Grumpkin Curve Eqn in SW form: Y^2 = X^3 − 17.
77
* Note: Grumpkin forms a 2-cycle with BN254, i.e the base field of one is the scalar field of the other and vice-versa.
88
*
9-
* Note that once TODO(#AVM-266) is complete, is_inf will no longer be part of our point representation and we must either:
9+
*
10+
* MW NOTE: USING APPROACH 1 BELOW:
11+
* Note that once TODO(#AVM-266) is complete, is_inf will no longer be part of our point representation and we must either:
1012
* - continue to rely on the 'calling' trace to inject a constrained is_inf, or
1113
* - derive is_inf (<==> (X, Y) == (INFINITY_X, INFINITY_Y)) within this trace.
1214
*
1315
* USAGE: This is a non-memory aware subtrace used to constrain point addition as defined above. Each point can be looked up
1416
* by coordinates (lookup as defined in ecc_mem.pil):
1517
* #[INPUT_OUTPUT_ECC_ADD]
1618
* sel_should_exec {
17-
* p_x_n, p_y_n, p_is_inf, // Point P
18-
* q_x_n, q_y_n, q_is_inf, // Point Q
19-
* res_x, res_y, res_is_inf // Point R
19+
* p_x_n, p_y_n, // Point P
20+
* p_is_inf, // P == O
21+
* q_x_n, q_y_n, // Point Q
22+
* q_is_inf, // Q == O
23+
* res_x, res_y // Point R
2024
* } in ecc.sel {
21-
* ecc.p_x, ecc.p_y, ecc.p_is_inf, // Point P
22-
* ecc.q_x, ecc.q_y, ecc.q_is_inf, // Point Q
23-
* ecc.r_x, ecc.r_y, ecc.r_is_inf // Point R
25+
* ecc.p_x, ecc.p_y, // Point P
26+
* ecc.p_is_inf, // P == O
27+
* ecc.q_x, ecc.q_y,, // Point Q
28+
* ecc.q_is_inf, // Q == O
29+
* ecc.r_x, ecc.r_y // Point R
2430
* };
2531
*
32+
* MW NOTE: For now, the calling trace MUST constrain that p_is_inf, q_is_inf above are correct. This is so if we have a calling
33+
* trace in which we know inf would never be an input we can simply use precomputed.zero and avoid wasting gates on deriving is_inf.
34+
*
2635
* TRACE SHAPE: 1 single row per computation (P + Q = R).
2736
*
2837
* INTERACTIONS: This subtrace is looked up by:
@@ -41,11 +50,11 @@ namespace ecc;
4150
// We perform point addition over our Short Weierstrass (SW) curve with 3 cases outlined in the last section ('Assign Result').
4251
// The notation will be as follows:
4352
// P + Q = R where:
44-
// P = (p_x, p_y, p_is_inf), Q = (q_x, q_y, q_is_inf), R = (r_x, r_y, r_is_inf),
53+
// P = (p_x, p_y), Q = (q_x, q_y), R = (r_x, r_y),
4554
// where the coordinates satisfy:
4655
// y^2 = x^3 - 17 (unless is_inf is true).
4756
// The point at infinity, O, does not have valid coordinates (a property of SW curves). We represent it as:
48-
// O = (0, 0, true).
57+
// O = (0, 0).
4958
// Note: this is NOT enforced here for inputs, see ecc_mem.pil for example of constraining.
5059
//
5160

@@ -74,20 +83,20 @@ namespace ecc;
7483
// Point P in affine form
7584
pol commit p_x;
7685
pol commit p_y;
86+
// Must be constrained by the calling trace:
7787
pol commit p_is_inf; // @boolean
7888
p_is_inf * (1 - p_is_inf) = 0;
7989

8090
// Point Q in affine form
8191
pol commit q_x;
8292
pol commit q_y;
93+
// Must be constrained by the calling trace:
8394
pol commit q_is_inf; // @boolean
8495
q_is_inf * (1 - q_is_inf) = 0;
8596

8697
// Resulting Point R in affine form
8798
pol commit r_x;
8899
pol commit r_y;
89-
pol commit r_is_inf; // @boolean
90-
r_is_inf * (1 - r_is_inf) = 0;
91100

92101
// Check x coordinates, i.e. p_x == q_x
93102
pol commit x_match; // @boolean
@@ -151,9 +160,9 @@ namespace ecc;
151160
// If P != Q where x_match, this implies p_y == -q_y <==> P == -Q (INVERSE_PRED == true):
152161
// R := O
153162
// If P == O:
154-
// R := Q (r_x := q_x, r_y := q_y, r_is_inf = q_is_inf)
163+
// R := Q (r_x := q_x, r_y := q_y)
155164
// Vice versa, if Q == O:
156-
// R := P (r_x := p_x, r_y := p_y, r_is_inf = p_is_inf)
165+
// R := P (r_x := p_x, r_y := p_y)
157166
//
158167

159168
pol INVERSE_PRED = x_match * (1 - y_match);
@@ -186,6 +195,4 @@ namespace ecc;
186195
sel * (r_x - (EITHER_INF * (p_is_inf * q_x + q_is_inf * p_x)) - result_infinity * INFINITY_X - use_computed_result * COMPUTED_R_X) = 0;
187196
#[OUTPUT_Y_COORD]
188197
sel * (r_y - (EITHER_INF * (p_is_inf * q_y + q_is_inf * p_y)) - result_infinity * INFINITY_Y - use_computed_result * COMPUTED_R_Y) = 0;
189-
#[OUTPUT_INF_FLAG]
190-
sel * (r_is_inf - result_infinity) = 0;
191198

barretenberg/cpp/pil/vm2/ecc_mem.pil

Lines changed: 37 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -24,50 +24,38 @@ include "precomputed.pil";
2424
* #[DISPATCH_TO_ECC_ADD]
2525
* sel_exec_dispatch_ecc_add {
2626
* clk, context_id,
27-
* register[0], register[1], register[2], // Point P
28-
* register[3], register[4], register[5], // Point Q
29-
* rop[6], // Dst address
27+
* register[0], register[1], // Point P
28+
* register[2], register[3], // Point Q
29+
* rop[4], // Dst address
3030
* sel_opcode_error // Error
3131
* } is ecc_add_mem.sel {
3232
* ecc_add_mem.execution_clk, ecc_add_mem.space_id,
33-
* ecc_add_mem.p_x, ecc_add_mem.p_y, ecc_add_mem.p_is_inf, // Point P
34-
* ecc_add_mem.q_x, ecc_add_mem.q_y, ecc_add_mem.q_is_inf, // Point Q
33+
* ecc_add_mem.p_x, ecc_add_mem.p_y, // Point P
34+
* ecc_add_mem.q_x, ecc_add_mem.q_y, // Point Q
3535
* ecc_add_mem.dst_addr[0], // Dst address
3636
* ecc_add_mem.err // Error
3737
* };
3838
*
3939
* Opcode operands (relevant in EXECUTION when interacting with this gadget):
4040
* - rop[0]: p_x_addr
4141
* - rop[1]: p_y_addr
42-
* - rop[2]: p_is_inf_addr (ignored)
43-
* - rop[3]: q_x_addr
44-
* - rop[4]: q_y_addr
45-
* - rop[5]: q_is_inf_addr (ignored)
46-
* - rop[6]: dst_addr
47-
*
48-
* Note: The values at p_is_inf_addr, q_is_inf_addr are ignored by this circuit and will be removed
49-
* in TODO(#AVM-266). We instead derive whether the point is infinity by checking its coordinates
50-
* for our standard representation of (0, 0). See below for details on infinity points.
42+
* - rop[2]: q_x_addr
43+
* - rop[3]: q_y_addr
44+
* - rop[4]: dst_addr
5145
*
5246
* Memory I/O:
5347
* - register[0]: M[p_x_addr] aka p_x (x coordinate of point P - read from memory by EXECUTION)
5448
* - p_x is tagged-checked by execution/registers to be FF based on instruction spec.
5549
* - register[1]: M[p_y_addr] aka p_y (y coordinate of point P - read from memory by EXECUTION)
5650
* - p_y is tagged-checked by execution/registers to be FF based on instruction spec.
57-
* - register[2]: M[p_is_inf_addr] aka p_is_inf (boolean flag if P is the point at infinity - read from memory by EXECUTION)
58-
* - Note: ignored by this circuit and will be removed in TODO(#AVM-266).
59-
* - register[3]: M[q_x_addr] aka q_x (x coordinate of point Q - read from memory by EXECUTION)
51+
* - register[2]: M[q_x_addr] aka q_x (x coordinate of point Q - read from memory by EXECUTION)
6052
* - q_x is tagged-checked by execution/registers to be FF based on instruction spec.
61-
* - register[4]: M[q_y_addr] aka q_y (y coordinate of point Q - read from memory by EXECUTION)
53+
* - register[3]: M[q_y_addr] aka q_y (y coordinate of point Q - read from memory by EXECUTION)
6254
* - q_y is tagged-checked by execution/registers to be FF based on instruction spec.
63-
* - register[5]: M[q_is_inf_addr] aka q_is_inf (boolean flag if Q is the point at infinity - read from memory by EXECUTION)
64-
* - Note: ignored by this circuit and will be removed in TODO(#AVM-266).
65-
* - M[rop[6]]: M[dst_addr] aka res_x (x coordinate of the resulting point RES - written by this gadget)
55+
* - M[rop[4]]: M[dst_addr] aka res_x (x coordinate of the resulting point RES - written by this gadget)
6656
* - guaranteed by this gadget to be FF.
67-
* - M[rop[6]+1]: M[dst_offset+1] aka res_y (y coordinate of the resulting point RES - written by this gadget)
57+
* - M[rop[4]+1]: M[dst_offset+1] aka res_y (y coordinate of the resulting point RES - written by this gadget)
6858
* - guaranteed by this gadget to be FF.
69-
* - M[rop[6]+2]: M[dst_offset+2] aka res_is_inf (boolean flag if RES is the point at infinity - written by this gadget)
70-
* - guaranteed by this gadget to be U1.
7159
*
7260
* ERROR HANDLING:
7361
* Two errors need to be handled as part of this trace,
@@ -84,11 +72,11 @@ include "precomputed.pil";
8472
* --> gt.pil
8573
* This subtrace is looked up by:
8674
* - execution.pil: To constrain the dispatch permutation for the ECADD opcode (#[DISPATCH_TO_ECC_ADD]). Includes memory
87-
* reads (register[0] to register[5]), the initial write address (rop[6]), and error flag (sel_opcode_error).
75+
* reads (register[0] to register[3]), the initial write address (rop[4]), and error flag (sel_opcode_error).
8876
*
8977
* This subtrace looks up:
90-
* - memory.pil: To write the output point values (res_x, res_y, res_is_inf) to memory with standard write permutations
91-
* (#[WRITE_MEM_i] for i = 0, 1, 2).
78+
* - memory.pil: To write the output point values (res_x, res_y) to memory with standard write permutations
79+
* (#[WRITE_MEM_i] for i = 0, 1).
9280
* - ecc.pil: To retrieve the output point R as the result of adding the points P and Q read from memory
9381
* (#[INPUT_OUTPUT_ECC_ADD]). See below for details on infinity points.
9482
* - gt.pil: To constrain that the maximum written memory address is within range (#[CHECK_DST_ADDR_IN_RANGE]).
@@ -103,9 +91,7 @@ include "precomputed.pil";
10391
* For now, we simply ignore any is_inf flags coming from memory (assigning and not reading the placeholder is_inf_), but
10492
* will eventually remove it from the operands TODO(#AVM-266).
10593
*
106-
* TODO(MW): Is ignoring i.e. leaving a memory operand unconstrained safe? Execution still reads them but will remove
107-
* p/q_is_inf_ if so.
108-
*
94+
* MW NOTE: Still using p_is_inf, q_is_inf just as flags to tell ecc.pil how to treat the points.
10995
* Until #AVM-266, the ECC subtrace still requires a correctly constrained is_inf flag for each point. We derive it within
11096
* this circuit by enforcing (0, 0) <==> is_inf for input points P and Q:
11197
* - (0, 0) ==> is_inf by #[P/Q_ON_CURVE_CHECK] (zero coordinates will fail this relation unless is_inf is set correctly).
@@ -123,17 +109,16 @@ namespace ecc_add_mem;
123109

124110
pol commit execution_clk;
125111
pol commit space_id;
126-
pol commit dst_addr[3];
112+
pol commit dst_addr[2];
127113

128114
// dst_addr[0] constrained by the permutation to execution
129115
#[WRITE_INCR_DST_ADDR]
130116
dst_addr[1] = sel * (dst_addr[0] + 1);
131-
dst_addr[2] = sel * (dst_addr[0] + 2);
132117

133-
// TODO(#AVM-266): Remove p_is_inf_, q_is_inf_ (currently placeholders for #[DISPATCH_TO_ECC_ADD]).
134-
pol commit p_x, p_y, p_is_inf_;
135-
pol commit q_x, q_y, q_is_inf_;
118+
pol commit p_x, p_y;
119+
pol commit q_x, q_y;
136120

121+
// MW NOTE: Still using p_is_inf, q_is_inf just as flags to tell ecc.pil how to treat the points.
137122
// TODO(#AVM-266): Remove p_is_inf, q_is_inf entirely.
138123
// Needs to be committed columns as they are used in the lookups
139124
pol commit p_is_inf, q_is_inf; // constrained to be @boolean in the ecc subtrace (see #[INPUT_OUTPUT_ECC_ADD])
@@ -145,15 +130,15 @@ namespace ecc_add_mem;
145130

146131
// Use the comparison gadget to check that the max addresses are within range
147132
// The comparison gadget provides the ability to test GreaterThan so we check
148-
// dst_addr[2] > max_mem_addr
133+
// dst_addr[1] > max_mem_addr
149134
pol commit max_mem_addr; // Column needed until we support constants in lookups
150135
sel * (max_mem_addr - constants.AVM_HIGHEST_MEM_ADDRESS) = 0;
151136

152137
// Preconditions to `gt` gadget require both inputs to be bounded by 2^128.
153-
// `dst_addr[2]` = dst_addr[0] + 2 where dst_addr[0] is an address (< 2^32), so dst_addr[2] < 2^33.
138+
// `dst_addr[1]` = dst_addr[0] + 1 where dst_addr[0] is an address (< 2^32), so dst_addr[1] < 2^33.
154139
// `max_mem_addr` = AVM_HIGHEST_MEM_ADDRESS which is < 2^32.
155140
#[CHECK_DST_ADDR_IN_RANGE]
156-
sel { dst_addr[2], max_mem_addr, sel_dst_out_of_range_err }
141+
sel { dst_addr[1], max_mem_addr, sel_dst_out_of_range_err }
157142
in
158143
gt.sel_others { gt.input_a, gt.input_b, gt.res };
159144

@@ -196,10 +181,14 @@ namespace ecc_add_mem;
196181
///////////////////////////////////////////////////////////////////////
197182
// Dispatch inputs to ecc add and retrieve outputs
198183
///////////////////////////////////////////////////////////////////////
199-
pol commit res_x, res_y, res_is_inf; // res_is_inf is constrained to be @boolean in the ecc subtrace (see #[INPUT_OUTPUT_ECC_ADD])
184+
pol commit res_x, res_y;
200185
pol commit sel_should_exec; // @boolean (by definition)
201186
sel_should_exec = sel * (1 - err);
202187

188+
// MW NOTE: Still using p_is_inf, q_is_inf just as flags to tell ecc.pil how to treat the points.
189+
// MW NOTE: Output inifinities - in ecc.pil, if result_infinity, then r_x = INFINITY_X = 0, r_y = INFINITY_Y = 0.
190+
// Sufficient to just lookup res_x, res_y here?
191+
203192
// TODO(#AVM-266): Remove p_is_inf, q_is_inf entirely. For now, we ensure that the flag being set means that the coordinates
204193
// are set to our infinity representation: (INFINITY_X, INFINITY_Y) = (0, 0). The reverse ((INFINITY_X, INFINITY_Y) ==> is_inf)
205194
// is constrained by #[P/Q_ON_CURVE_CHECK]. Output infinities are already constrained to be (0, 0) in the subtrace.
@@ -217,12 +206,12 @@ namespace ecc_add_mem;
217206
sel_should_exec {
218207
p_x, p_y, p_is_inf,
219208
q_x, q_y, q_is_inf,
220-
res_x, res_y, res_is_inf
209+
res_x, res_y
221210
} in
222211
ecc.sel {
223212
ecc.p_x, ecc.p_y, ecc.p_is_inf,
224213
ecc.q_x, ecc.q_y, ecc.q_is_inf,
225-
ecc.r_x, ecc.r_y, ecc.r_is_inf
214+
ecc.r_x, ecc.r_y
226215
};
227216

228217
////////////////////////////////////////////////
@@ -244,11 +233,11 @@ namespace ecc_add_mem;
244233
memory.clk, memory.space_id, memory.address, memory.value, memory.tag, memory.rw
245234
};
246235

247-
#[WRITE_MEM_2]
248-
sel_should_exec {
249-
execution_clk, space_id, dst_addr[2], res_is_inf, /*U1_mem_tag=1*/ sel_should_exec, /*rw=1*/ sel_should_exec
250-
} is
251-
memory.sel_ecc_write[2] {
252-
memory.clk, memory.space_id, memory.address, memory.value, memory.tag, memory.rw
253-
};
236+
// #[WRITE_MEM_2]
237+
// sel_should_exec {
238+
// execution_clk, space_id, dst_addr[2], res_is_inf, /*U1_mem_tag=1*/ sel_should_exec, /*rw=1*/ sel_should_exec
239+
// } is
240+
// memory.sel_ecc_write[2] {
241+
// memory.clk, memory.space_id, memory.address, memory.value, memory.tag, memory.rw
242+
// };
254243

barretenberg/cpp/pil/vm2/execution.pil

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,11 +1277,10 @@ sel_exec_dispatch_keccakf1600 {
12771277
};
12781278

12791279
// ECADD DISPATCHING
1280-
// Each input point uses 3 registers:
1281-
// P = [x, y, is_inf] -> register[0..2], Q = [x, y, is_inf] -> register[3..5]
1282-
// TODO(#AVM-266): Remove is_inf and use 2 registers per point (for now, the 3rd register is read but ignored).
1280+
// Each input point uses 2 registers:
1281+
// P = [x, y] -> register[0..1], Q = [x, y] -> register[2..3]
12831282
// The output point is written to memory internally inside the ecc_add_mem (ecc_mem.pil) trace, starting at:
1284-
// dst_addr[0] -> rop[6]
1283+
// dst_addr[0] -> rop[4]
12851284
// Outputs (#[WRITE_MEM_x]) and memory write checks (#[CHECK_DST_ADDR_IN_RANGE]) are hence handled by the trace.
12861285

12871286
#[DISPATCH_TO_ECC_ADD]
@@ -1291,13 +1290,11 @@ sel_exec_dispatch_ecc_add {
12911290
// Point P
12921291
register[0],
12931292
register[1],
1294-
register[2],
12951293
// Point Q
1294+
register[2],
12961295
register[3],
1297-
register[4],
1298-
register[5],
12991296
// Dst address
1300-
rop[6],
1297+
rop[4],
13011298
// Error
13021299
sel_opcode_error
13031300
} is ecc_add_mem.sel {
@@ -1306,11 +1303,9 @@ sel_exec_dispatch_ecc_add {
13061303
// Point P
13071304
ecc_add_mem.p_x,
13081305
ecc_add_mem.p_y,
1309-
ecc_add_mem.p_is_inf_,
13101306
// Point Q
13111307
ecc_add_mem.q_x,
13121308
ecc_add_mem.q_y,
1313-
ecc_add_mem.q_is_inf_,
13141309
// Dst address
13151310
ecc_add_mem.dst_addr[0],
13161311
// Error

barretenberg/cpp/pil/vm2/scalar_mul.pil

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,12 @@ namespace scalar_mul;
175175
end * (temp_y - point_y) = 0;
176176
end * (temp_inf - point_inf) = 0;
177177

178+
// TODO(MW): Remove result_infinity?
178179
#[DOUBLE]
179180
sel_not_end { temp_x, temp_y, temp_inf, temp_x', temp_y', temp_inf', sel_not_end /* = 1 */ }
180181
in
181182
ecc.sel
182-
{ ecc.r_x, ecc.r_y, ecc.r_is_inf, ecc.p_x, ecc.p_y, ecc.p_is_inf, ecc.double_op };
183+
{ ecc.r_x, ecc.r_y, ecc.result_infinity, ecc.p_x, ecc.p_y, ecc.p_is_inf, ecc.double_op };
183184

184185
///////////////////////////////
185186
// Result Computation
@@ -203,11 +204,12 @@ namespace scalar_mul;
203204
SHOULD_PASS * (res_y - res_y') = 0;
204205
SHOULD_PASS * (res_inf - res_inf') = 0;
205206

207+
// TODO(MW): Remove result_infinity?
206208
#[ADD]
207209
should_add { res_x, res_y, res_inf, res_x', res_y', res_inf', temp_x, temp_y, temp_inf }
208210
in
209211
ecc.sel
210-
{ ecc.r_x, ecc.r_y, ecc.r_is_inf, ecc.p_x, ecc.p_y, ecc.p_is_inf, ecc.q_x, ecc.q_y, ecc.q_is_inf };
212+
{ ecc.r_x, ecc.r_y, ecc.result_infinity, ecc.p_x, ecc.p_y, ecc.p_is_inf, ecc.q_x, ecc.q_y, ecc.q_is_inf };
211213

212214

213215

0 commit comments

Comments
 (0)