Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,85 @@ TEST(ScalarMulConstrainingTest, BasicMul)
check_relation<scalar_mul>(trace);
}

// Edge case: Verify that 0 * P = infinity (point at infinity)
TEST(ScalarMulConstrainingTest, MulByZero)
{
EccTraceBuilder builder;

EventEmitter<EccAddEvent> ecc_add_event_emitter;
EventEmitter<ScalarMulEvent> scalar_mul_event_emitter;
NoopEventEmitter<EccAddMemoryEvent> ecc_add_memory_event_emitter;

StrictMock<MockExecutionIdManager> execution_id_manager;
StrictMock<MockGreaterThan> gt;
PureToRadix to_radix_simulator = PureToRadix();
EccSimulator ecc_simulator(execution_id_manager,
gt,
to_radix_simulator,
ecc_add_event_emitter,
scalar_mul_event_emitter,
ecc_add_memory_event_emitter);

// Multiply by zero - result should be point at infinity
FF scalar = FF(0);
EmbeddedCurvePoint result = ecc_simulator.scalar_mul(p, scalar);

// Verify result is infinity
ASSERT_TRUE(result.is_infinity());

TestTraceContainer trace({
{ { C::precomputed_first_row, 1 } },
});

builder.process_scalar_mul(scalar_mul_event_emitter.dump_events(), trace);
builder.process_add(ecc_add_event_emitter.dump_events(), trace);

EXPECT_EQ(trace.get_num_rows(), /*start_row=*/1 + 254);
check_relation<scalar_mul>(trace);
check_relation<ecc>(trace);
}

// Edge case: Verify scalar multiplication works with a large scalar near field modulus
TEST(ScalarMulConstrainingTest, MulByLargeScalar)
{
EccTraceBuilder builder;

EventEmitter<EccAddEvent> ecc_add_event_emitter;
EventEmitter<ScalarMulEvent> scalar_mul_event_emitter;
NoopEventEmitter<EccAddMemoryEvent> ecc_add_memory_event_emitter;

StrictMock<MockExecutionIdManager> execution_id_manager;
StrictMock<MockGreaterThan> gt;
PureToRadix to_radix_simulator = PureToRadix();
EccSimulator ecc_simulator(execution_id_manager,
gt,
to_radix_simulator,
ecc_add_event_emitter,
scalar_mul_event_emitter,
ecc_add_memory_event_emitter);

// Use a large scalar (p - 1, where p is the field modulus)
// BN254 scalar field modulus - 1: 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000
FF scalar = FF("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff");
EmbeddedCurvePoint result = ecc_simulator.scalar_mul(p, scalar);

// Verify result is a valid point (not infinity for non-zero scalar with non-infinity point)
// The exact result depends on the scalar and point, but it should be deterministic
EmbeddedCurvePoint expected_result = p * Fq(scalar);
EXPECT_EQ(result, expected_result);

TestTraceContainer trace({
{ { C::precomputed_first_row, 1 } },
});

builder.process_scalar_mul(scalar_mul_event_emitter.dump_events(), trace);
builder.process_add(ecc_add_event_emitter.dump_events(), trace);

// Note: Row count varies based on number of ECC operations (depends on scalar bit pattern)
check_relation<scalar_mul>(trace);
check_relation<ecc>(trace);
}

TEST(ScalarMulConstrainingTest, MultipleInvocations)
{
EccTraceBuilder builder;
Expand Down
Loading