arnaucube
arnaucube/go-dvotePublic Self-hosted repository
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}