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  }