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.

84 lines
1.6 KiB

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