Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
fr.test.cpp
Go to the documentation of this file.
1
10#include "fr.hpp"
12#include <gtest/gtest.h>
13
14using namespace bb;
15
16namespace {
18} // namespace
19
20// ================================
21// Fixed Compile-Time Tests (field-specific expected values)
22// These tests use hardcoded expected values that are only valid for native builds (R = 2^256).
23// WASM uses R = 2^261.
24// ================================
25
26#if defined(__SIZEOF_INT128__) && !defined(__wasm__)
27TEST(BN254Fr, CompileTimeMultiplication)
28{
29 constexpr fr a{ 0x20565a572c565a66, 0x7bccd0f01f5f7bff, 0x63ec2beaad64711f, 0x624953caaf44a814 };
30 constexpr fr b{ 0xa17307a2108adeea, 0x74629976c14c5e2b, 0x9ce6f072ab1740ee, 0x398c753702b2bef0 };
31 constexpr fr expected{ 0xe8cdd06343386834, 0x8cbb3f556258a9af, 0x5aef2f34f2d66fd4, 0x2d8263c7e10213ca };
32
33 constexpr fr result = a * b;
34 static_assert(result == expected);
35}
36
37TEST(BN254Fr, CompileTimeSquaring)
38{
39 constexpr fr a{ 0x20565a572c565a66, 0x7bccd0f01f5f7bff, 0x63ec2beaad64711f, 0x624953caaf44a814 };
40 constexpr fr expected{ 0x3e928bdb06267b99, 0x1e5834571f52dfbf, 0x3d63bdf9bf7d0d4b, 0x353bb31adaa033c7 };
41
42 constexpr fr result = a.sqr();
43 static_assert(result == expected);
44}
45
46TEST(BN254Fr, CompileTimeAddition)
47{
48 constexpr fr a{ 0x20565a572c565a66, 0x7bccd0f01f5f7bff, 0x63ec2beaad64711f, 0x624953caaf44a814 };
49 constexpr fr b{ 0xa17307a2108adeea, 0x74629976c14c5e2b, 0x9ce6f072ab1740ee, 0x398c753702b2bef0 };
50 constexpr fr expected{ 0x3a0576d15ce1394e, 0x9fc799d5ed38f908, 0x903290f055790153, 0x3b0d2c1bef9426b1 };
51
52 constexpr fr result = a + b;
53 static_assert(result == expected);
54}
55
56TEST(BN254Fr, CompileTimeSubtraction)
57{
58 constexpr fr a{ 0xcfbcfcf457cf2d38, 0x7b27af26ce62aa61, 0xf0378e90d48f2b92, 0x4734b22cb21ded };
59 constexpr fr b{ 0x569fdb1db5198770, 0x446ddccef8347d52, 0xef215227182d22a, 0x8281b4fb109306 };
60 constexpr fr expected{ 0xe10cfe82b5a5ca, 0x8721a2e8c9a10e32, 0x51e604db660f0a22, 0x608d4fe2f404cb3b };
61
62 constexpr fr result = a - b;
63 static_assert(result == expected);
64}
65#endif
66
67TEST(BN254Fr, CompileTimeInversion)
68{
69 constexpr fr a{ 0x20565a572c565a66, 0x7bccd0f01f5f7bff, 0x63ec2beaad64711f, 0x624953caaf44a814 };
70 constexpr fr inv = a.invert();
71 // Verify a * a^-1 = 1
72 static_assert(a * inv == fr::one());
73}
74
75// ================================
76// BN254 Scalar Field Specific
77// ================================
78
79TEST(BN254Fr, SplitIntoEndomorphismScalars)
80{
82 fr k1 = { 0, 0, 0, 0 };
83 fr k2 = { 0, 0, 0, 0 };
84
86
87 fr result{ 0, 0, 0, 0 };
88
91
92 EXPECT_LT(uint256_t(k1).get_msb(), 128);
93 EXPECT_LT(uint256_t(k2).get_msb(), 128);
94
95 fr lambda = fr::cube_root_of_unity();
96 result = k2 * lambda;
97 result = k1 - result;
98
100 EXPECT_EQ(result, k);
101}
102
103TEST(BN254Fr, SplitIntoEndomorphismScalarsSimple)
104{
105 fr input = { 1, 0, 0, 0 };
106 fr k = { 0, 0, 0, 0 };
107 fr k1 = { 0, 0, 0, 0 };
108 fr k2 = { 0, 0, 0, 0 };
109 fr::__copy(input, k);
110
112 fr result{ 0, 0, 0, 0 };
115
116 EXPECT_LT(uint256_t(k1).get_msb(), 128);
117 EXPECT_LT(uint256_t(k2).get_msb(), 128);
118
119 fr lambda = fr::cube_root_of_unity();
120 result = k2 * lambda;
121 result = k1 - result;
122
124 for (size_t i = 0; i < 4; ++i) {
125 EXPECT_EQ(result.data[i], k.data[i]);
126 }
127}
128
129// Regression: k = ceil(m * 2^256 / endo_g2), for m an integer, previously produced negative k2 in the GLV
130// splitting, causing 128-bit truncation to extract wrong values.
131TEST(BN254Fr, SplitEndomorphismNegativeK2)
132{
133 // clang-format off
134 struct test_case { std::array<uint64_t, 4> limbs; const char* tag; };
135 const std::array<test_case, 3> cases = {{
136 {{ 0x01624731e1195570, 0x3ba491482db4da14, 0x59e26bcea0d48bac, 0x0 }, "m=1"},
137 {{ 0x02c48e63c232aadf, 0x774922905b69b428, 0xb3c4d79d41a91758, 0x0 }, "m=2"},
138 {{ 0x0426d595a34c004e, 0xb2edb3d8891e8e3c, 0x0da7436be27da304, 0x1 }, "m=3"},
139 }};
140 // clang-format on
141
142 fr lambda = fr::cube_root_of_unity();
143
144 for (const auto& tc : cases) {
145 fr k{ tc.limbs[0], tc.limbs[1], tc.limbs[2], tc.limbs[3] };
146 fr k1{ 0, 0, 0, 0 };
147 fr k2{ 0, 0, 0, 0 };
148
150
151 k1.self_to_montgomery_form();
152 k2.self_to_montgomery_form();
153 fr result = k1 - k2 * lambda;
155
156 EXPECT_EQ(result, k) << tc.tag;
157 }
158}
159
160// ================================
161// Regression / Optimization Tests
162// ================================
163
164// Tests that (lo + 2^256 * hi) mod r == ((lo|hi) % r) in uint512_t
165// This validates the optimization of avoiding slow uint512_t modulo
166TEST(BN254Fr, EquivalentRandomness)
167{
168 uint512_t random_uint512 = engine.get_random_uint512();
169 auto random_lo = fr(random_uint512.lo);
170 auto random_hi = fr(random_uint512.hi);
172 constexpr auto pow_2_256 = fr(uint256_t(1) << 128).sqr();
173 EXPECT_EQ(random_lo + pow_2_256 * random_hi, fr((random_uint512 % r).lo));
174}
uint512_t get_random_uint512()
Definition engine.hpp:38
FF a
FF b
numeric::RNG & engine
constexpr T get_msb(const T in)
Definition get_msb.hpp:49
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
Definition engine.cpp:217
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
field< Bn254FrParams > fr
Definition fr.hpp:155
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static constexpr field cube_root_of_unity()
BB_INLINE constexpr void self_to_montgomery_form_reduced() &noexcept
static constexpr field one()
static constexpr uint256_t modulus
BB_INLINE constexpr void self_from_montgomery_form_reduced() &noexcept
static void split_into_endomorphism_scalars(const field &k, field &k1, field &k2)
Full-width endomorphism decomposition: k ≡ k1 - k2·λ (mod r). Modifies the field elements k1 and k2.
constexpr field invert() 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_from_montgomery_form() &noexcept
BB_INLINE constexpr void self_to_montgomery_form() &noexcept