Skip to content

Commit 9adced4

Browse files
committed
feat: derive inf from coordinates in exec, some docs
1 parent cad5d40 commit 9adced4

5 files changed

Lines changed: 50 additions & 27 deletions

File tree

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ namespace address_derivation;
186186

187187
// TODO(#AVM-266): Remove infinity flags from point representation. Note that we may still need to use
188188
// precomputed.zero in the hash preimages until address derivation removes them:
189-
// TODO(#7529): Remove all the 0s for is_infinity when removed from public_keys.nr
189+
// TODO(#7529)/TODO(F-553): Remove all the 0s for is_infinity when removed from public_keys.nr
190190
// https://github.com/AztecProtocol/aztec-packages/issues/7529
191191
// TODO(#14031): Compress keys in public_keys_hash
192192
// https://github.com/AztecProtocol/aztec-packages/issues/14031

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ template <typename AffinePoint> class StandardAffinePoint {
8080

8181
// Always returns the raw coordinates, when an operation results in infinity these will be (0,0).
8282
// If a point at infinity is constructed with non-zero coordinates, we likely want to preserve those.
83+
// TODO(#AVM-266): Now that Noir uses (0, 0) <==> is_infinite, the above may not be true.
8384
constexpr const BaseField& x() const noexcept { return x_coord; }
8485

8586
constexpr const BaseField& y() const noexcept { return y_coord; }

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

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <cstdio>
12
#include <gmock/gmock.h>
23
#include <gtest/gtest.h>
34

@@ -1388,29 +1389,43 @@ TEST(EccAddMemoryConstrainingTest, InfinityRepresentations)
13881389
check_relation<ecc>(trace);
13891390
EXPECT_EQ(trace.get(C::ecc_double_op, 0), 1);
13901391

1392+
ecc_simulator.add(memory, inf, inf_bb, dst_address);
1393+
1394+
// Set memory reads:
1395+
trace.set(0,
1396+
{ { // Execution
1397+
{ C::execution_sel, 1 },
1398+
{ C::execution_sel_exec_dispatch_ecc_add, 1 },
1399+
{ C::execution_rop_6_, dst_address + 3 },
1400+
{ C::execution_register_0_, inf.x() },
1401+
{ C::execution_register_1_, inf.y() },
1402+
{ C::execution_register_2_, inf.is_infinity() ? 1 : 0 },
1403+
{ C::execution_register_3_, inf_bb.x() },
1404+
{ C::execution_register_4_, inf_bb.y() },
1405+
{ C::execution_register_5_, inf_bb.is_infinity() ? 1 : 0 },
1406+
// GT - dst out of range check
1407+
{ C::gt_sel, 1 },
1408+
{ C::gt_input_a, dst_address + 2 },
1409+
{ C::gt_input_b, AVM_HIGHEST_MEM_ADDRESS },
1410+
{ C::gt_res, 0 } } });
1411+
1412+
builder.process_add_with_memory(ecc_add_memory_event_emitter.dump_events(), trace);
1413+
1414+
// The derived is_inf column must be true if the coordinates are (0, 0):
1415+
trace.set(C::ecc_add_mem_p_is_inf, 0, 0);
1416+
EXPECT_THROW_WITH_MESSAGE(check_relation<mem_aware_ecc>(trace, mem_aware_ecc::SR_P_CURVE_EQN), "P_CURVE_EQN");
1417+
1418+
// If is_if is set, the coordinates must be (0, 0):
1419+
trace.set(C::ecc_add_mem_q_x, 0, 1);
1420+
trace.set(C::ecc_add_mem_q_y, 0, 2);
1421+
EXPECT_THROW_WITH_MESSAGE(check_relation<mem_aware_ecc>(trace, mem_aware_ecc::SR_Q_INF_X_CHECK), "Q_INF_X_CHECK");
1422+
EXPECT_THROW_WITH_MESSAGE(check_relation<mem_aware_ecc>(trace, mem_aware_ecc::SR_Q_INF_Y_CHECK), "Q_INF_Y_CHECK");
1423+
13911424
// TODO(#AVM-266): Rework test when is_infinity flag is removed from point representations.
13921425
// We now derive is_inf from coordinates, whereas previously we remapped coordinates /from/ is_inf.
13931426
// The below test no longer makes sense since it checks we store non-(0,0) coordinates for an inf
13941427
// point, which we do not allow.
13951428

1396-
// // Set memory reads:
1397-
// trace.set(0,
1398-
// { { // Execution
1399-
// { C::execution_sel, 1 },
1400-
// { C::execution_sel_exec_dispatch_ecc_add, 1 },
1401-
// { C::execution_rop_6_, dst_address + 3 },
1402-
// { C::execution_register_0_, inf.x() },
1403-
// { C::execution_register_1_, inf.y() },
1404-
// { C::execution_register_2_, inf.is_infinity() ? 1 : 0 },
1405-
// { C::execution_register_3_, inf_bb.x() },
1406-
// { C::execution_register_4_, inf_bb.y() },
1407-
// { C::execution_register_5_, inf_bb.is_infinity() ? 1 : 0 },
1408-
// // GT - dst out of range check
1409-
// { C::gt_sel, 1 },
1410-
// { C::gt_input_a, dst_address + 2 },
1411-
// { C::gt_input_b, AVM_HIGHEST_MEM_ADDRESS },
1412-
// { C::gt_res, 0 } } });
1413-
14141429
// builder.process_add_with_memory(ecc_add_memory_event_emitter.dump_events(), trace);
14151430

14161431
// // The original coordinates are stored in memory for the read...
@@ -1422,7 +1437,8 @@ TEST(EccAddMemoryConstrainingTest, InfinityRepresentations)
14221437
// check_relation<mem_aware_ecc>(trace);
14231438
// check_relation<ecc>(trace);
14241439
// check_all_interactions<EccTraceBuilder>(trace);
1425-
// check_interaction<tracegen::ExecutionTraceBuilder, bb::avm2::perm_execution_dispatch_to_ecc_add_settings>(trace);
1440+
// check_interaction<tracegen::ExecutionTraceBuilder,
1441+
// bb::avm2::perm_execution_dispatch_to_ecc_add_settings>(trace);
14261442
}
14271443

14281444
} // namespace

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,10 @@ void Ecc::add(MemoryInterface& memory,
136136
throw InternalEccException("dst address out of range");
137137
}
138138

139+
// TODO(#AVM-266): Note: bb infinity points (is_inf=true with x=(P+1)/2, y=0) pass on_curve() without
140+
// throwing here, but would throw in the circuit. We assume here input points follow the Noir convention
141+
// of (x=0, y=0) <==> is_infinity.
139142
if (!p.on_curve() || !q.on_curve()) {
140-
// TODO(#AVM-266): Note: We now use this to enforce (X, Y) == (0, 0) ==> is_inf
141-
// until is_inf is removed. This means a bb inf point (!= (0, 0)) will
142-
// not throw here but would throw in the circuit. Since we remap such points to
143-
// (0, 0) below, it shouldn't reach the circuit at all.
144143
throw InternalEccException("One of the points is not on the curve");
145144
}
146145

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,19 +1505,26 @@ void Execution::ecc_add(ContextInterface& context,
15051505
// Read the points from memory.
15061506
const auto& p_x = memory.get(p_x_addr);
15071507
const auto& p_y = memory.get(p_y_addr);
1508+
// TODO(#AVM-266): Remove infinity flags from point representation, the below is currently ignored in-circuit.
15081509
const auto& p_inf = memory.get(p_inf_addr);
15091510

15101511
const auto& q_x = memory.get(q_x_addr);
15111512
const auto& q_y = memory.get(q_y_addr);
1513+
// TODO(#AVM-266): Remove infinity flags from point representation, the below is currently ignored in-circuit.
15121514
const auto& q_inf = memory.get(q_inf_addr);
15131515

15141516
set_and_validate_inputs(opcode, { p_x, p_y, p_inf, q_x, q_y, q_inf });
15151517
get_gas_tracker().consume_gas();
15161518

15171519
// Once inputs are tag checked the conversion to EmbeddedCurvePoint is safe, on curve checks are done in the add
1518-
// method.
1519-
EmbeddedCurvePoint p = EmbeddedCurvePoint(p_x.as_ff(), p_y.as_ff(), p_inf == MemoryValue::from<uint1_t>(1));
1520-
EmbeddedCurvePoint q = EmbeddedCurvePoint(q_x.as_ff(), q_y.as_ff(), q_inf == MemoryValue::from<uint1_t>(1));
1520+
// method. TODO(#AVM-266): We derive is_infinity from coordinates using the Noir convention of (x=0, y=0) <==>
1521+
// is_infinity. The flag will be removed in future.
1522+
const FF p_x_ff = p_x.as_ff();
1523+
const FF p_y_ff = p_y.as_ff();
1524+
EmbeddedCurvePoint p = EmbeddedCurvePoint(p_x_ff, p_y_ff, (p_x_ff == FF::zero()) && (p_y_ff == FF::zero()));
1525+
const FF q_x_ff = q_x.as_ff();
1526+
const FF q_y_ff = q_y.as_ff();
1527+
EmbeddedCurvePoint q = EmbeddedCurvePoint(q_x_ff, q_y_ff, (q_x_ff == FF::zero()) && (q_y_ff == FF::zero()));
15211528

15221529
try {
15231530
embedded_curve.add(memory, p, q, dst_addr);

0 commit comments

Comments
 (0)