github.com/consensys/gnark@v0.11.0/frontend/witness.go (about) 1 package frontend 2 3 import ( 4 "math/big" 5 "reflect" 6 7 "github.com/consensys/gnark/backend/witness" 8 "github.com/consensys/gnark/frontend/schema" 9 ) 10 11 // NewWitness build an ordered vector of field elements from the given assignment (Circuit) 12 // if PublicOnly is specified, returns the public part of the witness only 13 // else returns [public | secret]. The result can then be serialized to / from json & binary. 14 // 15 // See ExampleWitness in witness package for usage. 16 func NewWitness(assignment Circuit, field *big.Int, opts ...WitnessOption) (witness.Witness, error) { 17 opt, err := options(opts...) 18 if err != nil { 19 return nil, err 20 } 21 22 // count the leaves 23 s, err := schema.Walk(assignment, tVariable, nil) 24 if err != nil { 25 return nil, err 26 } 27 if opt.publicOnly { 28 s.Secret = 0 29 } 30 31 // allocate the witness 32 w, err := witness.New(field) 33 if err != nil { 34 return nil, err 35 } 36 37 // write the public | secret values in a chan 38 chValues := make(chan any) 39 go func() { 40 defer close(chValues) 41 schema.Walk(assignment, tVariable, func(leaf schema.LeafInfo, tValue reflect.Value) error { 42 if leaf.Visibility == schema.Public { 43 chValues <- tValue.Interface() 44 } 45 return nil 46 }) 47 if !opt.publicOnly { 48 schema.Walk(assignment, tVariable, func(leaf schema.LeafInfo, tValue reflect.Value) error { 49 if leaf.Visibility == schema.Secret { 50 chValues <- tValue.Interface() 51 } 52 return nil 53 }) 54 } 55 }() 56 if err := w.Fill(s.Public, s.Secret, chValues); err != nil { 57 return nil, err 58 } 59 60 return w, nil 61 } 62 63 // NewSchema returns the schema corresponding to the circuit structure. 64 // 65 // This is used to JSON (un)marshall witnesses. 66 func NewSchema(circuit Circuit) (*schema.Schema, error) { 67 return schema.New(circuit, tVariable) 68 } 69 70 // default options 71 func options(opts ...WitnessOption) (witnessConfig, error) { 72 // apply options 73 opt := witnessConfig{ 74 publicOnly: false, 75 } 76 for _, option := range opts { 77 if err := option(&opt); err != nil { 78 return opt, err 79 } 80 } 81 82 return opt, nil 83 } 84 85 // WitnessOption sets optional parameter to witness instantiation from an assignment 86 type WitnessOption func(*witnessConfig) error 87 88 type witnessConfig struct { 89 publicOnly bool 90 } 91 92 // PublicOnly enables to instantiate a witness with the public part only of the assignment 93 func PublicOnly() WitnessOption { 94 return func(opt *witnessConfig) error { 95 opt.publicOnly = true 96 return nil 97 } 98 }