barretenberg
Loading...
Searching...
No Matches
field.hpp
1#pragma once
2#include "../circuit_builders/circuit_builders_fwd.hpp"
3#include "../witness/witness.hpp"
4#include "barretenberg/common/assert.hpp"
5#include <functional>
6
7namespace proof_system::plonk::stdlib {
8
9template <typename Builder> class bool_t;
10template <typename Builder> class field_t {
11 public:
12 using View = field_t;
13
14 field_t(Builder* parent_context = nullptr);
15 field_t(Builder* parent_context, const barretenberg::fr& value);
16
17 field_t(const int value)
18 : context(nullptr)
19 , witness_index(IS_CONSTANT)
20 {
22 multiplicative_constant = barretenberg::fr(0);
23 }
24
25 // NOLINTNEXTLINE(google-runtime-int) intended behavior
26 field_t(const unsigned long long value)
27 : context(nullptr)
28 , witness_index(IS_CONSTANT)
29 {
31 multiplicative_constant = barretenberg::fr(0);
32 }
33
34 field_t(const unsigned int value)
35 : context(nullptr)
36 , witness_index(IS_CONSTANT)
37 {
39 multiplicative_constant = barretenberg::fr(0);
40 }
41
42 // NOLINTNEXTLINE(google-runtime-int) intended behavior
43 field_t(const unsigned long value)
44 : context(nullptr)
45 , witness_index(IS_CONSTANT)
46 {
48 multiplicative_constant = barretenberg::fr(0);
49 }
50
51 field_t(const barretenberg::fr& value)
52 : context(nullptr)
53 , additive_constant(value)
54 , multiplicative_constant(barretenberg::fr(1))
55 , witness_index(IS_CONSTANT)
56 {}
57
58 field_t(const uint256_t& value)
59 : context(nullptr)
60 , additive_constant(value)
61 , multiplicative_constant(barretenberg::fr(1))
62 , witness_index(IS_CONSTANT)
63 {}
64
65 field_t(const witness_t<Builder>& value);
66
67 field_t(const field_t& other)
68 : context(other.context)
70 , multiplicative_constant(other.multiplicative_constant)
72 {}
73
74 field_t(field_t&& other) noexcept
75 : context(other.context)
77 , multiplicative_constant(other.multiplicative_constant)
79 {}
80
81 field_t(const bool_t<Builder>& other);
82
83 ~field_t() = default;
84
85 static constexpr bool is_composite = false;
86 static constexpr uint256_t modulus = barretenberg::fr::modulus;
87
88 static field_t from_witness_index(Builder* parent_context, uint32_t witness_index);
89
90 explicit operator bool_t<Builder>() const;
91
92 field_t& operator=(const field_t& other)
93 {
94 if (this == &other) {
95 return *this;
96 }
98 multiplicative_constant = other.multiplicative_constant;
100 context = (other.context == nullptr ? nullptr : other.context);
101 return *this;
102 }
103
104 field_t& operator=(field_t&& other) noexcept
105 {
107 multiplicative_constant = other.multiplicative_constant;
109 context = (other.context == nullptr ? nullptr : other.context);
110 return *this;
111 }
112
113 static field_t copy_as_new_witness(Builder& context, field_t const& other)
114 {
115 auto result = field_t<Builder>(witness_t<Builder>(&context, other.get_value()));
116 result.assert_equal(other, "field_t::copy_as_new_witness, assert_equal");
117 return result;
118 }
119
120 field_t operator+(const field_t& other) const;
121 field_t operator-(const field_t& other) const;
122 field_t operator*(const field_t& other) const;
123 field_t operator/(const field_t& other) const;
124 field_t divide_no_zero_check(const field_t& other) const;
125
126 field_t sqr() const { return operator*(*this); }
127
128 // N.B. we implicitly range-constrain 'other' to be a 32-bit integer!
129 field_t pow(const field_t& exponent) const;
130
131 field_t operator+=(const field_t& other)
132 {
133 *this = *this + other;
134 return *this;
135 }
136 field_t operator-=(const field_t& other)
137 {
138 *this = *this - other;
139 return *this;
140 }
141 field_t operator*=(const field_t& other)
142 {
143 *this = *this * other;
144 return *this;
145 }
146 field_t operator/=(const field_t& other)
147 {
148 *this = *this / other;
149 return *this;
150 }
151
152 // Prefix increment (++x)
153 field_t& operator++()
154 {
155 *this = *this + 1;
156 return *this;
157 };
158
159 // Postfix increment (x++)
160 // NOLINTNEXTLINE
161 field_t operator++(const int)
162 {
163 field_t this_before_operation = field_t(*this);
164 *this = *this + 1;
165 return this_before_operation;
166 };
167
168 field_t invert() const { return (field_t(1) / field_t(*this)).normalize(); }
169
170 static field_t coset_generator(const size_t generator_idx)
171 {
172 return field_t(barretenberg::fr::coset_generator(generator_idx));
173 }
174
175 static field_t external_coset_generator() { return field_t(barretenberg::fr::external_coset_generator()); }
176
177 field_t operator-() const
178 {
179 field_t result(*this);
180 result.multiplicative_constant = -multiplicative_constant;
182
183 return result;
184 }
185
186 field_t conditional_negate(const bool_t<Builder>& predicate) const;
187
188 void assert_equal(const field_t& rhs, std::string const& msg = "field_t::assert_equal") const;
189
190 void assert_not_equal(const field_t& rhs, std::string const& msg = "field_t::assert_not_equal") const;
191
192 void assert_is_in_set(const std::vector<field_t>& set, std::string const& msg = "field_t::assert_not_in_set") const;
193
194 static field_t conditional_assign(const bool_t<Builder>& predicate, const field_t& lhs, const field_t& rhs);
195
196 static std::array<field_t, 4> preprocess_two_bit_table(const field_t& T0,
197 const field_t& T1,
198 const field_t& T2,
199 const field_t& T3);
200 static field_t select_from_two_bit_table(const std::array<field_t, 4>& table,
201 const bool_t<Builder>& t1,
202 const bool_t<Builder>& t0);
203
204 static std::array<field_t, 8> preprocess_three_bit_table(const field_t& T0,
205 const field_t& T1,
206 const field_t& T2,
207 const field_t& T3,
208 const field_t& T4,
209 const field_t& T5,
210 const field_t& T6,
211 const field_t& T7);
212 static field_t select_from_three_bit_table(const std::array<field_t, 8>& table,
213 const bool_t<Builder>& t2,
214 const bool_t<Builder>& t1,
215 const bool_t<Builder>& t0);
216
217 static void evaluate_linear_identity(const field_t& a, const field_t& b, const field_t& c, const field_t& d);
218 static void evaluate_polynomial_identity(const field_t& a, const field_t& b, const field_t& c, const field_t& d);
219
220 static field_t accumulate(const std::vector<field_t>& to_add);
221
226 field_t madd(const field_t& to_mul, const field_t& to_add) const;
227
228 // add_two costs 1 constraint for ultra plonk
229 field_t add_two(const field_t& add_a, const field_t& add_b) const;
230 bool_t<Builder> operator==(const field_t& other) const;
231 bool_t<Builder> operator!=(const field_t& other) const;
232
246 field_t normalize() const;
247
248 barretenberg::fr get_value() const;
249
250 Builder* get_context() const { return context; }
251
256 std::array<field_t, 3> slice(uint8_t msb, uint8_t lsb) const;
257
262 bool_t<Builder> is_zero() const;
263
264 void create_range_constraint(size_t num_bits, std::string const& msg = "field_t::range_constraint") const;
265 void assert_is_not_zero(std::string const& msg = "field_t::assert_is_not_zero") const;
266 void assert_is_zero(std::string const& msg = "field_t::assert_is_zero") const;
267 bool is_constant() const { return witness_index == IS_CONSTANT; }
268 void set_public() const { context->set_public_input(normalize().witness_index); }
269
275 {
276 ASSERT(witness_index == IS_CONSTANT);
277 context = ctx;
278 (*this) = field_t<Builder>(witness_t<Builder>(context, get_value()));
279 context->fix_witness(witness_index, get_value());
280 }
281
282 static field_t from_witness(Builder* ctx, const barretenberg::fr& input)
283 {
284 return field_t(witness_t<Builder>(ctx, input));
285 }
286
291 {
292 ASSERT(witness_index != IS_CONSTANT);
293 auto context = get_context();
294 ASSERT(context != nullptr);
295 context->fix_witness(witness_index, get_value());
296 }
297
298 uint32_t get_witness_index() const { return witness_index; }
299
300 std::vector<bool_t<Builder>> decompose_into_bits(
301 size_t num_bits = 256,
302 std::function<witness_t<Builder>(Builder* ctx, uint64_t, uint256_t)> get_bit =
303 [](Builder* ctx, uint64_t j, const uint256_t& val) {
304 return witness_t<Builder>(ctx, val.get_bit(j));
305 }) const;
306
318 template <size_t num_bits> bool_t<Builder> ranged_less_than(const field_t<Builder>& other) const
319 {
320 const auto& a = (*this);
321 const auto& b = other;
322 auto* ctx = a.context ? a.context : b.context;
323 if (a.is_constant() && b.is_constant()) {
324 return uint256_t(a.get_value()) < uint256_t(b.get_value());
325 }
326
327 // a < b
328 // both a and b are < K where K = 2^{input_bits} - 1
329 // if a < b, this implies b - a - 1 < K
330 // if a >= b, this implies b - a + K - 1 < K
331 // i.e. (b - a - 1) * q + (b - a + K - 1) * (1 - q) = r < K
332 // q.(b - a - b + a) + b - a + K - 1 - (K - 1).q - q = r
333 // b - a + (K - 1) - (K).q = r
334 uint256_t range_constant = (uint256_t(1) << num_bits);
335 bool predicate_witness = uint256_t(a.get_value()) < uint256_t(b.get_value());
336 bool_t<Builder> predicate(witness_t<Builder>(ctx, predicate_witness));
337 field_t predicate_valid = b.add_two(-(a) + range_constant - 1, -field_t(predicate) * range_constant);
338 predicate_valid.create_range_constraint(num_bits);
339 return predicate;
340 }
341
342 mutable Builder* context = nullptr;
343
380 mutable barretenberg::fr multiplicative_constant;
381
423 mutable uint32_t witness_index = IS_CONSTANT;
424};
425
426template <typename Builder> inline std::ostream& operator<<(std::ostream& os, field_t<Builder> const& v)
427{
428 return os << v.get_value();
429}
430
431EXTERN_STDLIB_TYPE(field_t);
432
433} // namespace proof_system::plonk::stdlib
Definition: uint256.hpp:25
virtual void set_public_input(const uint32_t witness_index)
Definition: circuit_builder_base.hpp:290
Definition: standard_circuit_builder.hpp:12
Definition: field.hpp:10
field_t operator*(const field_t &other) const
Definition: field.cpp:141
std::array< field_t, 3 > slice(uint8_t msb, uint8_t lsb) const
Definition: field.cpp:1033
static field_t accumulate(const std::vector< field_t > &to_add)
Definition: field.cpp:936
barretenberg::fr additive_constant
Definition: field.hpp:379
uint32_t witness_index
Definition: field.hpp:423
std::vector< bool_t< Builder > > decompose_into_bits(size_t num_bits=256, std::function< witness_t< Builder >(Builder *ctx, uint64_t, uint256_t)> get_bit=[](Builder *ctx, uint64_t j, const uint256_t &val) { return witness_t< Builder >(ctx, val.get_bit(j));}) const
Build a circuit allowing a user to prove that they have deomposed this into bits.
Definition: field.cpp:1090
void fix_witness()
Definition: field.hpp:290
void convert_constant_to_fixed_witness(Builder *ctx)
Definition: field.hpp:274
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^{input_bits} - 1 i...
Definition: field.hpp:318
field_t normalize() const
Definition: field.cpp:482
void assert_equal(const field_t &rhs, std::string const &msg="field_t::assert_equal") const
Constrain that this field is equal to the given field.
Definition: field.cpp:749
bool_t< Builder > is_zero() const
Definition: field.cpp:588
field_t madd(const field_t &to_mul, const field_t &to_add) const
Definition: field.cpp:384
field_t pow(const field_t &exponent) const
raise a field_t to a power of an exponent (field_t). Note that the exponent must not exceed 32 bits a...
Definition: field.cpp:346
Definition: witness.hpp:10