Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
field.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#include "../circuit_builders/circuit_builders_fwd.hpp"
9#include "../witness/witness.hpp"
12#include <functional>
13
14namespace bb::stdlib {
15// Base case: only one pointer
16template <typename T> T* validate_context(T* ptr)
17{
18 return ptr;
19}
20
21// Variadic version: compare first with the rest
22template <typename T, typename... Ts> T* validate_context(T* first, Ts*... rest)
23{
24 T* tail = validate_context(rest...);
25 if (!first) {
26 return tail; // first is null, rely on tail
27 }
28 if (!tail) {
29 return first; // tail is null, use first
30 }
31 ASSERT(first == tail && "Pointers refer to different builder objects!");
32 return first;
33}
34
35template <typename T, typename Container> T* validate_context(const Container& elements)
36{
37 T* result = nullptr;
38 for (const auto& element : elements) {
39 result = validate_context<T>(result, element.get_context());
40 }
41 return result;
42}
43
44template <typename Builder> class bool_t;
45template <typename Builder_> class field_t {
46 public:
47 using Builder = Builder_;
48
49 static constexpr size_t PUBLIC_INPUTS_SIZE = FR_PUBLIC_INPUTS_SIZE;
50
51 mutable Builder* context = nullptr;
52
90
132 mutable uint32_t witness_index = IS_CONSTANT;
133
134 mutable OriginTag tag{};
135
136 field_t(Builder* parent_context = nullptr);
137 field_t(Builder* parent_context, const bb::fr& value);
138
139 field_t(const int value)
140 : context(nullptr)
142 , multiplicative_constant(bb::fr::one())
143 , witness_index(IS_CONSTANT)
144 {}
145
146 // NOLINTNEXTLINE(google-runtime-int) intended behavior
147 field_t(const unsigned long long value)
148 : context(nullptr)
150 , multiplicative_constant(bb::fr::one())
151 , witness_index(IS_CONSTANT)
152 {}
153
154 field_t(const unsigned int value)
155 : context(nullptr)
157 , multiplicative_constant(bb::fr::one())
158 , witness_index(IS_CONSTANT)
159
160 {}
161
162 // NOLINTNEXTLINE(google-runtime-int) intended behavior
163 field_t(const unsigned long value)
164 : context(nullptr)
166 , multiplicative_constant(bb::fr::one())
167 , witness_index(IS_CONSTANT)
168 {}
169
170 // Construct a constant circuit element from a native field element
172 : context(nullptr)
174 , multiplicative_constant(bb::fr::one())
175 , witness_index(IS_CONSTANT)
176 {}
177
178 // Construct a constant circuit element from a uint256t, that is implicitly converted to a native field element
180 : context(nullptr)
182 , multiplicative_constant(bb::fr::one())
183 , witness_index(IS_CONSTANT)
184 {}
185
187
188 // field_t copy constructor
189 field_t(const field_t& other)
190 : context(other.context)
194 , tag(other.tag)
195 {}
196
197 // field_t move constructor
198 field_t(field_t&& other) noexcept
199 : context(other.context)
200 , additive_constant(other.additive_constant)
201 , multiplicative_constant(other.multiplicative_constant)
202 , witness_index(other.witness_index)
203 , tag(other.tag)
204 {}
205
206 // Copy constructor from a bool_t
207 field_t(const bool_t<Builder>& other);
208
209 ~field_t() = default;
210
211 static constexpr bool is_composite = false;
213
214 static field_t from_witness_index(Builder* ctx, uint32_t witness_index);
215
216 explicit operator bool_t<Builder>() const;
217
218 field_t& operator=(const field_t& other)
219 {
220 if (this == &other) {
221 return *this;
222 }
226 context = other.context;
227 tag = other.tag;
228 return *this;
229 }
230
231 field_t& operator=(field_t&& other) noexcept
232 {
233 additive_constant = other.additive_constant;
234 multiplicative_constant = other.multiplicative_constant;
235 witness_index = other.witness_index;
236 context = other.context;
237 tag = other.tag;
238 return *this;
239 }
240
242 {
243 auto result = field_t<Builder>(witness_t<Builder>(&context, other.get_value()));
244 result.assert_equal(other, "field_t::copy_as_new_witness, assert_equal");
245 result.tag = other.tag;
246 return result;
247 }
248
249 field_t operator+(const field_t& other) const;
250 field_t operator-(const field_t& other) const;
251 field_t operator*(const field_t& other) const;
252 field_t operator/(const field_t& other) const;
253 bool_t<Builder> operator==(const field_t& other) const;
254 bool_t<Builder> operator!=(const field_t& other) const;
255
256 field_t divide_no_zero_check(const field_t& other) const;
257
258 field_t sqr() const { return operator*(*this); }
259
260 field_t pow(const uint32_t& exponent) const;
261 // N.B. we implicitly range-constrain 'exponent' to be a 32-bit integer!
262 field_t pow(const field_t& exponent) const;
263
265 {
266 *this = *this + other;
267 return *this;
268 }
270 {
271 *this = *this - other;
272 return *this;
273 }
275 {
276 *this = *this * other;
277 return *this;
278 }
280 {
281 *this = *this / other;
282 return *this;
283 }
284
285 // Prefix increment (++x)
287 {
288 *this = *this + 1;
289 return *this;
290 };
291
292 // Postfix increment (x++)
293 // NOLINTNEXTLINE
295 {
296 field_t this_before_operation = field_t(*this);
297 *this = *this + 1;
298 return this_before_operation;
299 };
300
305 {
306 // Since the numerator is a constant 1, the constraint
307 // (this.v * this.mul + this.add) * inverse.v == 1;
308 // created by applying `assert_is_not_zero` to `*this` coincides with the constraint created by
309 // `divide_no_zero_check`, hence we can safely apply the latter instead of `/` operator.
310 auto* ctx = get_context();
311 if (is_constant()) {
312 ASSERT(!get_value().is_zero(), "field_t::invert denominator is constant 0");
313 }
314
315 if (get_value().is_zero() && !ctx->failed()) {
316 ctx->failure("field_t::invert denominator is 0");
317 }
318
319 return field_t(fr::one()).divide_no_zero_check(*this);
320 }
321
323 {
324 field_t result(*this);
326 if (!is_constant()) {
328 }
329 return result;
330 }
331
332 void set_origin_tag(const OriginTag& new_tag) const { tag = new_tag; }
333 OriginTag get_origin_tag() const { return tag; };
334
339
344
345 field_t conditional_negate(const bool_t<Builder>& predicate) const;
346
347 void assert_equal(const field_t& rhs, std::string const& msg = "field_t::assert_equal") const;
348
349 void assert_not_equal(const field_t& rhs, std::string const& msg = "field_t::assert_not_equal") const;
350
351 void assert_is_in_set(const std::vector<field_t>& set, std::string const& msg = "field_t::assert_not_in_set") const;
352
353 static field_t conditional_assign(const bool_t<Builder>& predicate, const field_t& lhs, const field_t& rhs);
354
356 const field_t& T1,
357 const field_t& T2,
358 const field_t& T3);
360 const bool_t<Builder>& t1,
361 const bool_t<Builder>& t0);
362
364 const field_t& T1,
365 const field_t& T2,
366 const field_t& T3,
367 const field_t& T4,
368 const field_t& T5,
369 const field_t& T6,
370 const field_t& T7);
372 const bool_t<Builder>& t2,
373 const bool_t<Builder>& t1,
374 const bool_t<Builder>& t0);
375
376 static void evaluate_linear_identity(const field_t& a, const field_t& b, const field_t& c, const field_t& d);
377 static void evaluate_polynomial_identity(const field_t& a, const field_t& b, const field_t& c, const field_t& d);
378
379 static field_t accumulate(const std::vector<field_t>& input);
380
381 field_t madd(const field_t& to_mul, const field_t& to_add) const;
382
383 field_t add_two(const field_t& add_b, const field_t& add_c) const;
384
385 [[nodiscard]] field_t normalize() const;
386
387 bb::fr get_value() const;
388
389 Builder* get_context() const { return context; }
390
392 const size_t lsb_index, const size_t num_bits = grumpkin::MAX_NO_WRAP_INTEGER_BIT_LENGTH) const;
393
394 bool_t<Builder> is_zero() const;
395
396 void create_range_constraint(size_t num_bits, std::string const& msg = "field_t::range_constraint") const;
397 void assert_is_not_zero(std::string const& msg = "field_t::assert_is_not_zero") const;
398 void assert_is_zero(std::string const& msg = "field_t::assert_is_zero") const;
399 bool is_constant() const { return witness_index == IS_CONSTANT; }
400 bool is_normalized() const
401 {
403 };
404 uint32_t set_public() const
405 {
407 return context->set_public_input(get_normalized_witness_index());
408 }
409
423
424 static field_t from_witness(Builder* ctx, const bb::fr& input)
425 {
426 auto result = field_t(witness_t<Builder>(ctx, input));
427 result.set_free_witness_tag();
428 return result;
429 }
430
432 {
433 return limbs[0];
434 }
435
442 {
445 // Let a := *this;
446 // q_l := 1
447 // q_c := -*this.get_value()
448 // Create an aritmetic gate constraining
449 // a.v * q_l - q_c = 0
450 context->fix_witness(witness_index, get_value());
452 }
453
461 uint32_t get_witness_index() const { return witness_index; }
462
472
479 template <size_t num_bits> bool_t<Builder> ranged_less_than(const field_t<Builder>& other) const
480 {
481
482 const auto& a = (*this);
483 const auto& b = other;
484 auto* ctx = validate_context(a.context, b.context);
485 if (a.is_constant() && b.is_constant()) {
486 return uint256_t(a.get_value()) < uint256_t(b.get_value());
487 }
488
489 // Let q = (a < b)
490 // Assume both a and b are < K where K = 2^{num_bits}
491 // q == 1 <=> 0 < b - a - 1 < K
492 // q == 0 <=> 0 < b - a + K - 1 < K
493 // i.e. for any bool value of q:
494 // (b - a - 1) * q + (b - a + K - 1) * (1 - q) = r < K
495 // q * (b - a - b + a) + b - a + K - 1 - (K - 1) * q - q = r < K
496 // b - a + (K - 1) - K * q = r < K
497
498 static constexpr uint256_t range_constant = (uint256_t(1) << num_bits);
499 // Since in the worst case scenario
500 // r = K - 1 + (K - 1) = 2 * K - 2,
501 // to ensure that it never wraps around the field modulus, we impose that it's smaller than half the modulus
502 static_assert(range_constant < bb::fr::modulus >> 1,
503 "ranged_less_than: 2^num_bits must be less than half the field modulus.");
504
505 bool predicate_witness = uint256_t(a.get_value()) < uint256_t(b.get_value());
506 bool_t<Builder> predicate(witness_t<Builder>(ctx, predicate_witness));
507 field_t predicate_valid = b.add_two(-(a) + range_constant - 1, -field_t(predicate) * range_constant);
508 predicate_valid.create_range_constraint(num_bits);
509 return predicate;
510 }
511
512 // Aliases used in Relations' `accumulate` methods
513 using View = field_t;
515
516 // Alias used in `biggroup` and `CycleGroup`
517 using native = bb::fr;
518};
519
520template <typename Builder> inline std::ostream& operator<<(std::ostream& os, field_t<Builder> const& v)
521{
522 return os << v.get_value();
523}
524} // namespace bb::stdlib
#define ASSERT(expression,...)
Definition assert.hpp:49
Implements boolean logic in-circuit.
Definition bool.hpp:59
void assert_is_zero(std::string const &msg="field_t::assert_is_zero") const
Enforce a copy constraint between *this and 0 stored at zero_idx of the Builder.
Definition field.cpp:676
static field_t reconstruct_from_public(const std::span< const field_t, PUBLIC_INPUTS_SIZE > &limbs)
Definition field.hpp:431
field_t conditional_negate(const bool_t< Builder > &predicate) const
If predicate's value == true, negate the value, else keep it unchanged.
Definition field.cpp:858
Builder_ Builder
Definition field.hpp:47
void assert_is_in_set(const std::vector< field_t > &set, std::string const &msg="field_t::assert_not_in_set") const
Constrain *this \in set by enforcing that P(X) = \prod_{s \in set} (X - s) is 0 at X = *this.
Definition field.cpp:974
uint32_t set_public() const
Definition field.hpp:404
field_t & operator=(const field_t &other)
Definition field.hpp:218
void assert_equal(const field_t &rhs, std::string const &msg="field_t::assert_equal") const
Copy constraint: constrain that *this field is equal to rhs element.
Definition field.cpp:929
void assert_not_equal(const field_t &rhs, std::string const &msg="field_t::assert_not_equal") const
Constrain *this to be not equal to rhs.
Definition field.cpp:964
field_t(const int value)
Definition field.hpp:139
bool is_normalized() const
Definition field.hpp:400
field_t operator*=(const field_t &other)
Definition field.hpp:274
field_t madd(const field_t &to_mul, const field_t &to_add) const
Definition field.cpp:507
static field_t from_witness_index(Builder *ctx, uint32_t witness_index)
Definition field.cpp:59
field_t operator+(const field_t &other) const
Field addition operator.
Definition field.cpp:121
bool_t< Builder > operator!=(const field_t &other) const
Compute a bool_t equal to (a != b)
Definition field.cpp:849
bb::fr additive_constant
Definition field.hpp:88
static field_t select_from_three_bit_table(const std::array< field_t, 8 > &table, const bool_t< Builder > &t2, const bool_t< Builder > &t1, const bool_t< Builder > &t0)
Given a multilinear polynomial in 3 variables, which is represented by a table of monomial coefficien...
Definition field.cpp:1058
field_t(const bb::fr &value)
Definition field.hpp:171
static field_t accumulate(const std::vector< field_t > &input)
Efficiently compute the sum of vector entries. Using big_add_gate we reduce the number of gates neede...
Definition field.cpp:1147
field_t invert() const
Definition field.hpp:304
static void evaluate_polynomial_identity(const field_t &a, const field_t &b, const field_t &c, const field_t &d)
Given a, b, c, d, constrain a * b + c + d = 0 by creating a big_mul_gate.
Definition field.cpp:1107
field_t operator-() const
Definition field.hpp:322
void create_range_constraint(size_t num_bits, std::string const &msg="field_t::range_constraint") const
Let x = *this.normalize(), constrain x.v < 2^{num_bits}.
Definition field.cpp:908
static field_t conditional_assign(const bool_t< Builder > &predicate, const field_t &lhs, const field_t &rhs)
If predicate == true then return lhs, else return rhs.
Definition field.cpp:884
field_t(const unsigned long value)
Definition field.hpp:163
field_t divide_no_zero_check(const field_t &other) const
Given field elements a = *this and b = other, output a / b without checking whether b = 0.
Definition field.cpp:309
Builder * context
Definition field.hpp:51
static std::array< field_t, 8 > preprocess_three_bit_table(const field_t &T0, const field_t &T1, const field_t &T2, const field_t &T3, const field_t &T4, const field_t &T5, const field_t &T6, const field_t &T7)
Given a table T of size 8, outputs the monomial coefficients of the multilinear polynomial in t0,...
Definition field.cpp:1010
bb::fr multiplicative_constant
Definition field.hpp:89
void unset_free_witness_tag() const
Unset the free witness flag for the field element's tag.
Definition field.hpp:343
static field_t copy_as_new_witness(Builder &context, field_t const &other)
Definition field.hpp:241
Builder * get_context() const
Definition field.hpp:389
field_t sqr() const
Definition field.hpp:258
field_t(field_t &&other) noexcept
Definition field.hpp:198
std::pair< field_t< Builder >, field_t< Builder > > split_at(const size_t lsb_index, const size_t num_bits=grumpkin::MAX_NO_WRAP_INTEGER_BIT_LENGTH) const
Splits the field element into (lo, hi), where:
Definition field.cpp:1268
static constexpr bool is_composite
Definition field.hpp:211
OriginTag get_origin_tag() const
Definition field.hpp:333
field_t operator-=(const field_t &other)
Definition field.hpp:269
bb::fr get_value() const
Given a := *this, compute its value given by a.v * a.mul + a.add.
Definition field.cpp:827
field_t operator*(const field_t &other) const
Field multiplication operator.
Definition field.cpp:189
field_t normalize() const
Return a new element, where the in-circuit witness contains the actual represented value (multiplicat...
Definition field.cpp:635
static field_t select_from_two_bit_table(const std::array< field_t, 4 > &table, const bool_t< Builder > &t1, const bool_t< Builder > &t0)
Given a multilinear polynomial in 2 variables, which is represented by a table of monomial coefficien...
Definition field.cpp:1036
static constexpr uint256_t modulus
Definition field.hpp:212
static void evaluate_linear_identity(const field_t &a, const field_t &b, const field_t &c, const field_t &d)
Constrain a + b + c + d to be equal to 0.
Definition field.cpp:1077
static field_t from_witness(Builder *ctx, const bb::fr &input)
Definition field.hpp:424
bool_t< Builder > is_zero() const
Validate whether a field_t element is zero.
Definition field.cpp:774
field_t pow(const uint32_t &exponent) const
Raise this field element to the power of the provided uint32_t exponent.
Definition field.cpp:419
field_t(const field_t &other)
Definition field.hpp:189
static constexpr size_t PUBLIC_INPUTS_SIZE
Definition field.hpp:49
void convert_constant_to_fixed_witness(Builder *ctx)
Definition field.hpp:414
bool is_constant() const
Definition field.hpp:399
static std::array< field_t, 4 > preprocess_two_bit_table(const field_t &T0, const field_t &T1, const field_t &T2, const field_t &T3)
Given a table T of size 4, outputs the monomial coefficients of the multilinear polynomial in t0,...
Definition field.cpp:992
uint32_t get_normalized_witness_index() const
Get the index of a normalized version of this element.
Definition field.hpp:471
field_t operator+=(const field_t &other)
Definition field.hpp:264
field_t & operator=(field_t &&other) noexcept
Definition field.hpp:231
field_t(const unsigned int value)
Definition field.hpp:154
field_t(const uint256_t &value)
Definition field.hpp:179
field_t operator++(const int)
Definition field.hpp:294
void set_free_witness_tag()
Set the free witness flag for the field element's tag.
Definition field.hpp:338
void set_origin_tag(const OriginTag &new_tag) const
Definition field.hpp:332
uint32_t witness_index
Definition field.hpp:132
field_t add_two(const field_t &add_b, const field_t &add_c) const
Efficiently compute (this + a + b) using big_mul gate.
Definition field.cpp:572
field_t & operator++()
Definition field.hpp:286
field_t(const unsigned long long value)
Definition field.hpp:147
void assert_is_not_zero(std::string const &msg="field_t::assert_is_not_zero") const
Constrain *this to be non-zero by establishing that it has an inverse.
Definition field.cpp:707
field_t operator/(const field_t &other) const
Since in divide_no_zero_check, we check by the constraint , if , we can set to any value and it wil...
Definition field.cpp:299
field_t operator/=(const field_t &other)
Definition field.hpp:279
bool_t< Builder > operator==(const field_t &other) const
Compute a bool_t equal to (a == b)
Definition field.cpp:841
uint32_t get_witness_index() const
Get the witness index of the current field element.
Definition field.hpp:461
bool_t< Builder > ranged_less_than(const field_t< Builder > &other) const
Return (a < b) as bool circuit type. This method assumes that both a and b are < 2^{num_bits} i....
Definition field.hpp:479
FF a
FF b
constexpr size_t MAX_NO_WRAP_INTEGER_BIT_LENGTH
Definition grumpkin.hpp:15
std::ostream & operator<<(std::ostream &os, uint256_t const &a)
Definition uint256.hpp:246
T * validate_context(T *ptr)
Definition field.hpp:16
std::conditional_t< IsGoblinBigGroup< C, Fq, Fr, G >, element_goblin::goblin_element< C, goblin_field< C >, Fr, G >, element_default::element< C, Fq, Fr, G > > element
element wraps either element_default::element or element_goblin::goblin_element depending on parametr...
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
This file contains part of the logic for the Origin Tag mechanism that tracks the use of in-circuit p...
void unset_free_witness()
void set_free_witness()
static constexpr field one()
static constexpr uint256_t modulus
BB_INLINE constexpr void self_neg() &noexcept
static constexpr field zero()