diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 8d34ab8f9..736e299c4 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -15,9 +15,10 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi - P2P Protocol - Go API + - [crypto] [\#4721](https://github.com/tendermint/tendermint/pull/4721) Remove `SimpleHashFromMap()` and `SimpleProofsFromMap()` (@erikgrinaker) -- Blockchain Protocol +- Blockchain Protocol ### FEATURES: - [evidence] [\#4532](https://github.com/tendermint/tendermint/pull/4532) Handle evidence from light clients (@melekes) diff --git a/crypto/merkle/simple_map.go b/crypto/merkle/simple_map.go deleted file mode 100644 index 840bebd51..000000000 --- a/crypto/merkle/simple_map.go +++ /dev/null @@ -1,95 +0,0 @@ -package merkle - -import ( - "bytes" - - amino "github.com/tendermint/go-amino" - - "github.com/tendermint/tendermint/crypto/tmhash" - "github.com/tendermint/tendermint/libs/kv" -) - -// Merkle tree from a map. -// Leaves are `hash(key) | hash(value)`. -// Leaves are sorted before Merkle hashing. -type simpleMap struct { - kvs kv.Pairs - sorted bool -} - -func newSimpleMap() *simpleMap { - return &simpleMap{ - kvs: nil, - sorted: false, - } -} - -// Set creates a kv pair of the key and the hash of the value, -// and then appends it to simpleMap's kv pairs. -func (sm *simpleMap) Set(key string, value []byte) { - sm.sorted = false - - // The value is hashed, so you can - // check for equality with a cached value (say) - // and make a determination to fetch or not. - vhash := tmhash.Sum(value) - - sm.kvs = append(sm.kvs, kv.Pair{ - Key: []byte(key), - Value: vhash, - }) -} - -// Hash Merkle root hash of items sorted by key -// (UNSTABLE: and by value too if duplicate key). -func (sm *simpleMap) Hash() []byte { - sm.Sort() - return hashKVPairs(sm.kvs) -} - -func (sm *simpleMap) Sort() { - if sm.sorted { - return - } - sm.kvs.Sort() - sm.sorted = true -} - -// Returns a copy of sorted KVPairs. -// NOTE these contain the hashed key and value. -func (sm *simpleMap) KVPairs() kv.Pairs { - sm.Sort() - kvs := make(kv.Pairs, len(sm.kvs)) - copy(kvs, sm.kvs) - return kvs -} - -//---------------------------------------- - -// A local extension to KVPair that can be hashed. -// Key and value are length prefixed and concatenated, -// then hashed. -type KVPair kv.Pair - -// Bytes returns key || value, with both the -// key and value length prefixed. -func (kv KVPair) Bytes() []byte { - var b bytes.Buffer - err := amino.EncodeByteSlice(&b, kv.Key) - if err != nil { - panic(err) - } - err = amino.EncodeByteSlice(&b, kv.Value) - if err != nil { - panic(err) - } - return b.Bytes() -} - -func hashKVPairs(kvs kv.Pairs) []byte { - kvsH := make([][]byte, len(kvs)) - for i, kvp := range kvs { - kvsH[i] = KVPair(kvp).Bytes() - } - return SimpleHashFromByteSlices(kvsH) -} diff --git a/crypto/merkle/simple_map_test.go b/crypto/merkle/simple_map_test.go deleted file mode 100644 index 20868a782..000000000 --- a/crypto/merkle/simple_map_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package merkle - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestSimpleMap(t *testing.T) { - tests := []struct { - keys []string - values []string // each string gets converted to []byte in test - want string - }{ - {[]string{"key1"}, []string{"value1"}, "a44d3cc7daba1a4600b00a2434b30f8b970652169810d6dfa9fb1793a2189324"}, - {[]string{"key1"}, []string{"value2"}, "0638e99b3445caec9d95c05e1a3fc1487b4ddec6a952ff337080360b0dcc078c"}, - // swap order with 2 keys - { - []string{"key1", "key2"}, - []string{"value1", "value2"}, - "8fd19b19e7bb3f2b3ee0574027d8a5a4cec370464ea2db2fbfa5c7d35bb0cff3", - }, - { - []string{"key2", "key1"}, - []string{"value2", "value1"}, - "8fd19b19e7bb3f2b3ee0574027d8a5a4cec370464ea2db2fbfa5c7d35bb0cff3", - }, - // swap order with 3 keys - { - []string{"key1", "key2", "key3"}, - []string{"value1", "value2", "value3"}, - "1dd674ec6782a0d586a903c9c63326a41cbe56b3bba33ed6ff5b527af6efb3dc", - }, - { - []string{"key1", "key3", "key2"}, - []string{"value1", "value3", "value2"}, - "1dd674ec6782a0d586a903c9c63326a41cbe56b3bba33ed6ff5b527af6efb3dc", - }, - } - for i, tc := range tests { - db := newSimpleMap() - for i := 0; i < len(tc.keys); i++ { - db.Set(tc.keys[i], []byte(tc.values[i])) - } - got := db.Hash() - assert.Equal(t, tc.want, fmt.Sprintf("%x", got), "Hash didn't match on tc %d", i) - } -} diff --git a/crypto/merkle/simple_proof.go b/crypto/merkle/simple_proof.go index 44b97f606..26c8baeda 100644 --- a/crypto/merkle/simple_proof.go +++ b/crypto/merkle/simple_proof.go @@ -47,31 +47,6 @@ func SimpleProofsFromByteSlices(items [][]byte) (rootHash []byte, proofs []*Simp return } -// SimpleProofsFromMap generates proofs from a map. The keys/values of the map will be used as the keys/values -// in the underlying key-value pairs. -// The keys are sorted before the proofs are computed. -func SimpleProofsFromMap(m map[string][]byte) (rootHash []byte, proofs map[string]*SimpleProof, keys []string) { - sm := newSimpleMap() - for k, v := range m { - sm.Set(k, v) - } - sm.Sort() - kvs := sm.kvs - kvsBytes := make([][]byte, len(kvs)) - for i, kvp := range kvs { - kvsBytes[i] = KVPair(kvp).Bytes() - } - - rootHash, proofList := SimpleProofsFromByteSlices(kvsBytes) - proofs = make(map[string]*SimpleProof) - keys = make([]string, len(proofList)) - for i, kvp := range kvs { - proofs[string(kvp.Key)] = proofList[i] - keys[i] = string(kvp.Key) - } - return -} - // Verify that the SimpleProof proves the root hash. // Check sp.Index/sp.Total manually if needed func (sp *SimpleProof) Verify(rootHash []byte, leaf []byte) error { diff --git a/crypto/merkle/simple_tree.go b/crypto/merkle/simple_tree.go index 2a57bbe72..d2b931ec7 100644 --- a/crypto/merkle/simple_tree.go +++ b/crypto/merkle/simple_tree.go @@ -91,18 +91,6 @@ func SimpleHashFromByteSlicesIterative(input [][]byte) []byte { } } -// SimpleHashFromMap computes a Merkle tree from sorted map. -// Like calling SimpleHashFromHashers with -// `item = []byte(Hash(key) | Hash(value))`, -// sorted by `item`. -func SimpleHashFromMap(m map[string][]byte) []byte { - sm := newSimpleMap() - for k, v := range m { - sm.Set(k, v) - } - return sm.Hash() -} - // getSplitPoint returns the largest power of 2 less than length func getSplitPoint(length int) int { if length < 1 {