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;
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
67 static std::vector<bb::fr> convert_grumpkin_fr_to_bn254_frs(const fq& val)
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
78 std::vector<bb::fr> out(2);
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>) {
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 BB_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>) {
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 TOTAL_BITS = bb::fr::modulus.get_msb() + 1; // 254
167 static constexpr size_t LO_BITS = TOTAL_BITS / 2; // 127
168 static constexpr size_t HI_BITS = TOTAL_BITS - LO_BITS; // 127
169
170 const uint256_t u = static_cast<uint256_t>(challenge);
171 const uint256_t lo = u.slice(0, LO_BITS);
172 const uint256_t hi = u.slice(LO_BITS, LO_BITS + HI_BITS);
173
174 return { bb::fr(lo), bb::fr(hi) };
175 }
176
180 template <typename T> static T convert_challenge(const bb::fr& challenge)
181 {
182 if constexpr (std::is_same_v<T, bb::fr>) {
183 return challenge;
184 } else if constexpr (std::is_same_v<T, fq>) {
185 BB_ASSERT_LT(static_cast<uint256_t>(challenge).get_msb(),
186 2 * stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION,
187 "field_conversion: convert challenge");
188 return fq(challenge);
189 }
190 }
191};
192
194 public:
196 using fr = bb::fr;
200
201 // Size calculators
202 template <typename T> static constexpr size_t calc_num_fields()
203 {
205 return 1;
207 // In contrast to bb::fr, bn254 points can be represented by only 2 uint256_t elements
208 return 2;
209 } else {
210 // Array or Univariate
211 return calc_num_fields<typename T::value_type>() * (std::tuple_size<T>::value);
212 }
213 }
214
215 // ---------------------------------------------------------------------
216 // Deserialize
217 // ---------------------------------------------------------------------
218 template <typename T> static T deserialize_from_fields(std::span<const uint256_t> vec)
219 {
220 BB_ASSERT_EQ(vec.size(), calc_num_fields<T>());
221 if constexpr (IsAnyOf<T, bool>) {
222 return static_cast<bool>(vec[0]);
224 return static_cast<T>(vec[0]);
226 using BaseField = typename T::Fq;
227 constexpr size_t N = calc_num_fields<BaseField>();
228 T val;
229 val.x = deserialize_from_fields<BaseField>(vec.subspan(0, N));
230 val.y = deserialize_from_fields<BaseField>(vec.subspan(N, N));
231 if (val.x == BaseField::zero() && val.y == BaseField::zero()) {
232 val.self_set_infinity();
233 }
234 BB_ASSERT(val.on_curve());
235 return val;
236 } else {
237 // Array or Univariate
238 T val;
239 constexpr size_t SZ = calc_num_fields<typename T::value_type>();
240 size_t i = 0;
241 for (auto& x : val) {
242 x = deserialize_from_fields<typename T::value_type>(vec.subspan(SZ * i, SZ));
243 ++i;
244 }
245 return val;
246 }
247 }
248
252 template <typename T> static std::vector<uint256_t> serialize_to_fields(const T& val)
253 {
255 return { val };
257 using BaseField = typename T::Fq;
258 std::vector<uint256_t> uint256_vec_x;
259 std::vector<uint256_t> uint256_vec_y;
260 // When encountering a point at infinity we pass a zero point in the proof to ensure that on the receiving
261 // size there are no inconsistencies whenre constructing and hashing.
262 if (val.is_point_at_infinity()) {
263 uint256_vec_x = serialize_to_fields(BaseField::zero());
264 uint256_vec_y = serialize_to_fields(BaseField::zero());
265 } else {
266 uint256_vec_x = serialize_to_fields<BaseField>(val.x);
267 uint256_vec_y = serialize_to_fields<BaseField>(val.y);
268 }
269 std::vector<uint256_t> uint256_vec(uint256_vec_x.begin(), uint256_vec_x.end());
270 uint256_vec.insert(uint256_vec.end(), uint256_vec_y.begin(), uint256_vec_y.end());
271 return uint256_vec;
272 } else {
273 // Array or Univariate
275 for (auto& e : val) {
276 auto tmp = serialize_to_fields(e);
277 out.insert(out.end(), tmp.begin(), tmp.end());
278 }
279 return out;
280 }
281 }
282
292 {
293 static constexpr size_t TOTAL_BITS = bb::fr::modulus.get_msb() + 1; // 254
294 static constexpr size_t LO_BITS = TOTAL_BITS / 2; // 127
295 static constexpr size_t HI_BITS = TOTAL_BITS - LO_BITS; // 127
296
297 const uint256_t u = static_cast<uint256_t>(challenge);
298 const uint256_t lo = u.slice(0, LO_BITS);
299 const uint256_t hi = u.slice(LO_BITS, LO_BITS + HI_BITS);
300
301 return { uint256_t(lo), uint256_t(hi) };
302 }
303
307 template <typename T> static T convert_challenge(const bb::fr& challenge)
308 {
309 if constexpr (std::is_same_v<T, bb::fr>) {
310 return challenge;
311 } else if constexpr (std::is_same_v<T, fq>) {
312 BB_ASSERT_LT(static_cast<uint256_t>(challenge).get_msb(),
313 2 * stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION,
314 "field_conversion: convert challenge");
315 return fq(challenge);
316 }
317 }
318};
319
320} // namespace bb
#define BB_ASSERT(expression,...)
Definition assert.hpp:67
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:77
#define BB_ASSERT_LT(left, right,...)
Definition assert.hpp:137
curve::BN254::AffineElement bn254_commitment
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 equal-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).
static T deserialize_from_fields(std::span< const fr > fr_vec)
curve::Grumpkin::AffineElement grumpkin_commitment
static constexpr size_t calc_num_fields()
curve::BN254::AffineElement bn254_commitment
curve::Grumpkin::AffineElement grumpkin_commitment
static constexpr size_t calc_num_fields()
static std::array< uint256_t, 2 > split_challenge(const uint256_t &challenge)
Split a challenge field element into two equal-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)
typename Group::affine_element AffineElement
Definition bn254.hpp:22
typename Group::affine_element AffineElement
Definition grumpkin.hpp:63
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.
Definition api.hpp:5
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