github.com/Finschia/finschia-sdk@v0.49.1/store/internal/maps/maps.go (about) 1 package maps 2 3 import ( 4 "encoding/binary" 5 6 "github.com/Finschia/ostracon/crypto/merkle" 7 "github.com/Finschia/ostracon/crypto/tmhash" 8 tmcrypto "github.com/tendermint/tendermint/proto/tendermint/crypto" 9 10 "github.com/Finschia/finschia-sdk/types/kv" 11 ) 12 13 // merkleMap defines a merkle-ized tree from a map. Leave values are treated as 14 // hash(key) | hash(value). Leaves are sorted before Merkle hashing. 15 type merkleMap struct { 16 kvs kv.Pairs 17 sorted bool 18 } 19 20 func newMerkleMap() *merkleMap { 21 return &merkleMap{ 22 kvs: kv.Pairs{}, 23 sorted: false, 24 } 25 } 26 27 // Set creates a kv.Pair from the provided key and value. The value is hashed prior 28 // to creating a kv.Pair. The created kv.Pair is appended to the MerkleMap's slice 29 // of kv.Pairs. Whenever called, the MerkleMap must be resorted. 30 func (sm *merkleMap) set(key string, value []byte) { 31 byteKey := []byte(key) 32 assertValidKey(byteKey) 33 34 sm.sorted = false 35 36 // The value is hashed, so you can check for equality with a cached value (say) 37 // and make a determination to fetch or not. 38 vhash := tmhash.Sum(value) 39 40 sm.kvs.Pairs = append(sm.kvs.Pairs, kv.Pair{ 41 Key: byteKey, 42 Value: vhash, 43 }) 44 } 45 46 // Hash returns the merkle root of items sorted by key. Note, it is unstable. 47 func (sm *merkleMap) hash() []byte { 48 sm.sort() 49 return hashKVPairs(sm.kvs) 50 } 51 52 func (sm *merkleMap) sort() { 53 if sm.sorted { 54 return 55 } 56 57 sm.kvs.Sort() 58 sm.sorted = true 59 } 60 61 // hashKVPairs hashes a kvPair and creates a merkle tree where the leaves are 62 // byte slices. 63 func hashKVPairs(kvs kv.Pairs) []byte { 64 kvsH := make([][]byte, len(kvs.Pairs)) 65 for i, kvp := range kvs.Pairs { 66 kvsH[i] = KVPair(kvp).Bytes() 67 } 68 69 return merkle.HashFromByteSlices(kvsH) 70 } 71 72 // --------------------------------------------- 73 74 // Merkle tree from a map. 75 // Leaves are `hash(key) | hash(value)`. 76 // Leaves are sorted before Merkle hashing. 77 type simpleMap struct { 78 Kvs kv.Pairs 79 sorted bool 80 } 81 82 func newSimpleMap() *simpleMap { 83 return &simpleMap{ 84 Kvs: kv.Pairs{}, 85 sorted: false, 86 } 87 } 88 89 // Set creates a kv pair of the key and the hash of the value, 90 // and then appends it to SimpleMap's kv pairs. 91 func (sm *simpleMap) Set(key string, value []byte) { 92 byteKey := []byte(key) 93 assertValidKey(byteKey) 94 sm.sorted = false 95 96 // The value is hashed, so you can 97 // check for equality with a cached value (say) 98 // and make a determination to fetch or not. 99 vhash := tmhash.Sum(value) 100 101 sm.Kvs.Pairs = append(sm.Kvs.Pairs, kv.Pair{ 102 Key: byteKey, 103 Value: vhash, 104 }) 105 } 106 107 // Hash Merkle root hash of items sorted by key 108 // (UNSTABLE: and by value too if duplicate key). 109 func (sm *simpleMap) Hash() []byte { 110 sm.Sort() 111 return hashKVPairs(sm.Kvs) 112 } 113 114 func (sm *simpleMap) Sort() { 115 if sm.sorted { 116 return 117 } 118 sm.Kvs.Sort() 119 sm.sorted = true 120 } 121 122 // Returns a copy of sorted KVPairs. 123 // NOTE these contain the hashed key and value. 124 func (sm *simpleMap) KVPairs() kv.Pairs { 125 sm.Sort() 126 kvs := kv.Pairs{ 127 Pairs: make([]kv.Pair, len(sm.Kvs.Pairs)), 128 } 129 130 copy(kvs.Pairs, sm.Kvs.Pairs) 131 return kvs 132 } 133 134 //---------------------------------------- 135 136 // A local extension to KVPair that can be hashed. 137 // Key and value are length prefixed and concatenated, 138 // then hashed. 139 type KVPair kv.Pair 140 141 // NewKVPair takes in a key and value and creates a kv.Pair 142 // wrapped in the local extension KVPair 143 func NewKVPair(key, value []byte) KVPair { 144 return KVPair(kv.Pair{ 145 Key: key, 146 Value: value, 147 }) 148 } 149 150 // Bytes returns key || value, with both the 151 // key and value length prefixed. 152 func (kv KVPair) Bytes() []byte { 153 // In the worst case: 154 // * 8 bytes to Uvarint encode the length of the key 155 // * 8 bytes to Uvarint encode the length of the value 156 // So preallocate for the worst case, which will in total 157 // be a maximum of 14 bytes wasted, if len(key)=1, len(value)=1, 158 // but that's going to rare. 159 buf := make([]byte, 8+len(kv.Key)+8+len(kv.Value)) 160 161 // Encode the key, prefixed with its length. 162 nlk := binary.PutUvarint(buf, uint64(len(kv.Key))) 163 nk := copy(buf[nlk:], kv.Key) 164 165 // Encode the value, prefixing with its length. 166 nlv := binary.PutUvarint(buf[nlk+nk:], uint64(len(kv.Value))) 167 nv := copy(buf[nlk+nk+nlv:], kv.Value) 168 169 return buf[:nlk+nk+nlv+nv] 170 } 171 172 // HashFromMap computes a merkle tree from sorted map and returns the merkle 173 // root. 174 func HashFromMap(m map[string][]byte) []byte { 175 mm := newMerkleMap() 176 for k, v := range m { 177 mm.set(k, v) 178 } 179 180 return mm.hash() 181 } 182 183 // ProofsFromMap generates proofs from a map. The keys/values of the map will be used as the keys/values 184 // in the underlying key-value pairs. 185 // The keys are sorted before the proofs are computed. 186 func ProofsFromMap(m map[string][]byte) ([]byte, map[string]*tmcrypto.Proof, []string) { 187 sm := newSimpleMap() 188 for k, v := range m { 189 sm.Set(k, v) 190 } 191 192 sm.Sort() 193 kvs := sm.Kvs 194 kvsBytes := make([][]byte, len(kvs.Pairs)) 195 for i, kvp := range kvs.Pairs { 196 kvsBytes[i] = KVPair(kvp).Bytes() 197 } 198 199 rootHash, proofList := merkle.ProofsFromByteSlices(kvsBytes) 200 proofs := make(map[string]*tmcrypto.Proof) 201 keys := make([]string, len(proofList)) 202 203 for i, kvp := range kvs.Pairs { 204 proofs[string(kvp.Key)] = proofList[i].ToProto() 205 keys[i] = string(kvp.Key) 206 } 207 208 return rootHash, proofs, keys 209 } 210 211 func assertValidKey(key []byte) { 212 if len(key) == 0 { 213 panic("key is nil") 214 } 215 }