Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
field_conversion.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
7#pragma once
8
15#include "barretenberg/stdlib/primitives/bigfield/constants.hpp" // NUM_LIMB_BITS_IN_FIELD_SIMULATION
16
17namespace bb {
18
19class FrCodec {
20 public:
22 using fr = bb::fr;
26
27 // Size calculators
28 template <typename T> static constexpr size_t calc_num_fields()
29 {
31 return 1;
32 } else if constexpr (IsAnyOf<T, bb::fr, fq>) {
33 return T::Params::NUM_BN254_SCALARS;
34 } else if constexpr (IsAnyOf<T, bn254_point, grumpkin_point>) {
35 return 2 * calc_num_fields<typename T::Fq>();
36 } else {
37 // Array or Univariate
38 return calc_num_fields<typename T::value_type>() * (std::tuple_size<T>::value);
39 }
40 }
41
47 {
48 // expects 2 fr limbs; caller already asserts size
49 constexpr uint64_t NUM_LIMB_BITS = stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION; // 68
50 constexpr uint64_t TOTAL_BITS = 254;
51
52 BB_ASSERT_LT(uint256_t(fr_vec[0]),
53 (uint256_t(1) << (NUM_LIMB_BITS * 2)),
54 "Conversion error here usually implies some bad proof serde or parsing");
55 BB_ASSERT_LT(uint256_t(fr_vec[1]),
56 (uint256_t(1) << (TOTAL_BITS - NUM_LIMB_BITS * 2)),
57 "Conversion error here usually implies some bad proof serde or parsing");
58
59 const uint256_t value = uint256_t(fr_vec[0]) + (uint256_t(fr_vec[1]) << (NUM_LIMB_BITS * 2));
60
61 return fq(value);
62 }
63
68 {
69 constexpr uint64_t NUM_LIMB_BITS = stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION; // 68
70 constexpr uint64_t TOTAL_BITS = 254;
71
72 constexpr uint64_t LOWER_BITS = 2 * NUM_LIMB_BITS; // 136
73 constexpr uint256_t LOWER_MASK = (uint256_t(1) << LOWER_BITS) - 1;
74
75 const uint256_t value = uint256_t(val);
76 BB_ASSERT_LT(value, (uint256_t(1) << TOTAL_BITS));
77
79 out[0] = static_cast<uint256_t>(value & LOWER_MASK);
80 out[1] = static_cast<uint256_t>(value >> LOWER_BITS);
81
82 BB_ASSERT_LT(static_cast<uint256_t>(out[1]), (uint256_t(1) << (TOTAL_BITS - LOWER_BITS)));
83 return out;
84 }
85
86 // ---------------------------------------------------------------------
87 // Deserialize
88 // ---------------------------------------------------------------------
89 template <typename T> static T deserialize_from_fields(std::span<const fr> fr_vec)
90 {
91 BB_ASSERT_EQ(fr_vec.size(), calc_num_fields<T>());
92 if constexpr (IsAnyOf<T, bool>) {
93 return static_cast<bool>(fr_vec[0]);
94 } else if constexpr (IsAnyOf<T, uint32_t, uint64_t, bb::fr>) {
95 return static_cast<T>(fr_vec[0]);
96 } else if constexpr (IsAnyOf<T, fq>) {
98 } else if constexpr (IsAnyOf<T, bn254_point, grumpkin_point>) {
99 using BaseField = typename T::Fq;
100 constexpr size_t BASE = calc_num_fields<BaseField>();
101 T val;
102 val.x = deserialize_from_fields<BaseField>(fr_vec.subspan(0, BASE));
103 val.y = deserialize_from_fields<BaseField>(fr_vec.subspan(BASE, BASE));
104 if (val.x == BaseField::zero() && val.y == BaseField::zero()) {
105 val.self_set_infinity();
106 }
107 ASSERT(val.on_curve());
108 return val;
109 } else {
110 // Array or Univariate
111 T val;
112 constexpr size_t SZ = calc_num_fields<typename T::value_type>();
113 size_t i = 0;
114 for (auto& x : val) {
115 x = deserialize_from_fields<typename T::value_type>(fr_vec.subspan(SZ * i, SZ));
116 ++i;
117 }
118 return val;
119 }
120 }
121
125 template <typename T> static std::vector<fr> serialize_to_fields(const T& val)
126 {
128 return { val };
129 } else if constexpr (IsAnyOf<T, fq>) {
131 } else if constexpr (IsAnyOf<T, bn254_point, grumpkin_point>) {
132 using BaseField = typename T::Fq;
133 std::vector<bb::fr> fr_vec_x;
134 std::vector<bb::fr> fr_vec_y;
135 if (val.is_point_at_infinity()) {
136 fr_vec_x = serialize_to_fields(BaseField::zero());
137 fr_vec_y = serialize_to_fields(BaseField::zero());
138 } else {
139 fr_vec_x = serialize_to_fields(val.x);
140 fr_vec_y = serialize_to_fields(val.y);
141 }
142 std::vector<bb::fr> fr_vec(fr_vec_x.begin(), fr_vec_x.end());
143 fr_vec.insert(fr_vec.end(), fr_vec_y.begin(), fr_vec_y.end());
144 return fr_vec;
145 } else {
146 // Array or Univariate
147 std::vector<fr> out;
148 for (auto& x : val) {
149 auto tmp = serialize_to_fields(x);
150 out.insert(out.end(), tmp.begin(), tmp.end());
151 }
152 return out;
153 }
154 }
155
165 {
166 static constexpr size_t LO_BITS = bb::fr::Params::MAX_BITS_PER_ENDOMORPHISM_SCALAR; // 128
167 static constexpr size_t HI_BITS = bb::fr::modulus.get_msb() + 1 - LO_BITS; // 126
168
169 const uint256_t u = static_cast<uint256_t>(challenge);
170 const uint256_t lo = u.slice(0, LO_BITS);
171 const uint256_t hi = u.slice(LO_BITS, LO_BITS + HI_BITS);
172
173 return { bb::fr(lo), bb::fr(hi) };
174 }
175
179 template <typename T> static T convert_challenge(const bb::fr& challenge)
180 {
181 if constexpr (std::is_same_v<T, bb::fr>) {
182 return challenge;
183 } else if constexpr (std::is_same_v<T, fq>) {
184 BB_ASSERT_LT(static_cast<uint256_t>(challenge).get_msb(),
185 2 * stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION,
186 "field_conversion: convert challenge");
187 return fq(challenge);
188 }
189 }
190};
191
193 public:
195 using fr = bb::fr;
199
200 // Size calculators
201 template <typename T> static constexpr size_t calc_num_fields()
202 {
204 return 1;
205 } else if constexpr (IsAnyOf<T, bn254_point, grumpkin_point>) {
206 // In contrast to bb::fr, bn254 points can be represented by only 2 uint256_t elements
207 return 2;
208 } else {
209 // Array or Univariate
210 return calc_num_fields<typename T::value_type>() * (std::tuple_size<T>::value);
211 }
212 }
213
214 // ---------------------------------------------------------------------
215 // Deserialize
216 // ---------------------------------------------------------------------
217 template <typename T> static T deserialize_from_fields(std::span<const uint256_t> vec)
218 {
219 BB_ASSERT_EQ(vec.size(), calc_num_fields<T>());
220 if constexpr (IsAnyOf<T, bool>) {
221 return static_cast<bool>(vec[0]);
223 return static_cast<T>(vec[0]);
224 } else if constexpr (IsAnyOf<T, bn254_point, grumpkin_point>) {
225 using BaseField = typename T::Fq;
226 constexpr size_t N = calc_num_fields<BaseField>();
227 T val;
228 val.x = deserialize_from_fields<BaseField>(vec.subspan(0, N));
229 val.y = deserialize_from_fields<BaseField>(vec.subspan(N, N));
230 if (val.x == BaseField::zero() && val.y == BaseField::zero()) {
231 val.self_set_infinity();
232 }
233 ASSERT(val.on_curve());
234 return val;
235 } else {
236 // Array or Univariate
237 T val;
238 constexpr size_t SZ = calc_num_fields<typename T::value_type>();
239 size_t i = 0;
240 for (auto& x : val) {
241 x = deserialize_from_fields<typename T::value_type>(vec.subspan(SZ * i, SZ));
242 ++i;
243 }
244 return val;
245 }
246 }
247
251 template <typename T> static std::vector<uint256_t> serialize_to_fields(const T& val)
252 {
254 return { val };
255 } else if constexpr (IsAnyOf<T, bn254_point, grumpkin_point>) {
256 using BaseField = typename T::Fq;
257 std::vector<uint256_t> uint256_vec_x;
258 std::vector<uint256_t> uint256_vec_y;
259 // When encountering a point at infinity we pass a zero point in the proof to ensure that on the receiving
260 // size there are no inconsistencies whenre constructing and hashing.
261 if (val.is_point_at_infinity()) {
262 uint256_vec_x = serialize_to_fields(BaseField::zero());
263 uint256_vec_y = serialize_to_fields(BaseField::zero());
264 } else {
265 uint256_vec_x = serialize_to_fields<BaseField>(val.x);
266 uint256_vec_y = serialize_to_fields<BaseField>(val.y);
267 }
268 std::vector<uint256_t> uint256_vec(uint256_vec_x.begin(), uint256_vec_x.end());
269 uint256_vec.insert(uint256_vec.end(), uint256_vec_y.begin(), uint256_vec_y.end());
270 return uint256_vec;
271 } else {
272 // Array or Univariate
274 for (auto& e : val) {
275 auto tmp = serialize_to_fields(e);
276 out.insert(out.end(), tmp.begin(), tmp.end());
277 }
278 return out;
279 }
280 }
281
291 {
292 static constexpr size_t LO_BITS = bb::fr::Params::MAX_BITS_PER_ENDOMORPHISM_SCALAR; // 128
293 static constexpr size_t HI_BITS = bb::fr::modulus.get_msb() + 1 - LO_BITS; // 126
294
295 const uint256_t u = static_cast<uint256_t>(challenge);
296 const uint256_t lo = u.slice(0, LO_BITS);
297 const uint256_t hi = u.slice(LO_BITS, LO_BITS + HI_BITS);
298
299 return { uint256_t(lo), uint256_t(hi) };
300 }
301
305 template <typename T> static T convert_challenge(const bb::fr& challenge)
306 {
307 if constexpr (std::is_same_v<T, bb::fr>) {
308 return challenge;
309 } else if constexpr (std::is_same_v<T, fq>) {
310 BB_ASSERT_LT(static_cast<uint256_t>(challenge).get_msb(),
311 2 * stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION,
312 "field_conversion: convert challenge");
313 return fq(challenge);
314 }
315 }
316};
317
318} // namespace bb
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:88
#define BB_ASSERT_LT(left, right,...)
Definition assert.hpp:148
#define ASSERT(expression,...)
Definition assert.hpp:77
grumpkin::fr fq
static std::vector< fr > serialize_to_fields(const T &val)
Conversion from transcript values to bb::frs.
static std::array< bb::fr, 2 > split_challenge(const bb::fr &challenge)
Split a challenge field element into two half-width challenges.
static T convert_challenge(const bb::fr &challenge)
Convert an fr challenge to a target type (fr or fq). Assumes challenge is "short".
static fq convert_grumpkin_fr_from_bn254_frs(std::span< const bb::fr > fr_vec)
Converts 2 bb::fr elements to fq.
static std::vector< bb::fr > convert_grumpkin_fr_to_bn254_frs(const fq &val)
Converts fq to 2 bb::fr elements (inverse of the above).
curve::Grumpkin::AffineElement grumpkin_point
curve::BN254::AffineElement bn254_point
static T deserialize_from_fields(std::span< const fr > fr_vec)
static constexpr size_t calc_num_fields()
static constexpr size_t calc_num_fields()
curve::Grumpkin::AffineElement grumpkin_point
static std::array< uint256_t, 2 > split_challenge(const uint256_t &challenge)
Split a challenge field element into two half-width challenges.
static T convert_challenge(const bb::fr &challenge)
Convert an fr challenge to a target type (fr or fq). Assumes challenge is "short".
static std::vector< uint256_t > serialize_to_fields(const T &val)
Conversion from transcript values to uint256_ts.
static T deserialize_from_fields(std::span< const uint256_t > vec)
curve::BN254::AffineElement bn254_point
typename Group::affine_element AffineElement
Definition bn254.hpp:22
typename Group::affine_element AffineElement
Definition grumpkin.hpp:56
constexpr uint256_t slice(uint64_t start, uint64_t end) const
constexpr uint64_t get_msb() const
constexpr T get_msb(const T in)
Definition get_msb.hpp:47
Entry point for Barretenberg command-line interface.
field< Bn254FrParams > fr
Definition fr.hpp:174
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static constexpr uint256_t modulus