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: Complete, auditors: [Sergei], commit: 458fb330efa8c470567ab4b84a8a92a58b00586a}
3// external_1: { status: Complete, auditors: [@ed25519, @JakubHeba (Spearbit)], commit:
4// 4433c06ae693451c6f69a2f63b7da6628078d872}
5// external_2: { status: not started, auditors: [], commit: }
6// =====================
7
8#pragma once
9#include "../circuit_builders/circuit_builders_fwd.hpp"
10#include "../witness/witness.hpp"
13#include <functional>
14
15namespace bb::stdlib {
16// Base case: only one pointer
17template <typename T> T* validate_context(T* ptr)
18{
19 return ptr;
20}
21
22// Variadic version: compare first with the rest
23template <typename T, typename... Ts> T* validate_context(T* first, Ts*... rest)
24{
25 T* tail = validate_context(rest...);
26 if (!first) {
27 return tail; // first is null, rely on tail
28 }
29 if (!tail) {
30 return first; // tail is null, use first
31 }
32 BB_ASSERT(first == tail, "Pointers refer to different builder objects!");
33 return first;
34}
35
36template <typename T, typename Container> T* validate_context(const Container& elements)
37{
38 T* result = nullptr;
39 for (const auto& element : elements) {
40 result = validate_context<T>(result, element.get_context());
41 }
42 return result;
43}
44
45template <typename Builder> class bool_t;
46template <typename Builder_> class field_t {
47 public:
48 using Builder = Builder_;
49
50 static constexpr size_t PUBLIC_INPUTS_SIZE = FR_PUBLIC_INPUTS_SIZE;
51
52 // Friend declarations for classes that need direct witness_index access
53 template <typename B> friend class bool_t;
54 template <typename B, typename T> friend class bigfield;
55 template <typename B> friend void mark_witness_as_used(const field_t<B>& field);
56
57 mutable Builder* context = nullptr;
58
96
97 private:
145 mutable uint32_t witness_index = IS_CONSTANT;
146
147 public:
148 mutable OriginTag tag;
149
150 field_t(Builder* parent_context = nullptr);
151 field_t(Builder* parent_context, const bb::fr& value);
152
153 field_t(const int value)
154 : context(nullptr)
156 , multiplicative_constant(bb::fr::one())
157 , witness_index(IS_CONSTANT)
158 {
160 }
161
162 // NOLINTNEXTLINE(google-runtime-int) intended behavior
163 field_t(const unsigned long long value)
164 : context(nullptr)
166 , multiplicative_constant(bb::fr::one())
167 , witness_index(IS_CONSTANT)
168 {
170 }
171
172 field_t(const unsigned int value)
173 : context(nullptr)
175 , multiplicative_constant(bb::fr::one())
176 , witness_index(IS_CONSTANT)
177 {
179 }
180
181 // NOLINTNEXTLINE(google-runtime-int) intended behavior
182 field_t(const unsigned long value)
183 : context(nullptr)
185 , multiplicative_constant(bb::fr::one())
186 , witness_index(IS_CONSTANT)
187 {
189 }
190
191 // Construct a constant circuit element from a native field element
193 : context(nullptr)
195 , multiplicative_constant(bb::fr::one())
196 , witness_index(IS_CONSTANT)
197 {
199 }
200
201 // Construct a constant circuit element from a uint256t, that is implicitly converted to a native field element
203 : context(nullptr)
205 , multiplicative_constant(bb::fr::one())
206 , witness_index(IS_CONSTANT)
207 {
209 }
210
212
213 // field_t copy constructor
214 field_t(const field_t& other)
215 : context(other.context)
219 , tag(other.tag)
220 {}
221
222 // field_t move constructor
223 field_t(field_t&& other) noexcept
224 : context(other.context)
225 , additive_constant(other.additive_constant)
226 , multiplicative_constant(other.multiplicative_constant)
227 , witness_index(other.witness_index)
228 , tag(other.tag)
229 {}
230
231 // Copy constructor from a bool_t
232 field_t(const bool_t<Builder>& other);
233
234 ~field_t() = default;
235
236 static constexpr bool is_composite = false;
238
239 static field_t from_witness_index(Builder* ctx, uint32_t witness_index);
240
241 explicit operator bool_t<Builder>() const;
242
243 field_t& operator=(const field_t& other)
244 {
245 if (this == &other) {
246 return *this;
247 }
251 context = other.context;
252 tag = other.tag;
253 return *this;
254 }
255
256 field_t& operator=(field_t&& other) noexcept
257 {
258 additive_constant = other.additive_constant;
259 multiplicative_constant = other.multiplicative_constant;
260 witness_index = other.witness_index;
261 context = other.context;
262 tag = other.tag;
263 return *this;
264 }
265
267 {
268 auto result = field_t<Builder>(witness_t<Builder>(&context, other.get_value()));
269 result.assert_equal(other, "field_t::copy_as_new_witness, assert_equal");
270 result.tag = other.tag;
271 return result;
272 }
273
274 field_t operator+(const field_t& other) const;
275 field_t operator-(const field_t& other) const;
276 field_t operator*(const field_t& other) const;
277 field_t operator/(const field_t& other) const;
278 bool_t<Builder> operator==(const field_t& other) const;
279 bool_t<Builder> operator!=(const field_t& other) const;
280
281 field_t divide_no_zero_check(const field_t& other) const;
282
283 field_t sqr() const { return operator*(*this); }
284
285 field_t pow(const uint32_t& exponent) const;
286 // N.B. we implicitly range-constrain 'exponent' to be a 32-bit integer!
287 field_t pow(const field_t& exponent) const;
288
290 {
291 *this = *this + other;
292 return *this;
293 }
295 {
296 *this = *this - other;
297 return *this;
298 }
300 {
301 *this = *this * other;
302 return *this;
303 }
305 {
306 *this = *this / other;
307 return *this;
308 }
309
310 // Prefix increment (++x)
312 {
313 *this = *this + 1;
314 return *this;
315 };
316
317 // Postfix increment (x++)
318 // NOLINTNEXTLINE
320 {
321 field_t this_before_operation = field_t(*this);
322 *this = *this + 1;
323 return this_before_operation;
324 };
325
330 {
331 // Since the numerator is a constant 1, the constraint
332 // (this.v * this.mul + this.add) * inverse.v == 1;
333 // created by applying `assert_is_not_zero` to `*this` coincides with the constraint created by
334 // `divide_no_zero_check`, hence we can safely apply the latter instead of `/` operator.
335 auto* ctx = get_context();
336 if (is_constant()) {
337 BB_ASSERT(!get_value().is_zero(), "field_t::invert denominator is constant 0");
338 }
339
340 if (get_value().is_zero() && !ctx->failed()) {
341 ctx->failure("field_t::invert denominator is 0");
342 }
343
344 return field_t(fr::one()).divide_no_zero_check(*this);
345 }
346
348 {
349 field_t result(*this);
351 if (!is_constant()) {
353 }
354 return result;
355 }
356
357 void set_origin_tag(const OriginTag& new_tag) const { tag = new_tag; }
358 OriginTag get_origin_tag() const { return tag; };
359
364
369
371
372 field_t conditional_negate(const bool_t<Builder>& predicate) const;
373
374 void assert_equal(const field_t& rhs, std::string const& msg = "field_t::assert_equal") const;
375
376 void assert_not_equal(const field_t& rhs, std::string const& msg = "field_t::assert_not_equal") const;
377
378 void assert_is_in_set(const std::vector<field_t>& set, std::string const& msg = "field_t::assert_not_in_set") const;
379
381 const field_t& lhs,
382 const field_t& rhs);
383
384 static field_t conditional_assign(const bool_t<Builder>& predicate, const field_t& lhs, const field_t& rhs)
385 {
386 return conditional_assign_internal(predicate, lhs, rhs).normalize();
387 }
388
390 const field_t& T1,
391 const field_t& T2,
392 const field_t& T3);
394 const bool_t<Builder>& t1,
395 const bool_t<Builder>& t0);
396
398 const field_t& T1,
399 const field_t& T2,
400 const field_t& T3,
401 const field_t& T4,
402 const field_t& T5,
403 const field_t& T6,
404 const field_t& T7);
406 const bool_t<Builder>& t2,
407 const bool_t<Builder>& t1,
408 const bool_t<Builder>& t0);
409
410 static void evaluate_linear_identity(const field_t& a,
411 const field_t& b,
412 const field_t& c,
413 const field_t& d,
414 const std::string& msg = "field_t::evaluate_linear_identity");
415 static void evaluate_polynomial_identity(const field_t& a,
416 const field_t& b,
417 const field_t& c,
418 const field_t& d,
419 const std::string& msg = "field_t::evaluate_polynomial_identity");
420
421 static field_t accumulate(const std::vector<field_t>& input);
422
423 field_t madd(const field_t& to_mul, const field_t& to_add) const;
424
425 field_t add_two(const field_t& add_b, const field_t& add_c) const;
426
427 [[nodiscard]] field_t normalize() const;
428
429 bb::fr get_value() const;
430
431 Builder* get_context() const { return context; }
432
434 const size_t lsb_index, const size_t num_bits = grumpkin::MAX_NO_WRAP_INTEGER_BIT_LENGTH) const;
435
436 bool_t<Builder> is_zero() const;
437
438 void create_range_constraint(size_t num_bits, std::string const& msg = "field_t::range_constraint") const;
439 void assert_is_not_zero(std::string const& msg = "field_t::assert_is_not_zero") const;
440 void assert_is_zero(std::string const& msg = "field_t::assert_is_zero") const;
441 bool is_constant() const { return witness_index == IS_CONSTANT; }
442 bool is_normalized() const
443 {
445 };
446 uint32_t set_public() const
447 {
449 return context->set_public_input(normalize().witness_index);
450 }
451
465
466 static field_t from_witness(Builder* ctx, const bb::fr& input)
467 {
468 auto result = field_t(witness_t<Builder>(ctx, input));
469 result.set_free_witness_tag();
470 return result;
471 }
472
473 // Disallow from_witness for non-bb::fr types to prevent implicit conversions (specifically, using indices rather
474 // than values)
475 template <typename T> static field_t from_witness(Builder* ctx, const T& input) = delete;
476
478 {
479 return limbs[0];
480 }
481
488 {
491 // Normalize first to ensure witness_index points to a witness that contains the actual value
492 // (i.e., multiplicative_constant = 1, additive_constant = 0)
493 *this = normalize();
494 // Let a := *this;
495 // q_l := 1
496 // q_c := -*this.get_value()
497 // Create an aritmetic gate constraining
498 // a.v * q_l - q_c = 0
499 context->fix_witness(witness_index, get_value());
501 }
502
518 uint32_t get_witness_index() const { return normalize().witness_index; }
519
531 static bool witness_indices_match(const field_t& a, const field_t& b) { return a.witness_index == b.witness_index; }
532
539 template <size_t num_bits> bool_t<Builder> ranged_less_than(const field_t<Builder>& other) const
540 {
541
542 const auto& a = (*this);
543 const auto& b = other;
544 auto* ctx = validate_context(a.context, b.context);
545 if (a.is_constant() && b.is_constant()) {
546 return uint256_t(a.get_value()) < uint256_t(b.get_value());
547 }
548
549 // Let q = (a < b)
550 // Assume both a and b are < K where K = 2^{num_bits}
551 // q == 1 <=> 0 < b - a - 1 < K
552 // q == 0 <=> 0 < b - a + K - 1 < K
553 // i.e. for any bool value of q:
554 // (b - a - 1) * q + (b - a + K - 1) * (1 - q) = r < K
555 // q * (b - a - b + a) + b - a + K - 1 - (K - 1) * q - q = r < K
556 // b - a + (K - 1) - K * q = r < K
557
558 static constexpr uint256_t range_constant = (uint256_t(1) << num_bits);
559 // Since in the worst case scenario
560 // r = K - 1 + (K - 1) = 2 * K - 2,
561 // to ensure that it never wraps around the field modulus, we impose that it's smaller than half the modulus
562 static_assert(range_constant < bb::fr::modulus >> 1,
563 "ranged_less_than: 2^num_bits must be less than half the field modulus.");
564
565 bool predicate_witness = uint256_t(a.get_value()) < uint256_t(b.get_value());
566 bool_t<Builder> predicate(witness_t<Builder>(ctx, predicate_witness));
567 field_t predicate_valid = b.add_two(-(a) + range_constant - 1, -field_t(predicate) * range_constant);
568 predicate_valid.create_range_constraint(num_bits);
569 return predicate;
570 }
571
572 // Aliases used in Relations' `accumulate` methods
573 using View = field_t;
575
576 // Alias used in `biggroup` and `CycleGroup`
577 using native = bb::fr;
578};
579
580template <typename Builder> inline std::ostream& operator<<(std::ostream& os, field_t<Builder> const& v)
581{
582 return os << v.get_value();
583}
584} // namespace bb::stdlib
#define BB_ASSERT(expression,...)
Definition assert.hpp:70
Implements boolean logic in-circuit.
Definition bool.hpp:60
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:687
static field_t reconstruct_from_public(const std::span< const field_t, PUBLIC_INPUTS_SIZE > &limbs)
Definition field.hpp:477
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:867
Builder_ Builder
Definition field.hpp:48
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:996
uint32_t set_public() const
Definition field.hpp:446
field_t & operator=(const field_t &other)
Definition field.hpp:243
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:940
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:986
field_t(const int value)
Definition field.hpp:153
bool is_normalized() const
Definition field.hpp:442
field_t operator*=(const field_t &other)
Definition field.hpp:299
field_t madd(const field_t &to_mul, const field_t &to_add) const
Definition field.cpp:518
static field_t from_witness_index(Builder *ctx, uint32_t witness_index)
Definition field.cpp:67
field_t operator+(const field_t &other) const
Field addition operator.
Definition field.cpp:132
bool_t< Builder > operator!=(const field_t &other) const
Compute a bool_t equal to (a != b)
Definition field.cpp:858
bb::fr additive_constant
Definition field.hpp:94
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:1080
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:1135
field_t(const bb::fr &value)
Definition field.hpp:192
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:1178
field_t invert() const
Definition field.hpp:329
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:531
void clear_round_provenance() const
Definition field.hpp:370
field_t operator-() const
Definition field.hpp:347
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:919
field_t(const unsigned long value)
Definition field.hpp:182
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:320
Builder * context
Definition field.hpp:57
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:1032
bb::fr multiplicative_constant
Definition field.hpp:95
void unset_free_witness_tag() const
Unset the free witness flag for the field element's tag.
Definition field.hpp:368
static field_t copy_as_new_witness(Builder &context, field_t const &other)
Definition field.hpp:266
Builder * get_context() const
Definition field.hpp:431
field_t sqr() const
Definition field.hpp:283
field_t(field_t &&other) noexcept
Definition field.hpp:223
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:893
static constexpr bool is_composite
Definition field.hpp:236
OriginTag get_origin_tag() const
Definition field.hpp:358
field_t operator-=(const field_t &other)
Definition field.hpp:294
bb::fr get_value() const
Given a := *this, compute its value given by a.v * a.mul + a.add.
Definition field.cpp:836
field_t operator*(const field_t &other) const
Field multiplication operator.
Definition field.cpp:200
field_t normalize() const
Return a new element, where the in-circuit witness contains the actual represented value (multiplicat...
Definition field.cpp:646
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:1058
static constexpr uint256_t modulus
Definition field.hpp:237
static field_t from_witness(Builder *ctx, const bb::fr &input)
Definition field.hpp:466
bool_t< Builder > is_zero() const
Validate whether a field_t element is zero.
Definition field.cpp:783
field_t pow(const uint32_t &exponent) const
Raise this field element to the power of the provided uint32_t exponent.
Definition field.cpp:430
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:1099
field_t(const field_t &other)
Definition field.hpp:214
static constexpr size_t PUBLIC_INPUTS_SIZE
Definition field.hpp:50
void convert_constant_to_fixed_witness(Builder *ctx)
Definition field.hpp:456
bool is_constant() const
Definition field.hpp:441
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:1014
field_t operator+=(const field_t &other)
Definition field.hpp:289
static field_t from_witness(Builder *ctx, const T &input)=delete
field_t & operator=(field_t &&other) noexcept
Definition field.hpp:256
field_t(const unsigned int value)
Definition field.hpp:172
field_t(const uint256_t &value)
Definition field.hpp:202
field_t operator++(const int)
Definition field.hpp:319
void set_free_witness_tag()
Set the free witness flag for the field element's tag.
Definition field.hpp:363
void set_origin_tag(const OriginTag &new_tag) const
Definition field.hpp:357
uint32_t witness_index
Definition field.hpp:145
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:583
static field_t conditional_assign(const bool_t< Builder > &predicate, const field_t &lhs, const field_t &rhs)
Definition field.hpp:384
field_t & operator++()
Definition field.hpp:311
field_t(const unsigned long long value)
Definition field.hpp:163
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:1302
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:718
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:310
field_t operator/=(const field_t &other)
Definition field.hpp:304
bool_t< Builder > operator==(const field_t &other) const
Compute a bool_t equal to (a == b)
Definition field.cpp:850
uint32_t get_witness_index() const
Get the witness index of the current field element.
Definition field.hpp:518
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:539
FF a
FF b
stdlib::field_t< Builder > field_t
constexpr size_t MAX_NO_WRAP_INTEGER_BIT_LENGTH
Definition grumpkin.hpp:16
std::ostream & operator<<(std::ostream &os, uint256_t const &a)
Definition uint256.hpp:258
T * validate_context(T *ptr)
Definition field.hpp:17
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.
Definition api.hpp:5
field< Bn254FrParams > fr
Definition fr.hpp:155
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()
static OriginTag constant()
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()