Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
secp256r1.test.cpp
Go to the documentation of this file.
1#include "secp256r1.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 secp256r1 elliptic curve group operations.
12
13TEST(secp256r1, CurveCoefficients)
14{
15 secp256r1::fq expected_a = secp256r1::fq("0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc");
16 secp256r1::fq expected_b = secp256r1::fq("0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b");
17
18 EXPECT_EQ(secp256r1::G1Params::a, expected_a);
19 EXPECT_EQ(secp256r1::G1Params::b, expected_b);
20}
21
22TEST(secp256r1, GeneratorOnCurve)
23{
25 secp256r1::fq expected_x = secp256r1::fq("0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296");
26 secp256r1::fq expected_y = secp256r1::fq("0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5");
27
28 EXPECT_EQ(result.x, expected_x);
29 EXPECT_EQ(result.y, expected_y);
30 EXPECT_EQ(result.on_curve(), true);
31}
32
33TEST(secp256r1, RandomElement)
34{
35 secp256r1::g1::element result = secp256r1::g1::element::random_element();
36 EXPECT_EQ(result.on_curve(), true);
37}
38
39TEST(secp256r1, RandomAffineElement)
40{
41 secp256r1::g1::affine_element result = secp256r1::g1::element::random_element();
42 EXPECT_EQ(result.on_curve(), true);
43}
44
45TEST(secp256r1, Eq)
46{
47 secp256r1::g1::element a = secp256r1::g1::element::random_element();
48 secp256r1::g1::element b = a.normalize();
49
50 EXPECT_EQ(a == b, true);
51 EXPECT_EQ(a == a, true);
52
53 b.self_set_infinity();
54
55 EXPECT_EQ(a == b, false);
56 secp256r1::g1::element c = secp256r1::g1::element::random_element();
57
58 EXPECT_EQ(a == c, false);
59
60 a.self_set_infinity();
61
62 EXPECT_EQ(a == b, true);
63}
64
65TEST(secp256r1, CheckGroupModulus)
66{
67 // secp256r1::g1::affine_element expected = secp256r1::g1::affine_one;
68 secp256r1::fr exponent = -secp256r1::fr(1);
70 result += secp256r1::g1::one;
71 result += secp256r1::g1::one;
72 EXPECT_EQ(result.on_curve(), true);
73 EXPECT_EQ(result == secp256r1::g1::one, true);
74}
75
76TEST(secp256r1, AddExceptionTestInfinity)
77{
78 secp256r1::g1::element lhs = secp256r1::g1::element::random_element();
81
82 rhs = -lhs;
83
84 result = lhs + rhs;
85
86 EXPECT_EQ(result.is_point_at_infinity(), true);
87
89 rhs_b = rhs;
90 rhs_b.self_set_infinity();
91
92 result = lhs + rhs_b;
93
94 EXPECT_EQ(lhs == result, true);
95
97 result = lhs + rhs;
98
99 EXPECT_EQ(rhs == result, true);
100}
101
102TEST(secp256r1, AddExceptionTestDbl)
103{
104 secp256r1::g1::element lhs = secp256r1::g1::element::random_element();
106 rhs = lhs;
107
109 secp256r1::g1::element expected;
110
111 result = lhs + rhs;
112 expected = lhs.dbl();
113
114 EXPECT_EQ(result == expected, true);
115}
116
117TEST(secp256r1, AddDblConsistency)
118{
120 secp256r1::g1::element b = a.dbl(); // 2P
121
122 secp256r1::g1::element c = b.dbl(); // 4P
123 c = c.dbl(); // 8P
124
125 secp256r1::g1::element d = a + b; // 3P
126 d = d + b; // 5P
127 d = d + a; // 6P
128 d = d + a; // 7P
129 d = d + a; // 8P
130 EXPECT_EQ(c, d);
131}
132
133TEST(secp256r1, AddDblConsistencyRepeated)
134{
135 secp256r1::g1::element a = secp256r1::g1::element::random_element();
140
142 secp256r1::g1::element expected;
143
144 b = a.dbl(); // b = 2a
145 c = b.dbl(); // c = 4a
146
147 d = a + b; // d = 3a
148 e = a + c; // e = 5a
149 result = d + e; // result = 8a
150
151 expected = c.dbl(); // expected = 8a
152
153 EXPECT_EQ(result == expected, true);
154}
155
156TEST(secp256r1, MixedAddExceptionTestInfinity)
157{
159 secp256r1::g1::affine_element rhs = secp256r1::g1::element::random_element();
160 secp256r1::fq::__copy(rhs.x, lhs.x);
161 lhs.y = -rhs.y;
162
164 result = lhs + rhs;
165
166 EXPECT_EQ(result.is_point_at_infinity(), true);
167
168 lhs.self_set_infinity();
169 result = lhs + rhs;
171 rhs_c = secp256r1::g1::element(rhs);
172
173 EXPECT_EQ(rhs_c == result, true);
174}
175
176TEST(secp256r1, MixedAddExceptionTestDbl)
177{
178 secp256r1::g1::affine_element rhs = secp256r1::g1::element::random_element();
180 lhs = secp256r1::g1::element(rhs);
181
183 secp256r1::g1::element expected;
184 result = lhs + rhs;
185
186 expected = lhs.dbl();
187
188 EXPECT_EQ(result == expected, true);
189}
190
191TEST(secp256r1, AddMixedAddConsistencyCheck)
192{
193 secp256r1::g1::affine_element rhs = secp256r1::g1::element::random_element();
194 secp256r1::g1::element lhs = secp256r1::g1::element::random_element();
196 rhs_b = secp256r1::g1::element(rhs);
197
198 secp256r1::g1::element add_result;
199 secp256r1::g1::element mixed_add_result;
200 add_result = lhs + rhs_b;
201 mixed_add_result = lhs + rhs;
202
203 EXPECT_EQ(add_result == mixed_add_result, true);
204}
205
206TEST(secp256r1, OnCurve)
207{
208 for (size_t i = 0; i < 100; ++i) {
209 secp256r1::g1::element test = secp256r1::g1::element::random_element();
210 EXPECT_EQ(test.on_curve(), true);
211 secp256r1::g1::affine_element affine_test = secp256r1::g1::element::random_element();
212 EXPECT_EQ(affine_test.on_curve(), true);
213 }
214}
215TEST(secp256r1, BatchNormalize)
216{
217 size_t num_points = 2;
218 std::vector<secp256r1::g1::element> points(num_points);
219 std::vector<secp256r1::g1::element> normalized(num_points);
220 for (size_t i = 0; i < num_points; ++i) {
221 secp256r1::g1::element a = secp256r1::g1::element::random_element();
222 secp256r1::g1::element b = secp256r1::g1::element::random_element();
223 points[i] = a + b;
224 normalized[i] = points[i];
225 }
226 secp256r1::g1::element::batch_normalize(&normalized[0], num_points);
227
228 for (size_t i = 0; i < num_points; ++i) {
229 secp256r1::fq zz;
230 secp256r1::fq zzz;
231 secp256r1::fq result_x;
232 secp256r1::fq result_y;
233 zz = points[i].z.sqr();
234 zzz = points[i].z * zz;
235 result_x = normalized[i].x * zz;
236 result_y = normalized[i].y * zzz;
237
238 EXPECT_EQ((result_x == points[i].x), true);
239 EXPECT_EQ((result_y == points[i].y), true);
240 }
241}
242
243TEST(secp256r1, GroupExponentiationZeroAndOne)
244{
246
247 EXPECT_EQ(result.is_point_at_infinity(), true);
249
250 EXPECT_EQ(result.is_point_at_infinity(), true);
251 EXPECT_NE(pif, secp256r1::g1::one);
252
254
255 EXPECT_EQ(result == secp256r1::g1::affine_one, true);
256}
257
258TEST(secp256r1, GroupExponentiationConsistencyCheck)
259{
262
264 c = a * b;
265
267 secp256r1::g1::affine_element result = input * a;
268 result = result * b;
269
270 secp256r1::g1::affine_element expected = input * c;
271
272 EXPECT_EQ(result == expected, true);
273}
274
280TEST(secp256r1, AdditionSubtractionRegressionCheck)
281{
282 secp256r1::fq fq1(uint256_t{ 0xfffffe0000000200, 0x200fffff9ff, 0xfffffbfffffffe00, 0xfffffbff00000400 });
283 secp256r1::fq fq2(uint256_t{ 0xfffffe0000000200, 0x200fffff9ff, 0xfffffbfffffffe00, 0xfffffbff00000400 });
284 secp256r1::fq fq3(0);
285 secp256r1::fq fq4(0);
287 fq1 += secp256r1::fq(2);
288
289 fq3 -= fq1;
290 fq4 -= fq2;
291 EXPECT_EQ(fq1 + fq1, fq2 + fq2);
292 EXPECT_EQ(fq3, fq4);
293}
294
295/* TODO (#LARGE_MODULUS_AFFINE_POINT_COMPRESSION): Rewrite this test after designing point compression for p>2^255
296TEST(secp256r1, derive_generators)
297{
298 constexpr size_t num_generators = 128;
299 auto result = secp256r1::g1::derive_generators<num_generators>();
300
301 const auto is_unique = [&result](const secp256r1::g1::affine_element& y, const size_t j) {
302 for (size_t i = 0; i < result.size(); ++i) {
303 if ((i != j) && result[i] == y) {
304 return false;
305 }
306 }
307 return true;
308 };
309
310 for (size_t k = 0; k < num_generators; ++k) {
311 EXPECT_EQ(is_unique(result[k], k), true);
312 EXPECT_EQ(result[k].on_curve(), true);
313 }
314}
315TEST(secp256r1, check_compression_constructor)
316{
317 secp256r1::g1::affine_element el(uint256_t(10));
318 std::cout << "Affine element: " << el << std::endl;
319}**/
320
321#if defined(__SIZEOF_INT128__) && !defined(__wasm__)
322TEST(secp256r1, MontgomeryMulBigBug)
323{
325 a.data[0] = 0xC5BF4F6AFF993D09;
326 a.data[1] = 0xA3361BDA67E62E0E;
327 a.data[2] = 0xAAAAAAAAAAAAAAAA;
328 a.data[3] = 0xFFFFFFFFE38E38E3;
329 secp256r1::fr a_sqr = a.sqr();
330 secp256r1::fr expected(uint256_t{ 0x57abc6aa0349c084, 0x65b21b232a4cb7a5, 0x5ba781948b0fcd6e, 0xd6e9e0644bda12f7 });
331 EXPECT_EQ((a_sqr == expected), true);
332}
333#endif
334
335TEST(secp256r1, CheckPrecomputedGenerators)
336{
337 ASSERT_TRUE((bb::check_precomputed_generators<secp256r1::g1, "biggroup offset generator", 1UL>()));
338 ASSERT_TRUE((bb::check_precomputed_generators<secp256r1::g1, "biggroup table offset generator", 1UL>()));
339}
340
341// Hacky: wasm does not properly find main() from gmock_main.
342// We only want to run wasm tests specifically for ecc ops as our field handling is different.
343// We need to make sure the hardcoded generators make sense.
344// As this is our narrow focus, we hack this so ecc_tests can run.
345#ifdef __wasm__
346GTEST_API_ int main(int argc, char** argv)
347{
348 testing::InitGoogleTest(&argc, argv);
349 return RUN_ALL_TESTS();
350}
351#endif
int main(int argc, char **argv)
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
FF a
FF b
field< FrParams > fr
field< FqParams > fq
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
field2< fq, Bn254Fq2Params > fq2
Definition fq2.hpp:71
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 one()
static field random_element(numeric::RNG *engine=nullptr) noexcept
BB_INLINE constexpr field sqr() const noexcept
static constexpr uint256_t modulus_minus_two
static BB_INLINE void __copy(const field &a, field &r) noexcept
static constexpr field zero()
static constexpr fq a
static constexpr fq b