arbo/circomproofs.go
circomproofs.goRaw
1package arbo
2
3import (
4 "encoding/json"
5)
6
7// CircomVerifierProof contains the needed data to check a Circom Verifier Proof
8// inside a circom circuit. CircomVerifierProof allow to verify through a
9// zkSNARK proof the inclusion/exclusion of a leaf in a tree.
10type CircomVerifierProof struct {
11 Root []byte `json:"root"`
12 Siblings [][]byte `json:"siblings"`
13 OldKey []byte `json:"oldKey"`
14 OldValue []byte `json:"oldValue"`
15 IsOld0 bool `json:"isOld0"`
16 Key []byte `json:"key"`
17 Value []byte `json:"value"`
18 Fnc int `json:"fnc"` // 0: inclusion, 1: non inclusion
19}
20
21// MarshalJSON implements the JSON marshaler
22func (cvp CircomVerifierProof) MarshalJSON() ([]byte, error) {
23 m := make(map[string]interface{})
24
25 m["root"] = BytesToBigInt(cvp.Root).String()
26 m["siblings"] = siblingsToStringArray(cvp.Siblings)
27 m["oldKey"] = BytesToBigInt(cvp.OldKey).String()
28 m["oldValue"] = BytesToBigInt(cvp.OldValue).String()
29 if cvp.IsOld0 {
30 m["isOld0"] = "1"
31 } else {
32 m["isOld0"] = "0"
33 }
34 m["key"] = BytesToBigInt(cvp.Key).String()
35 m["value"] = BytesToBigInt(cvp.Value).String()
36 m["fnc"] = cvp.Fnc
37
38 return json.Marshal(m)
39}
40
41func siblingsToStringArray(s [][]byte) []string {
42 var r []string
43 for i := 0; i < len(s); i++ {
44 r = append(r, BytesToBigInt(s[i]).String())
45 }
46 return r
47}
48
49// FillMissingEmptySiblings adds the empty values to the array of siblings for
50// the Tree number of max levels
51func (t *Tree) FillMissingEmptySiblings(s [][]byte) [][]byte {
52 for i := len(s); i < t.maxLevels; i++ {
53 s = append(s, emptyValue)
54 }
55 return s
56}
57
58// GenerateCircomVerifierProof generates a CircomVerifierProof for a given key
59// in the Tree
60func (t *Tree) GenerateCircomVerifierProof(k []byte) (*CircomVerifierProof, error) {
61 kAux, v, siblings, existence, err := t.GenProof(k)
62 if err != nil && err != ErrKeyNotFound {
63 return nil, err
64 }
65 var cp CircomVerifierProof
66 cp.Root, err = t.Root()
67 if err != nil {
68 return nil, err
69 }
70 s, err := UnpackSiblings(t.hashFunction, siblings)
71 if err != nil {
72 return nil, err
73 }
74 cp.Siblings = t.FillMissingEmptySiblings(s)
75 if !existence {
76 cp.OldKey = kAux
77 cp.OldValue = v
78 } else {
79 cp.OldKey = emptyValue
80 cp.OldValue = emptyValue
81 }
82 cp.Key = k
83 cp.Value = v
84 if existence {
85 cp.Fnc = 0 // inclusion
86 } else {
87 cp.Fnc = 1 // non inclusion
88 }
89
90 return &cp, nil
91}