4#include <gtest/gtest.h>
10template <
typename Group,
typename Fr>
11typename Group::affine_element naive_scalar_mul(
const typename Group::element& base,
const Fr& scalar)
13 typename Group::element acc = Group::point_at_infinity;
14 typename Group::element runner = base;
16 for (
size_t i = 0; i < 256; ++i) {
17 if (bits.get_bit(i)) {
20 runner = runner.dbl();
22 return typename Group::affine_element(acc);
43 EXPECT_EQ(
a ==
b,
true);
44 EXPECT_EQ(
a ==
a,
true);
46 b.self_set_infinity();
48 EXPECT_EQ(
a ==
b,
false);
51 EXPECT_EQ(
a == c,
false);
53 a.self_set_infinity();
55 EXPECT_EQ(
a ==
b,
true);
58TEST(
g1, MixedAddCheckAgainstConstants)
60 fq a_x{ 0x92716caa6cac6d26, 0x1e6e234136736544, 0x1bb04588cde00af0, 0x9a2ac922d97e6f5 };
61 fq a_y{ 0x9e693aeb52d79d2d, 0xf0c1895a61e5e975, 0x18cd7f5310ced70f, 0xac67920a22939ad };
62 fq a_z{ 0xfef593c9ce1df132, 0xe0486f801303c27d, 0x9bbd01ab881dc08e, 0x2a589badf38ec0f9 };
63 fq b_x{ 0xa1ec5d1398660db8, 0x6be3e1f6fd5d8ab1, 0x69173397dd272e11, 0x12575bbfe1198886 };
64 fq b_y{ 0xcfbfd4441138823e, 0xb5f817e28a1ef904, 0xefb7c5629dcc1c42, 0x1a9ed3d6f846230e };
65 fq expected_x{ 0x2a9d0201fccca20, 0x36f969b294f31776, 0xee5534422a6f646, 0x911dbc6b02310b6 };
66 fq expected_y{ 0x14c30aaeb4f135ef, 0x9c27c128ea2017a1, 0xf9b7d80c8315eabf, 0x35e628df8add760 };
67 fq expected_z{ 0xa43fe96673d10eb3, 0x88fbe6351753d410, 0x45c21cc9d99cb7d, 0x3018020aa6e9ede5 };
75 rhs.x = b_x.to_montgomery_form();
76 rhs.y = b_y.to_montgomery_form();
82 EXPECT_EQ(result == expected,
true);
87 fq a_x{ 0x8d1703aa518d827f, 0xd19cc40779f54f63, 0xabc11ce30d02728c, 0x10938940de3cbeec };
88 fq a_y{ 0xcf1798994f1258b4, 0x36307a354ad90a25, 0xcd84adb348c63007, 0x6266b85241aff3f };
89 fq a_z{ 0xe213e18fd2df7044, 0xb2f42355982c5bc8, 0xf65cf5150a3a9da1, 0xc43bde08b03aca2 };
90 fq expected_x{ 0xd5c6473044b2e67c, 0x89b185ea20951f3a, 0x4ac597219cf47467, 0x2d00482f63b12c86 };
91 fq expected_y{ 0x4e7e6c06a87e4314, 0x906a877a71735161, 0xaa7b9893cc370d39, 0x62f206bef795a05 };
92 fq expected_z{ 0x8813bdca7b0b115a, 0x929104dffdfabd22, 0x3fff575136879112, 0x18a299c1f683bdca };
107 EXPECT_EQ(result == expected,
true);
112 fq a_x{ 0x184b38afc6e2e09a, 0x4965cd1c3687f635, 0x334da8e7539e71c4, 0xf708d16cfe6e14 };
113 fq a_y{ 0x2a6ff6ffc739b3b6, 0x70761d618b513b9, 0xbf1645401de26ba1, 0x114a1616c164b980 };
114 fq a_z{ 0x10143ade26bbd57a, 0x98cf4e1f6c214053, 0x6bfdc534f6b00006, 0x1875e5068ababf2c };
115 fq b_x{ 0xafdb8a15c98bf74c, 0xac54df622a8d991a, 0xc6e5ae1f3dad4ec8, 0x1bd3fb4a59e19b52 };
116 fq b_y{ 0x21b3bb529bec20c0, 0xaabd496406ffb8c1, 0xcd3526c26ac5bdcb, 0x187ada6b8693c184 };
117 fq b_z{ 0xffcd440a228ed652, 0x8a795c8f234145f1, 0xd5279cdbabb05b95, 0xbdf19ba16fc607a };
118 fq expected_x{ 0x18764da36aa4cd81, 0xd15388d1fea9f3d3, 0xeb7c437de4bbd748, 0x2f09b712adf6f18f };
119 fq expected_y{ 0x50c5f3cab191498c, 0xe50aa3ce802ea3b5, 0xd9d6125b82ebeff8, 0x27e91ba0686e54fe };
120 fq expected_z{ 0xe4b81ef75fedf95, 0xf608edef14913c75, 0xfd9e178143224c96, 0xa8ae44990c8accd };
129 rhs.x = b_x.to_montgomery_form();
130 rhs.y = b_y.to_montgomery_form();
131 rhs.z = b_z.to_montgomery_form();
138 EXPECT_EQ(result == expected,
true);
157 result = lhs + rhs_b;
159 EXPECT_EQ(lhs == result,
true);
164 EXPECT_EQ(rhs == result,
true);
186 expected = lhs.
dbl();
188 EXPECT_EQ(result == expected,
true);
219 dbl_result =
a.dbl();
221 EXPECT_EQ(add_result == dbl_result,
true);
244 EXPECT_EQ(result == expected,
true);
264 EXPECT_EQ(rhs_c == result,
true);
277 expected = lhs.
dbl();
279 EXPECT_EQ(result == expected,
true);
291 add_result = lhs + rhs_b;
292 mixed_add_result = lhs + rhs;
294 EXPECT_EQ(add_result == mixed_add_result,
true);
299 size_t num_points = 2;
302 for (
size_t i = 0; i < num_points; ++i) {
306 normalized[i] = points[i];
308 g1::element::batch_normalize(&normalized[0], num_points);
310 for (
size_t i = 0; i < num_points; ++i) {
315 zz = points[i].z.
sqr();
316 zzz = points[i].z * zz;
317 result_x = normalized[i].x * zz;
318 result_y = normalized[i].y * zzz;
320 EXPECT_EQ((result_x == points[i].x),
true);
321 EXPECT_EQ((result_y == points[i].y),
true);
325TEST(
g1, GroupExponentiationCheckAgainstConstants)
327 fr a{ 0xb67299b792199cf0, 0xc1da7df1e7e12768, 0x692e427911532edf, 0x13dd85e87dc89978 };
330 fq expected_x{ 0x9bf840faf1b4ba00, 0xe81b7260d068e663, 0x7610c9a658d2c443, 0x278307cd3d0cddb0 };
331 fq expected_y{ 0xf6ed5fb779ebecb, 0x414ca771acbe183c, 0xe3692cb56dfbdb67, 0x3d3c5ed19b080a3 };
334 expected.
x = expected_x.to_montgomery_form();
335 expected.
y = expected_y.to_montgomery_form();
339 EXPECT_EQ(result == expected,
true);
347 fr scalar{ 0xcfbfd4441138823e, 0xb5f817e28a1ef904, 0xefb7c5629dcc1c42, 0x1a9ed3d6f846230e };
378TEST(
g1, GroupExponentiationConsistencyCheck)
392 EXPECT_EQ(result == expected,
true);
397 constexpr size_t num_generators = 128;
401 for (
size_t i = 0; i < result.size(); ++i) {
402 if ((i != j) && result[i] == y) {
409 for (
size_t k = 0; k < num_generators; ++k) {
410 EXPECT_EQ(is_unique(result[k], k),
true);
411 EXPECT_EQ(result[k].on_curve(),
true);
421 g1::affine_element::serialize_to_buffer(expected, &
buffer[0]);
425 EXPECT_EQ(result == expected,
true);
427template <
class T>
void write(
const T t)
429 FILE* fp = fopen(
"/dev/null",
"wb");
430 static_cast<void>(fwrite(&t,
sizeof(t), 1, fp));
431 static_cast<void>(fclose(fp));
434#if !defined(__wasm__)
438 EXPECT_NO_THROW(write<g1::affine_element>({}));
444 ASSERT_TRUE((bb::check_precomputed_generators<g1, "biggroup table offset generator", 1UL>()));
445 ASSERT_TRUE((bb::check_precomputed_generators<g1, "biggroup offset generator", 1UL>()));
446 ASSERT_TRUE((bb::check_precomputed_generators<g1, "ECCVM_OFFSET_GENERATOR", 1UL>()));
447 ASSERT_TRUE((bb::check_precomputed_generators<g1, "test generators", 2UL>()));
458 {{ 0x01624731e1195570, 0x3ba491482db4da14, 0x59e26bcea0d48bac, 0x0 },
"m=1"},
459 {{ 0x02c48e63c232aadf, 0x774922905b69b428, 0xb3c4d79d41a91758, 0x0 },
"m=2"},
460 {{ 0x0426d595a34c004e, 0xb2edb3d8891e8e3c, 0x0da7436be27da304, 0x1 },
"m=3"},
464 for (
const auto& tc : boundary_cases) {
465 fr base_scalar{ tc.limbs[0], tc.limbs[1], tc.limbs[2], tc.limbs[3] };
470 EXPECT_EQ(naive_result.
on_curve(),
true) << tc.tag;
471 EXPECT_EQ(endo_result.
on_curve(),
true) << tc.tag;
472 EXPECT_EQ(endo_result, naive_result) << tc.tag;
475 for (
size_t i = 0; i < 100; ++i) {
478 fr scalar = base_scalar +
fr(offset_int);
482 EXPECT_EQ(naive_res.
on_curve(),
true) << tc.tag <<
" offset " << i;
483 EXPECT_EQ(endo_res.
on_curve(),
true) << tc.tag <<
" offset " << i;
484 EXPECT_EQ(endo_res, naive_res) << tc.tag <<
" offset " << i;
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....
constexpr element dbl() const noexcept
constexpr void self_dbl() 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
group class. Represents an elliptic curve group element. Group is parametrised by Fq and Fr
group_elements::affine_element< Fq, Fr, Params > affine_element
static constexpr element one
static constexpr affine_element affine_one
group_elements::element< Fq, Fr, Params > element
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.
std::unique_ptr< uint8_t[]> buffer
Entry point for Barretenberg command-line interface.
field< Bn254FrParams > fr
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
static constexpr field one()
BB_INLINE constexpr field to_montgomery_form() const noexcept
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
BB_INLINE constexpr void self_to_montgomery_form() &noexcept
static constexpr field zero()