diff --git a/glide.lock b/glide.lock index e23eb217..8ed27e0b 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 1990fb145d5c5098b5ee467c59506e81b6c3b973667eeb63d83abd7ef831b919 -updated: 2018-01-14T21:24:21.241420637-08:00 +updated: 2018-01-21T03:46:56.821595635-08:00 imports: - name: github.com/davecgh/go-spew version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9 @@ -65,7 +65,7 @@ imports: - name: github.com/spf13/pflag version: 97afa5e7ca8a08a383cb259e06636b5e2cc7897f - name: github.com/spf13/viper - version: 8ef37cbca71638bf32f3d5e194117d4cb46da163 + version: 25b30aa063fc18e48662b86996252eabdcf2f0c7 - name: github.com/syndtr/goleveldb version: b89cc31ef7977104127d34c1bd31ebd1a9db2199 subpackages: @@ -82,7 +82,7 @@ imports: - leveldb/table - leveldb/util - name: github.com/tendermint/go-wire - version: b93ebdd4f306833936c243561ec30af3455dc764 + version: 0cce10e82786f2d501827fbe158747dbc4ceeb43 - name: github.com/tendermint/log15 version: f91285dece9f4875421b481da3e613d83d44f29b - name: golang.org/x/crypto diff --git a/merkle/simple_map.go b/merkle/simple_map.go index f637d30a..b09b71d5 100644 --- a/merkle/simple_map.go +++ b/merkle/simple_map.go @@ -18,25 +18,25 @@ func NewSimpleMap() *SimpleMap { } } -func (sm *SimpleMap) Set(key string, value interface{}) { +func (sm *SimpleMap) Set(key string, value Hasher) { sm.sorted = false - // Is value Hashable? - var vBytes []byte - if hashable, ok := value.(Hashable); ok { - vBytes = hashable.Hash() - } else { - vBytes, _ = wire.MarshalBinary(value) - } + // Hash the key to blind it... why not? + khash := SimpleHashFromBytes([]byte(key)) + + // And the value is hashed too, so you can + // check for equality with a cached value (say) + // and make a determination to fetch or not. + vhash := value.Hash() sm.kvs = append(sm.kvs, cmn.KVPair{ - Key: []byte(key), - Value: vBytes, + Key: khash, + Value: vhash, }) } -// Merkle root hash of items sorted by key. -// NOTE: Behavior is undefined when key is duplicate. +// 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) @@ -51,7 +51,6 @@ func (sm *SimpleMap) Sort() { } // Returns a copy of sorted KVPairs. -// CONTRACT: The returned slice must not be mutated. func (sm *SimpleMap) KVPairs() cmn.KVPairs { sm.Sort() kvs := make(cmn.KVPairs, len(sm.kvs)) @@ -78,9 +77,9 @@ func (kv kvPair) Hash() []byte { } func hashKVPairs(kvs cmn.KVPairs) []byte { - kvsH := make([]Hashable, 0, len(kvs)) + kvsH := make([]Hasher, 0, len(kvs)) for _, kvp := range kvs { kvsH = append(kvsH, kvPair(kvp)) } - return SimpleHashFromHashables(kvsH) + return SimpleHashFromHashers(kvsH) } diff --git a/merkle/simple_map_test.go b/merkle/simple_map_test.go index 94685855..61210132 100644 --- a/merkle/simple_map_test.go +++ b/merkle/simple_map_test.go @@ -7,41 +7,47 @@ import ( "github.com/stretchr/testify/assert" ) +type strHasher string + +func (str strHasher) Hash() []byte { + return SimpleHashFromBytes([]byte(str)) +} + func TestSimpleMap(t *testing.T) { { db := NewSimpleMap() - db.Set("key1", "value1") - assert.Equal(t, "d7df3e1d47fe38b51f8d897a88828026807a86b6", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + db.Set("key1", strHasher("value1")) + assert.Equal(t, "19618304d1ad2635c4238bce87f72331b22a11a1", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { db := NewSimpleMap() - db.Set("key1", "value2") - assert.Equal(t, "db415336c9be129ac38259b935a49d8e9c248c88", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + db.Set("key1", strHasher("value2")) + assert.Equal(t, "51cb96d3d41e1714def72eb4bacc211de9ddf284", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { db := NewSimpleMap() - db.Set("key1", "value1") - db.Set("key2", "value2") - assert.Equal(t, "fdb900a04c1de42bd3d924fc644e28a4bdce30ce", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + db.Set("key1", strHasher("value1")) + db.Set("key2", strHasher("value2")) + assert.Equal(t, "58a0a99d5019fdcad4bcf55942e833b2dfab9421", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { db := NewSimpleMap() - db.Set("key2", "value2") // NOTE: out of order - db.Set("key1", "value1") - assert.Equal(t, "fdb900a04c1de42bd3d924fc644e28a4bdce30ce", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + db.Set("key2", strHasher("value2")) // NOTE: out of order + db.Set("key1", strHasher("value1")) + assert.Equal(t, "58a0a99d5019fdcad4bcf55942e833b2dfab9421", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { db := NewSimpleMap() - db.Set("key1", "value1") - db.Set("key2", "value2") - db.Set("key3", "value3") - assert.Equal(t, "488cfdaea108ef8bd406f6163555752392ae1b4a", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + db.Set("key1", strHasher("value1")) + db.Set("key2", strHasher("value2")) + db.Set("key3", strHasher("value3")) + assert.Equal(t, "cb56db3c7993e977f4c2789559ae3e5e468a6e9b", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } { db := NewSimpleMap() - db.Set("key2", "value2") // NOTE: out of order - db.Set("key1", "value1") - db.Set("key3", "value3") - assert.Equal(t, "488cfdaea108ef8bd406f6163555752392ae1b4a", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") + db.Set("key2", strHasher("value2")) // NOTE: out of order + db.Set("key1", strHasher("value1")) + db.Set("key3", strHasher("value3")) + assert.Equal(t, "cb56db3c7993e977f4c2789559ae3e5e468a6e9b", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") } } diff --git a/merkle/simple_proof.go b/merkle/simple_proof.go index f75568fd..83f89e59 100644 --- a/merkle/simple_proof.go +++ b/merkle/simple_proof.go @@ -10,8 +10,8 @@ type SimpleProof struct { } // proofs[0] is the proof for items[0]. -func SimpleProofsFromHashables(items []Hashable) (rootHash []byte, proofs []*SimpleProof) { - trails, rootSPN := trailsFromHashables(items) +func SimpleProofsFromHashers(items []Hasher) (rootHash []byte, proofs []*SimpleProof) { + trails, rootSPN := trailsFromHashers(items) rootHash = rootSPN.Hash proofs = make([]*SimpleProof, len(items)) for i, trail := range trails { @@ -109,7 +109,7 @@ func (spn *SimpleProofNode) FlattenAunts() [][]byte { // trails[0].Hash is the leaf hash for items[0]. // trails[i].Parent.Parent....Parent == root for all i. -func trailsFromHashables(items []Hashable) (trails []*SimpleProofNode, root *SimpleProofNode) { +func trailsFromHashers(items []Hasher) (trails []*SimpleProofNode, root *SimpleProofNode) { // Recursive impl. switch len(items) { case 0: @@ -118,8 +118,8 @@ func trailsFromHashables(items []Hashable) (trails []*SimpleProofNode, root *Sim trail := &SimpleProofNode{items[0].Hash(), nil, nil, nil} return []*SimpleProofNode{trail}, trail default: - lefts, leftRoot := trailsFromHashables(items[:(len(items)+1)/2]) - rights, rightRoot := trailsFromHashables(items[(len(items)+1)/2:]) + lefts, leftRoot := trailsFromHashers(items[:(len(items)+1)/2]) + rights, rightRoot := trailsFromHashers(items[(len(items)+1)/2:]) rootHash := SimpleHashFromTwoHashes(leftRoot.Hash, rightRoot.Hash) root := &SimpleProofNode{rootHash, nil, nil, nil} leftRoot.Parent = root diff --git a/merkle/simple_tree.go b/merkle/simple_tree.go index 86b0bf26..182f2fda 100644 --- a/merkle/simple_tree.go +++ b/merkle/simple_tree.go @@ -54,28 +54,25 @@ func SimpleHashFromHashes(hashes [][]byte) []byte { } } -// Convenience for SimpleHashFromHashes. -func SimpleHashFromBinaries(items []interface{}) []byte { - hashes := make([][]byte, len(items)) - for i, item := range items { - hashes[i] = SimpleHashFromBinary(item) +// NOTE: Do not implement this, use SimpleHashFromByteslices instead. +// type Byteser interface { Bytes() []byte } +// func SimpleHashFromBytesers(items []Byteser) []byte { ... } + +func SimpleHashFromByteslices(bzs [][]byte) []byte { + hashes := make([][]byte, len(bzs)) + for i, bz := range bzs { + hashes[i] = SimpleHashFromBytes(bz) } return SimpleHashFromHashes(hashes) } -// General Convenience -func SimpleHashFromBinary(item interface{}) []byte { +func SimpleHashFromBytes(bz []byte) []byte { hasher := ripemd160.New() - bz, err := wire.MarshalBinary(item) - if err != nil { - panic(err) - } hasher.Write(bz) return hasher.Sum(nil) } -// Convenience for SimpleHashFromHashes. -func SimpleHashFromHashables(items []Hashable) []byte { +func SimpleHashFromHashers(items []Hasher) []byte { hashes := make([][]byte, len(items)) for i, item := range items { hash := item.Hash() @@ -84,8 +81,7 @@ func SimpleHashFromHashables(items []Hashable) []byte { return SimpleHashFromHashes(hashes) } -// Convenience for SimpleHashFromHashes. -func SimpleHashFromMap(m map[string]interface{}) []byte { +func SimpleHashFromMap(m map[string]Hasher) []byte { sm := NewSimpleMap() for k, v := range m { sm.Set(k, v) diff --git a/merkle/simple_tree_test.go b/merkle/simple_tree_test.go index 6299fa33..26f35c80 100644 --- a/merkle/simple_tree_test.go +++ b/merkle/simple_tree_test.go @@ -19,14 +19,14 @@ func TestSimpleProof(t *testing.T) { total := 100 - items := make([]Hashable, total) + items := make([]Hasher, total) for i := 0; i < total; i++ { items[i] = testItem(RandBytes(32)) } - rootHash := SimpleHashFromHashables(items) + rootHash := SimpleHashFromHashers(items) - rootHash2, proofs := SimpleProofsFromHashables(items) + rootHash2, proofs := SimpleProofsFromHashers(items) if !bytes.Equal(rootHash, rootHash2) { t.Errorf("Unmatched root hashes: %X vs %X", rootHash, rootHash2) diff --git a/merkle/types.go b/merkle/types.go index 93541eda..1a6d75e0 100644 --- a/merkle/types.go +++ b/merkle/types.go @@ -18,6 +18,6 @@ type Tree interface { IterateRange(start []byte, end []byte, ascending bool, fx func(key []byte, value []byte) (stop bool)) (stopped bool) } -type Hashable interface { +type Hasher interface { Hash() []byte }