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.

149 lines
3.4 KiB

  1. // Package arbotree provides the functions for creating and managing an arbo
  2. // merkletree adapted to the CensusTree interface
  3. package arbotree
  4. import (
  5. "bytes"
  6. "encoding/hex"
  7. "fmt"
  8. "path/filepath"
  9. "strings"
  10. "sync/atomic"
  11. "time"
  12. "github.com/arnaucube/arbo"
  13. "github.com/iden3/go-merkletree/db/leveldb"
  14. "go.vocdoni.io/dvote/censustree"
  15. )
  16. type Tree struct {
  17. Tree *arbo.Tree
  18. public uint32
  19. lastAccessUnix int64 // a unix timestamp, used via sync/atomic
  20. }
  21. func (t *Tree) Init(name, storageDir string) error {
  22. dbDir := filepath.Join(storageDir, "arbotree.db."+strings.TrimSpace(name))
  23. storage, err := leveldb.NewLevelDbStorage(dbDir, false) // TODO TMP
  24. if err != nil {
  25. return err
  26. }
  27. mt, err := arbo.NewTree(storage, 140, arbo.HashFunctionBlake2b) // TODO here the hash function would depend on the usage
  28. if err != nil {
  29. return err
  30. }
  31. t.Tree = mt
  32. return nil
  33. }
  34. func (t *Tree) MaxKeySize() int {
  35. return t.Tree.HashFunction().Len()
  36. }
  37. func (t *Tree) LastAccess() int64 {
  38. return atomic.LoadInt64(&t.lastAccessUnix)
  39. }
  40. func (t *Tree) updateAccessTime() {
  41. atomic.StoreInt64(&t.lastAccessUnix, time.Now().Unix())
  42. }
  43. // Publish makes a merkle tree available for queries.
  44. // Application layer should check IsPublish() before considering the Tree available.
  45. func (t *Tree) Publish() {
  46. atomic.StoreUint32(&t.public, 1)
  47. }
  48. // UnPublish makes a merkle tree not available for queries
  49. func (t *Tree) UnPublish() {
  50. atomic.StoreUint32(&t.public, 0)
  51. }
  52. // IsPublic returns true if the tree is available
  53. func (t *Tree) IsPublic() bool {
  54. return atomic.LoadUint32(&t.public) == 1
  55. }
  56. func (t *Tree) Add(index, value []byte) error {
  57. t.updateAccessTime()
  58. return t.Tree.Add(index, value)
  59. }
  60. func (t *Tree) AddBatch(indexes, values [][]byte) ([]int, error) {
  61. t.updateAccessTime()
  62. return t.Tree.AddBatch(indexes, values)
  63. }
  64. func (t *Tree) GenProof(index, value []byte) ([]byte, error) {
  65. t.updateAccessTime()
  66. v, siblings, err := t.Tree.GenProof(index)
  67. if err != nil {
  68. return nil, err
  69. }
  70. if !bytes.Equal(v, value) {
  71. return nil, fmt.Errorf("value does not match %s!=%s", hex.EncodeToString(v), hex.EncodeToString(value))
  72. }
  73. return siblings, nil
  74. }
  75. func (t *Tree) CheckProof(index, value, root, mproof []byte) (bool, error) {
  76. t.updateAccessTime()
  77. if root == nil {
  78. root = t.Root()
  79. }
  80. return arbo.CheckProof(t.Tree.HashFunction(), index, value, root, mproof)
  81. }
  82. func (t *Tree) Root() []byte {
  83. t.updateAccessTime()
  84. return t.Tree.Root()
  85. }
  86. func (t *Tree) Dump(root []byte) ([]byte, error) {
  87. return t.Tree.Dump() // TODO pass root once arbo is updated
  88. }
  89. func (t *Tree) DumpPlain(root []byte) ([][]byte, [][]byte, error) {
  90. t.updateAccessTime()
  91. var indexes, values [][]byte
  92. // TODO pass root once arbo is updated
  93. err := t.Tree.Iterate(func(k, v []byte) {
  94. if v[0] != arbo.PrefixValueLeaf {
  95. return
  96. }
  97. leafK, leafV := arbo.ReadLeafValue(v)
  98. indexes = append(indexes, leafK)
  99. values = append(values, leafV)
  100. })
  101. return indexes, values, err
  102. }
  103. func (t *Tree) ImportDump(data []byte) error {
  104. t.updateAccessTime()
  105. return t.Tree.ImportDump(data)
  106. }
  107. func (t *Tree) Size(root []byte) (int64, error) {
  108. count := 0
  109. err := t.Tree.Iterate(func(k, v []byte) {
  110. if v[0] != arbo.PrefixValueLeaf {
  111. return
  112. }
  113. count++
  114. })
  115. return int64(count), err
  116. }
  117. func (t *Tree) Snapshot(root []byte) (censustree.Tree, error) {
  118. // TODO
  119. return t, nil
  120. }
  121. func (t *Tree) HashExists(hash []byte) (bool, error) {
  122. _, _, err := t.Tree.Get(hash)
  123. if err != nil {
  124. return false, err
  125. }
  126. return true, nil
  127. }