|
| | field_t (Builder *parent_context=nullptr) |
| |
| | field_t (Builder *parent_context, const bb::fr &value) |
| |
| | field_t (const int value) |
| |
| | field_t (const unsigned long long value) |
| |
| | field_t (const unsigned int value) |
| |
| | field_t (const unsigned long value) |
| |
| | field_t (const bb::fr &value) |
| |
| | field_t (const uint256_t &value) |
| |
| | field_t (const witness_t< Builder > &value) |
| |
| | field_t (const field_t &other) |
| |
| | field_t (field_t &&other) noexcept |
| |
| | field_t (const bool_t< Builder > &other) |
| |
| | ~field_t ()=default |
| |
| | operator bool_t< Builder > () const |
| | Convert field_t element to bool_t and enforce bool constraints.
|
| |
| field_t & | operator= (const field_t &other) |
| |
| field_t & | operator= (field_t &&other) noexcept |
| |
| field_t | operator+ (const field_t &other) const |
| | Field addition operator.
|
| |
| field_t | operator- (const field_t &other) const |
| | Subtraction operator deduced from the addition operator.
|
| |
| field_t | operator* (const field_t &other) const |
| | Field multiplication operator.
|
| |
| field_t | operator/ (const field_t &other) const |
| | Since in divide_no_zero_check, we check \( a / b = q \) by the constraint \( a = b \cdot q\), if \( a =
b= 0\), we can set \( q \) to any value and it will pass the constraint. Hence, when not having prior knowledge of \( b \) not being zero it is essential to check.
|
| |
| bool_t< Builder > | operator== (const field_t &other) const |
| | Compute a bool_t equal to (a == b)
|
| |
| bool_t< Builder > | operator!= (const field_t &other) const |
| | Compute a bool_t equal to (a != b)
|
| |
| 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.
|
| |
| field_t | sqr () const |
| |
| field_t | pow (const uint32_t &exponent) const |
| | Raise this field element to the power of the provided uint32_t exponent.
|
| |
| 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 and is implicitly range constrained.
|
| |
| field_t | operator+= (const field_t &other) |
| |
| field_t | operator-= (const field_t &other) |
| |
| field_t | operator*= (const field_t &other) |
| |
| field_t | operator/= (const field_t &other) |
| |
| field_t & | operator++ () |
| |
| field_t | operator++ (const int) |
| |
| field_t | invert () const |
| |
| field_t | operator- () const |
| |
| void | set_origin_tag (const OriginTag &new_tag) const |
| |
| OriginTag | get_origin_tag () const |
| |
| void | set_free_witness_tag () |
| | Set the free witness flag for the field element's tag.
|
| |
| void | unset_free_witness_tag () const |
| | Unset the free witness flag for the field element's tag.
|
| |
| field_t | conditional_negate (const bool_t< Builder > &predicate) const |
| | If predicate's value == true, negate the value, else keep it unchanged.
|
| |
| 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.
|
| |
| 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.
|
| |
| 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.
|
| |
| field_t | madd (const field_t &to_mul, const field_t &to_add) const |
| |
| field_t | add_two (const field_t &add_b, const field_t &add_c) const |
| | Efficiently compute (this + a + b) using big_mul gate.
|
| |
| field_t | normalize () const |
| | Return a new element, where the in-circuit witness contains the actual represented value (multiplicative constant is 1 and additive_constant is 0)
|
| |
| bb::fr | get_value () const |
| | Given a := *this, compute its value given by a.v * a.mul + a.add.
|
| |
| Builder * | get_context () const |
| |
| 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:
|
| |
| bool_t< Builder > | is_zero () const |
| | Validate whether a field_t element is zero.
|
| |
| 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}.
|
| |
| 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.
|
| |
| 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.
|
| |
| bool | is_constant () const |
| |
| bool | is_normalized () const |
| |
| uint32_t | set_public () const |
| |
| void | convert_constant_to_fixed_witness (Builder *ctx) |
| |
| void | fix_witness () |
| |
| uint32_t | get_witness_index () const |
| | Get the witness index of the current field element.
|
| |
| uint32_t | get_normalized_witness_index () const |
| | Get the index of a normalized version of this element.
|
| |
| template<size_t num_bits> |
| 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.e. it is not checked here, we assume this has been done previously.
|
| |
|
| static field_t | from_witness_index (Builder *ctx, uint32_t witness_index) |
| |
| static field_t | copy_as_new_witness (Builder &context, field_t const &other) |
| |
| 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.
|
| |
| 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, t1 that on a input binary string b of length 2, equals T_b. In the Lagrange basis, the desired polynomial is given by the formula (1 - t0)(1 - t1).T0 + t0(1 - t1).T1 + (1 - t0)t1.T2 + t0.t1.T3.
|
| |
| 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 coefficients, compute its evaluation at the point (t0, t1) using minimal number of gates.
|
| |
| 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, t1, t2, that on a input binary string b of length 3, equals T_b.
|
| |
| 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 coefficients, compute its evaluation at (t0, t1, t2) using minimal number of gates.
|
| |
| 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.
|
| |
| 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.
|
| |
| 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 needed to compute from input.size() to input_size.size() / 3.
|
| |
| static field_t | from_witness (Builder *ctx, const bb::fr &input) |
| |
| static field_t | reconstruct_from_public (const std::span< const field_t, PUBLIC_INPUTS_SIZE > &limbs) |
| |
template<typename Builder_>
class bb::stdlib::field_t< Builder_ >
Definition at line 45 of file field.hpp.
Validate whether a field_t element is zero.
Let a := (*this).normalize() is_zero := (a == 0)
To check whether a = 0, we use the fact that, if a != 0, it has a modular inverse I, such that a * I = 1.
We reduce the check to the following algebraic constraints 1) a * I - 1 + is_zero = 0 2) -is_zero * I + is_zero = 0
If the value of is_zero is false, the first equation reduces to a * I = 1 then I must be the modular inverse of a, therefore a != 0. This explains the first constraint.
If is_zero = true, then either a or I is zero (or both). To ensure that a = 0 && I != 0 we use the second constraint, it validates that (is_zero.v = true) ==> (I = 1) This way, if a * I = 0, we know that a = 0.
- Warning
- If you want to ENFORCE that a field_t object is zero, use
assert_is_zero
Definition at line 776 of file field.cpp.
template<typename Builder_ >
additive_constant and multiplicative_constant are constant scaling factors applied to a field_t object.
The 'value' represented by a field_t is calculated as:
- For
field_ts with witness_index = IS_CONSTANT: this.additive_constant
- For non-constant
field_ts: this.context->variables[this.witness_index] * this.multiplicative_constant + this.additive_constant
We track these scaling factors, because we can apply the same scaling factors to Plonk wires when creating gates. I.e. if we want to multiply a wire by a constant, or add a constant, we do not need to add extra gates to do this. Instead, we track the scaling factors, and apply them to the relevant wires when adding constraints.
This also makes constant field_t objects effectively free. (Where 'constant' is a circuit constant, not a C++ constant!). E.g. the following 3 lines of code add 0 constraints into a circuit:
field_t foo = 1; field_t bar = 5; field_t bar *= foo;
Similarly if we add in:
field_t zip = witness_t(context, 10); zip *= bar + foo;
The above adds 0 constraints, the only effect is that zip's scaling factors have been modified. However if we now add:
field_t zap = witness_t(context, 50); zip *= zap;
This will add a constraint, as both zip and zap map to circuit witnesses.
Definition at line 88 of file field.hpp.
template<typename Builder_ >
Every builder object contains a vector variables (a.k.a. 'witnesses'); circuit variables that can be assigned to wires when creating constraints. witness_index describes a location in this container. I.e. it 'points' to a circuit variable.
A witness is not the same thing as a 'wire' in a circuit. Multiple wires can be assigned to the same witness via Plonk's copy constraints. Alternatively, a witness might not be assigned to any wires! This case would be similar to an unused variable in a regular program
E.g. if we write field_t foo = witness_t(context, 100), this will add the value 100 into context's list of circuit variables. However if we do not use foo in any operations, then this value will never be assigned to a wire in a circuit.
For a more in depth example, consider the following code:
field_t foo = witness_t(context, 10); field_t bar = witness_t(context, 50); field_t baz = foo * (bar + 7);
This will add 3 new circuit witnesses (10, 50, 570) to variables. One constraint will also be created, that validates baz has been correctly constructed. The builder will assign foo, bar, baz to wires w_1, w_2, w_3 in a new gate which checks that:
w_1 * w_2 + w_1 * 7 - w_3 = 0
If any of foo, bar, baz are used in future arithmetic, copy constraints will be automatically applied, this ensure that all gate wires that map to foo, for example, will contain the same value.
If witness_index == IS_CONSTANT, the object represents a constant value. i.e. a value that's hardcoded in the circuit, that a prover cannot change by modifying their witness transcript.
A Plonk gate is a mix of witness values and selector values. e.g. the regular PLONK arithmetic gate checks that:
w_1 * w_2 * q_m + w_1 * q_1 + w_2 * q_2 + w_3 * q_3 + q_c = 0
The w value are wires, the q values are selector constants. If a field object contains a witness_index, it will be assigned to w values when constraints are applied. If it's a circuit constant, it will be assigned to q values.
TLDR: witness_index is a pseudo pointer to a circuit witness
Definition at line 132 of file field.hpp.