arnaucube
arnaucube/go-dvotePublic Self-hosted repository
go-dvote/tree/tree.go
tree/tree.goRaw
  1package tree
  2
  3import (
  4	"bytes"
  5	"errors"
  6	"os/user"
  7
  8	common3 "github.com/iden3/go-iden3/common"
  9	mkcore "github.com/iden3/go-iden3/core"
 10	db "github.com/iden3/go-iden3/db"
 11	merkletree "github.com/iden3/go-iden3/merkletree"
 12)
 13
 14type Tree struct {
 15	Storage   string
 16	Tree      *merkletree.MerkleTree
 17	DbStorage *db.LevelDbStorage
 18}
 19
 20func (t *Tree) Init(namespace string) error {
 21	if len(t.Storage) < 1 {
 22		if len(namespace) < 1 {
 23			return errors.New("namespace not valid")
 24		}
 25		usr, err := user.Current()
 26		if err == nil {
 27			t.Storage = usr.HomeDir + "/.dvote/census/" + namespace
 28		} else {
 29			t.Storage = "./dvoteTree/" + namespace
 30		}
 31	}
 32	mtdb, err := db.NewLevelDbStorage(t.Storage, false)
 33	if err != nil {
 34		return err
 35	}
 36	mt, err := merkletree.NewMerkleTree(mtdb, 140)
 37	if err != nil {
 38		return err
 39	}
 40	t.DbStorage = mtdb
 41	t.Tree = mt
 42	return nil
 43}
 44
 45func (t *Tree) Close() {
 46	defer t.Tree.Storage().Close()
 47}
 48
 49func (t *Tree) GetClaim(data []byte) (*mkcore.ClaimBasic, error) {
 50	if len(data) > 496/8 {
 51		return nil, errors.New("claim data too large")
 52	}
 53	for i := len(data); i <= 496/8; i++ {
 54		data = append(data, byte('.'))
 55	}
 56	var indexSlot [400 / 8]byte
 57	var dataSlot [496 / 8]byte
 58	copy(indexSlot[:], data[:400/8])
 59	copy(dataSlot[:], data[:496/8])
 60	e := mkcore.NewClaimBasic(indexSlot, dataSlot)
 61	return e, nil
 62}
 63
 64func (t *Tree) AddClaim(data []byte) error {
 65	e, err := t.GetClaim(data)
 66	if err != nil {
 67		return err
 68	}
 69	return t.Tree.Add(e.Entry())
 70}
 71
 72func (t *Tree) GenProof(data []byte) (string, error) {
 73	e, err := t.GetClaim(data)
 74	if err != nil {
 75		return "", err
 76	}
 77	mp, err := t.Tree.GenerateProof(e.Entry().HIndex())
 78	if err != nil {
 79		return "", err
 80	}
 81	mpHex := common3.HexEncode(mp.Bytes())
 82	return mpHex, nil
 83}
 84
 85func (t *Tree) CheckProof(data []byte, mpHex string) (bool, error) {
 86	mpBytes, err := common3.HexDecode(mpHex)
 87	if err != nil {
 88		return false, err
 89	}
 90	mp, err := merkletree.NewProofFromBytes(mpBytes)
 91	if err != nil {
 92		return false, err
 93	}
 94	e, err := t.GetClaim(data)
 95	if err != nil {
 96		return false, err
 97	}
 98	return merkletree.VerifyProof(t.Tree.RootKey(), mp,
 99		e.Entry().HIndex(), e.Entry().HValue()), nil
100}
101
102func (t *Tree) GetRoot() string {
103	return t.Tree.RootKey().String()
104}
105
106func (t *Tree) GetIndex(data []byte) (string, error) {
107	e, err := t.GetClaim(data)
108	if err != nil {
109		return "", err
110	}
111	index, err := t.Tree.GetDataByIndex(e.Entry().HIndex())
112	return index.String(), err
113}
114
115/*
116func (t *Tree) Dump() ([]string, error) {
117	var response []string
118
119	err := t.Tree.Walk(t.Tree.RootKey(), func(n *merkletree.Node) {
120		if n.Type == merkletree.NodeTypeLeaf {
121			rawValue := n.Value()
122			var cleanValue []byte
123			for i := 0; i < len(rawValue); i++ {
124				if rawValue[i] == byte('.') {
125					break
126				}
127				cleanValue = append(cleanValue, rawValue[i])
128			}
129			response = append(response, fmt.Sprintf("%s", cleanValue))
130		}
131	})
132	return response, err
133}
134*/
135
136func (t *Tree) Dump() (string, error) {
137	w := bytes.NewBufferString("")
138	err := t.Tree.DumpClaims(w, nil) // as rootKey we can pass a nil pointer, and it will use the current RootKey
139
140	return w.String(), err
141}
142
143func (t *Tree) Snapshot(root string) (*Tree, error) {
144	var rootHash merkletree.Hash
145	copy(rootHash[:32], root)
146	mt, err := t.Tree.Snapshot(&rootHash)
147	snapshotTree := new(Tree)
148	snapshotTree.Tree = mt
149	return snapshotTree, err
150}