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,
377 const field_t& b,
378 const field_t& c,
379 const field_t& d,
380 const std::string& msg = "field_t::evaluate_linear_identity");
381 static void evaluate_polynomial_identity(const field_t& a,
382 const field_t& b,
383 const field_t& c,
384 const field_t& d,
385 const std::string& msg = "field_t::evaluate_polynomial_identity");
386
387 static field_t accumulate(const std::vector<field_t>& input);
388
389 field_t madd(const field_t& to_mul, const field_t& to_add) const;
390
391 field_t add_two(const field_t& add_b, const field_t& add_c) const;
392
393 [[nodiscard]] field_t normalize() const;
394
395 bb::fr get_value() const;
396
397 Builder* get_context() const { return context; }
398
400 const size_t lsb_index, const size_t num_bits = grumpkin::MAX_NO_WRAP_INTEGER_BIT_LENGTH) const;
401
402 bool_t<Builder> is_zero() const;
403
404 void create_range_constraint(size_t num_bits, std::string const& msg = "field_t::range_constraint") const;
405 void assert_is_not_zero(std::string const& msg = "field_t::assert_is_not_zero") const;
406 void assert_is_zero(std::string const& msg = "field_t::assert_is_zero") const;
407 bool is_constant() const { return witness_index == IS_CONSTANT; }
408 bool is_normalized() const
409 {
411 };
412 uint32_t set_public() const
413 {
415 return context->set_public_input(get_normalized_witness_index());
416 }
417
431
432 static field_t from_witness(Builder* ctx, const bb::fr& input)
433 {
434 auto result = field_t(witness_t<Builder>(ctx, input));
435 result.set_free_witness_tag();
436 return result;
437 }
438
440 {
441 return limbs[0];
442 }
443
450 {
453 // Let a := *this;
454 // q_l := 1
455 // q_c := -*this.get_value()
456 // Create an aritmetic gate constraining
457 // a.v * q_l - q_c = 0
458 context->fix_witness(witness_index, get_value());
460 }
461
469 uint32_t get_witness_index() const { return witness_index; }
470
480
487 template <size_t num_bits> bool_t<Builder> ranged_less_than(const field_t<Builder>& other) const
488 {
489
490 const auto& a = (*this);
491 const auto& b = other;
492 auto* ctx = validate_context(a.context, b.context);
493 if (a.is_constant() && b.is_constant()) {
494 return uint256_t(a.get_value()) < uint256_t(b.get_value());
495 }
496
497 // Let q = (a < b)
498 // Assume both a and b are < K where K = 2^{num_bits}
499 // q == 1 <=> 0 < b - a - 1 < K
500 // q == 0 <=> 0 < b - a + K - 1 < K
501 // i.e. for any bool value of q:
502 // (b - a - 1) * q + (b - a + K - 1) * (1 - q) = r < K
503 // q * (b - a - b + a) + b - a + K - 1 - (K - 1) * q - q = r < K
504 // b - a + (K - 1) - K * q = r < K
505
506 static constexpr uint256_t range_constant = (uint256_t(1) << num_bits);
507 // Since in the worst case scenario
508 // r = K - 1 + (K - 1) = 2 * K - 2,
509 // to ensure that it never wraps around the field modulus, we impose that it's smaller than half the modulus
510 static_assert(range_constant < bb::fr::modulus >> 1,
511 "ranged_less_than: 2^num_bits must be less than half the field modulus.");
512
513 bool predicate_witness = uint256_t(a.get_value()) < uint256_t(b.get_value());
514 bool_t<Builder> predicate(witness_t<Builder>(ctx, predicate_witness));
515 field_t predicate_valid = b.add_two(-(a) + range_constant - 1, -field_t(predicate) * range_constant);
516 predicate_valid.create_range_constraint(num_bits);
517 return predicate;
518 }
519
520 // Aliases used in Relations' `accumulate` methods
521 using View = field_t;
523
524 // Alias used in `biggroup` and `CycleGroup`
525 using native = bb::fr;
526};
527
528template <typename Builder> inline std::ostream& operator<<(std::ostream& os, field_t<Builder> const& v)
529{
530 return os << v.get_value();
531}
532} // namespace bb::stdlib
#define ASSERT(expression,...)
Definition assert.hpp:77
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:678
static field_t reconstruct_from_public(const std::span< const field_t, PUBLIC_INPUTS_SIZE > &limbs)
Definition field.hpp:439
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: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:975
uint32_t set_public() const
Definition field.hpp:412
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: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:965
field_t(const int value)
Definition field.hpp:139
bool is_normalized() const
Definition field.hpp:408
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:509
static field_t from_witness_index(Builder *ctx, uint32_t witness_index)
Definition field.cpp:61
field_t operator+(const field_t &other) const
Field addition operator.
Definition field.cpp:123
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: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:1059
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:1114
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:1157
field_t invert() const
Definition field.hpp:304
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:910
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:886
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:311
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:1011
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:397
field_t sqr() const
Definition field.hpp:258
field_t(field_t &&other) noexcept
Definition field.hpp:198
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:829
field_t operator*(const field_t &other) const
Field multiplication operator.
Definition field.cpp:191
field_t normalize() const
Return a new element, where the in-circuit witness contains the actual represented value (multiplicat...
Definition field.cpp:637
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:1037
static constexpr uint256_t modulus
Definition field.hpp:212
static field_t from_witness(Builder *ctx, const bb::fr &input)
Definition field.hpp:432
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:421
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:1078
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:422
bool is_constant() const
Definition field.hpp:407
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:993
uint32_t get_normalized_witness_index() const
Get the index of a normalized version of this element.
Definition field.hpp:479
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:574
field_t & operator++()
Definition field.hpp:286
field_t(const unsigned long long value)
Definition field.hpp:147
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:1281
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:709
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:301
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:843
uint32_t get_witness_index() const
Get the witness index of the current field element.
Definition field.hpp:469
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:487
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: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...
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()