Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
grumpkin.test.cpp
Go to the documentation of this file.
1#include "grumpkin.hpp"
3#include <chrono>
4#include <gtest/gtest.h>
5
6using namespace bb;
7
8TEST(grumpkin, CheckB)
9{
11 fr seventeen = 17;
12 EXPECT_EQ(seventeen, -b);
13}
14
15TEST(grumpkin, RandomElement)
16{
17 grumpkin::g1::element result = grumpkin::g1::element::random_element();
18 EXPECT_EQ(result.on_curve(), true);
19}
20
21TEST(grumpkin, RandomAffineElement)
22{
23 grumpkin::g1::affine_element result = grumpkin::g1::element::random_element();
24 EXPECT_EQ(result.on_curve(), true);
25}
26
27TEST(grumpkin, Eq)
28{
29 grumpkin::g1::element a = grumpkin::g1::element::random_element();
31
32 EXPECT_EQ(a == b, true);
33 EXPECT_EQ(a == a, true);
34
35 b.self_set_infinity();
36
37 EXPECT_EQ(a == b, false);
38 grumpkin::g1::element c = grumpkin::g1::element::random_element();
39
40 EXPECT_EQ(a == c, false);
41
42 a.self_set_infinity();
43
44 EXPECT_EQ(a == b, true);
45}
46
47TEST(grumpkin, CheckGroupModulus)
48{
49 // grumpkin::g1::affine_element expected = grumpkin::g1::affine_one;
50 grumpkin::fr exponent = -grumpkin::fr(1);
51 grumpkin::g1::element result = grumpkin::g1::one * exponent;
52 result += grumpkin::g1::one;
53 result += grumpkin::g1::one;
54 EXPECT_EQ(result.on_curve(), true);
55 EXPECT_EQ(result == grumpkin::g1::one, true);
56}
57
58TEST(grumpkin, AddExceptionTestInfinity)
59{
60 grumpkin::g1::element lhs = grumpkin::g1::element::random_element();
63
64 rhs = -lhs;
65
66 result = lhs + rhs;
67
68 EXPECT_EQ(result.is_point_at_infinity(), true);
69
71 rhs_b = rhs;
72 rhs_b.self_set_infinity();
73
74 result = lhs + rhs_b;
75
76 EXPECT_EQ(lhs == result, true);
77
79 result = lhs + rhs;
80
81 EXPECT_EQ(rhs == result, true);
82}
83
84TEST(grumpkin, AddExceptionTestDbl)
85{
86 grumpkin::g1::element lhs = grumpkin::g1::element::random_element();
88 rhs = lhs;
89
91 grumpkin::g1::element expected;
92
93 result = lhs + rhs;
94 expected = lhs.dbl();
95
96 EXPECT_EQ(result == expected, true);
97}
98
99TEST(grumpkin, AddDblConsistency)
100{
101 grumpkin::g1::element a = grumpkin::g1::element::random_element();
102 grumpkin::g1::element b = grumpkin::g1::element::random_element();
103
106 grumpkin::g1::element add_result;
107 grumpkin::g1::element dbl_result;
108
109 c = a + b;
110 b = -b;
111 d = a + b;
112
113 add_result = c + d;
114 dbl_result = a.dbl();
115
116 EXPECT_EQ(add_result == dbl_result, true);
117}
118
119TEST(grumpkin, AddDblConsistencyRepeated)
120{
121 grumpkin::g1::element a = grumpkin::g1::element::random_element();
126
128 grumpkin::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(grumpkin, MixedAddExceptionTestInfinity)
143{
145 grumpkin::g1::affine_element rhs = grumpkin::g1::element::random_element();
146 grumpkin::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 = grumpkin::g1::element(rhs);
158
159 EXPECT_EQ(rhs_c == result, true);
160}
161
162TEST(grumpkin, MixedAddExceptionTestDbl)
163{
164 grumpkin::g1::affine_element rhs = grumpkin::g1::element::random_element();
166 lhs = grumpkin::g1::element(rhs);
167
169 grumpkin::g1::element expected;
170 result = lhs + rhs;
171
172 expected = lhs.dbl();
173
174 EXPECT_EQ(result == expected, true);
175}
176
177TEST(grumpkin, AddMixedAddConsistencyCheck)
178{
179 grumpkin::g1::affine_element rhs = grumpkin::g1::element::random_element();
180 grumpkin::g1::element lhs = grumpkin::g1::element::random_element();
182 rhs_b = grumpkin::g1::element(rhs);
183
184 grumpkin::g1::element add_result;
185 grumpkin::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(grumpkin, OnCurve)
193{
194 for (size_t i = 0; i < 100; ++i) {
195 grumpkin::g1::element test = grumpkin::g1::element::random_element();
196 EXPECT_EQ(test.on_curve(), true);
197 grumpkin::g1::affine_element affine_test = grumpkin::g1::element::random_element();
198 EXPECT_EQ(affine_test.on_curve(), true);
199 }
200}
201TEST(grumpkin, BatchNormalize)
202{
203 size_t num_points = 2;
204 std::vector<grumpkin::g1::element> points(num_points);
205 std::vector<grumpkin::g1::element> normalized(num_points);
206 for (size_t i = 0; i < num_points; ++i) {
207 grumpkin::g1::element a = grumpkin::g1::element::random_element();
208 grumpkin::g1::element b = grumpkin::g1::element::random_element();
209 points[i] = a + b;
210 normalized[i] = points[i];
211 }
212 grumpkin::g1::element::batch_normalize(&normalized[0], num_points);
213
214 for (size_t i = 0; i < num_points; ++i) {
215 grumpkin::fq zz;
216 grumpkin::fq zzz;
217 grumpkin::fq result_x;
218 grumpkin::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(grumpkin, GroupExponentiationZeroAndOne)
230{
232
233 EXPECT_EQ(result.is_point_at_infinity(), true);
234
236
237 EXPECT_EQ(result == grumpkin::g1::affine_one, true);
238}
239
240TEST(grumpkin, GroupExponentiationConsistencyCheck)
241{
244
245 grumpkin::fr c;
246 c = a * b;
247
249 grumpkin::g1::affine_element result = input * a;
250 result = result * b;
251
252 grumpkin::g1::affine_element expected = input * c;
253
254 EXPECT_EQ(result == expected, true);
255}
256
257TEST(grumpkin, DeriveGenerators)
258{
259 constexpr size_t num_generators = 128;
260 auto result = grumpkin::g1::derive_generators("test generators", num_generators);
261 const auto is_unique = [&result](const grumpkin::g1::affine_element& y, const size_t j) {
262 for (size_t i = 0; i < result.size(); ++i) {
263 if ((i != j) && result[i] == y) {
264 return false;
265 }
266 }
267 return true;
268 };
269
270 for (size_t k = 0; k < num_generators; ++k) {
271 EXPECT_EQ(is_unique(result[k], k), true);
272 EXPECT_EQ(result[k].on_curve(), true);
273 }
274}
275
276TEST(grumpkin, BatchMul)
277{
278 constexpr size_t num_points = 1024;
279
281 for (size_t i = 0; i < num_points; ++i) {
282 points.emplace_back(grumpkin::g1::element::random_element());
283 }
284 grumpkin::g1::element::batch_normalize(&points[0], num_points);
285
287 for (size_t i = 0; i < num_points; ++i) {
288 affine_points.emplace_back(points[i]);
289 }
291
292 std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
293
295 expected.reserve(num_points);
296 for (const auto& point : points) {
297 expected.emplace_back((point * exponent).normalize());
298 }
299
300 std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
301 std::chrono::milliseconds diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
302 std::cout << "regular mul operations: " << diff.count() << "ms" << std::endl;
303
304 start = std::chrono::steady_clock::now();
305
306 const auto result = grumpkin::g1::element::batch_mul_with_endomorphism(affine_points, exponent);
307 end = std::chrono::steady_clock::now();
308 diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
309 std::cout << "batched mul operations: " << diff.count() << "ms" << std::endl;
310
311 for (size_t i = 0; i < num_points; ++i) {
312 EXPECT_EQ(result[i].x, expected[i].x);
313 EXPECT_EQ(result[i].y, expected[i].y);
314 }
315}
316// Checks for "bad points" in terms of sharing a y-coordinate as explained here:
317// https://github.com/AztecProtocol/aztec2-internal/issues/437
318TEST(grumpkin, BadPoints)
319{
321 auto beta_sqr = beta * beta;
322 bool res = true;
323 grumpkin::fr c(1);
324 for (size_t i = 0; i < 256; i++) {
325 auto val = c / (grumpkin::fr(1) + c);
326 if (val == beta || val == beta_sqr) {
327 res = false;
328 }
329 c *= grumpkin::fr(4);
330 }
331 EXPECT_TRUE(res);
332}
333
334TEST(grumpkin, CheckPrecomputedGenerators)
335{
336 ASSERT_TRUE((bb::check_precomputed_generators<grumpkin::g1, "pedersen_hash_length", 1UL>()));
337 ASSERT_TRUE((bb::check_precomputed_generators<grumpkin::g1, "DEFAULT_DOMAIN_SEPARATOR", 8UL>()));
338}
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
constexpr element normalize() 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 constexpr Fq curve_b
Definition group.hpp:51
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
FF a
FF b
Entry point for Barretenberg command-line interface.
TEST(MegaCircuitBuilder, CopyConstructor)
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 field random_element(numeric::RNG *engine=nullptr) noexcept
BB_INLINE constexpr field sqr() const noexcept
static BB_INLINE void __copy(const field &a, field &r) noexcept
static constexpr field zero()