Skip to content

Commit 4cd7f3d

Browse files
authored
chore(avm)!: Remove is_infinite flag from point wrapper constructor (#22921)
This branch solely contains the changes needed to remove the `is_infinite` flag from our `StandardAffinePoint` C++ wrapper. Now, we check whether `x` and `y` are zero to assign an `inf` underlying point. Will close [Foundation AVM Issue 17](https://linear.app/aztec-foundation/issue/AVM-17/remove-is-inf-flag-from-avms-standardaffinepoint) --- Stack: - #22745 - #22564 - `mw/avm-rem-inf-point-wrapper` <-- here - #22795 - #22945 - #23031
1 parent b01d712 commit 4cd7f3d

9 files changed

Lines changed: 76 additions & 154 deletions

File tree

barretenberg/cpp/src/barretenberg/avm_fuzzer/harness/ecc.fuzzer.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -288,13 +288,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
288288
// Verify output in memory
289289
MemoryValue res_x = mem->get(input.addresses[6]);
290290
MemoryValue res_y = mem->get(input.addresses[6] + 1);
291-
MemoryValue res_inf = mem->get(input.addresses[6] + 2);
292291

293-
EmbeddedCurvePoint result_point = EmbeddedCurvePoint(res_x.as_ff(), res_y.as_ff(), res_inf.as_ff() == FF(1));
292+
EmbeddedCurvePoint result_point = EmbeddedCurvePoint(res_x.as_ff(), res_y.as_ff());
294293

295294
BB_ASSERT(result_point.x() == expected_result.x(), "Result x-coordinate mismatch");
296295
BB_ASSERT(result_point.y() == expected_result.y(), "Result y-coordinate mismatch");
297-
BB_ASSERT(result_point.is_infinity() == expected_result.is_infinity(), "Result infinity flag mismatch");
298296

299297
// Non mem-aware ecmul result:
300298
expected_result = point_p * input.scalar;

barretenberg/cpp/src/barretenberg/vm2/common/standard_affine_point.hpp

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,15 @@
66
namespace bb::avm2 {
77

88
/**
9-
* AVM bytecode expects the representation of points to be triplets, the two coordinates and an is_infinity boolean.
10-
* Furthermore, its representation of infinity is inherited from noir's and is expected to be 0,0,true.
11-
* BB, however, uses only the two coordinates to represent points. Infinity in barretenberg is represented as (P+1)/2,0.
12-
* This class is a wrapper of the BB representation, needed to operate with points, that allows us to extract the
13-
* standard representation that AVM bytecode expects.
9+
* The AVM's representation of infinity is inherited from noir's and is expected to be 0,0.
10+
* BB, however, uses only the two coordinates to represent points. Infinity in barretenberg is represented as
11+
* (P+1)/2,0,true. This class is a wrapper of the BB representation, needed to operate with points, that allows us to
12+
* extract the standard representation that AVM bytecode expects.
1413
*
1514
* NOTE: When constructing infinity from BB's two element representation, we keep the original AffinePoint so operations
1615
* can use it in the background, but set extractable coordinates to be our represention of (0,0).
17-
* NOTE: When constructing infinity via BaseFields, input coordinates are overwritten to our representation of (0,0)
18-
* if the input is_infinity is true, so will mismatch the underlying AffinePoint's coordinates.
19-
*
20-
* TODO(#AVM-266): Remove is_infinity flag from point representation.
16+
* NOTE: When constructing infinity via BaseFields (equiv. inputting (0, 0), the underlying AffinePoint is set to BB's
17+
* representation so operations can use it in the background.
2118
*/
2219
template <typename AffinePoint> class StandardAffinePoint {
2320
public:
@@ -32,12 +29,10 @@ template <typename AffinePoint> class StandardAffinePoint {
3229
, y_coord(val.is_point_at_infinity() ? zero : val.y)
3330
{}
3431

35-
// TODO(MW): Do we want to silently discard input x, y if is_infinity = true?
36-
// Or, discard is_infinity and set point to AffinePoint::infinity() iff x = y = 0?
37-
constexpr StandardAffinePoint(BaseField x, BaseField y, bool is_infinity) noexcept
38-
: point(is_infinity ? AffinePoint::infinity() : AffinePoint(x, y))
39-
, x_coord(is_infinity ? zero : x)
40-
, y_coord(is_infinity ? zero : y)
32+
constexpr StandardAffinePoint(BaseField x, BaseField y) noexcept
33+
: point((x.is_zero() && y.is_zero()) ? AffinePoint::infinity() : AffinePoint(x, y))
34+
, x_coord(x)
35+
, y_coord(y)
4136
{}
4237

4338
constexpr StandardAffinePoint operator+(const StandardAffinePoint& other) const noexcept
@@ -87,7 +82,7 @@ template <typename AffinePoint> class StandardAffinePoint {
8782

8883
static const StandardAffinePoint& infinity()
8984
{
90-
static auto infinity = StandardAffinePoint(zero, zero, true);
85+
static auto infinity = StandardAffinePoint(zero, zero);
9186
return infinity;
9287
}
9388

barretenberg/cpp/src/barretenberg/vm2/common/standard_affine_point.test.cpp

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,17 @@ using EmbeddedCurvePoint = StandardAffinePoint<grumpkin::g1::affine_element>;
1010
using Fr = grumpkin::fr;
1111
using Fq = grumpkin::fq;
1212

13-
TEST(StandardAffinePointTest, InfinityDiscardsRawCoordinates)
13+
TEST(StandardAffinePointTest, ConstructingInfinityNormalized)
1414
{
15-
// NOTE: As of #AVM-248, we moved from preserving raw coordinates in
16-
// infinity points to our (0,0) representation when using x() and y().
17-
// The underlying AffinePoint is set to AffinePoint::infinity() for
18-
// bb operations.
19-
20-
// When constructing an infinity point with non-zero coordinates,
21-
// x() and y() should return our standard representation.
22-
Fq raw_x = 1;
23-
Fq raw_y = 2;
24-
25-
// Note that raw x and y are silently discarded.
26-
EmbeddedCurvePoint point(raw_x, raw_y, /*is_infinity=*/true);
27-
28-
EXPECT_TRUE(point.is_infinity());
29-
EXPECT_TRUE(point.x().is_zero());
30-
EXPECT_TRUE(point.y().is_zero());
15+
// Constructing a point with (0,0) coordinates should result in infinity
16+
EmbeddedCurvePoint inf(0, 0);
17+
EXPECT_TRUE(inf.is_infinity());
18+
// Constructing a point with BB's inf should result in infinity with (0,0) coordinates
19+
EmbeddedCurvePoint inf_bb(grumpkin::g1::affine_element::infinity());
20+
EXPECT_TRUE(inf_bb.is_infinity());
21+
EXPECT_TRUE(inf_bb.x().is_zero());
22+
EXPECT_TRUE(inf_bb.y().is_zero());
23+
EXPECT_EQ(inf, inf_bb);
3124
}
3225

3326
TEST(StandardAffinePointTest, NormalPointCoordinates)
@@ -78,7 +71,7 @@ TEST(StandardAffinePointTest, ScalarMultiplicationResultingInInfinityNormalized)
7871

7972
TEST(StandardAffinePointTest, StaticInfinityHasZeroCoordinates)
8073
{
81-
// The static infinity() method should return (0,0,true)
74+
// The static infinity() method should return (0,0)
8275
auto& inf = EmbeddedCurvePoint::infinity();
8376

8477
EXPECT_TRUE(inf.is_infinity());
@@ -88,10 +81,8 @@ TEST(StandardAffinePointTest, StaticInfinityHasZeroCoordinates)
8881

8982
TEST(StandardAffinePointTest, NegatingInfinity)
9083
{
91-
// Negating an infinity point should return (0,0,true)
92-
EmbeddedCurvePoint inf(0, 0, /*is_infinity=*/true);
93-
94-
auto neg_inf = -inf;
84+
// Negating an infinity point should return (0,0)
85+
auto neg_inf = -EmbeddedCurvePoint::infinity();
9586

9687
EXPECT_TRUE(neg_inf.is_infinity());
9788
EXPECT_TRUE(neg_inf.x().is_zero());

barretenberg/cpp/src/barretenberg/vm2/constraining/relations/ecc.test.cpp

Lines changed: 22 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ using simulation::ToRadixMemoryEvent;
6464
// Known good points for P and Q
6565
FF p_x("0x04c95d1b26d63d46918a156cae92db1bcbc4072a27ec81dc82ea959abdbcf16a");
6666
FF p_y("0x035b6dd9e63c1370462c74775765d07fc21fd1093cc988149d3aa763bb3dbb60");
67-
EmbeddedCurvePoint p(p_x, p_y, false);
67+
EmbeddedCurvePoint p(p_x, p_y);
6868

6969
FF q_x("0x009242167ec31949c00cbe441cd36757607406e87844fa2c8c4364a4403e66d7");
7070
FF q_y("0x0fe3016d64cfa8045609f375284b6b739b5fa282e4cbb75cc7f1687ecc7420e3");
71-
EmbeddedCurvePoint q(q_x, q_y, false);
71+
EmbeddedCurvePoint q(q_x, q_y);
7272

7373
TEST(EccAddConstrainingTest, EccEmptyRow)
7474
{
@@ -80,7 +80,7 @@ TEST(EccAddConstrainingTest, EccAdd)
8080
// R = P + Q;
8181
FF r_x("0x2b01df0ef6d941a826bea23bece8243cbcdc159d5e97fbaa2171f028e05ba9b6");
8282
FF r_y("0x0cc4c71e882bc62b7b3d1964a8540cb5211339dfcddd2e095fd444bf1aed4f09");
83-
EmbeddedCurvePoint r(r_x, r_y, false);
83+
EmbeddedCurvePoint r(r_x, r_y);
8484

8585
auto trace = TestTraceContainer({ {
8686
{ C::ecc_add_op, 1 },
@@ -124,7 +124,7 @@ TEST(EccAddConstrainingTest, EccDouble)
124124
// R = P + P;
125125
FF r_x("0x088b996194bb5e6e8e5e49733bb671c3e660cf77254f743f366cc8e33534ee3b");
126126
FF r_y("0x2807ffa01c0f522d0be1e1acfb6914ac8eabf1acf420c0629d37beee992e9a0e");
127-
EmbeddedCurvePoint r(r_x, r_y, false);
127+
EmbeddedCurvePoint r(r_x, r_y);
128128

129129
auto trace = TestTraceContainer({ {
130130
{ C::ecc_add_op, 0 },
@@ -174,13 +174,13 @@ TEST(EccAddConstrainingTest, EccAddSameYDifferentX)
174174
// Point P - known valid point on Grumpkin
175175
FF local_p_x("0x04c95d1b26d63d46918a156cae92db1bcbc4072a27ec81dc82ea959abdbcf16a");
176176
FF local_p_y("0x035b6dd9e63c1370462c74775765d07fc21fd1093cc988149d3aa763bb3dbb60");
177-
EmbeddedCurvePoint local_p(local_p_x, local_p_y, false);
177+
EmbeddedCurvePoint local_p(local_p_x, local_p_y);
178178

179179
// Point Q - p_x * omega (cube root of unity), same y-coordinate!
180180
// omega = 0x0000000000000000b3c4d79d41a917585bfc41088d8daaa78b17ea66b99c90dd
181181
FF local_q_x("0x14dd39aa19e1c8b29e0c530a28106a7d64d2213486baba3c86dce51bdddf75bb");
182182
FF local_q_y("0x035b6dd9e63c1370462c74775765d07fc21fd1093cc988149d3aa763bb3dbb60");
183-
EmbeddedCurvePoint local_q(local_q_x, local_q_y, false);
183+
EmbeddedCurvePoint local_q(local_q_x, local_q_y);
184184

185185
// Verify preconditions: same y, different x
186186
ASSERT_NE(local_p.x(), local_q.x());
@@ -189,7 +189,7 @@ TEST(EccAddConstrainingTest, EccAddSameYDifferentX)
189189
// Expected result R = P + Q (lambda = 0 since y's are equal)
190190
FF local_r_x("0x16bdb7ada0799a3088b9dd3faade12c3f79dbfe9cb1234783a1a7add546398dc");
191191
FF local_r_y("0x2d08e098faf58cb97223d13f2a1b87dd6614173f3cefe87ca6a74e3034c244a1");
192-
EmbeddedCurvePoint local_r(local_r_x, local_r_y, false);
192+
EmbeddedCurvePoint local_r(local_r_x, local_r_y);
193193

194194
// Use simulation to generate events
195195
EventEmitter<EccAddEvent> ecc_add_event_emitter;
@@ -222,8 +222,8 @@ TEST(EccAddConstrainingTest, EccAddSameYDifferentX)
222222
TEST(EccAddConstrainingTest, EccAddResultingInInfinity)
223223
{
224224
// R = P + (-P) = O; , where O is the point at infinity
225-
EmbeddedCurvePoint q(p.x(), -p.y(), false);
226-
EmbeddedCurvePoint r(0, 0, true);
225+
EmbeddedCurvePoint q(p.x(), -p.y());
226+
EmbeddedCurvePoint r(0, 0);
227227

228228
auto trace = TestTraceContainer({ {
229229
{ C::ecc_add_op, 0 },
@@ -262,11 +262,11 @@ TEST(EccAddConstrainingTest, EccAddResultingInInfinity)
262262

263263
TEST(EccAddConstrainingTest, EccAddingToInfinity)
264264
{
265-
EmbeddedCurvePoint p(0, 0, true);
265+
EmbeddedCurvePoint p(0, 0);
266266

267267
// R = O + Q = Q; , where O is the point at infinity
268268

269-
EmbeddedCurvePoint r(q.x(), q.y(), false);
269+
EmbeddedCurvePoint r(q.x(), q.y());
270270

271271
auto trace = TestTraceContainer({ {
272272
{ C::ecc_add_op, 1 },
@@ -305,10 +305,10 @@ TEST(EccAddConstrainingTest, EccAddingToInfinity)
305305

306306
TEST(EccAddConstrainingTest, EccAddingInfinity)
307307
{
308-
EmbeddedCurvePoint q(0, 0, true);
308+
EmbeddedCurvePoint q(0, 0);
309309

310310
// R = P + O = P; , where O is the point at infinity
311-
EmbeddedCurvePoint r(p.x(), p.y(), false);
311+
EmbeddedCurvePoint r(p.x(), p.y());
312312

313313
auto trace = TestTraceContainer({ {
314314
{ C::ecc_add_op, 1 },
@@ -348,10 +348,10 @@ TEST(EccAddConstrainingTest, EccAddingInfinity)
348348

349349
TEST(EccAddConstrainingTest, EccDoublingInf)
350350
{
351-
EmbeddedCurvePoint p(0, 0, true);
351+
EmbeddedCurvePoint p(0, 0);
352352

353353
// r = O + O = O; , where O is the point at infinity
354-
EmbeddedCurvePoint r(0, 0, true);
354+
EmbeddedCurvePoint r(0, 0);
355355

356356
auto trace = TestTraceContainer({ {
357357
{ C::ecc_add_op, 0 },
@@ -470,7 +470,7 @@ TEST(EccAddConstrainingTest, EccNegativeBadAdd)
470470

471471
FF r_x("0x20f096ae3de9aea007e0b94a0274b2443d6682d1901f6909f284ec967bc169be");
472472
FF r_y("0x27948713833bb314e828f2b6f45f408da6564a3ac03b9e430a9c6634bb849ef2");
473-
EmbeddedCurvePoint r(r_x, r_y, false);
473+
EmbeddedCurvePoint r(r_x, r_y);
474474

475475
auto trace = TestTraceContainer({ {
476476
{ C::ecc_add_op, 1 },
@@ -514,7 +514,7 @@ TEST(EccAddConstrainingTest, EccNegativeBadDouble)
514514

515515
FF r_x("0x2b01df0ef6d941a826bea23bece8243cbcdc159d5e97fbaa2171f028e05ba9b6");
516516
FF r_y("0x0cc4c71e882bc62b7b3d1964a8540cb5211339dfcddd2e095fd444bf1aed4f09");
517-
EmbeddedCurvePoint r(r_x, r_y, false);
517+
EmbeddedCurvePoint r(r_x, r_y);
518518

519519
auto trace = TestTraceContainer({ {
520520
{ C::ecc_add_op, 0 },
@@ -772,40 +772,6 @@ TEST(ScalarMulConstrainingTest, MulAddInteractionsInfinity)
772772
EventEmitter<ScalarMulEvent> scalar_mul_event_emitter;
773773
NoopEventEmitter<EccAddMemoryEvent> ecc_add_memory_event_emitter;
774774

775-
StrictMock<MockExecutionIdManager> execution_id_manager;
776-
StrictMock<MockGreaterThan> gt;
777-
PureToRadix to_radix_simulator = PureToRadix();
778-
EccSimulator ecc_simulator(execution_id_manager,
779-
gt,
780-
to_radix_simulator,
781-
ecc_add_event_emitter,
782-
scalar_mul_event_emitter,
783-
ecc_add_memory_event_emitter);
784-
785-
EmbeddedCurvePoint result = ecc_simulator.scalar_mul(EmbeddedCurvePoint::infinity(), FF(10));
786-
ASSERT_TRUE(result.is_infinity());
787-
788-
TestTraceContainer trace({
789-
{ { C::precomputed_first_row, 1 } },
790-
});
791-
792-
builder.process_scalar_mul(scalar_mul_event_emitter.dump_events(), trace);
793-
builder.process_add(ecc_add_event_emitter.dump_events(), trace);
794-
795-
check_interaction<EccTraceBuilder, lookup_scalar_mul_double_settings, lookup_scalar_mul_add_settings>(trace);
796-
797-
check_relation<scalar_mul>(trace);
798-
check_relation<ecc>(trace);
799-
}
800-
801-
TEST(ScalarMulConstrainingTest, MulAddInteractionsInfinityRep)
802-
{
803-
EccTraceBuilder builder;
804-
805-
EventEmitter<EccAddEvent> ecc_add_event_emitter;
806-
EventEmitter<ScalarMulEvent> scalar_mul_event_emitter;
807-
NoopEventEmitter<EccAddMemoryEvent> ecc_add_memory_event_emitter;
808-
809775
StrictMock<MockExecutionIdManager> execution_id_manager;
810776
StrictMock<MockGreaterThan> gt;
811777
PureToRadix to_radix_simulator = PureToRadix();
@@ -817,16 +783,13 @@ TEST(ScalarMulConstrainingTest, MulAddInteractionsInfinityRep)
817783
ecc_add_memory_event_emitter);
818784

819785
EmbeddedCurvePoint inf = EmbeddedCurvePoint::infinity();
820-
// TODO(#AVM-266): Rework test when is_infinity flag is removed from point representations.
821-
// We now derive is_inf from coordinates, whereas previously we remapped coordinates /from/ is_inf.
822-
// EmbeddedCurvePoint preserves raw coordinates (see StandardAffinePointTest)
786+
823787
EmbeddedCurvePoint inf_bb = EmbeddedCurvePoint(avm2::AffinePoint::infinity());
824-
EmbeddedCurvePoint inf_alt = EmbeddedCurvePoint(1, 2, true);
825788

826789
EmbeddedCurvePoint result = ecc_simulator.scalar_mul(inf_bb, FF(10));
827790
ASSERT_TRUE(result.is_infinity());
828-
result = ecc_simulator.scalar_mul(inf_alt, FF(10));
829-
ASSERT_TRUE(result.is_infinity());
791+
EXPECT_EQ(result.x(), inf.x());
792+
EXPECT_EQ(result.y(), inf.y());
830793

831794
TestTraceContainer trace({
832795
{ { C::precomputed_first_row, 1 } },
@@ -1309,7 +1272,7 @@ TEST(EccAddMemoryConstrainingTest, EccAddMemoryPointError)
13091272
// Point P is not on the curve
13101273
FF p_x("0x0000000000063d46918a156cae92db1bcbc4072a27ec81dc82ea959abdbcf16a");
13111274
FF p_y("0x00000000000c1370462c74775765d07fc21fd1093cc988149d3aa763bb3dbb60");
1312-
EmbeddedCurvePoint p(p_x, p_y, false);
1275+
EmbeddedCurvePoint p(p_x, p_y);
13131276

13141277
uint32_t dst_address = 0x1000;
13151278

@@ -1369,16 +1332,12 @@ TEST(EccAddMemoryConstrainingTest, InfinityRepresentations)
13691332
ecc_add_memory_event_emitter);
13701333
MemoryAddress dst_address = 5;
13711334

1372-
// TODO(#AVM-266): Rework test when is_infinity flag is removed from point representations.
1373-
// We now derive is_inf from coordinates, whereas previously we remapped coordinates /from/ is_inf.
1374-
13751335
// Point P is infinity
13761336
EmbeddedCurvePoint inf = EmbeddedCurvePoint::infinity();
13771337
// EmbeddedCurvePoint always sets extractable coordinates as (0,0) and the underlying point as
13781338
// AffinePoint::infinity() for input infinity points.
13791339
EmbeddedCurvePoint inf_bb = EmbeddedCurvePoint(avm2::AffinePoint::infinity());
1380-
EmbeddedCurvePoint inf_alt = EmbeddedCurvePoint(0, 7, true);
1381-
EXPECT_EQ(inf_bb, inf_alt);
1340+
EXPECT_EQ(inf_bb, inf);
13821341
TestTraceContainer trace;
13831342

13841343
// The circuit correctly assigns double_op = true when doubling inf:
@@ -1419,25 +1378,6 @@ TEST(EccAddMemoryConstrainingTest, InfinityRepresentations)
14191378
trace.set(C::ecc_add_mem_q_y, 0, 2);
14201379
EXPECT_THROW_WITH_MESSAGE(check_relation<mem_aware_ecc>(trace, mem_aware_ecc::SR_Q_INF_X_CHECK), "Q_INF_X_CHECK");
14211380
EXPECT_THROW_WITH_MESSAGE(check_relation<mem_aware_ecc>(trace, mem_aware_ecc::SR_Q_INF_Y_CHECK), "Q_INF_Y_CHECK");
1422-
1423-
// TODO(#AVM-266): Rework test when is_infinity flag is removed from point representations.
1424-
// We now derive is_inf from coordinates, whereas previously we remapped coordinates /from/ is_inf.
1425-
// The below test no longer makes sense since it checks we store non-(0,0) coordinates for an inf
1426-
// point, which we do not allow.
1427-
1428-
// builder.process_add_with_memory(ecc_add_memory_event_emitter.dump_events(), trace);
1429-
1430-
// // The original coordinates are stored in memory for the read...
1431-
// EXPECT_EQ(trace.get(C::ecc_add_mem_q_x, 1), inf_bb.x());
1432-
// EXPECT_EQ(trace.get(C::ecc_add_mem_q_y, 1), inf_bb.y());
1433-
// // ...but normalised coordinates are sent to the ecc subtrace:
1434-
// EXPECT_EQ(trace.get(C::ecc_add_mem_q_x_n, 1), 0);
1435-
// EXPECT_EQ(trace.get(C::ecc_add_mem_q_y_n, 1), 0);
1436-
// check_relation<mem_aware_ecc>(trace);
1437-
// check_relation<ecc>(trace);
1438-
// check_all_interactions<EccTraceBuilder>(trace);
1439-
// check_interaction<tracegen::ExecutionTraceBuilder,
1440-
// bb::avm2::perm_execution_dispatch_to_ecc_add_settings>(trace);
14411381
}
14421382

14431383
} // namespace

barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/ecc.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,9 @@ void Ecc::add(MemoryInterface& memory,
146146
} catch (const InternalEccException& e) {
147147
// Note this point is not on the curve, but corresponds
148148
// to default values the circuit will assign.
149-
EmbeddedCurvePoint res = EmbeddedCurvePoint(0, 0, false);
149+
// TODO(MW): This is now a point on the curve technically (inf) - check this doesnt cause issues now res.is_inf
150+
// is true:
151+
EmbeddedCurvePoint res = EmbeddedCurvePoint(0, 0);
150152
add_memory_events.emit({ .execution_clk = execution_clk,
151153
.space_id = space_id,
152154
.p = p,

0 commit comments

Comments
 (0)