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.
12
13TEST(secp256k1, GeneratorOnCurve)
14{
16 EXPECT_EQ(result.on_curve(), true);
17}
18
19TEST(secp256k1, RandomElement)
20{
21 secp256k1::g1::element result = secp256k1::g1::element::random_element();
22 EXPECT_EQ(result.on_curve(), true);
23}
24
25TEST(secp256k1, RandomAffineElement)
26{
27 secp256k1::g1::affine_element result = secp256k1::g1::element::random_element();
28 EXPECT_EQ(result.on_curve(), true);
29}
30
31TEST(secp256k1, Eq)
32{
33 secp256k1::g1::element a = secp256k1::g1::element::random_element();
34 secp256k1::g1::element b = a.normalize();
35
36 EXPECT_EQ(a == b, true);
37 EXPECT_EQ(a == a, true);
38
39 b.self_set_infinity();
40
41 EXPECT_EQ(a == b, false);
42 secp256k1::g1::element c = secp256k1::g1::element::random_element();
43
44 EXPECT_EQ(a == c, false);
45
46 a.self_set_infinity();
47
48 EXPECT_EQ(a == b, true);
49}
50
51TEST(secp256k1, CheckGroupModulus)
52{
53 // secp256k1::g1::affine_element expected = secp256k1::g1::affine_one;
54 secp256k1::fr exponent = -secp256k1::fr(1);
56 result += secp256k1::g1::one;
57 result += secp256k1::g1::one;
58 EXPECT_EQ(result.on_curve(), true);
59 EXPECT_EQ(result == secp256k1::g1::one, true);
60}
61
62TEST(secp256k1, AddExceptionTestInfinity)
63{
64 secp256k1::g1::element lhs = secp256k1::g1::element::random_element();
67
68 rhs = -lhs;
69
70 result = lhs + rhs;
71
72 EXPECT_EQ(result.is_point_at_infinity(), true);
73
75 rhs_b = rhs;
76 rhs_b.self_set_infinity();
77
78 result = lhs + rhs_b;
79
80 EXPECT_EQ(lhs == result, true);
81
83 result = lhs + rhs;
84
85 EXPECT_EQ(rhs == result, true);
86}
87
88TEST(secp256k1, AddExceptionTestDbl)
89{
90 secp256k1::g1::element lhs = secp256k1::g1::element::random_element();
92 rhs = lhs;
93
96
97 result = lhs + rhs;
98 expected = lhs.dbl();
99
100 EXPECT_EQ(result == expected, true);
101}
102
103TEST(secp256k1, AddDblConsistency)
104{
105 secp256k1::g1::element a = secp256k1::g1::element::random_element();
106 secp256k1::g1::element b = secp256k1::g1::element::random_element();
107
110 secp256k1::g1::element add_result;
111 secp256k1::g1::element dbl_result;
112
113 c = a + b;
114 b = -b;
115 d = a + b;
116
117 add_result = c + d;
118 dbl_result = a.dbl();
119
120 EXPECT_EQ(add_result == dbl_result, true);
121}
122
123TEST(secp256k1, AddDblConsistencyRepeated)
124{
125 secp256k1::g1::element a = secp256k1::g1::element::random_element();
130
132 secp256k1::g1::element expected;
133
134 b = a.dbl(); // b = 2a
135 c = b.dbl(); // c = 4a
136
137 d = a + b; // d = 3a
138 e = a + c; // e = 5a
139 result = d + e; // result = 8a
140
141 expected = c.dbl(); // expected = 8a
142
143 EXPECT_EQ(result == expected, true);
144}
145
146TEST(secp256k1, MixedAddExceptionTestInfinity)
147{
149 secp256k1::g1::affine_element rhs = secp256k1::g1::element::random_element();
150 secp256k1::fq::__copy(rhs.x, lhs.x);
151 lhs.y = -rhs.y;
152
154 result = lhs + rhs;
155
156 EXPECT_EQ(result.is_point_at_infinity(), true);
157
158 lhs.self_set_infinity();
159 result = lhs + rhs;
161 rhs_c = secp256k1::g1::element(rhs);
162
163 EXPECT_EQ(rhs_c == result, true);
164}
165
166TEST(secp256k1, MixedAddExceptionTestDbl)
167{
168 secp256k1::g1::affine_element rhs = secp256k1::g1::element::random_element();
170 lhs = secp256k1::g1::element(rhs);
171
173 secp256k1::g1::element expected;
174 result = lhs + rhs;
175
176 expected = lhs.dbl();
177
178 EXPECT_EQ(result == expected, true);
179}
180
181TEST(secp256k1, AddMixedAddConsistencyCheck)
182{
183 secp256k1::g1::affine_element rhs = secp256k1::g1::element::random_element();
184 secp256k1::g1::element lhs = secp256k1::g1::element::random_element();
186 rhs_b = secp256k1::g1::element(rhs);
187
188 secp256k1::g1::element add_result;
189 secp256k1::g1::element mixed_add_result;
190 add_result = lhs + rhs_b;
191 mixed_add_result = lhs + rhs;
192
193 EXPECT_EQ(add_result == mixed_add_result, true);
194}
195
196TEST(secp256k1, OnCurve)
197{
198 for (size_t i = 0; i < 100; ++i) {
199 secp256k1::g1::element test = secp256k1::g1::element::random_element();
200 EXPECT_EQ(test.on_curve(), true);
201 secp256k1::g1::affine_element affine_test = secp256k1::g1::element::random_element();
202 EXPECT_EQ(affine_test.on_curve(), true);
203 }
204}
205TEST(secp256k1, BatchNormalize)
206{
207 size_t num_points = 2;
208 std::vector<secp256k1::g1::element> points(num_points);
209 std::vector<secp256k1::g1::element> normalized(num_points);
210 for (size_t i = 0; i < num_points; ++i) {
211 secp256k1::g1::element a = secp256k1::g1::element::random_element();
212 secp256k1::g1::element b = secp256k1::g1::element::random_element();
213 points[i] = a + b;
214 normalized[i] = points[i];
215 }
216 secp256k1::g1::element::batch_normalize(&normalized[0], num_points);
217
218 for (size_t i = 0; i < num_points; ++i) {
219 secp256k1::fq zz;
220 secp256k1::fq zzz;
221 secp256k1::fq result_x;
222 secp256k1::fq result_y;
223 zz = points[i].z.sqr();
224 zzz = points[i].z * zz;
225 result_x = normalized[i].x * zz;
226 result_y = normalized[i].y * zzz;
227
228 EXPECT_EQ((result_x == points[i].x), true);
229 EXPECT_EQ((result_y == points[i].y), true);
230 }
231}
232
233TEST(secp256k1, GroupExponentiationZeroAndOne)
234{
236
237 EXPECT_EQ(result.is_point_at_infinity(), true);
238
240
241 EXPECT_EQ(result == secp256k1::g1::affine_one, true);
242}
243
244TEST(secp256k1, GroupExponentiationConsistencyCheck)
245{
248
250 c = a * b;
251
253 secp256k1::g1::affine_element result = input * a;
254 result = result * b;
255
256 secp256k1::g1::affine_element expected = input * c;
257
258 EXPECT_EQ(result == expected, true);
259}
260
261TEST(secp256k1, DeriveGenerators)
262{
263 constexpr size_t num_generators = 128;
264 auto result = secp256k1::g1::derive_generators("test generators", num_generators);
265
266 const auto is_unique = [&result](const secp256k1::g1::affine_element& y, const size_t j) {
267 for (size_t i = 0; i < result.size(); ++i) {
268 if ((i != j) && result[i] == y) {
269 return false;
270 }
271 }
272 return true;
273 };
274
275 for (size_t k = 0; k < num_generators; ++k) {
276 EXPECT_EQ(is_unique(result[k], k), true);
277 EXPECT_EQ(result[k].on_curve(), true);
278 }
279}
280
281TEST(secp256k1, CheckPrecomputedGenerators)
282{
283 ASSERT_TRUE((bb::check_precomputed_generators<secp256k1::g1, "biggroup offset generator", 1UL>()));
284 ASSERT_TRUE((bb::check_precomputed_generators<secp256k1::g1, "biggroup table offset generator", 1UL>()));
285}
286
287TEST(secp256k1, GetEndomorphismScalars)
288{
289 for (size_t i = 0; i < 2048; i++) {
291 secp256k1::fr k1 = 0;
292 secp256k1::fr k2 = 0;
293
295 bool k1_neg = false;
296 bool k2_neg = false;
297
299 k2 = -k2;
300 k2_neg = true;
301 }
302
303 EXPECT_LT(k1.uint256_t_no_montgomery_conversion().get_msb(), 129ULL);
304 EXPECT_LT(k2.uint256_t_no_montgomery_conversion().get_msb(), 129ULL);
305
306 if (k1_neg) {
307 k1 = -k1;
308 }
309 if (k2_neg) {
310 k2 = -k2;
311 }
312
315
317 secp256k1::fr expected = k1 - k2 * beta;
318
319 expected.self_from_montgomery_form();
320 EXPECT_EQ(k, expected);
321 if (k != expected) {
322 break;
323 }
324 }
325}
326
327TEST(secp256k1, TestEndomorphismScalars)
328{
330 secp256k1::fr k1 = 0;
331 secp256k1::fr k2 = 0;
332
334 bool k1_neg = false;
335 bool k2_neg = false;
336
338 k1 = -k1;
339 k1_neg = true;
340 }
342 k2 = -k2;
343 k2_neg = true;
344 }
345
346 EXPECT_LT(k1.uint256_t_no_montgomery_conversion().get_msb(), 129ULL);
347 EXPECT_LT(k2.uint256_t_no_montgomery_conversion().get_msb(), 129ULL);
348
349 if (k1_neg) {
350 k1 = -k1;
351 }
352 if (k2_neg) {
353 k2 = -k2;
354 }
357 static const uint256_t secp256k1_const_lambda{
358 0xDF02967C1B23BD72ULL, 0x122E22EA20816678UL, 0xA5261C028812645AULL, 0x5363AD4CC05C30E0ULL
359 };
360
361 secp256k1::fr expected = k1 - k2 * secp256k1_const_lambda;
362
363 expected.self_from_montgomery_form();
364 EXPECT_EQ(k, expected);
365}
366
367TEST(secp256k1, NegAndSelfNeg0CmpRegression)
368{
369 secp256k1::fq a = 0;
370 secp256k1::fq a_neg = -a;
371 EXPECT_EQ((a == a_neg), true);
372 a = 0;
373 a_neg = 0;
374 a_neg.self_neg();
375 EXPECT_EQ((a == a_neg), true);
376}
377
378TEST(secp256k1, MontgomeryMulBigBug)
379{
380 secp256k1::fq a(uint256_t{ 0xfffffffe630dc02f, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff });
381 secp256k1::fq a_sqr = a.sqr();
382 secp256k1::fq expected(uint256_t{ 0x60381e557e100000, 0x0, 0x0, 0x0 });
383 EXPECT_EQ((a_sqr == expected), true);
384}
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
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
static constexpr field cube_root_of_unity()
static constexpr field one()
static void split_into_endomorphism_scalars(const field &k, field &k1, field &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()