You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

118 lines
3.0 KiB

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