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