From ca3e337ef9f978e308f4885281b81d17d6e4db29 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 2 Jul 2018 14:32:27 -0400 Subject: [PATCH] remove libs/merkle --- libs/merkle/README.md | 4 - libs/merkle/simple_map.go | 84 ------------------- libs/merkle/simple_map_test.go | 53 ------------ libs/merkle/simple_proof.go | 144 -------------------------------- libs/merkle/simple_tree.go | 91 -------------------- libs/merkle/simple_tree_test.go | 87 ------------------- libs/merkle/tmhash/hash.go | 41 --------- libs/merkle/tmhash/hash_test.go | 23 ----- libs/merkle/types.go | 47 ----------- 9 files changed, 574 deletions(-) delete mode 100644 libs/merkle/README.md delete mode 100644 libs/merkle/simple_map.go delete mode 100644 libs/merkle/simple_map_test.go delete mode 100644 libs/merkle/simple_proof.go delete mode 100644 libs/merkle/simple_tree.go delete mode 100644 libs/merkle/simple_tree_test.go delete mode 100644 libs/merkle/tmhash/hash.go delete mode 100644 libs/merkle/tmhash/hash_test.go delete mode 100644 libs/merkle/types.go diff --git a/libs/merkle/README.md b/libs/merkle/README.md deleted file mode 100644 index c4497836..00000000 --- a/libs/merkle/README.md +++ /dev/null @@ -1,4 +0,0 @@ -## Simple Merkle Tree - -For smaller static data structures that don't require immutable snapshots or mutability; -for instance the transactions and validation signatures of a block can be hashed using this simple merkle tree logic. diff --git a/libs/merkle/simple_map.go b/libs/merkle/simple_map.go deleted file mode 100644 index 65653e3c..00000000 --- a/libs/merkle/simple_map.go +++ /dev/null @@ -1,84 +0,0 @@ -package merkle - -import ( - cmn "github.com/tendermint/tendermint/libs/common" - "github.com/tendermint/tendermint/libs/merkle/tmhash" -) - -type SimpleMap struct { - kvs cmn.KVPairs - sorted bool -} - -func NewSimpleMap() *SimpleMap { - return &SimpleMap{ - kvs: nil, - sorted: false, - } -} - -func (sm *SimpleMap) Set(key string, value Hasher) { - sm.sorted = false - - // 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: khash, - Value: vhash, - }) -} - -// 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. -func (sm *SimpleMap) KVPairs() cmn.KVPairs { - sm.Sort() - kvs := make(cmn.KVPairs, len(sm.kvs)) - copy(kvs, sm.kvs) - return kvs -} - -//---------------------------------------- - -// A local extension to KVPair that can be hashed. -type KVPair cmn.KVPair - -func (kv KVPair) Hash() []byte { - hasher := tmhash.New() - err := encodeByteSlice(hasher, kv.Key) - if err != nil { - panic(err) - } - err = encodeByteSlice(hasher, kv.Value) - if err != nil { - panic(err) - } - return hasher.Sum(nil) -} - -func hashKVPairs(kvs cmn.KVPairs) []byte { - kvsH := make([]Hasher, 0, len(kvs)) - for _, kvp := range kvs { - kvsH = append(kvsH, KVPair(kvp)) - } - return SimpleHashFromHashers(kvsH) -} diff --git a/libs/merkle/simple_map_test.go b/libs/merkle/simple_map_test.go deleted file mode 100644 index 6e1004db..00000000 --- a/libs/merkle/simple_map_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package merkle - -import ( - "fmt" - "testing" - - "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", strHasher("value1")) - assert.Equal(t, "3dafc06a52039d029be57c75c9d16356a4256ef4", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") - } - { - db := NewSimpleMap() - db.Set("key1", strHasher("value2")) - assert.Equal(t, "03eb5cfdff646bc4e80fec844e72fd248a1c6b2c", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") - } - { - db := NewSimpleMap() - db.Set("key1", strHasher("value1")) - db.Set("key2", strHasher("value2")) - assert.Equal(t, "acc3971eab8513171cc90ce8b74f368c38f9657d", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") - } - { - db := NewSimpleMap() - db.Set("key2", strHasher("value2")) // NOTE: out of order - db.Set("key1", strHasher("value1")) - assert.Equal(t, "acc3971eab8513171cc90ce8b74f368c38f9657d", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") - } - { - db := NewSimpleMap() - db.Set("key1", strHasher("value1")) - db.Set("key2", strHasher("value2")) - db.Set("key3", strHasher("value3")) - assert.Equal(t, "0cd117ad14e6cd22edcd9aa0d84d7063b54b862f", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") - } - { - db := NewSimpleMap() - db.Set("key2", strHasher("value2")) // NOTE: out of order - db.Set("key1", strHasher("value1")) - db.Set("key3", strHasher("value3")) - assert.Equal(t, "0cd117ad14e6cd22edcd9aa0d84d7063b54b862f", fmt.Sprintf("%x", db.Hash()), "Hash didn't match") - } -} diff --git a/libs/merkle/simple_proof.go b/libs/merkle/simple_proof.go deleted file mode 100644 index ca6ccf37..00000000 --- a/libs/merkle/simple_proof.go +++ /dev/null @@ -1,144 +0,0 @@ -package merkle - -import ( - "bytes" - "fmt" -) - -type SimpleProof struct { - Aunts [][]byte `json:"aunts"` // Hashes from leaf's sibling to a root's child. -} - -// proofs[0] is the proof for items[0]. -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 { - proofs[i] = &SimpleProof{ - Aunts: trail.FlattenAunts(), - } - } - return -} - -func SimpleProofsFromMap(m map[string]Hasher) (rootHash []byte, proofs []*SimpleProof) { - sm := NewSimpleMap() - for k, v := range m { - sm.Set(k, v) - } - sm.Sort() - kvs := sm.kvs - kvsH := make([]Hasher, 0, len(kvs)) - for _, kvp := range kvs { - kvsH = append(kvsH, KVPair(kvp)) - } - return SimpleProofsFromHashers(kvsH) -} - -// Verify that leafHash is a leaf hash of the simple-merkle-tree -// which hashes to rootHash. -func (sp *SimpleProof) Verify(index int, total int, leafHash []byte, rootHash []byte) bool { - computedHash := computeHashFromAunts(index, total, leafHash, sp.Aunts) - return computedHash != nil && bytes.Equal(computedHash, rootHash) -} - -func (sp *SimpleProof) String() string { - return sp.StringIndented("") -} - -func (sp *SimpleProof) StringIndented(indent string) string { - return fmt.Sprintf(`SimpleProof{ -%s Aunts: %X -%s}`, - indent, sp.Aunts, - indent) -} - -// Use the leafHash and innerHashes to get the root merkle hash. -// If the length of the innerHashes slice isn't exactly correct, the result is nil. -// Recursive impl. -func computeHashFromAunts(index int, total int, leafHash []byte, innerHashes [][]byte) []byte { - if index >= total || index < 0 || total <= 0 { - return nil - } - switch total { - case 0: - panic("Cannot call computeHashFromAunts() with 0 total") - case 1: - if len(innerHashes) != 0 { - return nil - } - return leafHash - default: - if len(innerHashes) == 0 { - return nil - } - numLeft := (total + 1) / 2 - if index < numLeft { - leftHash := computeHashFromAunts(index, numLeft, leafHash, innerHashes[:len(innerHashes)-1]) - if leftHash == nil { - return nil - } - return SimpleHashFromTwoHashes(leftHash, innerHashes[len(innerHashes)-1]) - } - rightHash := computeHashFromAunts(index-numLeft, total-numLeft, leafHash, innerHashes[:len(innerHashes)-1]) - if rightHash == nil { - return nil - } - return SimpleHashFromTwoHashes(innerHashes[len(innerHashes)-1], rightHash) - } -} - -// Helper structure to construct merkle proof. -// The node and the tree is thrown away afterwards. -// Exactly one of node.Left and node.Right is nil, unless node is the root, in which case both are nil. -// node.Parent.Hash = hash(node.Hash, node.Right.Hash) or -// hash(node.Left.Hash, node.Hash), depending on whether node is a left/right child. -type SimpleProofNode struct { - Hash []byte - Parent *SimpleProofNode - Left *SimpleProofNode // Left sibling (only one of Left,Right is set) - Right *SimpleProofNode // Right sibling (only one of Left,Right is set) -} - -// Starting from a leaf SimpleProofNode, FlattenAunts() will return -// the inner hashes for the item corresponding to the leaf. -func (spn *SimpleProofNode) FlattenAunts() [][]byte { - // Nonrecursive impl. - innerHashes := [][]byte{} - for spn != nil { - if spn.Left != nil { - innerHashes = append(innerHashes, spn.Left.Hash) - } else if spn.Right != nil { - innerHashes = append(innerHashes, spn.Right.Hash) - } else { - break - } - spn = spn.Parent - } - return innerHashes -} - -// trails[0].Hash is the leaf hash for items[0]. -// trails[i].Parent.Parent....Parent == root for all i. -func trailsFromHashers(items []Hasher) (trails []*SimpleProofNode, root *SimpleProofNode) { - // Recursive impl. - switch len(items) { - case 0: - return nil, nil - case 1: - trail := &SimpleProofNode{items[0].Hash(), nil, nil, nil} - return []*SimpleProofNode{trail}, trail - default: - 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 - leftRoot.Right = rightRoot - rightRoot.Parent = root - rightRoot.Left = leftRoot - return append(lefts, rights...), root - } -} diff --git a/libs/merkle/simple_tree.go b/libs/merkle/simple_tree.go deleted file mode 100644 index c7bc17db..00000000 --- a/libs/merkle/simple_tree.go +++ /dev/null @@ -1,91 +0,0 @@ -/* -Computes a deterministic minimal height merkle tree hash. -If the number of items is not a power of two, some leaves -will be at different levels. Tries to keep both sides of -the tree the same size, but the left may be one greater. - -Use this for short deterministic trees, such as the validator list. -For larger datasets, use IAVLTree. - - * - / \ - / \ - / \ - / \ - * * - / \ / \ - / \ / \ - / \ / \ - * * * h6 - / \ / \ / \ - h0 h1 h2 h3 h4 h5 - -*/ - -package merkle - -import ( - "github.com/tendermint/tendermint/libs/merkle/tmhash" -) - -func SimpleHashFromTwoHashes(left []byte, right []byte) []byte { - var hasher = tmhash.New() - err := encodeByteSlice(hasher, left) - if err != nil { - panic(err) - } - err = encodeByteSlice(hasher, right) - if err != nil { - panic(err) - } - return hasher.Sum(nil) -} - -func SimpleHashFromHashes(hashes [][]byte) []byte { - // Recursive impl. - switch len(hashes) { - case 0: - return nil - case 1: - return hashes[0] - default: - left := SimpleHashFromHashes(hashes[:(len(hashes)+1)/2]) - right := SimpleHashFromHashes(hashes[(len(hashes)+1)/2:]) - return SimpleHashFromTwoHashes(left, right) - } -} - -// 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) -} - -func SimpleHashFromBytes(bz []byte) []byte { - hasher := tmhash.New() - hasher.Write(bz) - return hasher.Sum(nil) -} - -func SimpleHashFromHashers(items []Hasher) []byte { - hashes := make([][]byte, len(items)) - for i, item := range items { - hash := item.Hash() - hashes[i] = hash - } - return SimpleHashFromHashes(hashes) -} - -func SimpleHashFromMap(m map[string]Hasher) []byte { - sm := NewSimpleMap() - for k, v := range m { - sm.Set(k, v) - } - return sm.Hash() -} diff --git a/libs/merkle/simple_tree_test.go b/libs/merkle/simple_tree_test.go deleted file mode 100644 index f5c04af7..00000000 --- a/libs/merkle/simple_tree_test.go +++ /dev/null @@ -1,87 +0,0 @@ -package merkle - -import ( - "bytes" - - cmn "github.com/tendermint/tendermint/libs/common" - . "github.com/tendermint/tendermint/libs/test" - - "testing" -) - -type testItem []byte - -func (tI testItem) Hash() []byte { - return []byte(tI) -} - -func TestSimpleProof(t *testing.T) { - - total := 100 - - items := make([]Hasher, total) - for i := 0; i < total; i++ { - items[i] = testItem(cmn.RandBytes(32)) - } - - rootHash := SimpleHashFromHashers(items) - - rootHash2, proofs := SimpleProofsFromHashers(items) - - if !bytes.Equal(rootHash, rootHash2) { - t.Errorf("Unmatched root hashes: %X vs %X", rootHash, rootHash2) - } - - // For each item, check the trail. - for i, item := range items { - itemHash := item.Hash() - proof := proofs[i] - - // Verify success - ok := proof.Verify(i, total, itemHash, rootHash) - if !ok { - t.Errorf("Verification failed for index %v.", i) - } - - // Wrong item index should make it fail - { - ok = proof.Verify((i+1)%total, total, itemHash, rootHash) - if ok { - t.Errorf("Expected verification to fail for wrong index %v.", i) - } - } - - // Trail too long should make it fail - origAunts := proof.Aunts - proof.Aunts = append(proof.Aunts, cmn.RandBytes(32)) - { - ok = proof.Verify(i, total, itemHash, rootHash) - if ok { - t.Errorf("Expected verification to fail for wrong trail length.") - } - } - proof.Aunts = origAunts - - // Trail too short should make it fail - proof.Aunts = proof.Aunts[0 : len(proof.Aunts)-1] - { - ok = proof.Verify(i, total, itemHash, rootHash) - if ok { - t.Errorf("Expected verification to fail for wrong trail length.") - } - } - proof.Aunts = origAunts - - // Mutating the itemHash should make it fail. - ok = proof.Verify(i, total, MutateByteSlice(itemHash), rootHash) - if ok { - t.Errorf("Expected verification to fail for mutated leaf hash") - } - - // Mutating the rootHash should make it fail. - ok = proof.Verify(i, total, itemHash, MutateByteSlice(rootHash)) - if ok { - t.Errorf("Expected verification to fail for mutated root hash") - } - } -} diff --git a/libs/merkle/tmhash/hash.go b/libs/merkle/tmhash/hash.go deleted file mode 100644 index de69c406..00000000 --- a/libs/merkle/tmhash/hash.go +++ /dev/null @@ -1,41 +0,0 @@ -package tmhash - -import ( - "crypto/sha256" - "hash" -) - -var ( - Size = 20 - BlockSize = sha256.BlockSize -) - -type sha256trunc struct { - sha256 hash.Hash -} - -func (h sha256trunc) Write(p []byte) (n int, err error) { - return h.sha256.Write(p) -} -func (h sha256trunc) Sum(b []byte) []byte { - shasum := h.sha256.Sum(b) - return shasum[:Size] -} - -func (h sha256trunc) Reset() { - h.sha256.Reset() -} - -func (h sha256trunc) Size() int { - return Size -} - -func (h sha256trunc) BlockSize() int { - return h.sha256.BlockSize() -} - -func New() hash.Hash { - return sha256trunc{ - sha256: sha256.New(), - } -} diff --git a/libs/merkle/tmhash/hash_test.go b/libs/merkle/tmhash/hash_test.go deleted file mode 100644 index 9744a893..00000000 --- a/libs/merkle/tmhash/hash_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package tmhash_test - -import ( - "crypto/sha256" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/tendermint/tendermint/libs/merkle/tmhash" -) - -func TestHash(t *testing.T) { - testVector := []byte("abc") - hasher := tmhash.New() - hasher.Write(testVector) - bz := hasher.Sum(nil) - - hasher = sha256.New() - hasher.Write(testVector) - bz2 := hasher.Sum(nil) - bz2 = bz2[:20] - - assert.Equal(t, bz, bz2) -} diff --git a/libs/merkle/types.go b/libs/merkle/types.go deleted file mode 100644 index a0c491a7..00000000 --- a/libs/merkle/types.go +++ /dev/null @@ -1,47 +0,0 @@ -package merkle - -import ( - "encoding/binary" - "io" -) - -type Tree interface { - Size() (size int) - Height() (height int8) - Has(key []byte) (has bool) - Proof(key []byte) (value []byte, proof []byte, exists bool) // TODO make it return an index - Get(key []byte) (index int, value []byte, exists bool) - GetByIndex(index int) (key []byte, value []byte) - Set(key []byte, value []byte) (updated bool) - Remove(key []byte) (value []byte, removed bool) - HashWithCount() (hash []byte, count int) - Hash() (hash []byte) - Save() (hash []byte) - Load(hash []byte) - Copy() Tree - Iterate(func(key []byte, value []byte) (stop bool)) (stopped bool) - IterateRange(start []byte, end []byte, ascending bool, fx func(key []byte, value []byte) (stop bool)) (stopped bool) -} - -type Hasher interface { - Hash() []byte -} - -//----------------------------------------------------------------------- -// NOTE: these are duplicated from go-amino so we dont need go-amino as a dep - -func encodeByteSlice(w io.Writer, bz []byte) (err error) { - err = encodeUvarint(w, uint64(len(bz))) - if err != nil { - return - } - _, err = w.Write(bz) - return -} - -func encodeUvarint(w io.Writer, i uint64) (err error) { - var buf [10]byte - n := binary.PutUvarint(buf[:], i) - _, err = w.Write(buf[0:n]) - return -}