package merkle
|
|
|
|
import (
|
|
"sort"
|
|
|
|
wire "github.com/tendermint/go-wire"
|
|
"golang.org/x/crypto/ripemd160"
|
|
)
|
|
|
|
// NOTE: Behavior is undefined with dup keys.
|
|
type KVPair struct {
|
|
Key string
|
|
Value interface{} // Can be Hashable or not.
|
|
}
|
|
|
|
func (kv KVPair) Hash() []byte {
|
|
hasher, n, err := ripemd160.New(), new(int), new(error)
|
|
wire.WriteString(kv.Key, hasher, n, err)
|
|
if kvH, ok := kv.Value.(Hashable); ok {
|
|
wire.WriteByteSlice(kvH.Hash(), hasher, n, err)
|
|
} else {
|
|
wire.WriteBinary(kv.Value, hasher, n, err)
|
|
}
|
|
if *err != nil {
|
|
panic(*err)
|
|
}
|
|
return hasher.Sum(nil)
|
|
}
|
|
|
|
type KVPairs []KVPair
|
|
|
|
func (kvps KVPairs) Len() int { return len(kvps) }
|
|
func (kvps KVPairs) Less(i, j int) bool { return kvps[i].Key < kvps[j].Key }
|
|
func (kvps KVPairs) Swap(i, j int) { kvps[i], kvps[j] = kvps[j], kvps[i] }
|
|
func (kvps KVPairs) Sort() { sort.Sort(kvps) }
|
|
|
|
func MakeSortedKVPairs(m map[string]interface{}) []Hashable {
|
|
kvPairs := make([]KVPair, 0, len(m))
|
|
for k, v := range m {
|
|
kvPairs = append(kvPairs, KVPair{k, v})
|
|
}
|
|
KVPairs(kvPairs).Sort()
|
|
kvPairsH := make([]Hashable, 0, len(kvPairs))
|
|
for _, kvp := range kvPairs {
|
|
kvPairsH = append(kvPairsH, kvp)
|
|
}
|
|
return kvPairsH
|
|
}
|