Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
secp256k1.test.cpp
Go to the documentation of this file.
1#include "secp256k1.hpp"
4#include <gtest/gtest.h>
5
6using namespace bb;
7
8// Field tests (add, sub, mul, sqr, sqrt, montgomery form) are in:
9// - barretenberg/ecc/fields/field.test.cpp (generic field tests)
10// - barretenberg/ecc/fields/prime_field.test.cpp (prime field specific tests)
11// The tests below are for the secp256k1 elliptic curve group operations.
12TEST(secp256k1, CurveCoefficients)
13{
14 secp256k1::fq expected_a = secp256k1::fq(0);
15 secp256k1::fq expected_b = secp256k1::fq(7);
16
17 EXPECT_EQ(secp256k1::G1Params::a, expected_a);
18 EXPECT_EQ(secp256k1::G1Params::b, expected_b);
19}
20
21TEST(secp256k1, GeneratorOnCurve)
22{
24 secp256k1::fq expected_x = secp256k1::fq("0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798");
25 secp256k1::fq expected_y = secp256k1::fq("0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8");
26
27 EXPECT_EQ(result.x, expected_x);
28 EXPECT_EQ(result.y, expected_y);
29 EXPECT_EQ(result.on_curve(), true);
30}
31
32TEST(secp256k1, RandomElement)
33{
34 secp256k1::g1::element result = secp256k1::g1::element::random_element();
35 EXPECT_EQ(result.on_curve(), true);
36}
37
38TEST(secp256k1, RandomAffineElement)
39{
40 secp256k1::g1::affine_element result = secp256k1::g1::element::random_element();
41 EXPECT_EQ(result.on_curve(), true);
42}
43
44TEST(secp256k1, Eq)
45{
46 secp256k1::g1::element a = secp256k1::g1::element::random_element();
47 secp256k1::g1::element b = a.normalize();
48
49 EXPECT_EQ(a == b, true);
50 EXPECT_EQ(a == a, true);
51
52 b.self_set_infinity();
53
54 EXPECT_EQ(a == b, false);
55 secp256k1::g1::element c = secp256k1::g1::element::random_element();
56
57 EXPECT_EQ(a == c, false);
58
59 a.self_set_infinity();
60
61 EXPECT_EQ(a == b, true);
62}
63
64TEST(secp256k1, CheckGroupModulus)
65{
66 // secp256k1::g1::affine_element expected = secp256k1::g1::affine_one;
67 secp256k1::fr exponent = -secp256k1::fr(1);
69 result += secp256k1::g1::one;
70 result += secp256k1::g1::one;
71 EXPECT_EQ(result.on_curve(), true);
72 EXPECT_EQ(result == secp256k1::g1::one, true);
73}
74
75TEST(secp256k1, AddExceptionTestInfinity)
76{
77 secp256k1::g1::element lhs = secp256k1::g1::element::random_element();
80
81 rhs = -lhs;
82
83 result = lhs + rhs;
84
85 EXPECT_EQ(result.is_point_at_infinity(), true);
86
88 rhs_b = rhs;
89 rhs_b.self_set_infinity();
90
91 result = lhs + rhs_b;
92
93 EXPECT_EQ(lhs == result, true);
94
96 result = lhs + rhs;
97
98 EXPECT_EQ(rhs == result, true);
99}
100
101TEST(secp256k1, AddExceptionTestDbl)
102{
103 secp256k1::g1::element lhs = secp256k1::g1::element::random_element();
105 rhs = lhs;
106
108 secp256k1::g1::element expected;
109
110 result = lhs + rhs;
111 expected = lhs.dbl();
112
113 EXPECT_EQ(result == expected, true);
114}
115
116TEST(secp256k1, AddDblConsistency)
117{
118 secp256k1::g1::element a = secp256k1::g1::element::random_element();
119 secp256k1::g1::element b = secp256k1::g1::element::random_element();
120
123 secp256k1::g1::element add_result;
124 secp256k1::g1::element dbl_result;
125
126 c = a + b;
127 b = -b;
128 d = a + b;
129
130 add_result = c + d;
131 dbl_result = a.dbl();
132
133 EXPECT_EQ(add_result == dbl_result, true);
134}
135
136TEST(secp256k1, AddDblConsistencyRepeated)
137{
138 secp256k1::g1::element a = secp256k1::g1::element::random_element();
143
145 secp256k1::g1::element expected;
146
147 b = a.dbl(); // b = 2a
148 c = b.dbl(); // c = 4a
149
150 d = a + b; // d = 3a
151 e = a + c; // e = 5a
152 result = d + e; // result = 8a
153
154 expected = c.dbl(); // expected = 8a
155
156 EXPECT_EQ(result == expected, true);
157}
158
159TEST(secp256k1, MixedAddExceptionTestInfinity)
160{
162 secp256k1::g1::affine_element rhs = secp256k1::g1::element::random_element();
163 secp256k1::fq::__copy(rhs.x, lhs.x);
164 lhs.y = -rhs.y;
165
167 result = lhs + rhs;
168
169 EXPECT_EQ(result.is_point_at_infinity(), true);
170
171 lhs.self_set_infinity();
172 result = lhs + rhs;
174 rhs_c = secp256k1::g1::element(rhs);
175
176 EXPECT_EQ(rhs_c == result, true);
177}
178
179TEST(secp256k1, MixedAddExceptionTestDbl)
180{
181 secp256k1::g1::affine_element rhs = secp256k1::g1::element::random_element();
183 lhs = secp256k1::g1::element(rhs);
184
186 secp256k1::g1::element expected;
187 result = lhs + rhs;
188
189 expected = lhs.dbl();
190
191 EXPECT_EQ(result == expected, true);
192}
193
194TEST(secp256k1, AddMixedAddConsistencyCheck)
195{
196 secp256k1::g1::affine_element rhs = secp256k1::g1::element::random_element();
197 secp256k1::g1::element lhs = secp256k1::g1::element::random_element();
199 rhs_b = secp256k1::g1::element(rhs);
200
201 secp256k1::g1::element add_result;
202 secp256k1::g1::element mixed_add_result;
203 add_result = lhs + rhs_b;
204 mixed_add_result = lhs + rhs;
205
206 EXPECT_EQ(add_result == mixed_add_result, true);
207}
208
209TEST(secp256k1, OnCurve)
210{
211 for (size_t i = 0; i < 100; ++i) {
212 secp256k1::g1::element test = secp256k1::g1::element::random_element();
213 EXPECT_EQ(test.on_curve(), true);
214 secp256k1::g1::affine_element affine_test = secp256k1::g1::element::random_element();
215 EXPECT_EQ(affine_test.on_curve(), true);
216 }
217}
218TEST(secp256k1, BatchNormalize)
219{
220 size_t num_points = 2;
221 std::vector<secp256k1::g1::element> points(num_points);
222 std::vector<secp256k1::g1::element> normalized(num_points);
223 for (size_t i = 0; i < num_points; ++i) {
224 secp256k1::g1::element a = secp256k1::g1::element::random_element();
225 secp256k1::g1::element b = secp256k1::g1::element::random_element();
226 points[i] = a + b;
227 normalized[i] = points[i];
228 }
229 secp256k1::g1::element::batch_normalize(&normalized[0], num_points);
230
231 for (size_t i = 0; i < num_points; ++i) {
232 secp256k1::fq zz;
233 secp256k1::fq zzz;
234 secp256k1::fq result_x;
235 secp256k1::fq result_y;
236 zz = points[i].z.sqr();
237 zzz = points[i].z * zz;
238 result_x = normalized[i].x * zz;
239 result_y = normalized[i].y * zzz;
240
241 EXPECT_EQ((result_x == points[i].x), true);
242 EXPECT_EQ((result_y == points[i].y), true);
243 }
244}
245
246TEST(secp256k1, GroupExponentiationZeroAndOne)
247{
249
250 EXPECT_EQ(result.is_point_at_infinity(), true);
251
253
254 EXPECT_EQ(result == secp256k1::g1::affine_one, true);
255}
256
257TEST(secp256k1, GroupExponentiationConsistencyCheck)
258{
261
263 c = a * b;
264
266 secp256k1::g1::affine_element result = input * a;
267 result = result * b;
268
269 secp256k1::g1::affine_element expected = input * c;
270
271 EXPECT_EQ(result == expected, true);
272}
273
274TEST(secp256k1, DeriveGenerators)
275{
276 constexpr size_t num_generators = 128;
277 auto result = secp256k1::g1::derive_generators("test generators", num_generators);
278
279 const auto is_unique = [&result](const secp256k1::g1::affine_element& y, const size_t j) {
280 for (size_t i = 0; i < result.size(); ++i) {
281 if ((i != j) && result[i] == y) {
282 return false;
283 }
284 }
285 return true;
286 };
287
288 for (size_t k = 0; k < num_generators; ++k) {
289 EXPECT_EQ(is_unique(result[k], k), true);
290 EXPECT_EQ(result[k].on_curve(), true);
291 }
292}
293
294TEST(secp256k1, CheckPrecomputedGenerators)
295{
296 ASSERT_TRUE((bb::check_precomputed_generators<secp256k1::g1, "biggroup offset generator", 1UL>()));
297 ASSERT_TRUE((bb::check_precomputed_generators<secp256k1::g1, "biggroup table offset generator", 1UL>()));
298}
299
300TEST(secp256k1, GetEndomorphismScalars)
301{
302 for (size_t i = 0; i < 2048; i++) {
304 secp256k1::fr k1 = 0;
305 secp256k1::fr k2 = 0;
306
308 bool k1_neg = false;
309 bool k2_neg = false;
310
312 k2 = -k2;
313 k2_neg = true;
314 }
315
316 EXPECT_LT(k1.uint256_t_no_montgomery_conversion().get_msb(), 129ULL);
317 EXPECT_LT(k2.uint256_t_no_montgomery_conversion().get_msb(), 129ULL);
318
319 if (k1_neg) {
320 k1 = -k1;
321 }
322 if (k2_neg) {
323 k2 = -k2;
324 }
325
328
330 secp256k1::fr expected = k1 - k2 * beta;
331
332 expected.self_from_montgomery_form();
333 EXPECT_EQ(k, expected);
334 if (k != expected) {
335 break;
336 }
337 }
338}
339
340TEST(secp256k1, TestEndomorphismScalars)
341{
343 secp256k1::fr k1 = 0;
344 secp256k1::fr k2 = 0;
345
347 bool k1_neg = false;
348 bool k2_neg = false;
349
351 k1 = -k1;
352 k1_neg = true;
353 }
355 k2 = -k2;
356 k2_neg = true;
357 }
358
359 EXPECT_LT(k1.uint256_t_no_montgomery_conversion().get_msb(), 129ULL);
360 EXPECT_LT(k2.uint256_t_no_montgomery_conversion().get_msb(), 129ULL);
361
362 if (k1_neg) {
363 k1 = -k1;
364 }
365 if (k2_neg) {
366 k2 = -k2;
367 }
370 static const uint256_t secp256k1_const_lambda{
371 0xDF02967C1B23BD72ULL, 0x122E22EA20816678UL, 0xA5261C028812645AULL, 0x5363AD4CC05C30E0ULL
372 };
373
374 secp256k1::fr expected = k1 - k2 * secp256k1_const_lambda;
375
376 expected.self_from_montgomery_form();
377 EXPECT_EQ(k, expected);
378}
379
380TEST(secp256k1, NegAndSelfNeg0CmpRegression)
381{
382 secp256k1::fq a = 0;
383 secp256k1::fq a_neg = -a;
384 EXPECT_EQ((a == a_neg), true);
385 a = 0;
386 a_neg = 0;
387 a_neg.self_neg();
388 EXPECT_EQ((a == a_neg), true);
389}
390
391TEST(secp256k1, MontgomeryMulBigBug)
392{
393 secp256k1::fq a(uint256_t{ 0xfffffffe630dc02f, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff });
394 secp256k1::fq a_sqr = a.sqr();
395 secp256k1::fq expected(uint256_t{ 0x60381e557e100000, 0x0, 0x0, 0x0 });
396 EXPECT_EQ((a_sqr == expected), true);
397}
constexpr bool is_point_at_infinity() const noexcept
constexpr bool on_curve() const noexcept
element class. Implements ecc group arithmetic using Jacobian coordinates See https://hyperelliptic....
Definition element.hpp:33
constexpr element dbl() const noexcept
BB_INLINE constexpr bool on_curve() const noexcept
BB_INLINE constexpr void self_set_infinity() noexcept
BB_INLINE constexpr bool is_point_at_infinity() const noexcept
static constexpr element one
Definition group.hpp:46
static constexpr affine_element affine_one
Definition group.hpp:48
group_elements::element< Fq, Fr, Params > element
Definition group.hpp:41
static std::vector< affine_element > derive_generators(const std::vector< uint8_t > &domain_separator_bytes, const size_t num_generators, const size_t starting_index=0)
Derives generator points via hash-to-curve.
Definition group.hpp:87
constexpr uint64_t get_msb() const
FF a
FF b
field< FrParams > fr
field< FqParams > fq
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
General class for prime fields see Prime field documentation["field documentation"] for general imple...
static constexpr field cube_root_of_unity()
static constexpr field one()
static void split_into_endomorphism_scalars(const field &k, field &k1, field &k2)
Full-width endomorphism decomposition: k ≡ k1 - k2·λ (mod r). Modifies the field elements k1 and k2.
BB_INLINE constexpr void self_neg() &noexcept
static field random_element(numeric::RNG *engine=nullptr) noexcept
BB_INLINE constexpr field sqr() const noexcept
constexpr uint256_t uint256_t_no_montgomery_conversion() const noexcept
static BB_INLINE void __copy(const field &a, field &r) noexcept
BB_INLINE constexpr void self_from_montgomery_form() &noexcept
BB_INLINE constexpr void self_to_montgomery_form() &noexcept
static constexpr field zero()
static constexpr fq b
static constexpr fq a