github.com/Finschia/finschia-sdk@v0.48.1/store/internal/maps/maps.go (about)

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