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 {}
159
160 // NOLINTNEXTLINE(google-runtime-int) intended behavior
161 field_t(const unsigned long long value)
162 : context(nullptr)
164 , multiplicative_constant(bb::fr::one())
165 , witness_index(IS_CONSTANT)
166 {}
167
168 field_t(const unsigned int value)
169 : context(nullptr)
171 , multiplicative_constant(bb::fr::one())
172 , witness_index(IS_CONSTANT)
173
174 {}
175
176 // NOLINTNEXTLINE(google-runtime-int) intended behavior
177 field_t(const unsigned long value)
178 : context(nullptr)
180 , multiplicative_constant(bb::fr::one())
181 , witness_index(IS_CONSTANT)
182 {}
183
184 // Construct a constant circuit element from a native field element
186 : context(nullptr)
188 , multiplicative_constant(bb::fr::one())
189 , witness_index(IS_CONSTANT)
190 {}
191
192 // Construct a constant circuit element from a uint256t, that is implicitly converted to a native field element
194 : context(nullptr)
196 , multiplicative_constant(bb::fr::one())
197 , witness_index(IS_CONSTANT)
198 {}
199
201
202 // field_t copy constructor
203 field_t(const field_t& other)
204 : context(other.context)
208 , tag(other.tag)
209 {}
210
211 // field_t move constructor
212 field_t(field_t&& other) noexcept
213 : context(other.context)
214 , additive_constant(other.additive_constant)
215 , multiplicative_constant(other.multiplicative_constant)
216 , witness_index(other.witness_index)
217 , tag(other.tag)
218 {}
219
220 // Copy constructor from a bool_t
221 field_t(const bool_t<Builder>& other);
222
223 ~field_t() = default;
224
225 static constexpr bool is_composite = false;
227
228 static field_t from_witness_index(Builder* ctx, uint32_t witness_index);
229
230 explicit operator bool_t<Builder>() const;
231
232 field_t& operator=(const field_t& other)
233 {
234 if (this == &other) {
235 return *this;
236 }
240 context = other.context;
241 tag = other.tag;
242 return *this;
243 }
244
245 field_t& operator=(field_t&& other) noexcept
246 {
247 additive_constant = other.additive_constant;
248 multiplicative_constant = other.multiplicative_constant;
249 witness_index = other.witness_index;
250 context = other.context;
251 tag = other.tag;
252 return *this;
253 }
254
256 {
257 auto result = field_t<Builder>(witness_t<Builder>(&context, other.get_value()));
258 result.assert_equal(other, "field_t::copy_as_new_witness, assert_equal");
259 result.tag = other.tag;
260 return result;
261 }
262
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 field_t operator/(const field_t& other) const;
267 bool_t<Builder> operator==(const field_t& other) const;
268 bool_t<Builder> operator!=(const field_t& other) const;
269
270 field_t divide_no_zero_check(const field_t& other) const;
271
272 field_t sqr() const { return operator*(*this); }
273
274 field_t pow(const uint32_t& exponent) const;
275 // N.B. we implicitly range-constrain 'exponent' to be a 32-bit integer!
276 field_t pow(const field_t& exponent) const;
277
279 {
280 *this = *this + other;
281 return *this;
282 }
284 {
285 *this = *this - other;
286 return *this;
287 }
289 {
290 *this = *this * other;
291 return *this;
292 }
294 {
295 *this = *this / other;
296 return *this;
297 }
298
299 // Prefix increment (++x)
301 {
302 *this = *this + 1;
303 return *this;
304 };
305
306 // Postfix increment (x++)
307 // NOLINTNEXTLINE
309 {
310 field_t this_before_operation = field_t(*this);
311 *this = *this + 1;
312 return this_before_operation;
313 };
314
319 {
320 // Since the numerator is a constant 1, the constraint
321 // (this.v * this.mul + this.add) * inverse.v == 1;
322 // created by applying `assert_is_not_zero` to `*this` coincides with the constraint created by
323 // `divide_no_zero_check`, hence we can safely apply the latter instead of `/` operator.
324 auto* ctx = get_context();
325 if (is_constant()) {
326 BB_ASSERT(!get_value().is_zero(), "field_t::invert denominator is constant 0");
327 }
328
329 if (get_value().is_zero() && !ctx->failed()) {
330 ctx->failure("field_t::invert denominator is 0");
331 }
332
333 return field_t(fr::one()).divide_no_zero_check(*this);
334 }
335
337 {
338 field_t result(*this);
340 if (!is_constant()) {
342 }
343 return result;
344 }
345
346 void set_origin_tag(const OriginTag& new_tag) const { tag = new_tag; }
347 OriginTag get_origin_tag() const { return tag; };
348
353
358
360
361 field_t conditional_negate(const bool_t<Builder>& predicate) const;
362
363 void assert_equal(const field_t& rhs, std::string const& msg = "field_t::assert_equal") const;
364
365 void assert_not_equal(const field_t& rhs, std::string const& msg = "field_t::assert_not_equal") const;
366
367 void assert_is_in_set(const std::vector<field_t>& set, std::string const& msg = "field_t::assert_not_in_set") const;
368
370 const field_t& lhs,
371 const field_t& rhs);
372
373 static field_t conditional_assign(const bool_t<Builder>& predicate, const field_t& lhs, const field_t& rhs)
374 {
375 return conditional_assign_internal(predicate, lhs, rhs).normalize();
376 }
377
379 const field_t& T1,
380 const field_t& T2,
381 const field_t& T3);
383 const bool_t<Builder>& t1,
384 const bool_t<Builder>& t0);
385
387 const field_t& T1,
388 const field_t& T2,
389 const field_t& T3,
390 const field_t& T4,
391 const field_t& T5,
392 const field_t& T6,
393 const field_t& T7);
395 const bool_t<Builder>& t2,
396 const bool_t<Builder>& t1,
397 const bool_t<Builder>& t0);
398
399 static void evaluate_linear_identity(const field_t& a,
400 const field_t& b,
401 const field_t& c,
402 const field_t& d,
403 const std::string& msg = "field_t::evaluate_linear_identity");
404 static void evaluate_polynomial_identity(const field_t& a,
405 const field_t& b,
406 const field_t& c,
407 const field_t& d,
408 const std::string& msg = "field_t::evaluate_polynomial_identity");
409
410 static field_t accumulate(const std::vector<field_t>& input);
411
412 field_t madd(const field_t& to_mul, const field_t& to_add) const;
413
414 field_t add_two(const field_t& add_b, const field_t& add_c) const;
415
416 [[nodiscard]] field_t normalize() const;
417
418 bb::fr get_value() const;
419
420 Builder* get_context() const { return context; }
421
423 const size_t lsb_index, const size_t num_bits = grumpkin::MAX_NO_WRAP_INTEGER_BIT_LENGTH) const;
424
425 bool_t<Builder> is_zero() const;
426
427 void create_range_constraint(size_t num_bits, std::string const& msg = "field_t::range_constraint") const;
428 void assert_is_not_zero(std::string const& msg = "field_t::assert_is_not_zero") const;
429 void assert_is_zero(std::string const& msg = "field_t::assert_is_zero") const;
430 bool is_constant() const { return witness_index == IS_CONSTANT; }
431 bool is_normalized() const
432 {
434 };
435 uint32_t set_public() const
436 {
438 return context->set_public_input(normalize().witness_index);
439 }
440
454
455 static field_t from_witness(Builder* ctx, const bb::fr& input)
456 {
457 auto result = field_t(witness_t<Builder>(ctx, input));
458 result.set_free_witness_tag();
459 return result;
460 }
461
462 // Disallow from_witness for non-bb::fr types to prevent implicit conversions (specifically, using indices rather
463 // than values)
464 template <typename T> static field_t from_witness(Builder* ctx, const T& input) = delete;
465
467 {
468 return limbs[0];
469 }
470
477 {
480 // Normalize first to ensure witness_index points to a witness that contains the actual value
481 // (i.e., multiplicative_constant = 1, additive_constant = 0)
482 *this = normalize();
483 // Let a := *this;
484 // q_l := 1
485 // q_c := -*this.get_value()
486 // Create an aritmetic gate constraining
487 // a.v * q_l - q_c = 0
488 context->fix_witness(witness_index, get_value());
490 }
491
507 uint32_t get_witness_index() const { return normalize().witness_index; }
508
520 static bool witness_indices_match(const field_t& a, const field_t& b) { return a.witness_index == b.witness_index; }
521
528 template <size_t num_bits> bool_t<Builder> ranged_less_than(const field_t<Builder>& other) const
529 {
530
531 const auto& a = (*this);
532 const auto& b = other;
533 auto* ctx = validate_context(a.context, b.context);
534 if (a.is_constant() && b.is_constant()) {
535 return uint256_t(a.get_value()) < uint256_t(b.get_value());
536 }
537
538 // Let q = (a < b)
539 // Assume both a and b are < K where K = 2^{num_bits}
540 // q == 1 <=> 0 < b - a - 1 < K
541 // q == 0 <=> 0 < b - a + K - 1 < K
542 // i.e. for any bool value of q:
543 // (b - a - 1) * q + (b - a + K - 1) * (1 - q) = r < K
544 // q * (b - a - b + a) + b - a + K - 1 - (K - 1) * q - q = r < K
545 // b - a + (K - 1) - K * q = r < K
546
547 static constexpr uint256_t range_constant = (uint256_t(1) << num_bits);
548 // Since in the worst case scenario
549 // r = K - 1 + (K - 1) = 2 * K - 2,
550 // to ensure that it never wraps around the field modulus, we impose that it's smaller than half the modulus
551 static_assert(range_constant < bb::fr::modulus >> 1,
552 "ranged_less_than: 2^num_bits must be less than half the field modulus.");
553
554 bool predicate_witness = uint256_t(a.get_value()) < uint256_t(b.get_value());
555 bool_t<Builder> predicate(witness_t<Builder>(ctx, predicate_witness));
556 field_t predicate_valid = b.add_two(-(a) + range_constant - 1, -field_t(predicate) * range_constant);
557 predicate_valid.create_range_constraint(num_bits);
558 return predicate;
559 }
560
561 // Aliases used in Relations' `accumulate` methods
562 using View = field_t;
564
565 // Alias used in `biggroup` and `CycleGroup`
566 using native = bb::fr;
567};
568
569template <typename Builder> inline std::ostream& operator<<(std::ostream& os, field_t<Builder> const& v)
570{
571 return os << v.get_value();
572}
573} // 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:680
static field_t reconstruct_from_public(const std::span< const field_t, PUBLIC_INPUTS_SIZE > &limbs)
Definition field.hpp:466
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:860
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:986
uint32_t set_public() const
Definition field.hpp:435
field_t & operator=(const field_t &other)
Definition field.hpp:232
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:931
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:976
field_t(const int value)
Definition field.hpp:153
bool is_normalized() const
Definition field.hpp:431
field_t operator*=(const field_t &other)
Definition field.hpp:288
field_t madd(const field_t &to_mul, const field_t &to_add) const
Definition field.cpp:511
static field_t from_witness_index(Builder *ctx, uint32_t witness_index)
Definition field.cpp:63
field_t operator+(const field_t &other) const
Field addition operator.
Definition field.cpp:125
bool_t< Builder > operator!=(const field_t &other) const
Compute a bool_t equal to (a != b)
Definition field.cpp:851
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:1070
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:1125
field_t(const bb::fr &value)
Definition field.hpp:185
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:1168
field_t invert() const
Definition field.hpp:318
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:520
void clear_round_provenance() const
Definition field.hpp:359
field_t operator-() const
Definition field.hpp:336
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:910
field_t(const unsigned long value)
Definition field.hpp:177
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:313
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:1022
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:357
static field_t copy_as_new_witness(Builder &context, field_t const &other)
Definition field.hpp:255
Builder * get_context() const
Definition field.hpp:420
field_t sqr() const
Definition field.hpp:272
field_t(field_t &&other) noexcept
Definition field.hpp:212
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:886
static constexpr bool is_composite
Definition field.hpp:225
OriginTag get_origin_tag() const
Definition field.hpp:347
field_t operator-=(const field_t &other)
Definition field.hpp:283
bb::fr get_value() const
Given a := *this, compute its value given by a.v * a.mul + a.add.
Definition field.cpp:829
field_t operator*(const field_t &other) const
Field multiplication operator.
Definition field.cpp:193
field_t normalize() const
Return a new element, where the in-circuit witness contains the actual represented value (multiplicat...
Definition field.cpp:639
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:1048
static constexpr uint256_t modulus
Definition field.hpp:226
static field_t from_witness(Builder *ctx, const bb::fr &input)
Definition field.hpp:455
bool_t< Builder > is_zero() const
Validate whether a field_t element is zero.
Definition field.cpp:776
field_t pow(const uint32_t &exponent) const
Raise this field element to the power of the provided uint32_t exponent.
Definition field.cpp:423
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:1089
field_t(const field_t &other)
Definition field.hpp:203
static constexpr size_t PUBLIC_INPUTS_SIZE
Definition field.hpp:50
void convert_constant_to_fixed_witness(Builder *ctx)
Definition field.hpp:445
bool is_constant() const
Definition field.hpp:430
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:1004
field_t operator+=(const field_t &other)
Definition field.hpp:278
static field_t from_witness(Builder *ctx, const T &input)=delete
field_t & operator=(field_t &&other) noexcept
Definition field.hpp:245
field_t(const unsigned int value)
Definition field.hpp:168
field_t(const uint256_t &value)
Definition field.hpp:193
field_t operator++(const int)
Definition field.hpp:308
void set_free_witness_tag()
Set the free witness flag for the field element's tag.
Definition field.hpp:352
void set_origin_tag(const OriginTag &new_tag) const
Definition field.hpp:346
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:576
static field_t conditional_assign(const bool_t< Builder > &predicate, const field_t &lhs, const field_t &rhs)
Definition field.hpp:373
field_t & operator++()
Definition field.hpp:300
field_t(const unsigned long long value)
Definition field.hpp:161
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:1292
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:711
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:303
field_t operator/=(const field_t &other)
Definition field.hpp:293
bool_t< Builder > operator==(const field_t &other) const
Compute a bool_t equal to (a == b)
Definition field.cpp:843
uint32_t get_witness_index() const
Get the witness index of the current field element.
Definition field.hpp:507
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:528
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:254
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...
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()