Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
ecc.test.cpp
Go to the documentation of this file.
2
3#include <gmock/gmock.h>
4#include <gtest/gtest.h>
5#include <stdexcept>
6
15
16using ::testing::AllOf;
17using ::testing::ElementsAre;
18using ::testing::Return;
19using ::testing::SizeIs;
20using ::testing::StrictMock;
21
22namespace bb::avm2::simulation {
23namespace {
24
25TEST(AvmSimulationEccTest, Add)
26{
27 EventEmitter<EccAddEvent> ecc_event_emitter;
28 EventEmitter<ScalarMulEvent> scalar_mul_event_emitter;
29 EventEmitter<EccAddMemoryEvent> ecc_add_memory_event_emitter;
30
31 StrictMock<MockExecutionIdManager> execution_id_manager;
32 StrictMock<MockGreaterThan> gt;
33 StrictMock<MockToRadix> to_radix;
34
35 Ecc ecc(
36 execution_id_manager, gt, to_radix, ecc_event_emitter, scalar_mul_event_emitter, ecc_add_memory_event_emitter);
37
38 FF p_x("0x04c95d1b26d63d46918a156cae92db1bcbc4072a27ec81dc82ea959abdbcf16a");
39 FF p_y("0x035b6dd9e63c1370462c74775765d07fc21fd1093cc988149d3aa763bb3dbb60");
40 EmbeddedCurvePoint p(p_x, p_y, false);
41
42 FF q_x("0x009242167ec31949c00cbe441cd36757607406e87844fa2c8c4364a4403e66d7");
43 FF q_y("0x0fe3016d64cfa8045609f375284b6b739b5fa282e4cbb75cc7f1687ecc7420e3");
44 EmbeddedCurvePoint q(q_x, q_y, false);
45
46 EmbeddedCurvePoint result = ecc.add(p, q);
47
48 FF r_x("0x2b01df0ef6d941a826bea23bece8243cbcdc159d5e97fbaa2171f028e05ba9b6");
49 FF r_y("0x0cc4c71e882bc62b7b3d1964a8540cb5211339dfcddd2e095fd444bf1aed4f09");
50
51 EXPECT_EQ(result.x(), r_x);
52 EXPECT_EQ(result.y(), r_y);
53 EXPECT_EQ(result.is_infinity(), 0);
54
55 auto events = ecc_event_emitter.dump_events();
56 EXPECT_EQ(events.size(), 1);
57 EXPECT_EQ(events[0].p, p);
58 EXPECT_EQ(events[0].q, q);
59 EXPECT_EQ(events[0].result, result);
60}
61
62TEST(AvmSimulationEccTest, ScalarMul)
63{
64 EventEmitter<EccAddEvent> ecc_event_emitter;
65 EventEmitter<ScalarMulEvent> scalar_mul_event_emitter;
66 EventEmitter<EccAddMemoryEvent> ecc_add_memory_event_emitter;
67
68 StrictMock<MockExecutionIdManager> execution_id_manager;
69 StrictMock<MockGreaterThan> gt;
70 StrictMock<MockToRadix> to_radix;
71
72 Ecc ecc(
73 execution_id_manager, gt, to_radix, ecc_event_emitter, scalar_mul_event_emitter, ecc_add_memory_event_emitter);
74
75 FF scalar("0x009242167ec31949c00cbe441cd36757607406e87844fa2c8c4364a4403e66d7");
76 uint256_t scalar_num = scalar;
77 std::vector<bool> bits(254, false);
78 for (size_t i = 0; i < 254; ++i) {
79 bits[i] = scalar_num.get_bit(i);
80 }
81
82 EXPECT_CALL(to_radix, to_le_bits(scalar, 254)).WillOnce(Return(std::make_pair(bits, false)));
83
84 FF p_x("0x04c95d1b26d63d46918a156cae92db1bcbc4072a27ec81dc82ea959abdbcf16a");
85 FF p_y("0x035b6dd9e63c1370462c74775765d07fc21fd1093cc988149d3aa763bb3dbb60");
86 EmbeddedCurvePoint p(p_x, p_y, false);
87
88 EmbeddedCurvePoint result = ecc.scalar_mul(p, scalar);
89
91
92 EXPECT_EQ(result, expected_result);
93
95 intermediate_states.reserve(254);
96
98 EmbeddedCurvePoint temp = p;
99 uint256_t scalar_value = scalar;
100
101 for (size_t i = 0; i < 254; ++i) {
102 bool bit = scalar_value.get_bit(i);
103 if (bit) {
104 res = res + temp;
105 }
106 intermediate_states.push_back({ res, temp, bit });
107 temp = temp + temp;
108 }
109
110 auto events = scalar_mul_event_emitter.dump_events();
111 EXPECT_THAT(events, AllOf(ElementsAre(ScalarMulEvent{ p, scalar, intermediate_states, result }), SizeIs(1)));
112}
113
114// This is a death test, should be run in single-threaded context
115TEST(AvmSimulationEccDeathTest, ScalarMulNotOnCurve)
116{
117 EventEmitter<EccAddEvent> ecc_event_emitter;
118 EventEmitter<ScalarMulEvent> scalar_mul_event_emitter;
119 EventEmitter<EccAddMemoryEvent> ecc_add_memory_event_emitter;
120
121 StrictMock<MockExecutionIdManager> execution_id_manager;
122 StrictMock<MockGreaterThan> gt;
123 StrictMock<MockToRadix> to_radix;
124
125 Ecc ecc(
126 execution_id_manager, gt, to_radix, ecc_event_emitter, scalar_mul_event_emitter, ecc_add_memory_event_emitter);
127
128 // Point P is not on the curve
129 FF p_x("0x0000000000063d46918a156cae92db1bcbc4072a27ec81dc82ea959abdbcf16a");
130 FF p_y("0x00000000000c1370462c74775765d07fc21fd1093cc988149d3aa763bb3dbb60");
131 EmbeddedCurvePoint p(p_x, p_y, false);
132
133 FF scalar("0x009242167ec31949c00cbe441cd36757607406e87844fa2c8c4364a4403e66d7");
134
135 // prints: Point must be on the curve for scalar multiplication
136 ASSERT_THROW(ecc.scalar_mul(p, scalar), std::runtime_error);
137}
138
139TEST(AvmSimulationEccTest, AddWithMemory)
140{
141 EventEmitter<EccAddEvent> ecc_event_emitter;
142 EventEmitter<ScalarMulEvent> scalar_mul_event_emitter;
143 EventEmitter<EccAddMemoryEvent> ecc_add_memory_event_emitter;
144
145 StrictMock<MockExecutionIdManager> execution_id_manager;
146 StrictMock<MockGreaterThan> gt;
147 StrictMock<MockToRadix> to_radix;
148 MemoryStore memory;
149
150 EXPECT_CALL(execution_id_manager, get_execution_id()).WillOnce(Return(0));
151 EXPECT_CALL(gt, gt(0x1000 + 2, AVM_HIGHEST_MEM_ADDRESS)).WillOnce(Return(false));
152
153 Ecc ecc(
154 execution_id_manager, gt, to_radix, ecc_event_emitter, scalar_mul_event_emitter, ecc_add_memory_event_emitter);
155
156 FF p_x("0x04c95d1b26d63d46918a156cae92db1bcbc4072a27ec81dc82ea959abdbcf16a");
157 FF p_y("0x035b6dd9e63c1370462c74775765d07fc21fd1093cc988149d3aa763bb3dbb60");
158 EmbeddedCurvePoint p(p_x, p_y, false);
159
160 FF q_x("0x009242167ec31949c00cbe441cd36757607406e87844fa2c8c4364a4403e66d7");
161 FF q_y("0x0fe3016d64cfa8045609f375284b6b739b5fa282e4cbb75cc7f1687ecc7420e3");
162 EmbeddedCurvePoint q(q_x, q_y, false);
163
164 FF r_x("0x2b01df0ef6d941a826bea23bece8243cbcdc159d5e97fbaa2171f028e05ba9b6");
165 FF r_y("0x0cc4c71e882bc62b7b3d1964a8540cb5211339dfcddd2e095fd444bf1aed4f09");
166 EmbeddedCurvePoint expected_result(r_x, r_y, false);
167
168 uint32_t dst_address = 0x1000;
169 ecc.add(memory, p, q, dst_address);
170
171 EmbeddedCurvePoint result = { memory.get(dst_address).as_ff(),
172 memory.get(dst_address + 1).as_ff(),
173 static_cast<bool>(memory.get(dst_address + 2).as_ff()) };
174 EXPECT_EQ(result, expected_result);
175}
176
177TEST(AvmSimulationEccTest, AddNotOnCurve)
178{
179 EventEmitter<EccAddEvent> ecc_event_emitter;
180 EventEmitter<ScalarMulEvent> scalar_mul_event_emitter;
181 EventEmitter<EccAddMemoryEvent> ecc_add_memory_event_emitter;
182
183 StrictMock<MockExecutionIdManager> execution_id_manager;
184 StrictMock<MockGreaterThan> gt;
185 StrictMock<MockToRadix> to_radix;
186 MemoryStore memory;
187
188 EXPECT_CALL(execution_id_manager, get_execution_id()).WillOnce(Return(0));
189 EXPECT_CALL(gt, gt(0x1000 + 2, AVM_HIGHEST_MEM_ADDRESS)).WillOnce(Return(false));
190
191 Ecc ecc(
192 execution_id_manager, gt, to_radix, ecc_event_emitter, scalar_mul_event_emitter, ecc_add_memory_event_emitter);
193
194 // Point P is not on the curve
195 FF p_x("0x0000000000063d46918a156cae92db1bcbc4072a27ec81dc82ea959abdbcf16a");
196 FF p_y("0x00000000000c1370462c74775765d07fc21fd1093cc988149d3aa763bb3dbb60");
197 EmbeddedCurvePoint p(p_x, p_y, false);
198
199 // Point Q is on the curve
200 FF q_x("0x009242167ec31949c00cbe441cd36757607406e87844fa2c8c4364a4403e66d7");
201 FF q_y("0x0fe3016d64cfa8045609f375284b6b739b5fa282e4cbb75cc7f1687ecc7420e3");
202 EmbeddedCurvePoint q(q_x, q_y, false);
203
204 uint32_t dst_address = 0x1000;
205 EXPECT_THROW(ecc.add(memory, p, q, dst_address), EccException);
206}
207
208TEST(AvmSimulationEccTest, InfinityOnCurve)
209{
210 EventEmitter<EccAddEvent> ecc_event_emitter;
211 EventEmitter<ScalarMulEvent> scalar_mul_event_emitter;
212 EventEmitter<EccAddMemoryEvent> ecc_add_memory_event_emitter;
213
214 StrictMock<MockExecutionIdManager> execution_id_manager;
215 StrictMock<MockGreaterThan> gt;
216 StrictMock<MockToRadix> to_radix;
217 MemoryStore memory;
218
219 EXPECT_CALL(execution_id_manager, get_execution_id()).WillOnce(Return(0));
220 EXPECT_CALL(gt, gt(0x1000 + 2, AVM_HIGHEST_MEM_ADDRESS)).WillOnce(Return(false));
221
222 Ecc ecc(
223 execution_id_manager, gt, to_radix, ecc_event_emitter, scalar_mul_event_emitter, ecc_add_memory_event_emitter);
224
225 // Point P is not on the curve
227
228 // Point Q is on the curve
229 FF q_x("0x009242167ec31949c00cbe441cd36757607406e87844fa2c8c4364a4403e66d7");
230 FF q_y("0x0fe3016d64cfa8045609f375284b6b739b5fa282e4cbb75cc7f1687ecc7420e3");
231 EmbeddedCurvePoint q(q_x, q_y, false);
232
233 uint32_t dst_address = 0x1000;
234 ecc.add(memory, p, q, dst_address);
235
236 EmbeddedCurvePoint result = { memory.get(dst_address).as_ff(),
237 memory.get(dst_address + 1).as_ff(),
238 static_cast<bool>(memory.get(dst_address + 2).as_ff()) };
239 // INF + Q = Q
240 EXPECT_EQ(result, q);
241}
242
243} // namespace
244} // namespace bb::avm2::simulation
#define AVM_HIGHEST_MEM_ADDRESS
const MemoryValue & get(MemoryAddress index) const override
constexpr bool get_bit(uint64_t bit_index) const
ExecutionIdManager execution_id_manager
GreaterThan gt
bool expected_result
TEST(EmitUnencryptedLogTest, Basic)
StandardAffinePoint< AvmFlavorSettings::EmbeddedCurve::AffineElement > EmbeddedCurvePoint
Definition field.hpp:12
AvmFlavorSettings::G1::Fq Fq
Definition field.hpp:11
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
MemoryStore memory