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