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.

91 lines
1.9 KiB

7 years ago
7 years ago
  1. package merkle
  2. import (
  3. "github.com/tendermint/go-crypto/tmhash"
  4. cmn "github.com/tendermint/tmlibs/common"
  5. )
  6. // Merkle tree from a map.
  7. // Leaves are `hash(key) | hash(value)`.
  8. // Leaves are sorted before Merkle hashing.
  9. type simpleMap struct {
  10. kvs cmn.KVPairs
  11. sorted bool
  12. }
  13. func newSimpleMap() *simpleMap {
  14. return &simpleMap{
  15. kvs: nil,
  16. sorted: false,
  17. }
  18. }
  19. // Set hashes the key and value and appends it to the kv pairs.
  20. func (sm *simpleMap) Set(key string, value Hasher) {
  21. sm.sorted = false
  22. // Hash the key to blind it... why not?
  23. khash := tmhash.Sum([]byte(key))
  24. // And the value is hashed too, so you can
  25. // check for equality with a cached value (say)
  26. // and make a determination to fetch or not.
  27. vhash := value.Hash()
  28. sm.kvs = append(sm.kvs, cmn.KVPair{
  29. Key: khash,
  30. Value: vhash,
  31. })
  32. }
  33. // Hash Merkle root hash of items sorted by key
  34. // (UNSTABLE: and by value too if duplicate key).
  35. func (sm *simpleMap) Hash() []byte {
  36. sm.Sort()
  37. return hashKVPairs(sm.kvs)
  38. }
  39. func (sm *simpleMap) Sort() {
  40. if sm.sorted {
  41. return
  42. }
  43. sm.kvs.Sort()
  44. sm.sorted = true
  45. }
  46. // Returns a copy of sorted KVPairs.
  47. // NOTE these contain the hashed key and value.
  48. func (sm *simpleMap) KVPairs() cmn.KVPairs {
  49. sm.Sort()
  50. kvs := make(cmn.KVPairs, len(sm.kvs))
  51. copy(kvs, sm.kvs)
  52. return kvs
  53. }
  54. //----------------------------------------
  55. // A local extension to KVPair that can be hashed.
  56. // Key and value are length prefixed and concatenated,
  57. // then hashed.
  58. type kvPair cmn.KVPair
  59. func (kv kvPair) Hash() []byte {
  60. hasher := tmhash.New()
  61. err := encodeByteSlice(hasher, kv.Key)
  62. if err != nil {
  63. panic(err)
  64. }
  65. err = encodeByteSlice(hasher, kv.Value)
  66. if err != nil {
  67. panic(err)
  68. }
  69. return hasher.Sum(nil)
  70. }
  71. func hashKVPairs(kvs cmn.KVPairs) []byte {
  72. kvsH := make([]Hasher, len(kvs))
  73. for i, kvp := range kvs {
  74. kvsH[i] = kvPair(kvp)
  75. }
  76. return SimpleHashFromHashers(kvsH)
  77. }