github.com/okex/exchain@v1.8.0/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/okex/exchain/libs/tendermint/crypto/tmhash"
     9  	"github.com/okex/exchain/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  }