Documentation ¶
Overview ¶
Package witness provides serialization helpers to encode a witness into a []byte.
Binary protocol
Witness -> [uint32(nbPublic) | uint32(nbSecret) | fr.Vector(variables)] fr.Vector is a *field element* vector encoded a big-endian byte array like so: [uint32(len(vector)) | elements]
Ordering ¶
First, `publicVariables`, then `secretVariables`. Each subset is ordered from the order of definition in the circuit structure. For example, with this circuit on `ecc.BN254`
type Circuit struct { X frontend.Variable Y frontend.Variable `gnark:",public"` Z frontend.Variable }
A valid witness would be:
- `[uint32(1)|uint32(2)|uint32(3)|bytes(Y)|bytes(X)|bytes(Z)]`
- Hex representation with values `Y = 35`, `X = 3`, `Z = 2` `000000010000000200000003000000000000000000000000000000000000000000000000000000000000002300000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000002`
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrInvalidWitness = errors.New("invalid witness")
Functions ¶
This section is empty.
Types ¶
type Witness ¶
type Witness interface { io.WriterTo io.ReaderFrom encoding.BinaryMarshaler encoding.BinaryUnmarshaler // Public returns the Public an object containing the public part of the Witness only. Public() (Witness, error) // Vector returns the underlying fr.Vector slice Vector() any // ToJSON returns the JSON encoding of the witness following the provided Schema. This is a // convenience method and should be avoided in most cases. ToJSON(s *schema.Schema) ([]byte, error) // FromJSON parses a JSON data input and attempt to reconstruct a witness following the provided Schema. // This is a convenience method and should be avoided in most cases. FromJSON(s *schema.Schema, data []byte) error // Fill range over the provided chan to fill the underlying vector. // Will allocate the underlying vector with nbPublic + nbSecret elements. // This is typically call by internal APIs to fill the vector by walking a structure. Fill(nbPublic, nbSecret int, values <-chan any) error }
Witness represents a zkSNARK witness.
The underlying data structure is a vector of field elements, but a Witness also may have some additional meta information about the number of public elements and secret elements.
In most cases a Witness should be [de]serialized using a binary protocol. JSON conversions for pretty printing are slow and don't handle all complex circuit structures well.
Example ¶
package main import ( "bytes" "encoding/json" "fmt" "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/backend/witness" "github.com/consensys/gnark/frontend" ) type circuit struct { X frontend.Variable `gnark:",public"` Y frontend.Variable `gnark:",public"` E frontend.Variable } func (c *circuit) Define(frontend.API) error { return nil } func main() { // Witnesses can be created directly by "walking" through an assignment (circuit structure) // simple assignment assignment := &circuit{ X: 42, Y: 8000, E: 1, } w, _ := frontend.NewWitness(assignment, ecc.BN254.ScalarField()) // Binary [de]serialization data, _ := w.MarshalBinary() reconstructed, _ := witness.New(ecc.BN254.ScalarField()) reconstructed.UnmarshalBinary(data) // For pretty printing, we can do JSON conversions; they are not efficient and don't handle // complex circuit structures well. // first get the circuit expected schema schema, _ := frontend.NewSchema(assignment) ret, _ := reconstructed.ToJSON(schema) var b bytes.Buffer json.Indent(&b, ret, "", "\t") fmt.Println(b.String()) }
Output: { "X": 42, "Y": 8000, "E": 1 }