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.

777 lines
19 KiB

3 years ago
3 years ago
  1. /*
  2. Package arbo implements a Merkle Tree compatible with the circomlib
  3. implementation of the MerkleTree (when using the Poseidon hash function),
  4. following the specification from
  5. https://docs.iden3.io/publications/pdfs/Merkle-Tree.pdf and
  6. https://eprint.iacr.org/2018/955.
  7. Also allows to define which hash function to use. So for example, when working
  8. with zkSnarks the Poseidon hash function can be used, but when not, it can be
  9. used the Blake3 hash function, which improves the computation time.
  10. */
  11. package arbo
  12. import (
  13. "bytes"
  14. "encoding/hex"
  15. "fmt"
  16. "io"
  17. "math"
  18. "sync"
  19. "sync/atomic"
  20. "time"
  21. "github.com/iden3/go-merkletree/db"
  22. )
  23. const (
  24. // PrefixValueLen defines the bytes-prefix length used for the Value
  25. // bytes representation stored in the db
  26. PrefixValueLen = 2
  27. // PrefixValueEmpty is used for the first byte of a Value to indicate
  28. // that is an Empty value
  29. PrefixValueEmpty = 0
  30. // PrefixValueLeaf is used for the first byte of a Value to indicate
  31. // that is a Leaf value
  32. PrefixValueLeaf = 1
  33. // PrefixValueIntermediate is used for the first byte of a Value to
  34. // indicate that is a Intermediate value
  35. PrefixValueIntermediate = 2
  36. )
  37. var (
  38. dbKeyRoot = []byte("root")
  39. emptyValue = []byte{0}
  40. )
  41. // Tree defines the struct that implements the MerkleTree functionalities
  42. type Tree struct {
  43. sync.RWMutex
  44. tx db.Tx
  45. db db.Storage
  46. lastAccess int64 // in unix time
  47. maxLevels int
  48. root []byte
  49. hashFunction HashFunction
  50. }
  51. // NewTree returns a new Tree, if there is a Tree still in the given storage, it
  52. // will load it.
  53. func NewTree(storage db.Storage, maxLevels int, hash HashFunction) (*Tree, error) {
  54. t := Tree{db: storage, maxLevels: maxLevels, hashFunction: hash}
  55. t.updateAccessTime()
  56. root, err := t.dbGet(dbKeyRoot)
  57. if err == db.ErrNotFound {
  58. // store new root 0
  59. tx, err := t.db.NewTx()
  60. if err != nil {
  61. return nil, err
  62. }
  63. t.root = make([]byte, t.hashFunction.Len()) // empty
  64. if err = tx.Put(dbKeyRoot, t.root); err != nil {
  65. return nil, err
  66. }
  67. if err = tx.Commit(); err != nil {
  68. return nil, err
  69. }
  70. return &t, err
  71. } else if err != nil {
  72. return nil, err
  73. }
  74. t.root = root
  75. return &t, nil
  76. }
  77. func (t *Tree) updateAccessTime() {
  78. atomic.StoreInt64(&t.lastAccess, time.Now().Unix())
  79. }
  80. // LastAccess returns the last access timestamp in Unixtime
  81. func (t *Tree) LastAccess() int64 {
  82. return atomic.LoadInt64(&t.lastAccess)
  83. }
  84. // Root returns the root of the Tree
  85. func (t *Tree) Root() []byte {
  86. return t.root
  87. }
  88. // AddBatch adds a batch of key-values to the Tree. This method will be
  89. // optimized to do some internal parallelization. Returns an array containing
  90. // the indexes of the keys failed to add.
  91. func (t *Tree) AddBatch(keys, values [][]byte) ([]int, error) {
  92. t.updateAccessTime()
  93. if len(keys) != len(values) {
  94. return nil, fmt.Errorf("len(keys)!=len(values) (%d!=%d)",
  95. len(keys), len(values))
  96. }
  97. t.Lock()
  98. defer t.Unlock()
  99. var err error
  100. t.tx, err = t.db.NewTx()
  101. if err != nil {
  102. return nil, err
  103. }
  104. var indexes []int
  105. for i := 0; i < len(keys); i++ {
  106. err = t.add(keys[i], values[i])
  107. if err != nil {
  108. indexes = append(indexes, i)
  109. }
  110. }
  111. // store root to db
  112. if err := t.tx.Put(dbKeyRoot, t.root); err != nil {
  113. return indexes, err
  114. }
  115. if err := t.tx.Commit(); err != nil {
  116. return nil, err
  117. }
  118. return indexes, nil
  119. }
  120. // Add inserts the key-value into the Tree. If the inputs come from a *big.Int,
  121. // is expected that are represented by a Little-Endian byte array (for circom
  122. // compatibility).
  123. func (t *Tree) Add(k, v []byte) error {
  124. t.updateAccessTime()
  125. t.Lock()
  126. defer t.Unlock()
  127. var err error
  128. t.tx, err = t.db.NewTx()
  129. if err != nil {
  130. return err
  131. }
  132. err = t.add(k, v)
  133. if err != nil {
  134. return err
  135. }
  136. // store root to db
  137. if err := t.tx.Put(dbKeyRoot, t.root); err != nil {
  138. return err
  139. }
  140. return t.tx.Commit()
  141. }
  142. func (t *Tree) add(k, v []byte) error {
  143. // TODO check validity of key & value (for the Tree.HashFunction type)
  144. keyPath := make([]byte, t.hashFunction.Len())
  145. copy(keyPath[:], k)
  146. path := getPath(t.maxLevels, keyPath)
  147. // go down to the leaf
  148. var siblings [][]byte
  149. _, _, siblings, err := t.down(k, t.root, siblings, path, 0, false)
  150. if err != nil {
  151. return err
  152. }
  153. leafKey, leafValue, err := newLeafValue(t.hashFunction, k, v)
  154. if err != nil {
  155. return err
  156. }
  157. if err := t.tx.Put(leafKey, leafValue); err != nil {
  158. return err
  159. }
  160. // go up to the root
  161. if len(siblings) == 0 {
  162. t.root = leafKey
  163. return nil
  164. }
  165. root, err := t.up(leafKey, siblings, path, len(siblings)-1)
  166. if err != nil {
  167. return err
  168. }
  169. t.root = root
  170. return nil
  171. }
  172. // down goes down to the leaf recursively
  173. func (t *Tree) down(newKey, currKey []byte, siblings [][]byte,
  174. path []bool, l int, getLeaf bool) (
  175. []byte, []byte, [][]byte, error) {
  176. if l > t.maxLevels-1 {
  177. return nil, nil, nil, fmt.Errorf("max level")
  178. }
  179. var err error
  180. var currValue []byte
  181. emptyKey := make([]byte, t.hashFunction.Len())
  182. if bytes.Equal(currKey, emptyKey) {
  183. // empty value
  184. return currKey, emptyValue, siblings, nil
  185. }
  186. currValue, err = t.dbGet(currKey)
  187. if err != nil {
  188. return nil, nil, nil, err
  189. }
  190. switch currValue[0] {
  191. case PrefixValueEmpty: // empty
  192. // TODO WIP WARNING should not be reached, as the 'if' above should avoid
  193. // reaching this point
  194. // return currKey, empty, siblings, nil
  195. panic("should not be reached, as the 'if' above should avoid reaching this point") // TMP
  196. case PrefixValueLeaf: // leaf
  197. if bytes.Equal(newKey, currKey) {
  198. return nil, nil, nil, fmt.Errorf("key already exists")
  199. }
  200. if !bytes.Equal(currValue, emptyValue) {
  201. if getLeaf {
  202. return currKey, currValue, siblings, nil
  203. }
  204. oldLeafKey, _ := readLeafValue(currValue)
  205. oldLeafKeyFull := make([]byte, t.hashFunction.Len())
  206. copy(oldLeafKeyFull[:], oldLeafKey)
  207. // if currKey is already used, go down until paths diverge
  208. oldPath := getPath(t.maxLevels, oldLeafKeyFull)
  209. siblings, err = t.downVirtually(siblings, currKey, newKey, oldPath, path, l)
  210. if err != nil {
  211. return nil, nil, nil, err
  212. }
  213. }
  214. return currKey, currValue, siblings, nil
  215. case PrefixValueIntermediate: // intermediate
  216. if len(currValue) != PrefixValueLen+t.hashFunction.Len()*2 {
  217. return nil, nil, nil,
  218. fmt.Errorf("intermediate value invalid length (expected: %d, actual: %d)",
  219. PrefixValueLen+t.hashFunction.Len()*2, len(currValue))
  220. }
  221. // collect siblings while going down
  222. if path[l] {
  223. // right
  224. lChild, rChild := readIntermediateChilds(currValue)
  225. siblings = append(siblings, lChild)
  226. return t.down(newKey, rChild, siblings, path, l+1, getLeaf)
  227. }
  228. // left
  229. lChild, rChild := readIntermediateChilds(currValue)
  230. siblings = append(siblings, rChild)
  231. return t.down(newKey, lChild, siblings, path, l+1, getLeaf)
  232. default:
  233. return nil, nil, nil, fmt.Errorf("invalid value")
  234. }
  235. }
  236. // downVirtually is used when in a leaf already exists, and a new leaf which
  237. // shares the path until the existing leaf is being added
  238. func (t *Tree) downVirtually(siblings [][]byte, oldKey, newKey []byte, oldPath,
  239. newPath []bool, l int) ([][]byte, error) {
  240. var err error
  241. if l > t.maxLevels-1 {
  242. return nil, fmt.Errorf("max virtual level %d", l)
  243. }
  244. if oldPath[l] == newPath[l] {
  245. emptyKey := make([]byte, t.hashFunction.Len())
  246. siblings = append(siblings, emptyKey)
  247. siblings, err = t.downVirtually(siblings, oldKey, newKey, oldPath, newPath, l+1)
  248. if err != nil {
  249. return nil, err
  250. }
  251. return siblings, nil
  252. }
  253. // reached the divergence
  254. siblings = append(siblings, oldKey)
  255. return siblings, nil
  256. }
  257. // up goes up recursively updating the intermediate nodes
  258. func (t *Tree) up(key []byte, siblings [][]byte, path []bool, l int) ([]byte, error) {
  259. var k, v []byte
  260. var err error
  261. if path[l] {
  262. k, v, err = newIntermediate(t.hashFunction, siblings[l], key)
  263. if err != nil {
  264. return nil, err
  265. }
  266. } else {
  267. k, v, err = newIntermediate(t.hashFunction, key, siblings[l])
  268. if err != nil {
  269. return nil, err
  270. }
  271. }
  272. // store k-v to db
  273. if err = t.tx.Put(k, v); err != nil {
  274. return nil, err
  275. }
  276. if l == 0 {
  277. // reached the root
  278. return k, nil
  279. }
  280. return t.up(k, siblings, path, l-1)
  281. }
  282. func newLeafValue(hashFunc HashFunction, k, v []byte) ([]byte, []byte, error) {
  283. leafKey, err := hashFunc.Hash(k, v, []byte{1})
  284. if err != nil {
  285. return nil, nil, err
  286. }
  287. var leafValue []byte
  288. leafValue = append(leafValue, byte(1))
  289. leafValue = append(leafValue, byte(len(k)))
  290. leafValue = append(leafValue, k...)
  291. leafValue = append(leafValue, v...)
  292. return leafKey, leafValue, nil
  293. }
  294. func readLeafValue(b []byte) ([]byte, []byte) {
  295. if len(b) < PrefixValueLen {
  296. return []byte{}, []byte{}
  297. }
  298. kLen := b[1]
  299. if len(b) < PrefixValueLen+int(kLen) {
  300. return []byte{}, []byte{}
  301. }
  302. k := b[PrefixValueLen : PrefixValueLen+kLen]
  303. v := b[PrefixValueLen+kLen:]
  304. return k, v
  305. }
  306. func newIntermediate(hashFunc HashFunction, l, r []byte) ([]byte, []byte, error) {
  307. b := make([]byte, PrefixValueLen+hashFunc.Len()*2)
  308. b[0] = 2
  309. b[1] = byte(len(l))
  310. copy(b[PrefixValueLen:PrefixValueLen+hashFunc.Len()], l)
  311. copy(b[PrefixValueLen+hashFunc.Len():], r)
  312. key, err := hashFunc.Hash(l, r)
  313. if err != nil {
  314. return nil, nil, err
  315. }
  316. return key, b, nil
  317. }
  318. func readIntermediateChilds(b []byte) ([]byte, []byte) {
  319. if len(b) < PrefixValueLen {
  320. return []byte{}, []byte{}
  321. }
  322. lLen := b[1]
  323. if len(b) < PrefixValueLen+int(lLen) {
  324. return []byte{}, []byte{}
  325. }
  326. l := b[PrefixValueLen : PrefixValueLen+lLen]
  327. r := b[PrefixValueLen+lLen:]
  328. return l, r
  329. }
  330. func getPath(numLevels int, k []byte) []bool {
  331. path := make([]bool, numLevels)
  332. for n := 0; n < numLevels; n++ {
  333. path[n] = k[n/8]&(1<<(n%8)) != 0
  334. }
  335. return path
  336. }
  337. // Update updates the value for a given existing key. If the given key does not
  338. // exist, returns an error.
  339. func (t *Tree) Update(k, v []byte) error {
  340. t.updateAccessTime()
  341. t.Lock()
  342. defer t.Unlock()
  343. var err error
  344. t.tx, err = t.db.NewTx()
  345. if err != nil {
  346. return err
  347. }
  348. keyPath := make([]byte, t.hashFunction.Len())
  349. copy(keyPath[:], k)
  350. path := getPath(t.maxLevels, keyPath)
  351. var siblings [][]byte
  352. _, valueAtBottom, siblings, err := t.down(k, t.root, siblings, path, 0, true)
  353. if err != nil {
  354. return err
  355. }
  356. oldKey, _ := readLeafValue(valueAtBottom)
  357. if !bytes.Equal(oldKey, k) {
  358. return fmt.Errorf("key %s does not exist", hex.EncodeToString(k))
  359. }
  360. leafKey, leafValue, err := newLeafValue(t.hashFunction, k, v)
  361. if err != nil {
  362. return err
  363. }
  364. if err := t.tx.Put(leafKey, leafValue); err != nil {
  365. return err
  366. }
  367. // go up to the root
  368. if len(siblings) == 0 {
  369. t.root = leafKey
  370. return t.tx.Commit()
  371. }
  372. root, err := t.up(leafKey, siblings, path, len(siblings)-1)
  373. if err != nil {
  374. return err
  375. }
  376. t.root = root
  377. // store root to db
  378. if err := t.tx.Put(dbKeyRoot, t.root); err != nil {
  379. return err
  380. }
  381. return t.tx.Commit()
  382. }
  383. // GenProof generates a MerkleTree proof for the given key. If the key exists in
  384. // the Tree, the proof will be of existence, if the key does not exist in the
  385. // tree, the proof will be of non-existence.
  386. func (t *Tree) GenProof(k []byte) ([]byte, error) {
  387. t.updateAccessTime()
  388. keyPath := make([]byte, t.hashFunction.Len())
  389. copy(keyPath[:], k)
  390. path := getPath(t.maxLevels, keyPath)
  391. // go down to the leaf
  392. var siblings [][]byte
  393. _, value, siblings, err := t.down(k, t.root, siblings, path, 0, true)
  394. if err != nil {
  395. return nil, err
  396. }
  397. leafK, leafV := readLeafValue(value)
  398. if !bytes.Equal(k, leafK) {
  399. fmt.Println("key not in Tree")
  400. fmt.Println(leafK)
  401. fmt.Println(leafV)
  402. // TODO proof of non-existence
  403. panic(fmt.Errorf("unimplemented"))
  404. }
  405. s := PackSiblings(t.hashFunction, siblings)
  406. return s, nil
  407. }
  408. // PackSiblings packs the siblings into a byte array.
  409. // [ 1 byte | L bytes | S * N bytes ]
  410. // [ bitmap length (L) | bitmap | N non-zero siblings ]
  411. // Where the bitmap indicates if the sibling is 0 or a value from the siblings
  412. // array. And S is the size of the output of the hash function used for the
  413. // Tree.
  414. func PackSiblings(hashFunc HashFunction, siblings [][]byte) []byte {
  415. var b []byte
  416. var bitmap []bool
  417. emptySibling := make([]byte, hashFunc.Len())
  418. for i := 0; i < len(siblings); i++ {
  419. if bytes.Equal(siblings[i], emptySibling) {
  420. bitmap = append(bitmap, false)
  421. } else {
  422. bitmap = append(bitmap, true)
  423. b = append(b, siblings[i]...)
  424. }
  425. }
  426. bitmapBytes := bitmapToBytes(bitmap)
  427. l := len(bitmapBytes)
  428. res := make([]byte, l+1+len(b))
  429. res[0] = byte(l) // set the bitmapBytes length
  430. copy(res[1:1+l], bitmapBytes)
  431. copy(res[1+l:], b)
  432. return res
  433. }
  434. // UnpackSiblings unpacks the siblings from a byte array.
  435. func UnpackSiblings(hashFunc HashFunction, b []byte) ([][]byte, error) {
  436. l := b[0]
  437. bitmapBytes := b[1 : 1+l]
  438. bitmap := bytesToBitmap(bitmapBytes)
  439. siblingsBytes := b[1+l:]
  440. iSibl := 0
  441. emptySibl := make([]byte, hashFunc.Len())
  442. var siblings [][]byte
  443. for i := 0; i < len(bitmap); i++ {
  444. if iSibl >= len(siblingsBytes) {
  445. break
  446. }
  447. if bitmap[i] {
  448. siblings = append(siblings, siblingsBytes[iSibl:iSibl+hashFunc.Len()])
  449. iSibl += hashFunc.Len()
  450. } else {
  451. siblings = append(siblings, emptySibl)
  452. }
  453. }
  454. return siblings, nil
  455. }
  456. func bitmapToBytes(bitmap []bool) []byte {
  457. bitmapBytesLen := int(math.Ceil(float64(len(bitmap)) / 8)) //nolint:gomnd
  458. b := make([]byte, bitmapBytesLen)
  459. for i := 0; i < len(bitmap); i++ {
  460. if bitmap[i] {
  461. b[i/8] |= 1 << (i % 8)
  462. }
  463. }
  464. return b
  465. }
  466. func bytesToBitmap(b []byte) []bool {
  467. var bitmap []bool
  468. for i := 0; i < len(b); i++ {
  469. for j := 0; j < 8; j++ {
  470. bitmap = append(bitmap, b[i]&(1<<j) > 0)
  471. }
  472. }
  473. return bitmap
  474. }
  475. // Get returns the value for a given key
  476. func (t *Tree) Get(k []byte) ([]byte, []byte, error) {
  477. keyPath := make([]byte, t.hashFunction.Len())
  478. copy(keyPath[:], k)
  479. path := getPath(t.maxLevels, keyPath)
  480. // go down to the leaf
  481. var siblings [][]byte
  482. _, value, _, err := t.down(k, t.root, siblings, path, 0, true)
  483. if err != nil {
  484. return nil, nil, err
  485. }
  486. leafK, leafV := readLeafValue(value)
  487. if !bytes.Equal(k, leafK) {
  488. panic(fmt.Errorf("%s != %s", BytesToBigInt(k), BytesToBigInt(leafK)))
  489. }
  490. return leafK, leafV, nil
  491. }
  492. // CheckProof verifies the given proof. The proof verification depends on the
  493. // HashFunction passed as parameter.
  494. func CheckProof(hashFunc HashFunction, k, v, root, packedSiblings []byte) (bool, error) {
  495. siblings, err := UnpackSiblings(hashFunc, packedSiblings)
  496. if err != nil {
  497. return false, err
  498. }
  499. keyPath := make([]byte, hashFunc.Len())
  500. copy(keyPath[:], k)
  501. key, _, err := newLeafValue(hashFunc, k, v)
  502. if err != nil {
  503. return false, err
  504. }
  505. path := getPath(len(siblings), keyPath)
  506. for i := len(siblings) - 1; i >= 0; i-- {
  507. if path[i] {
  508. key, _, err = newIntermediate(hashFunc, siblings[i], key)
  509. if err != nil {
  510. return false, err
  511. }
  512. } else {
  513. key, _, err = newIntermediate(hashFunc, key, siblings[i])
  514. if err != nil {
  515. return false, err
  516. }
  517. }
  518. }
  519. if bytes.Equal(key[:], root) {
  520. return true, nil
  521. }
  522. return false, nil
  523. }
  524. func (t *Tree) dbGet(k []byte) ([]byte, error) {
  525. // if key is empty, return empty as value
  526. empty := make([]byte, t.hashFunction.Len())
  527. if bytes.Equal(k, empty) {
  528. return empty, nil
  529. }
  530. v, err := t.db.Get(k)
  531. if err == nil {
  532. return v, nil
  533. }
  534. if t.tx != nil {
  535. return t.tx.Get(k)
  536. }
  537. return nil, db.ErrNotFound
  538. }
  539. // Iterate iterates through the full Tree, executing the given function on each
  540. // node of the Tree.
  541. func (t *Tree) Iterate(f func([]byte, []byte)) error {
  542. t.updateAccessTime()
  543. return t.iter(t.root, f)
  544. }
  545. func (t *Tree) iter(k []byte, f func([]byte, []byte)) error {
  546. v, err := t.dbGet(k)
  547. if err != nil {
  548. return err
  549. }
  550. switch v[0] {
  551. case PrefixValueEmpty:
  552. f(k, v)
  553. case PrefixValueLeaf:
  554. f(k, v)
  555. case PrefixValueIntermediate:
  556. f(k, v)
  557. l, r := readIntermediateChilds(v)
  558. if err = t.iter(l, f); err != nil {
  559. return err
  560. }
  561. if err = t.iter(r, f); err != nil {
  562. return err
  563. }
  564. default:
  565. return fmt.Errorf("invalid value")
  566. }
  567. return nil
  568. }
  569. // Dump exports all the Tree leafs in a byte array of length:
  570. // [ N * (2+len(k+v)) ]. Where N is the number of key-values, and for each k+v:
  571. // [ 1 byte | 1 byte | S bytes | len(v) bytes ]
  572. // [ len(k) | len(v) | key | value ]
  573. // Where S is the size of the output of the hash function used for the Tree.
  574. func (t *Tree) Dump() ([]byte, error) {
  575. t.updateAccessTime()
  576. // WARNING current encoding only supports key & values of 255 bytes each
  577. // (due using only 1 byte for the length headers).
  578. var b []byte
  579. err := t.Iterate(func(k, v []byte) {
  580. if v[0] != PrefixValueLeaf {
  581. return
  582. }
  583. leafK, leafV := readLeafValue(v)
  584. kv := make([]byte, 2+len(leafK)+len(leafV))
  585. kv[0] = byte(len(leafK))
  586. kv[1] = byte(len(leafV))
  587. copy(kv[2:2+len(leafK)], leafK)
  588. copy(kv[2+len(leafK):], leafV)
  589. b = append(b, kv...)
  590. })
  591. return b, err
  592. }
  593. // ImportDump imports the leafs (that have been exported with the ExportLeafs
  594. // method) in the Tree.
  595. func (t *Tree) ImportDump(b []byte) error {
  596. t.updateAccessTime()
  597. r := bytes.NewReader(b)
  598. for {
  599. l := make([]byte, 2)
  600. _, err := io.ReadFull(r, l)
  601. if err == io.EOF {
  602. break
  603. } else if err != nil {
  604. return err
  605. }
  606. k := make([]byte, l[0])
  607. _, err = io.ReadFull(r, k)
  608. if err != nil {
  609. return err
  610. }
  611. v := make([]byte, l[1])
  612. _, err = io.ReadFull(r, v)
  613. if err != nil {
  614. return err
  615. }
  616. err = t.Add(k, v)
  617. if err != nil {
  618. return err
  619. }
  620. }
  621. return nil
  622. }
  623. // Graphviz iterates across the full tree to generate a string Graphviz
  624. // representation of the tree and writes it to w
  625. func (t *Tree) Graphviz(w io.Writer, rootKey []byte) error {
  626. fmt.Fprintf(w, `digraph hierarchy {
  627. node [fontname=Monospace,fontsize=10,shape=box]
  628. `)
  629. nChars := 4
  630. nEmpties := 0
  631. empty := make([]byte, t.hashFunction.Len())
  632. err := t.Iterate(func(k, v []byte) {
  633. switch v[0] {
  634. case PrefixValueEmpty:
  635. case PrefixValueLeaf:
  636. fmt.Fprintf(w, "\"%v\" [style=filled];\n", hex.EncodeToString(k[:nChars]))
  637. // key & value from the leaf
  638. kB, vB := readLeafValue(v)
  639. fmt.Fprintf(w, "\"%v\" -> {\"k:%v\\nv:%v\"}\n",
  640. hex.EncodeToString(k[:nChars]), hex.EncodeToString(kB[:nChars]),
  641. hex.EncodeToString(vB[:nChars]))
  642. fmt.Fprintf(w, "\"k:%v\\nv:%v\" [style=dashed]\n",
  643. hex.EncodeToString(kB[:nChars]), hex.EncodeToString(vB[:nChars]))
  644. case PrefixValueIntermediate:
  645. l, r := readIntermediateChilds(v)
  646. lStr := hex.EncodeToString(l[:nChars])
  647. rStr := hex.EncodeToString(r[:nChars])
  648. eStr := ""
  649. if bytes.Equal(l, empty) {
  650. lStr = fmt.Sprintf("empty%v", nEmpties)
  651. eStr += fmt.Sprintf("\"%v\" [style=dashed,label=0];\n",
  652. lStr)
  653. nEmpties++
  654. }
  655. if bytes.Equal(r, empty) {
  656. rStr = fmt.Sprintf("empty%v", nEmpties)
  657. eStr += fmt.Sprintf("\"%v\" [style=dashed,label=0];\n",
  658. rStr)
  659. nEmpties++
  660. }
  661. fmt.Fprintf(w, "\"%v\" -> {\"%v\" \"%v\"}\n", hex.EncodeToString(k[:nChars]),
  662. lStr, rStr)
  663. fmt.Fprint(w, eStr)
  664. default:
  665. }
  666. })
  667. fmt.Fprintf(w, "}\n")
  668. return err
  669. }
  670. // PrintGraphviz prints the output of Tree.Graphviz
  671. func (t *Tree) PrintGraphviz(rootKey []byte) error {
  672. if rootKey == nil {
  673. rootKey = t.Root()
  674. }
  675. w := bytes.NewBufferString("")
  676. fmt.Fprintf(w,
  677. "--------\nGraphviz of the Tree with Root "+hex.EncodeToString(rootKey)+":\n")
  678. err := t.Graphviz(w, nil)
  679. if err != nil {
  680. fmt.Println(w)
  681. return err
  682. }
  683. fmt.Fprintf(w,
  684. "End of Graphviz of the Tree with Root "+hex.EncodeToString(rootKey)+"\n--------\n")
  685. fmt.Println(w)
  686. return nil
  687. }
  688. // Purge WIP: unimplemented
  689. func (t *Tree) Purge(keys [][]byte) error {
  690. return nil
  691. }