go-dvote/tree/tree.go
tree/tree.goRaw
1package tree
2
3import (
4 "errors"
5 "fmt"
6 "os/user"
7 "strings"
8
9 common3 "github.com/vocdoni/go-iden3/common"
10 mkcore "github.com/vocdoni/go-iden3/core"
11 "github.com/vocdoni/go-iden3/db"
12 "github.com/vocdoni/go-iden3/merkletree"
13)
14
15type Tree struct {
16 Namespace string
17 Storage string
18 Tree *merkletree.MerkleTree
19 DbStorage *db.LevelDbStorage
20}
21
22func (t *Tree) Init() error {
23 if len(t.Storage) < 1 {
24 usr, err := user.Current()
25 if err == nil {
26 t.Storage = usr.HomeDir + "/.dvote/Tree"
27 } else {
28 t.Storage = "./dvoteTree"
29 }
30 }
31 mtdb, err := db.NewLevelDbStorage(t.Storage, false)
32 if err != nil {
33 return err
34 }
35 mt, err := merkletree.New(mtdb, 140)
36 if err != nil {
37 return err
38 }
39 t.DbStorage = mtdb
40 t.Tree = mt
41 return nil
42}
43
44func (t *Tree) Close() {
45 defer t.Tree.Storage().Close()
46}
47
48func (t *Tree) AddClaim(data []byte) error {
49 isSnapshot := strings.HasPrefix(t.Namespace, "0x")
50 if isSnapshot {
51 return errors.New("No new claims can be added to a Snapshot")
52 }
53 claim := mkcore.NewGenericClaim(t.Namespace, "default", data, nil)
54 return t.Tree.Add(claim)
55}
56
57func (t *Tree) GenProof(data []byte) (string, error) {
58 claim := mkcore.NewGenericClaim(t.Namespace, "default", data, nil)
59 mp, err := t.Tree.GenerateProof(claim.Hi())
60 if err != nil {
61 return "", err
62 }
63 mpHex := common3.BytesToHex(mp)
64 return mpHex, nil
65}
66
67func (t *Tree) CheckProof(data []byte, mpHex string) (bool, error) {
68 mp, err := common3.HexToBytes(mpHex)
69 if err != nil {
70 return false, err
71 }
72 claim := mkcore.NewGenericClaim(t.Namespace, "default", data, nil)
73 return merkletree.CheckProof(t.Tree.Root(), mp, claim.Hi(), claim.Ht(), t.Tree.NumLevels()), nil
74}
75
76func (t *Tree) GetRoot() string {
77 return t.Tree.Root().Hex()
78}
79
80/* Dump, Export and Snapshot functions are a bit tricky.
81 Since go-iden3 does not provide the necessary tools. Low level operations must be performed.
82 Once go-iden3 API is mature enough, these functions must be adapted.
83
84 To explore: Values are stored twice in the BD?
85*/
86func (t *Tree) Dump() ([]string, error) {
87 var response []string
88 substorage := t.DbStorage.WithPrefix([]byte(t.Namespace))
89 nsHash := merkletree.HashBytes([]byte(t.Namespace))
90 substorage.Iterate(func(key, value []byte) {
91 nsValue := value[5:37]
92 if fmt.Sprint(nsHash) == fmt.Sprint(nsValue) {
93 response = append(response, string(value[69:]))
94 }
95 })
96 return response, nil
97}
98
99func (t *Tree) Snapshot() (string, error) {
100 substorage := t.DbStorage.WithPrefix([]byte(t.Namespace))
101 nsHash := merkletree.HashBytes([]byte(t.Namespace))
102 snapshotNamespace := t.GetRoot()
103 fmt.Printf("Snapshoting %s\n", snapshotNamespace)
104 t.Namespace = snapshotNamespace
105 substorage.Iterate(func(key, value []byte) {
106 nsValue := value[5:37]
107 if fmt.Sprint(nsHash) == fmt.Sprint(nsValue) {
108 fmt.Printf("%x\n", value)
109 data := value[69:]
110 //claim := mkcore.NewGenericClaim(snapshotNamespace, "default", data, nil)
111 err := t.AddClaim(data)
112 if err != nil {
113 fmt.Println(err)
114 }
115 }
116 })
117 return snapshotNamespace, nil
118}