Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
field_conversion.test.cpp
Go to the documentation of this file.
4#include <gtest/gtest.h>
5
7
8class FieldConversionTest : public ::testing::Test {
9 public:
10 template <typename T> void check_conversion(T x)
11 {
12 size_t len = FrCodec::calc_num_fields<T>();
13 auto frs = FrCodec::serialize_to_fields(x);
14 EXPECT_EQ(len, frs.size());
15 auto y = FrCodec::deserialize_from_fields<T>(frs);
16 EXPECT_EQ(x, y);
17 }
18};
19
23TEST_F(FieldConversionTest, FieldConversionUint32)
24{
25 auto x = static_cast<uint32_t>(1) << 31;
26 check_conversion(x);
27}
28
32TEST_F(FieldConversionTest, FieldConversionFr)
33{
34 bb::fr x1(std::string("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789")); // 256 bits
35 check_conversion(x1);
36
37 bb::fr x2(bb::fr::modulus_minus_two); // modulus - 2
38 check_conversion(x2);
39}
40
45TEST_F(FieldConversionTest, FieldConversionGrumpkinFr)
46{
47 grumpkin::fr x1(std::string("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789")); // 256 bits
48 check_conversion(x1);
49}
50
51namespace {
52bb::fq derive_bn254_y(bb::fq x)
53{
54 auto [found, y] = (x.sqr() * x + Bn254G1Params::b).sqrt();
55 EXPECT_TRUE(found);
56 return y;
57}
58} // namespace
59
64TEST_F(FieldConversionTest, FieldConversionBN254AffineElement)
65{
66 curve::BN254::AffineElement x1(1, derive_bn254_y(1));
67 check_conversion(x1);
68
70 check_conversion(x2);
71}
72
73namespace {
74bb::grumpkin::fq derive_grumpkin_y(bb::grumpkin::fq x)
75{
76 auto [found, y] = (x.sqr() * x + grumpkin::G1Params::b + x * grumpkin::G1Params::a).sqrt();
77 EXPECT_TRUE(found);
78 return y;
79}
80} // namespace
81
85TEST_F(FieldConversionTest, FieldConversionGrumpkinAffineElement)
86{
87 curve::Grumpkin::AffineElement x1(1, derive_grumpkin_y(1));
88 check_conversion(x1);
89
91 check_conversion(x2);
92}
93
98TEST_F(FieldConversionTest, FieldConversionArrayBn254Fr)
99{
100 std::array<bb::fr, 4> x1{ 1, 2, 3, 4 };
101 check_conversion(x1);
102
105 215215125,
106 102701750,
107 367032,
108 12985028,
109 bb::fr::modulus_minus_two - 125015028 };
110 check_conversion(x2);
111}
112
117TEST_F(FieldConversionTest, FieldConversionArrayGrumpkinFr)
118{
119 std::array<grumpkin::fr, 4> x1{ 1, 2, 3, 4 };
120 check_conversion(x1);
121
124 215215125,
125 102701750,
126 367032,
127 12985028,
129 check_conversion(x2);
130}
131
136TEST_F(FieldConversionTest, FieldConversionUnivariateBn254Fr)
137{
138 std::array<bb::fr, 4> x1_arr{ 1, 2, 3, 4 };
139 bb::Univariate<bb::fr, 4> x1{ x1_arr };
140 check_conversion(x1);
141}
142
147TEST_F(FieldConversionTest, FieldConversionUnivariateGrumpkinFr)
148{
149 std::array<grumpkin::fr, 4> x1_arr{ 1, 2, 3, 4 };
151 check_conversion(x1);
152}
153
158TEST_F(FieldConversionTest, ConvertChallengeGrumpkinFr)
159{
160 uint256_t chal_raw(std::string("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789")); // 256 bits
161 bb::fr chal(chal_raw.slice(0, 136));
162 auto result = FrCodec::convert_challenge<grumpkin::fr>(chal);
163 auto expected = uint256_t(chal);
164 EXPECT_EQ(uint256_t(result), expected);
165}
166
167// ============================================================================
168// Additional FrCodec-specific tests
169// Note: Most rejection/acceptance tests are in stdlib/primitives/field/field_conversion.test.cpp
170// which tests both FrCodec and StdlibCodec together for consistency.
171// ============================================================================
172
177TEST_F(FieldConversionTest, AcceptCanonicalPointAtInfinity)
178{
179 // Test for BN254 points
180 {
181 std::vector<bb::fr> fr_vec = { bb::fr(0), bb::fr(0), bb::fr(0), bb::fr(0) };
182 auto point = FrCodec::deserialize_from_fields<curve::BN254::AffineElement>(fr_vec);
183 EXPECT_TRUE(point.is_point_at_infinity());
184 }
185
186 // Test for Grumpkin points
187 {
188 std::vector<bb::fr> fr_vec = { bb::fr(0), bb::fr(0) };
189 auto point = FrCodec::deserialize_from_fields<curve::Grumpkin::AffineElement>(fr_vec);
190 EXPECT_TRUE(point.is_point_at_infinity());
191 }
192}
193
199#ifndef __wasm__
200TEST_F(FieldConversionTest, RejectNonCanonicalFieldElements)
201{
202 using BN254Point = curve::BN254::AffineElement;
203 using GrumpkinPoint = curve::Grumpkin::AffineElement;
206
207 // BN254: Reject x-coordinate >= modulus
208 {
209 std::vector<bb::fr> vec = { bb::fr(fq::modulus.data[0]), bb::fr(fq::modulus.data[1]), bb::fr(0), bb::fr(0) };
210 EXPECT_THROW_OR_ABORT(FrCodec::deserialize_from_fields<BN254Point>(vec), "canonical");
211 }
212
213 // BN254: Reject y-coordinate >= modulus
214 {
215 std::vector<bb::fr> vec = { bb::fr(0), bb::fr(0), bb::fr(fq::modulus.data[0]), bb::fr(fq::modulus.data[1]) };
216 EXPECT_THROW_OR_ABORT(FrCodec::deserialize_from_fields<BN254Point>(vec), "canonical");
217 }
218
219 // BN254: Reject both coordinates >= modulus
220 {
221 std::vector<bb::fr> vec = { bb::fr(fq::modulus.data[0]),
224 bb::fr(fq::modulus.data[1]) };
225 EXPECT_THROW_OR_ABORT(FrCodec::deserialize_from_fields<BN254Point>(vec), "canonical");
226 }
227
228 // Grumpkin: Reject coordinate >= modulus (uses 2-limb encoding: 136-bit + 118-bit)
229 {
230 constexpr uint64_t LIMB_BITS = 68;
231 uint256_t gq_lo = gq::modulus & ((uint256_t(1) << (LIMB_BITS * 2)) - 1);
232 uint256_t gq_hi = gq::modulus >> (LIMB_BITS * 2);
233 std::vector<bb::fr> vec = { bb::fr(gq_lo), bb::fr(gq_hi) };
234 EXPECT_THROW_OR_ABORT(FrCodec::deserialize_from_fields<GrumpkinPoint>(vec), "canonical");
235 }
236
237 // Grumpkin: Reject limb overflow (lower limb must be < 2^136)
238 {
239 constexpr uint64_t LIMB_BITS = 68;
240 std::vector<bb::fr> vec = { bb::fr(uint256_t(1) << (LIMB_BITS * 2)), bb::fr(0) };
241 EXPECT_THROW_OR_ABORT(FrCodec::deserialize_from_fields<GrumpkinPoint>(vec), "Conversion error");
242 }
243
244 // Grumpkin: Reject limb overflow (upper limb must be < 2^118)
245 {
246 constexpr uint64_t LIMB_BITS = 68;
247 std::vector<bb::fr> vec = { bb::fr(0), bb::fr(uint256_t(1) << (254 - LIMB_BITS * 2)) };
248 EXPECT_THROW_OR_ABORT(FrCodec::deserialize_from_fields<GrumpkinPoint>(vec), "Conversion error");
249 }
250}
251#endif
252
257#ifndef __wasm__
258TEST_F(FieldConversionTest, RejectPointNotOnCurve)
259{
260 // Test for BN254: (1, 4) is not on the curve
261 {
262 std::vector<bb::fr> fr_vec = { bb::fr(1), bb::fr(0), bb::fr(4), bb::fr(0) };
263 EXPECT_THROW_OR_ABORT(FrCodec::deserialize_from_fields<curve::BN254::AffineElement>(fr_vec), "on_curve");
264 }
265
266 // Test for Grumpkin: (12, 100) is not on the curve
267 {
268 std::vector<bb::fr> fr_vec = { bb::fr(12), bb::fr(100) };
269 EXPECT_THROW_OR_ABORT(FrCodec::deserialize_from_fields<curve::Grumpkin::AffineElement>(fr_vec), "on_curve");
270 }
271}
272#endif
273
274} // namespace bb::field_conversion_tests
#define EXPECT_THROW_OR_ABORT(statement, matcher)
Definition assert.hpp:192
static std::vector< fr > serialize_to_fields(const T &val)
Conversion from transcript values to bb::frs.
A univariate polynomial represented by its values on {0, 1,..., domain_end - 1}.
bb::fq BaseField
Definition bn254.hpp:19
typename Group::affine_element AffineElement
Definition bn254.hpp:22
typename Group::affine_element AffineElement
Definition grumpkin.hpp:65
constexpr uint256_t slice(uint64_t start, uint64_t end) const
const std::vector< MemoryValue > data
TEST_F(FieldConversionTest, FieldConversionUint32)
Field conversion test for uint32_t.
field< Bn254FrParams > fr
Definition fr.hpp:155
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
uint8_t len
static constexpr fq b
Definition g1.hpp:31
static constexpr uint256_t modulus
BB_INLINE constexpr field sqr() const noexcept
static constexpr uint256_t modulus_minus_two
static constexpr bb::fr b
Definition grumpkin.hpp:31
static constexpr bb::fr a
Definition grumpkin.hpp:33