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.

94 lines
2.0 KiB

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