Documentation
¶
Overview ¶
Package uints implements optimised byte and long integer operations.
Usually arithmetic in a circuit is performed in the native field, which is of prime order. However, for compatibility with native operations we rely on operating on smaller primitive types as 8-bit, 32-bit and 64-bit integer. Naively, these operations have to be implemented bitwise as there are no closed equations for boolean operations (XOR, AND, OR).
However, the bitwise approach is very inefficient and leads to several constraints per bit. Accumulating over a long integer, it leads to very inefficients circuits.
This package performs boolean operations using lookup tables on bytes. So, long integers are split into 4 or 8 bytes and we perform the operations bytewise. In the lookup tables, we store results for all possible 2^8×2^8 inputs. With this approach, every bytewise operation costs as single lookup, which depending on the backend is relatively cheap (one to three constraints).
NB! The package is still work in progress. The interfaces and implementation details most certainly changes over time. We cannot ensure the soundness of the operations.
Index ¶
- func GetHints() []solver.Hint
- type BinaryField
- func (bf *BinaryField[T]) Add(a ...T) T
- func (bf *BinaryField[T]) And(a ...T) T
- func (bf *BinaryField[T]) AssertEq(a, b T)
- func (bf *BinaryField[T]) ByteAssertEq(a, b U8)
- func (bf *BinaryField[T]) ByteValueOf(a frontend.Variable) U8
- func (bf *BinaryField[T]) Lrot(a T, c int) T
- func (bf *BinaryField[T]) Not(a T) T
- func (bf *BinaryField[T]) Or(a ...T) T
- func (bf *BinaryField[T]) PackLSB(a ...U8) T
- func (bf *BinaryField[T]) PackMSB(a ...U8) T
- func (bf *BinaryField[T]) Rshift(a T, c int) T
- func (bf *BinaryField[T]) ToValue(a T) frontend.Variable
- func (bf *BinaryField[T]) UnpackLSB(a T) []U8
- func (bf *BinaryField[T]) UnpackMSB(a T) []U8
- func (bf *BinaryField[T]) ValueOf(a frontend.Variable) T
- func (bf *BinaryField[T]) Xor(a ...T) T
- type Bytes
- func (bf *Bytes) And(a ...U8) U8
- func (bf *Bytes) AssertIsEqual(a, b U8)
- func (bf *Bytes) Not(a U8) U8
- func (bf *Bytes) Or(a ...U8) U8
- func (bf *Bytes) Select(selector frontend.Variable, a, b U8) U8
- func (bf *Bytes) Value(a U8) frontend.Variable
- func (bf *Bytes) ValueOf(a frontend.Variable) U8
- func (bf *Bytes) ValueUnchecked(a U8) frontend.Variable
- func (bf *Bytes) Xor(a ...U8) U8
- type Long
- type U32
- type U64
- type U8
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type BinaryField ¶
func New ¶
func New[T Long](api frontend.API) (*BinaryField[T], error)
New is an alias to NewBinaryField. It is retained for backwards compatibility. New uses should use NewBinaryField instead.
func NewBinaryField ¶ added in v0.14.0
func NewBinaryField[T Long](api frontend.API) (*BinaryField[T], error)
NewBinaryField creates a new BinaryField for the given integer type T specified by parameter Long. It allows to manipulate long integers in circuit.
func (*BinaryField[T]) Add ¶
func (bf *BinaryField[T]) Add(a ...T) T
func (*BinaryField[T]) And ¶
func (bf *BinaryField[T]) And(a ...T) T
func (*BinaryField[T]) AssertEq ¶
func (bf *BinaryField[T]) AssertEq(a, b T)
func (*BinaryField[T]) ByteAssertEq ¶
func (bf *BinaryField[T]) ByteAssertEq(a, b U8)
func (*BinaryField[T]) ByteValueOf ¶
func (bf *BinaryField[T]) ByteValueOf(a frontend.Variable) U8
ByteValueOf converts a frontend.Variable into a single byte. If the input doesn't fit into a byte then solver fails.
func (*BinaryField[T]) Lrot ¶
func (bf *BinaryField[T]) Lrot(a T, c int) T
func (*BinaryField[T]) Not ¶
func (bf *BinaryField[T]) Not(a T) T
func (*BinaryField[T]) Or ¶ added in v0.12.0
func (bf *BinaryField[T]) Or(a ...T) T
func (*BinaryField[T]) PackLSB ¶
func (bf *BinaryField[T]) PackLSB(a ...U8) T
func (*BinaryField[T]) PackMSB ¶
func (bf *BinaryField[T]) PackMSB(a ...U8) T
func (*BinaryField[T]) Rshift ¶
func (bf *BinaryField[T]) Rshift(a T, c int) T
func (*BinaryField[T]) ToValue ¶
func (bf *BinaryField[T]) ToValue(a T) frontend.Variable
ToValue converts a long integer value into a single frontend.Variable.
func (*BinaryField[T]) UnpackLSB ¶
func (bf *BinaryField[T]) UnpackLSB(a T) []U8
func (*BinaryField[T]) UnpackMSB ¶
func (bf *BinaryField[T]) UnpackMSB(a T) []U8
func (*BinaryField[T]) ValueOf ¶
func (bf *BinaryField[T]) ValueOf(a frontend.Variable) T
ValueOf converts a frontend.Variable into a long integer. If the input doesn't fit into T then solver fails.
func (*BinaryField[T]) Xor ¶
func (bf *BinaryField[T]) Xor(a ...T) T
type Bytes ¶ added in v0.14.0
type Bytes struct {
// contains filtered or unexported fields
}
Bytes implements methods for manipulating bytes in circuit. Use NewBytes to create a new instance.
func NewBytes ¶ added in v0.14.0
NewBytes creates a new Bytes instance which can manipulate bytes and byte arrays. For manipulating long integers, use BinaryField instead.
This is a caching constructor, meaning that it will return the same instance if called multiple times. This is useful as internally it uses lookup tables for bitwise operations and it amortizes the cost of creating these lookup tables.
func (*Bytes) AssertIsEqual ¶ added in v0.14.0
func (*Bytes) Select ¶ added in v0.14.0
Select returns a new U8 value which is:
- if selector is true then a
- if selector is false then b
func (*Bytes) Value ¶ added in v0.14.0
Value returns the value of the U8 variables, ensuring that it is range checked. It is preferrable to use this method instead of directly using the [U8.Val] field.
func (*Bytes) ValueOf ¶ added in v0.14.0
ValueOf returns a constrainted U8 variable. For a constant value, use NewU8 instead.
func (*Bytes) ValueUnchecked ¶ added in v0.14.0
ValueUnchecked returns the value of the U8 variables without range checking.
type U32 ¶
type U32 [4]U8
func NewU32 ¶
NewU32 creates a new U32 value. It represents a 32-bit unsigned integer which is split into 4 bytes. It can both be used in-circuit to initialize a constant or as a witness assignment. For in-circuit initialization use BinaryField.ValueOf method instead which ensures that the value is range checked.
func NewU32Array ¶
NewU32Array is a utility method to create a slice of U32 from a slice of uint32.
type U64 ¶
type U64 [8]U8
func NewU64 ¶
NewU64 creates a new U64 value. It represents a 64-bit unsigned integer which is split into 4 bytes. It can both be used in-circuit to initialize a constant or as a witness assignment. For in-circuit initialization use BinaryField.ValueOf method instead which ensures that the value is range checked.
func NewU64Array ¶
NewU64Array is a utility method to create a slice of U64 from a slice of uint64.
type U8 ¶
type U8 struct { // Val is the value of the byte. It can be a constant or a variable. // NB! dont't access it directly! Val frontend.Variable // contains filtered or unexported fields }
U8 represents a single byte (uint8) in the circuit. Users should not create U8 values directly, but rather use NewU8 (for in-circuit constant initialization or witness assignment) or Bytes.ValueOf (for in-circuit variable initialization).
Users should not access the [U8.Val] field directly, but rather use Bytes.Value method to ensure that the value is range checked to be 8 bits.
func NewU8 ¶
NewU8 creates a new U8 value. It represents a single byte. It can both be used in-circuit to initialize a constant or as a witness assignment. For in-circuit initialization use Bytes.ValueOf method instead which ensures that the value is range checked.
func NewU8Array ¶
NewU8Array is a utility method to create a slice of U8 from a slice of uint8.