Files
arbo/circomproofs.go
arnaucube 5f6c35e435 Update Snapshot & Root approach
Update Snapshot & Root approach to get the root always from the db,
except in the cases that the tree is a snapshot, in which the root will
be in memory.
In this way, when a snapshot is performed and the original tree gets
modifyed, the snapshot will still point to the old root. Also, the root
obtained from the db, uses also the db.ReadTx, so if the root is being
modifyied in the current tx (db.WriteTx), when getting the root it will
be return the lastest version that is in the tx but not yet in the db.
2021-08-13 12:38:05 +02:00

92 lines
2.3 KiB
Go

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
}