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);
41
42 FF q_x("0x009242167ec31949c00cbe441cd36757607406e87844fa2c8c4364a4403e66d7");
43 FF q_y("0x0fe3016d64cfa8045609f375284b6b739b5fa282e4cbb75cc7f1687ecc7420e3");
44 EmbeddedCurvePoint q(q_x, q_y);
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);
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);
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);
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 + 1, 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);
159
160 FF q_x("0x009242167ec31949c00cbe441cd36757607406e87844fa2c8c4364a4403e66d7");
161 FF q_y("0x0fe3016d64cfa8045609f375284b6b739b5fa282e4cbb75cc7f1687ecc7420e3");
162 EmbeddedCurvePoint q(q_x, q_y);
163
164 FF r_x("0x2b01df0ef6d941a826bea23bece8243cbcdc159d5e97fbaa2171f028e05ba9b6");
165 FF r_y("0x0cc4c71e882bc62b7b3d1964a8540cb5211339dfcddd2e095fd444bf1aed4f09");
167
168 uint32_t dst_address = 0x1000;
169 ecc.add(memory, p, q, dst_address);
170
172 EXPECT_EQ(result, expected_result);
173}
174
175TEST(AvmSimulationEccTest, AddNotOnCurve)
176{
177 EventEmitter<EccAddEvent> ecc_event_emitter;
178 EventEmitter<ScalarMulEvent> scalar_mul_event_emitter;
179 EventEmitter<EccAddMemoryEvent> ecc_add_memory_event_emitter;
180
181 StrictMock<MockExecutionIdManager> execution_id_manager;
182 StrictMock<MockGreaterThan> gt;
183 StrictMock<MockToRadix> to_radix;
184 MemoryStore memory;
185
186 EXPECT_CALL(execution_id_manager, get_execution_id()).WillOnce(Return(0));
187 EXPECT_CALL(gt, gt(0x1000 + 1, AVM_HIGHEST_MEM_ADDRESS)).WillOnce(Return(false));
188
189 Ecc ecc(
190 execution_id_manager, gt, to_radix, ecc_event_emitter, scalar_mul_event_emitter, ecc_add_memory_event_emitter);
191
192 // Point P is not on the curve
193 FF p_x("0x0000000000063d46918a156cae92db1bcbc4072a27ec81dc82ea959abdbcf16a");
194 FF p_y("0x00000000000c1370462c74775765d07fc21fd1093cc988149d3aa763bb3dbb60");
195 EmbeddedCurvePoint p(p_x, p_y);
196
197 // Point Q is on the curve
198 FF q_x("0x009242167ec31949c00cbe441cd36757607406e87844fa2c8c4364a4403e66d7");
199 FF q_y("0x0fe3016d64cfa8045609f375284b6b739b5fa282e4cbb75cc7f1687ecc7420e3");
200 EmbeddedCurvePoint q(q_x, q_y);
201
202 uint32_t dst_address = 0x1000;
203 EXPECT_THROW(ecc.add(memory, p, q, dst_address), EccException);
204}
205
206TEST(AvmSimulationEccTest, InfinityOnCurve)
207{
208 EventEmitter<EccAddEvent> ecc_event_emitter;
209 EventEmitter<ScalarMulEvent> scalar_mul_event_emitter;
210 EventEmitter<EccAddMemoryEvent> ecc_add_memory_event_emitter;
211
212 StrictMock<MockExecutionIdManager> execution_id_manager;
213 StrictMock<MockGreaterThan> gt;
214 StrictMock<MockToRadix> to_radix;
215 MemoryStore memory;
216
217 EXPECT_CALL(execution_id_manager, get_execution_id()).WillOnce(Return(0));
218 EXPECT_CALL(gt, gt(0x1000 + 1, AVM_HIGHEST_MEM_ADDRESS)).WillOnce(Return(false));
219
220 Ecc ecc(
221 execution_id_manager, gt, to_radix, ecc_event_emitter, scalar_mul_event_emitter, ecc_add_memory_event_emitter);
222
223 // Point P is not on the curve
225
226 // Point Q is on the curve
227 FF q_x("0x009242167ec31949c00cbe441cd36757607406e87844fa2c8c4364a4403e66d7");
228 FF q_y("0x0fe3016d64cfa8045609f375284b6b739b5fa282e4cbb75cc7f1687ecc7420e3");
229 EmbeddedCurvePoint q(q_x, q_y);
230
231 uint32_t dst_address = 0x1000;
232 ecc.add(memory, p, q, dst_address);
233
235 // INF + Q = Q
236 EXPECT_EQ(result, q);
237}
238
239TEST(AvmSimulationEccTest, AddsUpToInfinity)
240{
241 EventEmitter<EccAddEvent> ecc_event_emitter;
242 EventEmitter<ScalarMulEvent> scalar_mul_event_emitter;
243 EventEmitter<EccAddMemoryEvent> ecc_add_memory_event_emitter;
244
245 StrictMock<MockExecutionIdManager> execution_id_manager;
246 StrictMock<MockGreaterThan> gt;
247 StrictMock<MockToRadix> to_radix;
248 MemoryStore memory;
249
250 EXPECT_CALL(execution_id_manager, get_execution_id()).WillOnce(Return(0));
251 EXPECT_CALL(gt, gt(0x1000 + 1, AVM_HIGHEST_MEM_ADDRESS)).WillOnce(Return(false));
252
253 Ecc ecc(
254 execution_id_manager, gt, to_radix, ecc_event_emitter, scalar_mul_event_emitter, ecc_add_memory_event_emitter);
255
256 // Both points on the curve, q = -p
257 FF p_x("0x04c95d1b26d63d46918a156cae92db1bcbc4072a27ec81dc82ea959abdbcf16a");
258 FF p_y("0x035b6dd9e63c1370462c74775765d07fc21fd1093cc988149d3aa763bb3dbb60");
259 EmbeddedCurvePoint p(p_x, p_y);
260
261 EmbeddedCurvePoint q = -p;
262
263 uint32_t dst_address = 0x1000;
264 ecc.add(memory, p, q, dst_address);
265
266 // Zero as coordinates
267 EXPECT_EQ(memory.get(dst_address).as_ff(), FF(0));
268 EXPECT_EQ(memory.get(dst_address + 1).as_ff(), FF(0));
269}
270
271} // namespace
272} // 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
AVM range check gadget for witness generation.
StandardAffinePoint< AvmFlavorSettings::EmbeddedCurve::AffineElement > EmbeddedCurvePoint
Definition field.hpp:12
AvmFlavorSettings::G1::Fq Fq
Definition field.hpp:11
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
MemoryStore memory