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 BB_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 // Friend declarations for classes that need direct witness_index access
52 template <typename B> friend class bool_t;
53 template <typename B, typename T> friend class bigfield;
54 template <typename B> friend void mark_witness_as_used(const field_t<B>& field);
55
56 mutable Builder* context = nullptr;
57
95
96 private:
144 mutable uint32_t witness_index = IS_CONSTANT;
145
146 public:
147 mutable OriginTag tag{};
148
149 field_t(Builder* parent_context = nullptr);
150 field_t(Builder* parent_context, const bb::fr& value);
151
152 field_t(const int value)
153 : context(nullptr)
155 , multiplicative_constant(bb::fr::one())
156 , witness_index(IS_CONSTANT)
157 {}
158
159 // NOLINTNEXTLINE(google-runtime-int) intended behavior
160 field_t(const unsigned long long value)
161 : context(nullptr)
163 , multiplicative_constant(bb::fr::one())
164 , witness_index(IS_CONSTANT)
165 {}
166
167 field_t(const unsigned int value)
168 : context(nullptr)
170 , multiplicative_constant(bb::fr::one())
171 , witness_index(IS_CONSTANT)
172
173 {}
174
175 // NOLINTNEXTLINE(google-runtime-int) intended behavior
176 field_t(const unsigned long value)
177 : context(nullptr)
179 , multiplicative_constant(bb::fr::one())
180 , witness_index(IS_CONSTANT)
181 {}
182
183 // Construct a constant circuit element from a native field element
185 : context(nullptr)
187 , multiplicative_constant(bb::fr::one())
188 , witness_index(IS_CONSTANT)
189 {}
190
191 // Construct a constant circuit element from a uint256t, that is implicitly converted to a native field element
193 : context(nullptr)
195 , multiplicative_constant(bb::fr::one())
196 , witness_index(IS_CONSTANT)
197 {}
198
200
201 // field_t copy constructor
202 field_t(const field_t& other)
203 : context(other.context)
207 , tag(other.tag)
208 {}
209
210 // field_t move constructor
211 field_t(field_t&& other) noexcept
212 : context(other.context)
213 , additive_constant(other.additive_constant)
214 , multiplicative_constant(other.multiplicative_constant)
215 , witness_index(other.witness_index)
216 , tag(other.tag)
217 {}
218
219 // Copy constructor from a bool_t
220 field_t(const bool_t<Builder>& other);
221
222 ~field_t() = default;
223
224 static constexpr bool is_composite = false;
226
227 static field_t from_witness_index(Builder* ctx, uint32_t witness_index);
228
229 explicit operator bool_t<Builder>() const;
230
231 field_t& operator=(const field_t& other)
232 {
233 if (this == &other) {
234 return *this;
235 }
239 context = other.context;
240 tag = other.tag;
241 return *this;
242 }
243
244 field_t& operator=(field_t&& other) noexcept
245 {
246 additive_constant = other.additive_constant;
247 multiplicative_constant = other.multiplicative_constant;
248 witness_index = other.witness_index;
249 context = other.context;
250 tag = other.tag;
251 return *this;
252 }
253
255 {
256 auto result = field_t<Builder>(witness_t<Builder>(&context, other.get_value()));
257 result.assert_equal(other, "field_t::copy_as_new_witness, assert_equal");
258 result.tag = other.tag;
259 return result;
260 }
261
262 field_t operator+(const field_t& other) const;
263 field_t operator-(const field_t& other) const;
264 field_t operator*(const field_t& other) const;
265 field_t operator/(const field_t& other) const;
266 bool_t<Builder> operator==(const field_t& other) const;
267 bool_t<Builder> operator!=(const field_t& other) const;
268
269 field_t divide_no_zero_check(const field_t& other) const;
270
271 field_t sqr() const { return operator*(*this); }
272
273 field_t pow(const uint32_t& exponent) const;
274 // N.B. we implicitly range-constrain 'exponent' to be a 32-bit integer!
275 field_t pow(const field_t& exponent) const;
276
278 {
279 *this = *this + other;
280 return *this;
281 }
283 {
284 *this = *this - other;
285 return *this;
286 }
288 {
289 *this = *this * other;
290 return *this;
291 }
293 {
294 *this = *this / other;
295 return *this;
296 }
297
298 // Prefix increment (++x)
300 {
301 *this = *this + 1;
302 return *this;
303 };
304
305 // Postfix increment (x++)
306 // NOLINTNEXTLINE
308 {
309 field_t this_before_operation = field_t(*this);
310 *this = *this + 1;
311 return this_before_operation;
312 };
313
318 {
319 // Since the numerator is a constant 1, the constraint
320 // (this.v * this.mul + this.add) * inverse.v == 1;
321 // created by applying `assert_is_not_zero` to `*this` coincides with the constraint created by
322 // `divide_no_zero_check`, hence we can safely apply the latter instead of `/` operator.
323 auto* ctx = get_context();
324 if (is_constant()) {
325 BB_ASSERT(!get_value().is_zero(), "field_t::invert denominator is constant 0");
326 }
327
328 if (get_value().is_zero() && !ctx->failed()) {
329 ctx->failure("field_t::invert denominator is 0");
330 }
331
332 return field_t(fr::one()).divide_no_zero_check(*this);
333 }
334
336 {
337 field_t result(*this);
339 if (!is_constant()) {
341 }
342 return result;
343 }
344
345 void set_origin_tag(const OriginTag& new_tag) const { tag = new_tag; }
346 OriginTag get_origin_tag() const { return tag; };
347
352
357
359
360 field_t conditional_negate(const bool_t<Builder>& predicate) const;
361
362 void assert_equal(const field_t& rhs, std::string const& msg = "field_t::assert_equal") const;
363
364 void assert_not_equal(const field_t& rhs, std::string const& msg = "field_t::assert_not_equal") const;
365
366 void assert_is_in_set(const std::vector<field_t>& set, std::string const& msg = "field_t::assert_not_in_set") const;
367
369 const field_t& lhs,
370 const field_t& rhs);
371
372 static field_t conditional_assign(const bool_t<Builder>& predicate, const field_t& lhs, const field_t& rhs)
373 {
374 return conditional_assign_internal(predicate, lhs, rhs).normalize();
375 }
376
378 const field_t& T1,
379 const field_t& T2,
380 const field_t& T3);
382 const bool_t<Builder>& t1,
383 const bool_t<Builder>& t0);
384
386 const field_t& T1,
387 const field_t& T2,
388 const field_t& T3,
389 const field_t& T4,
390 const field_t& T5,
391 const field_t& T6,
392 const field_t& T7);
394 const bool_t<Builder>& t2,
395 const bool_t<Builder>& t1,
396 const bool_t<Builder>& t0);
397
398 static void evaluate_linear_identity(const field_t& a,
399 const field_t& b,
400 const field_t& c,
401 const field_t& d,
402 const std::string& msg = "field_t::evaluate_linear_identity");
403 static void evaluate_polynomial_identity(const field_t& a,
404 const field_t& b,
405 const field_t& c,
406 const field_t& d,
407 const std::string& msg = "field_t::evaluate_polynomial_identity");
408
409 static field_t accumulate(const std::vector<field_t>& input);
410
411 field_t madd(const field_t& to_mul, const field_t& to_add) const;
412
413 field_t add_two(const field_t& add_b, const field_t& add_c) const;
414
415 [[nodiscard]] field_t normalize() const;
416
417 bb::fr get_value() const;
418
419 Builder* get_context() const { return context; }
420
422 const size_t lsb_index, const size_t num_bits = grumpkin::MAX_NO_WRAP_INTEGER_BIT_LENGTH) const;
423
424 bool_t<Builder> is_zero() const;
425
426 void create_range_constraint(size_t num_bits, std::string const& msg = "field_t::range_constraint") const;
427 void assert_is_not_zero(std::string const& msg = "field_t::assert_is_not_zero") const;
428 void assert_is_zero(std::string const& msg = "field_t::assert_is_zero") const;
429 bool is_constant() const { return witness_index == IS_CONSTANT; }
430 bool is_normalized() const
431 {
433 };
434 uint32_t set_public() const
435 {
437 return context->set_public_input(normalize().witness_index);
438 }
439
453
454 static field_t from_witness(Builder* ctx, const bb::fr& input)
455 {
456 auto result = field_t(witness_t<Builder>(ctx, input));
457 result.set_free_witness_tag();
458 return result;
459 }
460
461 // Disallow from_witness for non-bb::fr types to prevent implicit conversions (specifically, using indices rather
462 // than values)
463 template <typename T> static field_t from_witness(Builder* ctx, const T& input) = delete;
464
466 {
467 return limbs[0];
468 }
469
476 {
479 // Normalize first to ensure witness_index points to a witness that contains the actual value
480 // (i.e., multiplicative_constant = 1, additive_constant = 0)
481 *this = normalize();
482 // Let a := *this;
483 // q_l := 1
484 // q_c := -*this.get_value()
485 // Create an aritmetic gate constraining
486 // a.v * q_l - q_c = 0
487 context->fix_witness(witness_index, get_value());
489 }
490
506 uint32_t get_witness_index() const { return normalize().witness_index; }
507
519 static bool witness_indices_match(const field_t& a, const field_t& b) { return a.witness_index == b.witness_index; }
520
527 template <size_t num_bits> bool_t<Builder> ranged_less_than(const field_t<Builder>& other) const
528 {
529
530 const auto& a = (*this);
531 const auto& b = other;
532 auto* ctx = validate_context(a.context, b.context);
533 if (a.is_constant() && b.is_constant()) {
534 return uint256_t(a.get_value()) < uint256_t(b.get_value());
535 }
536
537 // Let q = (a < b)
538 // Assume both a and b are < K where K = 2^{num_bits}
539 // q == 1 <=> 0 < b - a - 1 < K
540 // q == 0 <=> 0 < b - a + K - 1 < K
541 // i.e. for any bool value of q:
542 // (b - a - 1) * q + (b - a + K - 1) * (1 - q) = r < K
543 // q * (b - a - b + a) + b - a + K - 1 - (K - 1) * q - q = r < K
544 // b - a + (K - 1) - K * q = r < K
545
546 static constexpr uint256_t range_constant = (uint256_t(1) << num_bits);
547 // Since in the worst case scenario
548 // r = K - 1 + (K - 1) = 2 * K - 2,
549 // to ensure that it never wraps around the field modulus, we impose that it's smaller than half the modulus
550 static_assert(range_constant < bb::fr::modulus >> 1,
551 "ranged_less_than: 2^num_bits must be less than half the field modulus.");
552
553 bool predicate_witness = uint256_t(a.get_value()) < uint256_t(b.get_value());
554 bool_t<Builder> predicate(witness_t<Builder>(ctx, predicate_witness));
555 field_t predicate_valid = b.add_two(-(a) + range_constant - 1, -field_t(predicate) * range_constant);
556 predicate_valid.create_range_constraint(num_bits);
557 return predicate;
558 }
559
560 // Aliases used in Relations' `accumulate` methods
561 using View = field_t;
563
564 // Alias used in `biggroup` and `CycleGroup`
565 using native = bb::fr;
566};
567
568template <typename Builder> inline std::ostream& operator<<(std::ostream& os, field_t<Builder> const& v)
569{
570 return os << v.get_value();
571}
572} // namespace bb::stdlib
#define BB_ASSERT(expression,...)
Definition assert.hpp:67
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:679
static field_t reconstruct_from_public(const std::span< const field_t, PUBLIC_INPUTS_SIZE > &limbs)
Definition field.hpp:465
friend void mark_witness_as_used(const field_t< B > &field)
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:859
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:985
uint32_t set_public() const
Definition field.hpp:434
field_t & operator=(const field_t &other)
Definition field.hpp:231
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:930
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:975
field_t(const int value)
Definition field.hpp:152
bool is_normalized() const
Definition field.hpp:430
field_t operator*=(const field_t &other)
Definition field.hpp:287
field_t madd(const field_t &to_mul, const field_t &to_add) const
Definition field.cpp:510
static field_t from_witness_index(Builder *ctx, uint32_t witness_index)
Definition field.cpp:62
field_t operator+(const field_t &other) const
Field addition operator.
Definition field.cpp:124
bool_t< Builder > operator!=(const field_t &other) const
Compute a bool_t equal to (a != b)
Definition field.cpp:850
bb::fr additive_constant
Definition field.hpp:93
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:1069
static void evaluate_polynomial_identity(const field_t &a, const field_t &b, const field_t &c, const field_t &d, const std::string &msg="field_t::evaluate_polynomial_identity")
Given a, b, c, d, constrain a * b + c + d = 0 by creating a big_mul_gate.
Definition field.cpp:1124
field_t(const bb::fr &value)
Definition field.hpp:184
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:1167
field_t invert() const
Definition field.hpp:317
static bool witness_indices_match(const field_t &a, const field_t &b)
Check if two field elements have the same witness index (for identity checks).
Definition field.hpp:519
void clear_round_provenance() const
Definition field.hpp:358
field_t operator-() const
Definition field.hpp:335
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:909
field_t(const unsigned long value)
Definition field.hpp:176
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:312
Builder * context
Definition field.hpp:56
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:1021
bb::fr multiplicative_constant
Definition field.hpp:94
void unset_free_witness_tag() const
Unset the free witness flag for the field element's tag.
Definition field.hpp:356
static field_t copy_as_new_witness(Builder &context, field_t const &other)
Definition field.hpp:254
Builder * get_context() const
Definition field.hpp:419
field_t sqr() const
Definition field.hpp:271
field_t(field_t &&other) noexcept
Definition field.hpp:211
static field_t conditional_assign_internal(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:885
static constexpr bool is_composite
Definition field.hpp:224
OriginTag get_origin_tag() const
Definition field.hpp:346
field_t operator-=(const field_t &other)
Definition field.hpp:282
bb::fr get_value() const
Given a := *this, compute its value given by a.v * a.mul + a.add.
Definition field.cpp:828
field_t operator*(const field_t &other) const
Field multiplication operator.
Definition field.cpp:192
field_t normalize() const
Return a new element, where the in-circuit witness contains the actual represented value (multiplicat...
Definition field.cpp:638
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:1047
static constexpr uint256_t modulus
Definition field.hpp:225
static field_t from_witness(Builder *ctx, const bb::fr &input)
Definition field.hpp:454
bool_t< Builder > is_zero() const
Validate whether a field_t element is zero.
Definition field.cpp:775
field_t pow(const uint32_t &exponent) const
Raise this field element to the power of the provided uint32_t exponent.
Definition field.cpp:422
static void evaluate_linear_identity(const field_t &a, const field_t &b, const field_t &c, const field_t &d, const std::string &msg="field_t::evaluate_linear_identity")
Constrain a + b + c + d to be equal to 0.
Definition field.cpp:1088
field_t(const field_t &other)
Definition field.hpp:202
static constexpr size_t PUBLIC_INPUTS_SIZE
Definition field.hpp:49
void convert_constant_to_fixed_witness(Builder *ctx)
Definition field.hpp:444
bool is_constant() const
Definition field.hpp:429
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:1003
field_t operator+=(const field_t &other)
Definition field.hpp:277
static field_t from_witness(Builder *ctx, const T &input)=delete
field_t & operator=(field_t &&other) noexcept
Definition field.hpp:244
field_t(const unsigned int value)
Definition field.hpp:167
field_t(const uint256_t &value)
Definition field.hpp:192
field_t operator++(const int)
Definition field.hpp:307
void set_free_witness_tag()
Set the free witness flag for the field element's tag.
Definition field.hpp:351
void set_origin_tag(const OriginTag &new_tag) const
Definition field.hpp:345
uint32_t witness_index
Definition field.hpp:144
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:575
static field_t conditional_assign(const bool_t< Builder > &predicate, const field_t &lhs, const field_t &rhs)
Definition field.hpp:372
field_t & operator++()
Definition field.hpp:299
field_t(const unsigned long long value)
Definition field.hpp:160
std::pair< field_t< Builder >, field_t< Builder > > no_wrap_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:1291
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:710
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:302
field_t operator/=(const field_t &other)
Definition field.hpp:292
bool_t< Builder > operator==(const field_t &other) const
Compute a bool_t equal to (a == b)
Definition field.cpp:842
uint32_t get_witness_index() const
Get the witness index of the current field element.
Definition field.hpp:506
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:527
FF a
FF b
stdlib::field_t< Builder > field_t
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:245
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...
Definition biggroup.hpp:995
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
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()
void clear_round_provenance()
Clear the round_provenance to address round provenance false positives.
General class for prime fields see Prime field documentation["field documentation"] for general imple...
static constexpr field one()
static constexpr uint256_t modulus
BB_INLINE constexpr void self_neg() &noexcept
static constexpr field zero()