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.

82 lines
3.1 KiB

  1. # arbo [![GoDoc](https://godoc.org/github.com/vocdoni/arbo?status.svg)](https://godoc.org/github.com/vocdoni/arbo) [![Go Report Card](https://goreportcard.com/badge/github.com/vocdoni/arbo)](https://goreportcard.com/report/github.com/vocdoni/arbo) [![Test](https://github.com/vocdoni/arbo/workflows/Test/badge.svg)](https://github.com/vocdoni/arbo/actions?query=workflow%3ATest)
  2. > *arbo*: tree in Esperanto.
  3. MerkleTree implementation in Go. Compatible with the circomlib implementation of
  4. the MerkleTree, following the specification from
  5. https://docs.iden3.io/publications/pdfs/Merkle-Tree.pdf and
  6. https://eprint.iacr.org/2018/955.
  7. Allows to define which hash function to use. So for example, when working with
  8. zkSnarks the Poseidon hash function can be used, but when not, it can be used
  9. the Blake2b hash function, which has much faster computation time.
  10. ## Usage
  11. ```go
  12. // create new database
  13. database, err := db.NewBadgerDB(c.TempDir())
  14. // create new Tree with maxLevels=100 and Blake2b hash function
  15. tree, err := arbo.NewTree(database, 100, arbo.HashFunctionBlake2b)
  16. key := []byte("hello")
  17. value := []byte("world")
  18. // Add a key & value into the merkle tree
  19. err = tree.Add(key, value)
  20. // There are cases where multiple key-values (leafs) are going to be added to a
  21. // Tree, for these cases is more efficient to use:
  22. invalids, err := tree.AddBatch(keys, values)
  23. // generate the merkle proof of a leaf by it's key
  24. value, siblings, err := tree.GenProof(key)
  25. // verify the proof
  26. verified, err := arbo.CheckProof(tree.hashFunction, key, value, tree.Root(), siblings)
  27. if !verified {
  28. fmt.Println("proof could not be verified")
  29. }
  30. // get the value of a leaf assigned to a key
  31. gettedKey, gettedValue, err := tree.Get(key)
  32. // update the value of a leaf assigned to a key
  33. err = tree.Update(key, value)
  34. // dump the tree (the leafs)
  35. dump, err := tree.Dump(nil) // instead of nil, a root to start from can be used
  36. // import the dump into a tree
  37. err = tree.ImportDump(dump)
  38. // print graphviz diagram of the tree
  39. err = tree.PrintGraphviz(nil) // instead of nil, a root to start from can be used
  40. ```
  41. ### Usage with SNARKs compatibility
  42. Arbo is designed to be compatible with [circom merkle
  43. tree](https://github.com/iden3/circomlib/tree/master/circuits/smt)'s
  44. snark-friendly merkletree.
  45. The only change needed is the hash function used for the Tree, for example using
  46. the Poseidon hash function:
  47. ```go
  48. tree, err := arbo.NewTree(database, 100, arbo.HashFunctionPoseidon)
  49. ```
  50. Be aware of the characteristics of this kind of hashes, such as using values
  51. inside the finite field used by the hash, and also the computation time.
  52. The interface of arbo uses byte arrays, and for the case of these kind of hashes
  53. (that usually work directly with finite field elements), arbo expects those
  54. values to be represented by little-endian byte arrays. There is a helper method
  55. to convert a `*big.Int` to `[]byte` using little-endian:
  56. ```go
  57. bLen := tree.HashFunction().Len()
  58. kBigInt := big.NewInt(100)
  59. // convert *big.Int to byte array
  60. kBytes := arbo.BigIntToBytes(bLen, kBigInt)
  61. // convert byte array to *big.Int
  62. kBigInt2 := arbo.BytesToBigInt(kBytes)
  63. ```