Merge pull request #5 from vulcanize/code

fix
This commit is contained in:
Ian Norden 2020-07-30 19:26:54 -05:00 committed by GitHub
commit d85825c0ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 28 deletions

View File

@ -17,8 +17,6 @@
package validator
import (
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto"
@ -75,20 +73,11 @@ func NewValidator(kvs ethdb.KeyValueStore, database ethdb.Database) *Validator {
// This does consider child storage tries
func (v *Validator) ValidateTrie(stateRoot common.Hash) error {
// Generate the state.NodeIterator for this root
stateDB, err := state.New(common.Hash{}, v.stateDatabase, nil)
stateDB, err := state.New(stateRoot, v.stateDatabase, nil)
if err != nil {
return err
}
it := state.NewNodeIterator(stateDB)
// state.NodeIterator won't throw an error if we can't find the root node
// check if it exists first
exists, err := v.kvs.Has(stateRoot.Bytes())
if err != nil {
return err
}
if !exists {
return fmt.Errorf("root node for hash %s does not exist in database", stateRoot.Hex())
}
for it.Next() {
// iterate through entire state trie and descendent storage tries
// it.Next() will return false when we have either completed iteration of the entire trie or have ran into an error (e.g. a missing node)

View File

@ -17,6 +17,7 @@
package validator_test
import (
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
@ -62,10 +63,12 @@ var (
})
stateRoot = crypto.Keccak256Hash(stateBranchRootNode)
mockCode = []byte{1, 2, 3, 4, 5}
codeHash = crypto.Keccak256Hash(mockCode)
contractAccount, _ = rlp.EncodeToBytes(state.Account{
Nonce: 1,
Balance: big.NewInt(0),
CodeHash: common.HexToHash("0xaaea5efba4fd7b45d7ec03918ac5d8b31aa93b48986af0e6b591f0f087c80127").Bytes(),
CodeHash: codeHash.Bytes(),
Root: crypto.Keccak256Hash(storageBranchRootNode),
})
contractAccountLeafNode, _ = rlp.EncodeToBytes([]interface{}{
@ -204,31 +207,40 @@ var _ = Describe("PG-IPFS Validator", func() {
Expect(err).ToNot(HaveOccurred())
})
It("Returns an error the state root node is missing", func() {
loadTrie(missingRootStateNodes, trieStorageNodes)
// we write code to ethdb, there should probably be an EthCode IPLD codec
// but there isn't, and we don't need one here since blockstore keys are mh-derived
loadTrie(append(missingRootStateNodes, mockCode), trieStorageNodes)
err = v.ValidateTrie(stateRoot)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("does not exist in database"))
Expect(err.Error()).To(ContainSubstring("missing trie node"))
})
It("Fails to return an error if the storage root node is missing", func() {
// NOTE this failure was not expected and renders this approach unreliable, this is an issue with the go-ethereum core/state/iterator.NodeIterator
loadTrie(trieStateNodes, missingRootStorageNodes)
It("Returns an error if the storage root node is missing", func() {
loadTrie(append(trieStateNodes, mockCode), missingRootStorageNodes)
err = v.ValidateTrie(stateRoot)
Expect(err).ToNot(HaveOccurred())
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("missing trie node"))
})
It("Fails to return an error if the entire state (state trie and storage tries) cannot be validated", func() {
// NOTE this failure was not expected and renders this approach unreliable, this is an issue with the go-ethereum core/state/iterator.NodeIterator
loadTrie(missingNodeStateNodes, trieStorageNodes)
It("Returns an error if the state trie is missing node(s)", func() {
loadTrie(append(missingNodeStateNodes, mockCode), trieStorageNodes)
err = v.ValidateTrie(stateRoot)
Expect(err).ToNot(HaveOccurred())
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("missing trie node"))
})
It("Fails to return an error if the entire state (state trie and storage tries) cannot be validated", func() {
// NOTE this failure was not expected and renders this approach unreliable, this is an issue with the go-ethereum core/state/iterator.NodeIterator
loadTrie(trieStateNodes, missingNodeStorageNodes)
It("Returns an error if the storage trie is missing node(s)", func() {
loadTrie(append(trieStateNodes, mockCode), missingNodeStorageNodes)
err = v.ValidateTrie(stateRoot)
Expect(err).ToNot(HaveOccurred())
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("missing trie node"))
})
It("Returns an error if contract code is missing", func() {
loadTrie(trieStateNodes, trieStorageNodes)
err = v.ValidateTrie(stateRoot)
Expect(err).To(HaveOccurred())
subStr := fmt.Sprintf("code %s: sql: no rows in result set", codeHash.Hex()[2:])
Expect(err.Error()).To(ContainSubstring(subStr))
})
It("Returns no error if the entire state (state trie and storage tries) can be validated", func() {
loadTrie(trieStateNodes, trieStorageNodes)
loadTrie(append(trieStateNodes, mockCode), trieStorageNodes)
err = v.ValidateTrie(stateRoot)
Expect(err).ToNot(HaveOccurred())
})