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.

88 lines
1.8 KiB

  1. package merkle
  2. import (
  3. "github.com/tendermint/tendermint/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. // The value is hashed, so you can
  23. // check for equality with a cached value (say)
  24. // and make a determination to fetch or not.
  25. vhash := value.Hash()
  26. sm.kvs = append(sm.kvs, cmn.KVPair{
  27. Key: []byte(key),
  28. Value: vhash,
  29. })
  30. }
  31. // Hash Merkle root hash of items sorted by key
  32. // (UNSTABLE: and by value too if duplicate key).
  33. func (sm *simpleMap) Hash() []byte {
  34. sm.Sort()
  35. return hashKVPairs(sm.kvs)
  36. }
  37. func (sm *simpleMap) Sort() {
  38. if sm.sorted {
  39. return
  40. }
  41. sm.kvs.Sort()
  42. sm.sorted = true
  43. }
  44. // Returns a copy of sorted KVPairs.
  45. // NOTE these contain the hashed key and value.
  46. func (sm *simpleMap) KVPairs() cmn.KVPairs {
  47. sm.Sort()
  48. kvs := make(cmn.KVPairs, len(sm.kvs))
  49. copy(kvs, sm.kvs)
  50. return kvs
  51. }
  52. //----------------------------------------
  53. // A local extension to KVPair that can be hashed.
  54. // Key and value are length prefixed and concatenated,
  55. // then hashed.
  56. type KVPair cmn.KVPair
  57. func (kv KVPair) Hash() []byte {
  58. hasher := tmhash.New()
  59. err := encodeByteSlice(hasher, kv.Key)
  60. if err != nil {
  61. panic(err)
  62. }
  63. err = encodeByteSlice(hasher, kv.Value)
  64. if err != nil {
  65. panic(err)
  66. }
  67. return hasher.Sum(nil)
  68. }
  69. func hashKVPairs(kvs cmn.KVPairs) []byte {
  70. kvsH := make([]Hasher, len(kvs))
  71. for i, kvp := range kvs {
  72. kvsH[i] = KVPair(kvp)
  73. }
  74. return SimpleHashFromHashers(kvsH)
  75. }