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 <gtest/gtest.h>
4
5using namespace bb;
6
7namespace {
8// Double-and-add scalar mul without endomorphism, used as reference for differential testing.
9template <typename Group, typename Fr>
10typename Group::affine_element naive_scalar_mul(const typename Group::element& base, const Fr& scalar)
11{
12 typename Group::element acc = Group::point_at_infinity;
13 typename Group::element runner = base;
14 uint256_t bits(scalar);
15 for (size_t i = 0; i < 256; ++i) {
16 if (bits.get_bit(i)) {
17 acc = acc + runner;
18 }
19 runner = runner.dbl();
20 }
21 return typename Group::affine_element(acc);
22}
23} // namespace
24
25// =========================
26// Parameter-related tests
27// =========================
28
29TEST(grumpkin, CheckB)
30{
32 fr seventeen = 17;
33 EXPECT_EQ(seventeen, -b);
34}
35
36TEST(grumpkin, SubgroupGenerator)
37{
40
41 EXPECT_NE(subgroup_generator.pow(3), fq::one());
42 EXPECT_NE(subgroup_generator.pow(29), fq::one());
43 EXPECT_EQ(subgroup_generator.pow(87), fq::one());
44 EXPECT_EQ(subgroup_generator * subgroup_generator_inverse, fq::one());
45}
46
47TEST(grumpkin, OneYIsCorrect)
48{
50 auto [_, expected] = (bb::grumpkin::G1Params::b + fr::one()).sqrt();
51
52 EXPECT_EQ(one_y, -expected);
53}
54
55// =========================
56// Group-related tests
57// =========================
58
59// Checks for "bad points" in terms of sharing a y-coordinate as explained here:
60// https://github.com/AztecProtocol/aztec2-internal/issues/437
61TEST(grumpkin, BadPoints)
62{
64 auto beta_sqr = beta * beta;
65 bool res = true;
66 grumpkin::fr c(1);
67 for (size_t i = 0; i < 256; i++) {
68 auto val = c / (grumpkin::fr(1) + c);
69 if (val == beta || val == beta_sqr) {
70 res = false;
71 }
72 c *= grumpkin::fr(4);
73 }
74 EXPECT_TRUE(res);
75}
76
77TEST(grumpkin, CheckPrecomputedGenerators)
78{
79 ASSERT_TRUE((bb::check_precomputed_generators<grumpkin::g1, "pedersen_hash_length", 1UL>()));
80 ASSERT_TRUE((bb::check_precomputed_generators<grumpkin::g1, "DEFAULT_DOMAIN_SEPARATOR", 8UL>()));
81}
82
83// Regression: boundary scalars k = ceil(m * 2^256 / endo_g2) (from endomorphism_scalars.py)
84// previously triggered the negative-k2 bug in split_into_endomorphism_scalars, producing wrong
85// scalar multiplication results. We test boundaries and random samples within each band.
86TEST(grumpkin, ScalarMulNegativeK2Regression)
87{
88 // clang-format off
89 struct test_case { std::array<uint64_t, 4> limbs; const char* tag; };
90 const std::array<test_case, 3> boundary_cases = {{
91 {{ 0x71922da036dca5f4, 0xd970a56127fb8227, 0x59e26bcea0d48bac, 0x0 }, "m=1"},
92 {{ 0xe3245b406db94be8, 0xb2e14ac24ff7044e, 0xb3c4d79d41a91759, 0x0 }, "m=2"},
93 {{ 0x54b688e0a495f1dc, 0x8c51f02377f28676, 0x0da7436be27da306, 0x1 }, "m=3"},
94 }};
95 // clang-format on
96
97 for (const auto& tc : boundary_cases) {
98 grumpkin::fr base_scalar{ tc.limbs[0], tc.limbs[1], tc.limbs[2], tc.limbs[3] };
99 base_scalar.self_to_montgomery_form();
100
101 grumpkin::g1::affine_element endo_result(grumpkin::g1::one * base_scalar);
102 grumpkin::g1::affine_element naive_result =
103 naive_scalar_mul<grumpkin::g1, grumpkin::fr>(grumpkin::g1::one, base_scalar);
104 EXPECT_EQ(naive_result.on_curve(), true) << tc.tag;
105 EXPECT_EQ(endo_result.on_curve(), true) << tc.tag;
106 EXPECT_EQ(endo_result, naive_result) << tc.tag;
107
108 // Random samples within the formerly-buggy band (~2^123-2^126 wide; 122-bit offsets).
109 for (size_t i = 0; i < 100; ++i) {
111 uint256_t offset_int = (rand_bits & ((uint256_t(1) << 122) - 1)) + 1;
112 grumpkin::fr scalar = base_scalar + grumpkin::fr(offset_int);
113
116 naive_scalar_mul<grumpkin::g1, grumpkin::fr>(grumpkin::g1::one, scalar);
117 EXPECT_EQ(naive_res.on_curve(), true) << tc.tag << " offset " << i;
118 EXPECT_EQ(endo_res.on_curve(), true) << tc.tag << " offset " << i;
119 EXPECT_EQ(endo_res, naive_res) << tc.tag << " offset " << i;
120 }
121 }
122}
static constexpr ScalarField subgroup_generator_inverse
Definition grumpkin.hpp:79
static constexpr ScalarField subgroup_generator
Definition grumpkin.hpp:77
constexpr bool on_curve() const noexcept
static constexpr element one
Definition group.hpp:48
static constexpr Fq curve_b
Definition group.hpp:53
FF b
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()
BB_INLINE constexpr field pow(const uint256_t &exponent) const noexcept
static field random_element(numeric::RNG *engine=nullptr) noexcept
BB_INLINE constexpr void self_to_montgomery_form() &noexcept
static constexpr bb::fr one_y
Definition grumpkin.hpp:41
static constexpr bb::fr b
Definition grumpkin.hpp:30