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