Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
constants.test.cpp
Go to the documentation of this file.
1
8#include "fq.hpp"
9#include "fr.hpp"
10#include <array>
11#include <gtest/gtest.h>
12
13using namespace bb;
14namespace {
15uint256_t native_q{
17};
18uint256_t native_r{
20};
21
22// Helper to convert a decimal string to uint256_t
23uint256_t from_decimal(const std::string& dec_str)
24{
25 uint256_t result = 0;
26 for (char c : dec_str) {
27 result = result * 10 + static_cast<uint64_t>(c - '0');
28 }
29 return result;
30}
31} // namespace
32
33TEST(FqConstants, Modulus)
34{
35 // BN254 base field prime: q = 21888242871839275222246405745257275088696311157297823662689037894645226208583
36 // References:
37 // [eip-196](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-196.md)
38 // [ark-works](https://docs.rs/ark-bn254/latest/ark_bn254/)
39 // [BN-254 for the rest of us](https://hackmd.io/@jpw/bn254)
40 uint256_t expected_q =
41 from_decimal("21888242871839275222246405745257275088696311157297823662689037894645226208583");
42 EXPECT_EQ(expected_q, native_q);
43}
44
45TEST(FqConstants, RSquared)
46{
47 // R^2 = (2^256)^2 mod q.
48 uint512_t R = (uint512_t(1) << 256) % native_q;
49 uint512_t expected_r_sqr_mod_q = (R * R) % native_q;
50 uint256_t actual_r_sqr_mod_q{
52 };
53 EXPECT_EQ(expected_r_sqr_mod_q.lo, actual_r_sqr_mod_q);
54}
55
56TEST(FqConstants, RInv)
57{
58 // r_inv = -q^{-1} mod 2^64
59 uint512_t r{ 0, 1 };
60 uint512_t q{ -native_q, 0 };
61 uint256_t q_inv = q.invmod(r).lo;
62 uint64_t expected = q_inv.data[0];
63 uint64_t result = Bn254FqParams::r_inv;
64 EXPECT_EQ(result, expected);
65}
66
67// multiplication generator for Fq
68// AUDITTODO: delete (misnamed, no longer used -- finds smallest quadratic non-residue.)
69TEST(FqConstants, MultiplicativeGenerator)
70{
71 EXPECT_EQ(fq::multiplicative_generator(), fq(3));
72}
73
74TEST(FqConstants, CubeRootOfUnity)
75{
76 // beta is be g^(2(q-1)/3) where g is the multiplicative generator
77 // AUDITTODO: if I kill multiplicative_generator, this part of test should be killed.
79 uint256_t exponent = uint256_t(2) * (native_q - 1) / 3;
80 fq expected_beta = g.pow(exponent);
81
83 EXPECT_EQ(beta, expected_beta);
84
85 // Verify beta^3 = 1 and beta != 1
86 EXPECT_EQ(beta * beta * beta, fq::one());
87 EXPECT_NE(beta, fq::one());
88}
89
90// ================================
91// WASM Consistency Tests
92// ================================
93
94TEST(FqConstants, WasmModulusConsistency)
95{
96 // WASM uses 9 x 29-bit limbs to represent the modulus
97 // Verify that the 29-bit limb representation reconstructs to the same value as the 4 x 64-bit limb representation
98 constexpr std::array<uint64_t, 9> wasm_limbs = { Bn254FqParams::modulus_wasm_0, Bn254FqParams::modulus_wasm_1,
103
104 uint512_t wasm_modulus = 0;
105 for (size_t i = 0; i < 9; i++) {
106 wasm_modulus += uint512_t(wasm_limbs[i]) << (29UL * i);
107 // Verify each limb fits in 29 bits
108 EXPECT_LT(wasm_limbs[i], uint64_t(1) << 29);
109 }
110
111 EXPECT_EQ(wasm_modulus.lo, native_q);
112 EXPECT_EQ(wasm_modulus.hi, uint256_t(0));
113}
114
115TEST(FqConstants, WasmRSquared)
116{
117 // WASM uses R = 2^261 (since 261 = 29 * 9)
118 // r_squared_wasm should be (2^261)^2 mod q = 2^522 mod q
119 uint512_t R_wasm = uint512_t(1) << 261;
120 uint512_t R_wasm_mod_q = R_wasm % native_q;
121 uint512_t expected_r_squared_wasm = (R_wasm_mod_q * R_wasm_mod_q) % native_q;
122
123 uint256_t actual_r_squared_wasm{ Bn254FqParams::r_squared_wasm_0,
127
128 EXPECT_EQ(expected_r_squared_wasm.lo, actual_r_squared_wasm);
129}
130
131TEST(FqConstants, WasmCubeRootConsistency)
132{
133 // The cube root in WASM Montgomery form should represent the same field element
134 // as the cube root in native Montgomery form.
135 //
136 // Native Montgomery form: cube_root_native = beta * R_native mod q, where R_native = 2^256
137 // WASM Montgomery form: cube_root_wasm = beta * R_wasm mod q, where R_wasm = 2^261
138 //
139 // Therefore: cube_root_wasm = cube_root_native * (R_wasm / R_native) mod q
140 // = cube_root_native * 2^5 mod q
141
142 uint256_t cube_root_native{
144 };
145
150
151 // R_wasm / R_native = 2^261 / 2^256 = 2^5 = 32
152 uint512_t expected_cube_root_wasm = (uint512_t(cube_root_native) * 32) % native_q;
153
154 EXPECT_EQ(expected_cube_root_wasm.lo, cube_root_wasm);
155}
156
157// ================================
158// Fr Constants Tests
159// ================================
160
161TEST(FrConstants, Modulus)
162{
163 // BN254 scalar field prime (also the Baby Jubjub base field):
164 // r = 21888242871839275222246405745257275088548364400416034343698204186575808495617
165 // References:
166 // [eip-196](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-196.md)
167 // [ark-works](https://docs.rs/ark-bn254/latest/ark_bn254/)
168 // [BN-254 for the rest of us](https://hackmd.io/@jpw/bn254)
169 uint256_t expected_r =
170 from_decimal("21888242871839275222246405745257275088548364400416034343698204186575808495617");
171 EXPECT_EQ(expected_r, native_r);
172}
173
174TEST(FrConstants, RSquared)
175{
176 // R^2 = (2^256)^2 mod r.
177 uint512_t R = (uint512_t(1) << 256) % native_r;
178 uint512_t expected_r_sqr_mod_r = (R * R) % native_r;
179 uint256_t actual_r_sqr_mod_r{
181 };
182 EXPECT_EQ(expected_r_sqr_mod_r.lo, actual_r_sqr_mod_r);
183}
184
185TEST(FrConstants, RInv)
186{
187 // r_inv = -r^{-1} mod 2^64
188 uint512_t two_64{ 0, 1 };
189 uint512_t neg_r{ -native_r, 0 };
190 uint256_t r_inv = neg_r.invmod(two_64).lo;
191 uint64_t expected = r_inv.data[0];
192 uint64_t result = Bn254FrParams::r_inv;
193 EXPECT_EQ(result, expected);
194}
195
196TEST(FrConstants, MultiplicativeGenerator)
197{
198 EXPECT_EQ(fr::multiplicative_generator(), fr(5));
199}
200
201TEST(FrConstants, CubeRootOfUnity)
202{
203 // beta is be g^((r-1)/3) where g is the multiplicative generator
205 uint256_t exponent = (native_r - 1) / 3;
206 fr expected_beta = g.pow(exponent);
207
208 fr beta = fr::cube_root_of_unity();
209 EXPECT_EQ(beta, expected_beta);
210
211 // Verify beta^3 = 1 and beta != 1
212 EXPECT_EQ(beta * beta * beta, fr::one());
213 EXPECT_NE(beta, fr::one());
214}
215
216// ================================
217// Fr WASM Consistency Tests
218// ================================
219
220TEST(FrConstants, WasmModulusConsistency)
221{
222 // WASM uses 9 x 29-bit limbs to represent the modulus
223 constexpr std::array<uint64_t, 9> wasm_limbs = { Bn254FrParams::modulus_wasm_0, Bn254FrParams::modulus_wasm_1,
228
229 uint512_t wasm_modulus = 0;
230 for (size_t i = 0; i < 9; i++) {
231 wasm_modulus += uint512_t(wasm_limbs[i]) << (29UL * i);
232 EXPECT_LT(wasm_limbs[i], uint64_t(1) << 29);
233 }
234
235 EXPECT_EQ(wasm_modulus.lo, native_r);
236 EXPECT_EQ(wasm_modulus.hi, uint256_t(0));
237}
238
239TEST(FrConstants, WasmRSquared)
240{
241 // WASM uses R = 2^261 (since 261 = 29 * 9)
242 uint512_t R_wasm = uint512_t(1) << 261;
243 uint512_t R_wasm_mod_r = R_wasm % native_r;
244 uint512_t expected_r_squared_wasm = (R_wasm_mod_r * R_wasm_mod_r) % native_r;
245
246 uint256_t actual_r_squared_wasm{ Bn254FrParams::r_squared_wasm_0,
250
251 EXPECT_EQ(expected_r_squared_wasm.lo, actual_r_squared_wasm);
252}
253
254TEST(FrConstants, WasmCubeRootConsistency)
255{
256 // The cube root in WASM Montgomery form should represent the same field element
257 // as the cube root in native Montgomery form.
258 uint256_t cube_root_native{
260 };
261
266
267 // R_wasm / R_native = 2^261 / 2^256 = 2^5 = 32
268 uint512_t expected_cube_root_wasm = (uint512_t(cube_root_native) * 32) % native_r;
269
270 EXPECT_EQ(expected_cube_root_wasm.lo, cube_root_wasm);
271}
static constexpr uint64_t cube_root_wasm_1
Definition fq.hpp:64
static constexpr uint64_t modulus_0
Definition fq.hpp:24
static constexpr uint64_t modulus_wasm_0
Definition fq.hpp:44
static constexpr uint64_t modulus_wasm_5
Definition fq.hpp:49
static constexpr uint64_t modulus_wasm_4
Definition fq.hpp:48
static constexpr uint64_t r_squared_3
Definition fq.hpp:34
static constexpr uint64_t r_squared_2
Definition fq.hpp:33
static constexpr uint64_t cube_root_wasm_3
Definition fq.hpp:66
static constexpr uint64_t modulus_wasm_7
Definition fq.hpp:51
static constexpr uint64_t modulus_wasm_1
Definition fq.hpp:45
static constexpr uint64_t modulus_3
Definition fq.hpp:27
static constexpr uint64_t r_squared_wasm_0
Definition fq.hpp:56
static constexpr uint64_t modulus_1
Definition fq.hpp:25
static constexpr uint64_t cube_root_wasm_0
Definition fq.hpp:63
static constexpr uint64_t r_squared_0
Definition fq.hpp:31
static constexpr uint64_t cube_root_wasm_2
Definition fq.hpp:65
static constexpr uint64_t modulus_2
Definition fq.hpp:26
static constexpr uint64_t modulus_wasm_8
Definition fq.hpp:52
static constexpr uint64_t r_squared_1
Definition fq.hpp:32
static constexpr uint64_t modulus_wasm_2
Definition fq.hpp:46
static constexpr uint64_t r_squared_wasm_1
Definition fq.hpp:57
static constexpr uint64_t cube_root_1
Definition fq.hpp:38
static constexpr uint64_t cube_root_0
Definition fq.hpp:37
static constexpr uint64_t r_squared_wasm_3
Definition fq.hpp:59
static constexpr uint64_t cube_root_2
Definition fq.hpp:39
static constexpr uint64_t r_squared_wasm_2
Definition fq.hpp:58
static constexpr uint64_t cube_root_3
Definition fq.hpp:40
static constexpr uint64_t modulus_wasm_6
Definition fq.hpp:50
static constexpr uint64_t modulus_wasm_3
Definition fq.hpp:47
static constexpr uint64_t r_inv
Definition fq.hpp:96
static constexpr uint64_t modulus_wasm_8
Definition fr.hpp:121
static constexpr uint64_t r_inv
Definition fr.hpp:68
static constexpr uint64_t modulus_wasm_3
Definition fr.hpp:116
static constexpr uint64_t modulus_wasm_4
Definition fr.hpp:117
static constexpr uint64_t cube_root_wasm_0
Definition fr.hpp:132
static constexpr uint64_t cube_root_wasm_3
Definition fr.hpp:135
static constexpr uint64_t r_squared_wasm_3
Definition fr.hpp:128
static constexpr uint64_t r_squared_3
Definition fr.hpp:37
static constexpr uint64_t modulus_0
Definition fr.hpp:28
static constexpr uint64_t r_squared_1
Definition fr.hpp:35
static constexpr uint64_t cube_root_3
Definition fr.hpp:43
static constexpr uint64_t modulus_wasm_6
Definition fr.hpp:119
static constexpr uint64_t modulus_wasm_0
Definition fr.hpp:113
static constexpr uint64_t cube_root_1
Definition fr.hpp:41
static constexpr uint64_t r_squared_wasm_1
Definition fr.hpp:126
static constexpr uint64_t r_squared_0
Definition fr.hpp:34
static constexpr uint64_t r_squared_2
Definition fr.hpp:36
static constexpr uint64_t cube_root_0
Definition fr.hpp:40
static constexpr uint64_t modulus_3
Definition fr.hpp:31
static constexpr uint64_t cube_root_wasm_1
Definition fr.hpp:133
static constexpr uint64_t modulus_wasm_5
Definition fr.hpp:118
static constexpr uint64_t modulus_wasm_2
Definition fr.hpp:115
static constexpr uint64_t modulus_wasm_1
Definition fr.hpp:114
static constexpr uint64_t cube_root_2
Definition fr.hpp:42
static constexpr uint64_t r_squared_wasm_0
Definition fr.hpp:125
static constexpr uint64_t r_squared_wasm_2
Definition fr.hpp:127
static constexpr uint64_t modulus_wasm_7
Definition fr.hpp:120
static constexpr uint64_t modulus_2
Definition fr.hpp:30
static constexpr uint64_t cube_root_wasm_2
Definition fr.hpp:134
static constexpr uint64_t modulus_1
Definition fr.hpp:29
uintx< uint256_t > uint512_t
Definition uintx.hpp:307
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
field< Bn254FqParams > fq
Definition fq.hpp:169
field< Bn254FrParams > fr
Definition fr.hpp:174
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
static constexpr field cube_root_of_unity()
static constexpr field one()
static constexpr field multiplicative_generator() noexcept