package arbo import ( "encoding/json" ) // CircomVerifierProof contains the needed data to check a Circom Verifier Proof // inside a circom circuit. CircomVerifierProof allow to verify through a // zkSNARK proof the inclusion/exclusion of a leaf in a tree. type CircomVerifierProof struct { Root []byte `json:"root"` Siblings [][]byte `json:"siblings"` OldKey []byte `json:"oldKey"` OldValue []byte `json:"oldValue"` IsOld0 bool `json:"isOld0"` Key []byte `json:"key"` Value []byte `json:"value"` Fnc int `json:"fnc"` // 0: inclusion, 1: non inclusion } // MarshalJSON implements the JSON marshaler func (cvp CircomVerifierProof) MarshalJSON() ([]byte, error) { m := make(map[string]interface{}) m["root"] = BytesToBigInt(cvp.Root).String() m["siblings"] = siblingsToStringArray(cvp.Siblings) m["oldKey"] = BytesToBigInt(cvp.OldKey).String() m["oldValue"] = BytesToBigInt(cvp.OldValue).String() if cvp.IsOld0 { m["isOld0"] = "1" } else { m["isOld0"] = "0" } m["key"] = BytesToBigInt(cvp.Key).String() m["value"] = BytesToBigInt(cvp.Value).String() m["fnc"] = cvp.Fnc return json.Marshal(m) } func siblingsToStringArray(s [][]byte) []string { var r []string for i := 0; i < len(s); i++ { r = append(r, BytesToBigInt(s[i]).String()) } return r } // FillMissingEmptySiblings adds the empty values to the array of siblings for // the Tree number of max levels func (t *Tree) FillMissingEmptySiblings(s [][]byte) [][]byte { for i := len(s); i < t.maxLevels; i++ { s = append(s, emptyValue) } return s } // GenerateCircomVerifierProof generates a CircomVerifierProof for a given key // in the Tree func (t *Tree) GenerateCircomVerifierProof(k []byte) (*CircomVerifierProof, error) { kAux, v, siblings, existence, err := t.GenProof(k) if err != nil && err != ErrKeyNotFound { return nil, err } var cp CircomVerifierProof cp.Root, err = t.Root() if err != nil { return nil, err } s, err := UnpackSiblings(t.hashFunction, siblings) if err != nil { return nil, err } cp.Siblings = t.FillMissingEmptySiblings(s) if !existence { cp.OldKey = kAux cp.OldValue = v } else { cp.OldKey = emptyValue cp.OldValue = emptyValue } cp.Key = k cp.Value = v if existence { cp.Fnc = 0 // inclusion } else { cp.Fnc = 1 // non inclusion } return &cp, nil }