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, GeneratorOnCurve)
14{
16 EXPECT_EQ(result.on_curve(), true);
17}
18
19TEST(secp256r1, RandomElement)
20{
21 secp256r1::g1::element result = secp256r1::g1::element::random_element();
22 EXPECT_EQ(result.on_curve(), true);
23}
24
25TEST(secp256r1, RandomAffineElement)
26{
27 secp256r1::g1::affine_element result = secp256r1::g1::element::random_element();
28 EXPECT_EQ(result.on_curve(), true);
29}
30
31TEST(secp256r1, Eq)
32{
33 secp256r1::g1::element a = secp256r1::g1::element::random_element();
34 secp256r1::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 secp256r1::g1::element c = secp256r1::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(secp256r1, CheckGroupModulus)
52{
53 // secp256r1::g1::affine_element expected = secp256r1::g1::affine_one;
54 secp256r1::fr exponent = -secp256r1::fr(1);
56 result += secp256r1::g1::one;
57 result += secp256r1::g1::one;
58 EXPECT_EQ(result.on_curve(), true);
59 EXPECT_EQ(result == secp256r1::g1::one, true);
60}
61
62TEST(secp256r1, AddExceptionTestInfinity)
63{
64 secp256r1::g1::element lhs = secp256r1::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(secp256r1, AddExceptionTestDbl)
89{
90 secp256r1::g1::element lhs = secp256r1::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(secp256r1, AddDblConsistency)
104{
106 secp256r1::g1::element b = a.dbl(); // 2P
107
108 secp256r1::g1::element c = b.dbl(); // 4P
109 c = c.dbl(); // 8P
110
111 secp256r1::g1::element d = a + b; // 3P
112 d = d + b; // 5P
113 d = d + a; // 6P
114 d = d + a; // 7P
115 d = d + a; // 8P
116 EXPECT_EQ(c, d);
117}
118
119TEST(secp256r1, AddDblConsistencyRepeated)
120{
121 secp256r1::g1::element a = secp256r1::g1::element::random_element();
126
128 secp256r1::g1::element expected;
129
130 b = a.dbl(); // b = 2a
131 c = b.dbl(); // c = 4a
132
133 d = a + b; // d = 3a
134 e = a + c; // e = 5a
135 result = d + e; // result = 8a
136
137 expected = c.dbl(); // expected = 8a
138
139 EXPECT_EQ(result == expected, true);
140}
141
142TEST(secp256r1, MixedAddExceptionTestInfinity)
143{
145 secp256r1::g1::affine_element rhs = secp256r1::g1::element::random_element();
146 secp256r1::fq::__copy(rhs.x, lhs.x);
147 lhs.y = -rhs.y;
148
150 result = lhs + rhs;
151
152 EXPECT_EQ(result.is_point_at_infinity(), true);
153
154 lhs.self_set_infinity();
155 result = lhs + rhs;
157 rhs_c = secp256r1::g1::element(rhs);
158
159 EXPECT_EQ(rhs_c == result, true);
160}
161
162TEST(secp256r1, MixedAddExceptionTestDbl)
163{
164 secp256r1::g1::affine_element rhs = secp256r1::g1::element::random_element();
166 lhs = secp256r1::g1::element(rhs);
167
169 secp256r1::g1::element expected;
170 result = lhs + rhs;
171
172 expected = lhs.dbl();
173
174 EXPECT_EQ(result == expected, true);
175}
176
177TEST(secp256r1, AddMixedAddConsistencyCheck)
178{
179 secp256r1::g1::affine_element rhs = secp256r1::g1::element::random_element();
180 secp256r1::g1::element lhs = secp256r1::g1::element::random_element();
182 rhs_b = secp256r1::g1::element(rhs);
183
184 secp256r1::g1::element add_result;
185 secp256r1::g1::element mixed_add_result;
186 add_result = lhs + rhs_b;
187 mixed_add_result = lhs + rhs;
188
189 EXPECT_EQ(add_result == mixed_add_result, true);
190}
191
192TEST(secp256r1, OnCurve)
193{
194 for (size_t i = 0; i < 100; ++i) {
195 secp256r1::g1::element test = secp256r1::g1::element::random_element();
196 EXPECT_EQ(test.on_curve(), true);
197 secp256r1::g1::affine_element affine_test = secp256r1::g1::element::random_element();
198 EXPECT_EQ(affine_test.on_curve(), true);
199 }
200}
201TEST(secp256r1, BatchNormalize)
202{
203 size_t num_points = 2;
204 std::vector<secp256r1::g1::element> points(num_points);
205 std::vector<secp256r1::g1::element> normalized(num_points);
206 for (size_t i = 0; i < num_points; ++i) {
207 secp256r1::g1::element a = secp256r1::g1::element::random_element();
208 secp256r1::g1::element b = secp256r1::g1::element::random_element();
209 points[i] = a + b;
210 normalized[i] = points[i];
211 }
212 secp256r1::g1::element::batch_normalize(&normalized[0], num_points);
213
214 for (size_t i = 0; i < num_points; ++i) {
215 secp256r1::fq zz;
216 secp256r1::fq zzz;
217 secp256r1::fq result_x;
218 secp256r1::fq result_y;
219 zz = points[i].z.sqr();
220 zzz = points[i].z * zz;
221 result_x = normalized[i].x * zz;
222 result_y = normalized[i].y * zzz;
223
224 EXPECT_EQ((result_x == points[i].x), true);
225 EXPECT_EQ((result_y == points[i].y), true);
226 }
227}
228
229TEST(secp256r1, GroupExponentiationZeroAndOne)
230{
232
233 EXPECT_EQ(result.is_point_at_infinity(), true);
235
236 EXPECT_EQ(result.is_point_at_infinity(), true);
237 EXPECT_NE(pif, secp256r1::g1::one);
238
240
241 EXPECT_EQ(result == secp256r1::g1::affine_one, true);
242}
243
244TEST(secp256r1, GroupExponentiationConsistencyCheck)
245{
248
250 c = a * b;
251
253 secp256r1::g1::affine_element result = input * a;
254 result = result * b;
255
256 secp256r1::g1::affine_element expected = input * c;
257
258 EXPECT_EQ(result == expected, true);
259}
260
266TEST(secp256r1, AdditionSubtractionRegressionCheck)
267{
268 secp256r1::fq fq1(uint256_t{ 0xfffffe0000000200, 0x200fffff9ff, 0xfffffbfffffffe00, 0xfffffbff00000400 });
269 secp256r1::fq fq2(uint256_t{ 0xfffffe0000000200, 0x200fffff9ff, 0xfffffbfffffffe00, 0xfffffbff00000400 });
270 secp256r1::fq fq3(0);
271 secp256r1::fq fq4(0);
273 fq1 += secp256r1::fq(2);
274
275 fq3 -= fq1;
276 fq4 -= fq2;
277 EXPECT_EQ(fq1 + fq1, fq2 + fq2);
278 EXPECT_EQ(fq3, fq4);
279}
280
281/* TODO (#LARGE_MODULUS_AFFINE_POINT_COMPRESSION): Rewrite this test after designing point compression for p>2^255
282TEST(secp256r1, derive_generators)
283{
284 constexpr size_t num_generators = 128;
285 auto result = secp256r1::g1::derive_generators<num_generators>();
286
287 const auto is_unique = [&result](const secp256r1::g1::affine_element& y, const size_t j) {
288 for (size_t i = 0; i < result.size(); ++i) {
289 if ((i != j) && result[i] == y) {
290 return false;
291 }
292 }
293 return true;
294 };
295
296 for (size_t k = 0; k < num_generators; ++k) {
297 EXPECT_EQ(is_unique(result[k], k), true);
298 EXPECT_EQ(result[k].on_curve(), true);
299 }
300}
301TEST(secp256r1, check_compression_constructor)
302{
303 secp256r1::g1::affine_element el(uint256_t(10));
304 std::cout << "Affine element: " << el << std::endl;
305}**/
306
307#if defined(__SIZEOF_INT128__) && !defined(__wasm__)
308TEST(secp256r1, MontgomeryMulBigBug)
309{
311 a.data[0] = 0xC5BF4F6AFF993D09;
312 a.data[1] = 0xA3361BDA67E62E0E;
313 a.data[2] = 0xAAAAAAAAAAAAAAAA;
314 a.data[3] = 0xFFFFFFFFE38E38E3;
315 secp256r1::fr a_sqr = a.sqr();
316 secp256r1::fr expected(uint256_t{ 0x57abc6aa0349c084, 0x65b21b232a4cb7a5, 0x5ba781948b0fcd6e, 0xd6e9e0644bda12f7 });
317 EXPECT_EQ((a_sqr == expected), true);
318}
319#endif
320
321TEST(secp256r1, CheckPrecomputedGenerators)
322{
323 ASSERT_TRUE((bb::check_precomputed_generators<secp256r1::g1, "biggroup offset generator", 1UL>()));
324 ASSERT_TRUE((bb::check_precomputed_generators<secp256r1::g1, "biggroup table offset generator", 1UL>()));
325}
326
327// Hacky: wasm does not properly find main() from gmock_main.
328// We only want to run wasm tests specifically for ecc ops as our field handling is different.
329// We need to make sure the hardcoded generators make sense.
330// As this is our narrow focus, we hack this so ecc_tests can run.
331#ifdef __wasm__
332GTEST_API_ int main(int argc, char** argv)
333{
334 testing::InitGoogleTest(&argc, argv);
335 return RUN_ALL_TESTS();
336}
337#endif
int main(int argc, char *argv[])
Definition main.cpp:3
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:67
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
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()