go-dvote/tree/tree.go
tree/tree.goRaw
1package tree
2
3import (
4 "errors"
5 "fmt"
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) Dump() ([]string, error) {
107 var response []string
108
109 err := t.Tree.Walk(t.Tree.RootKey(), func(n *merkletree.Node) {
110 if n.Type == merkletree.NodeTypeLeaf {
111 rawValue := n.Value()
112 var cleanValue []byte
113 for i := 0; i < len(rawValue); i++ {
114 if rawValue[i] == byte('.') {
115 break
116 }
117 cleanValue = append(cleanValue, rawValue[i])
118 }
119 response = append(response, fmt.Sprintf("%s", cleanValue))
120 }
121 })
122 return response, err
123}
124
125func (t *Tree) Snapshot() (string, error) {
126 snapshotNamespace := t.Tree.RootKey().String()
127 return snapshotNamespace, nil
128}