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.

420 lines
11 KiB

  1. package asmtree
  2. import (
  3. "bytes"
  4. "fmt"
  5. "path"
  6. "sync/atomic"
  7. "time"
  8. "go.vocdoni.io/dvote/censustree"
  9. "go.vocdoni.io/dvote/log"
  10. "git.sr.ht/~sircmpwn/go-bare"
  11. "github.com/p4u/asmt/db"
  12. asmt "github.com/p4u/asmt/smt"
  13. )
  14. // We use go-bare for export/import the trie. In order to support
  15. // big census (up to 8 Million entries) we need to increase the maximums.
  16. const bareMaxArrayLength uint64 = 1024 * 1014 * 8 // 8 Million
  17. const bareMaxUnmarshalBytes uint64 = 1024 * 1024 * 200 // 200 MiB
  18. type Tree struct {
  19. Tree *asmt.Trie
  20. db db.DB
  21. public uint32
  22. lastAccessUnix int64 // a unix timestamp, used via sync/atomic
  23. size uint64
  24. snapshotRoot []byte // if not nil, this trie is considered an inmutable snapshot
  25. snapshotSize uint64
  26. }
  27. type Proof struct {
  28. Bitmap []byte
  29. Length int
  30. Siblings [][]byte
  31. Value []byte
  32. }
  33. type exportElement struct {
  34. Key []byte `bare:"key"`
  35. Value []byte `bare:"value"`
  36. }
  37. type exportData struct {
  38. Elements []exportElement `bare:"elements"`
  39. }
  40. const (
  41. MaxKeySize = 256
  42. MaxValueSize = 256
  43. dbRootPrefix = "this is the last root for the SMT tree"
  44. )
  45. // NewTree initializes a new AergoSMT tree following the censustree.Tree interface specification.
  46. func NewTree(name, storageDir string) (censustree.Tree, error) {
  47. tr := &Tree{}
  48. err := tr.Init(name, storageDir)
  49. return tr, err
  50. }
  51. // newTree opens or creates a merkle tree under the given storage.
  52. func newTree(name, storageDir string) (*asmt.Trie, db.DB, error) {
  53. dir := path.Join(storageDir, name)
  54. log.Debugf("creating new tree on %s", dir)
  55. d := db.NewDB(db.LevelImpl, dir)
  56. root := d.Get([]byte(dbRootPrefix))
  57. tr := asmt.NewTrie(root, asmt.Hasher, d)
  58. if root != nil {
  59. if err := tr.LoadCache(root); err != nil {
  60. return nil, nil, err
  61. }
  62. }
  63. return tr, d, nil
  64. }
  65. // Init initializes a new asmt tree
  66. func (t *Tree) Init(name, storageDir string) error {
  67. var err error
  68. t.Tree, t.db, err = newTree(name, storageDir)
  69. t.updateAccessTime()
  70. t.size = 0
  71. return err
  72. }
  73. func (t *Tree) MaxKeySize() int {
  74. return MaxKeySize
  75. }
  76. // LastAccess returns the last time the Tree was accessed, in the form of a unix
  77. // timestamp.
  78. func (t *Tree) LastAccess() int64 {
  79. return atomic.LoadInt64(&t.lastAccessUnix)
  80. }
  81. func (t *Tree) updateAccessTime() {
  82. atomic.StoreInt64(&t.lastAccessUnix, time.Now().Unix())
  83. }
  84. // Publish makes a merkle tree available for queries.
  85. // Application layer should check IsPublish() before considering the Tree available.
  86. func (t *Tree) Publish() {
  87. atomic.StoreUint32(&t.public, 1)
  88. }
  89. // UnPublish makes a merkle tree not available for queries
  90. func (t *Tree) UnPublish() {
  91. atomic.StoreUint32(&t.public, 0)
  92. }
  93. // IsPublic returns true if the tree is available
  94. func (t *Tree) IsPublic() bool {
  95. return atomic.LoadUint32(&t.public) == 1
  96. }
  97. // Commit saves permanently the tree on disk
  98. func (t *Tree) Commit() error {
  99. if t.snapshotRoot != nil {
  100. return fmt.Errorf("cannot commit to a snapshot trie")
  101. }
  102. err := t.Tree.Commit()
  103. if err != nil {
  104. return err
  105. }
  106. t.db.Set([]byte(dbRootPrefix), t.Root())
  107. return nil
  108. }
  109. // Add adds a new claim to the merkle tree
  110. // A claim is composed of two parts: index and value
  111. // 1.index is mandatory, the data will be used for indexing the claim into to merkle tree
  112. // 2.value is optional, the data will not affect the indexing
  113. func (t *Tree) Add(index, value []byte) error {
  114. t.updateAccessTime()
  115. if t.snapshotRoot != nil {
  116. return fmt.Errorf("cannot add to a snapshot trie")
  117. }
  118. if len(index) < 4 {
  119. return fmt.Errorf("index too small (%d), minimum size is 4 bytes", len(index))
  120. }
  121. if len(value) > MaxValueSize {
  122. return fmt.Errorf("index or value claim data too big")
  123. }
  124. _, err := t.Tree.Update([][]byte{asmt.Hasher(index)}, [][]byte{asmt.Hasher(value)})
  125. if err != nil {
  126. return err
  127. }
  128. atomic.StoreUint64(&t.size, 0) // TBD: improve this
  129. return t.Commit()
  130. }
  131. // AddBatch adds a list of indexes and values.
  132. // The commit to disk is executed only once.
  133. // The values slince could be empty or as long as indexes.
  134. func (t *Tree) AddBatch(indexes, values [][]byte) ([]int, error) {
  135. var wrongIndexes []int
  136. t.updateAccessTime()
  137. if t.snapshotRoot != nil {
  138. return wrongIndexes, fmt.Errorf("cannot add to a snapshot trie")
  139. }
  140. if len(values) > 0 && len(indexes) != len(values) {
  141. return wrongIndexes, fmt.Errorf("indexes and values have different size")
  142. }
  143. var hashedIndexes [][]byte
  144. var hashedValues [][]byte
  145. var value []byte
  146. for i, key := range indexes {
  147. if len(key) < 4 {
  148. wrongIndexes = append(wrongIndexes, i)
  149. continue
  150. }
  151. value = nil
  152. if len(values) > 0 {
  153. if len(values[i]) > MaxValueSize {
  154. wrongIndexes = append(wrongIndexes, i)
  155. continue
  156. }
  157. value = values[i]
  158. }
  159. hashedIndexes = append(hashedIndexes, asmt.Hasher(key))
  160. hashedValues = append(hashedValues, asmt.Hasher(value))
  161. }
  162. _, err := t.Tree.Update(hashedIndexes, hashedValues)
  163. if err != nil {
  164. return wrongIndexes, err
  165. }
  166. atomic.StoreUint64(&t.size, 0) // TBD: improve this
  167. return wrongIndexes, t.Commit()
  168. }
  169. // Get returns the value of a key
  170. func (t *Tree) Get(key []byte) []byte { // Do something with error
  171. var value []byte
  172. if t.snapshotRoot != nil {
  173. value, _ = t.Tree.GetWithRoot(key, t.snapshotRoot)
  174. } else {
  175. value, _ = t.Tree.Get(key)
  176. }
  177. return value
  178. }
  179. // GenProof generates a merkle tree proof that can be later used on CheckProof() to validate it.
  180. func (t *Tree) GenProof(index, value []byte) ([]byte, error) {
  181. t.updateAccessTime()
  182. var err error
  183. var ap [][]byte
  184. var pvalue []byte
  185. var bitmap []byte
  186. var length int
  187. if t.snapshotRoot != nil {
  188. bitmap, ap, length, _, _, pvalue, err = t.Tree.MerkleProofCompressedR(
  189. asmt.Hasher(index),
  190. t.snapshotRoot)
  191. if err != nil {
  192. return nil, err
  193. }
  194. } else {
  195. bitmap, ap, length, _, _, pvalue, err = t.Tree.MerkleProofCompressed(
  196. asmt.Hasher(index))
  197. if err != nil {
  198. return nil, err
  199. }
  200. }
  201. //if !included {
  202. // return nil, fmt.Errorf("not included")
  203. //}
  204. if !bytes.Equal(pvalue, asmt.Hasher(value)) {
  205. return nil, fmt.Errorf("incorrect value on genProof")
  206. }
  207. return bare.Marshal(&Proof{Bitmap: bitmap, Length: length, Siblings: ap, Value: pvalue})
  208. }
  209. // CheckProof validates a merkle proof and its data.
  210. func (t *Tree) CheckProof(index, value, root, mproof []byte) (bool, error) {
  211. t.updateAccessTime()
  212. p := Proof{}
  213. if err := bare.Unmarshal(mproof, &p); err != nil {
  214. return false, err
  215. }
  216. if !bytes.Equal(p.Value, asmt.Hasher(value)) {
  217. return false, fmt.Errorf("values mismatch %x != %x", p.Value, asmt.Hasher(value))
  218. }
  219. if root != nil {
  220. return t.Tree.VerifyInclusionWithRootC(
  221. root,
  222. p.Bitmap,
  223. asmt.Hasher(index),
  224. p.Value,
  225. p.Siblings,
  226. p.Length), nil
  227. }
  228. if t.snapshotRoot != nil {
  229. return t.Tree.VerifyInclusionWithRootC(
  230. t.snapshotRoot,
  231. p.Bitmap,
  232. asmt.Hasher(index),
  233. p.Value,
  234. p.Siblings,
  235. p.Length), nil
  236. }
  237. return t.Tree.VerifyInclusionC(
  238. p.Bitmap,
  239. asmt.Hasher(index),
  240. p.Value,
  241. p.Siblings,
  242. p.Length), nil
  243. }
  244. // Root returns the current root hash of the merkle tree
  245. func (t *Tree) Root() []byte {
  246. t.updateAccessTime()
  247. if t.snapshotRoot != nil {
  248. return t.snapshotRoot
  249. }
  250. return t.Tree.Root
  251. }
  252. // Dump returns the whole merkle tree serialized in a format that can be used on Import.
  253. // Byte seralization is performed using bare message protocol, it is a 40% size win over JSON.
  254. func (t *Tree) Dump(root []byte) ([]byte, error) {
  255. t.updateAccessTime()
  256. if root == nil && t.snapshotRoot != nil {
  257. root = t.snapshotRoot
  258. }
  259. dump := exportData{}
  260. t.iterateWithRoot(root, nil, func(k, v []byte) bool {
  261. ee := exportElement{Key: make([]byte, len(k)), Value: make([]byte, len(v))}
  262. // Copy elements since it's not safe to hold on to the []byte values from Iterate
  263. copy(ee.Key, k[:])
  264. copy(ee.Value, v[:])
  265. dump.Elements = append(dump.Elements, ee)
  266. return false
  267. })
  268. bare.MaxArrayLength(bareMaxArrayLength)
  269. bare.MaxUnmarshalBytes(bareMaxUnmarshalBytes)
  270. return bare.Marshal(&dump)
  271. }
  272. // String returns a human readable representation of the tree.
  273. func (t *Tree) String() string {
  274. s := bytes.Buffer{}
  275. t.iterate(t.snapshotRoot, func(k, v []byte) bool {
  276. s.WriteString(fmt.Sprintf("%x => %x\n", k, v))
  277. return false
  278. })
  279. return s.String()
  280. }
  281. // Size returns the number of leaf nodes on the merkle tree.
  282. // TO-DO: root is currently ignored
  283. func (t *Tree) Size(root []byte) (int64, error) {
  284. if t.snapshotRoot != nil {
  285. return int64(t.snapshotSize), nil
  286. }
  287. return int64(t.count()), nil
  288. }
  289. // DumpPlain returns the entire list of added claims for a specific root hash.
  290. // First return parametre are the indexes and second the values.
  291. // If root is not specified, the last one is used.
  292. func (t *Tree) DumpPlain(root []byte) ([][]byte, [][]byte, error) {
  293. var indexes, values [][]byte
  294. var err error
  295. t.updateAccessTime()
  296. t.iterateWithRoot(root, nil, func(k, v []byte) bool {
  297. indexes = append(indexes, k)
  298. values = append(values, v)
  299. return false
  300. })
  301. return indexes, values, err
  302. }
  303. // ImportDump imports a partial or whole tree previously exported with Dump()
  304. func (t *Tree) ImportDump(data []byte) error {
  305. t.updateAccessTime()
  306. if t.snapshotRoot != nil {
  307. return fmt.Errorf("cannot import to a snapshot")
  308. }
  309. census := new(exportData)
  310. bare.MaxArrayLength(bareMaxArrayLength)
  311. bare.MaxUnmarshalBytes(bareMaxUnmarshalBytes)
  312. if err := bare.Unmarshal(data, census); err != nil {
  313. return fmt.Errorf("importdump cannot unmarshal data: %w", err)
  314. }
  315. keys := [][]byte{}
  316. values := [][]byte{}
  317. for _, ee := range census.Elements {
  318. keys = append(keys, ee.Key)
  319. values = append(values, ee.Value)
  320. }
  321. _, err := t.Tree.Update(keys, values)
  322. if err != nil {
  323. return err
  324. }
  325. atomic.StoreUint64(&t.size, 0) // TBD: improve this
  326. return t.Commit()
  327. }
  328. // Snapshot returns a Tree instance of a exiting merkle root.
  329. // A Snapshot cannot be modified.
  330. func (t *Tree) Snapshot(root []byte) (censustree.Tree, error) {
  331. exist, err := t.HashExists(root)
  332. if err != nil {
  333. return nil, err
  334. }
  335. if !exist {
  336. return nil, fmt.Errorf("root %x does not exist, cannot build snapshot", root)
  337. }
  338. return &Tree{Tree: t.Tree, public: t.public, snapshotRoot: root, snapshotSize: t.count()}, nil
  339. }
  340. func (t *Tree) Close() error {
  341. t.db.Close()
  342. return nil
  343. }
  344. // HashExists checks if a hash exists as a node in the merkle tree
  345. func (t *Tree) HashExists(hash []byte) (bool, error) {
  346. t.updateAccessTime()
  347. return t.Tree.TrieRootExists(hash), nil
  348. }
  349. func (t *Tree) count() uint64 {
  350. if v := atomic.LoadUint64(&t.size); v != 0 {
  351. return v
  352. }
  353. counter := uint64(0)
  354. if err := t.Tree.Walk(t.snapshotRoot, func(*asmt.WalkResult) int32 {
  355. counter++
  356. return 0
  357. }); err != nil {
  358. return 0
  359. }
  360. atomic.StoreUint64(&t.size, counter)
  361. return counter
  362. }
  363. func (t *Tree) iterate(prefix []byte, callback func(key, value []byte) bool) {
  364. t.Tree.Walk(t.snapshotRoot, func(v *asmt.WalkResult) int32 {
  365. if callback(v.Key, v.Value) {
  366. return 1
  367. } else {
  368. return 0
  369. }
  370. })
  371. }
  372. func (t *Tree) iterateWithRoot(root, prefix []byte, callback func(key, value []byte) bool) {
  373. t.Tree.Walk(root, func(v *asmt.WalkResult) int32 {
  374. if callback(v.Key, v.Value) {
  375. return 1
  376. } else {
  377. return 0
  378. }
  379. })
  380. }