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 package validator
import ( import (
"fmt"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto" "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 // This does consider child storage tries
func (v *Validator) ValidateTrie(stateRoot common.Hash) error { func (v *Validator) ValidateTrie(stateRoot common.Hash) error {
// Generate the state.NodeIterator for this root // 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 { if err != nil {
return err return err
} }
it := state.NewNodeIterator(stateDB) 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() { for it.Next() {
// iterate through entire state trie and descendent storage tries // 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) // 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 package validator_test
import ( import (
"fmt"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -62,10 +63,12 @@ var (
}) })
stateRoot = crypto.Keccak256Hash(stateBranchRootNode) stateRoot = crypto.Keccak256Hash(stateBranchRootNode)
mockCode = []byte{1, 2, 3, 4, 5}
codeHash = crypto.Keccak256Hash(mockCode)
contractAccount, _ = rlp.EncodeToBytes(state.Account{ contractAccount, _ = rlp.EncodeToBytes(state.Account{
Nonce: 1, Nonce: 1,
Balance: big.NewInt(0), Balance: big.NewInt(0),
CodeHash: common.HexToHash("0xaaea5efba4fd7b45d7ec03918ac5d8b31aa93b48986af0e6b591f0f087c80127").Bytes(), CodeHash: codeHash.Bytes(),
Root: crypto.Keccak256Hash(storageBranchRootNode), Root: crypto.Keccak256Hash(storageBranchRootNode),
}) })
contractAccountLeafNode, _ = rlp.EncodeToBytes([]interface{}{ contractAccountLeafNode, _ = rlp.EncodeToBytes([]interface{}{
@ -204,31 +207,40 @@ var _ = Describe("PG-IPFS Validator", func() {
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
}) })
It("Returns an error the state root node is missing", func() { 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) err = v.ValidateTrie(stateRoot)
Expect(err).To(HaveOccurred()) 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() { It("Returns 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(append(trieStateNodes, mockCode), missingRootStorageNodes)
loadTrie(trieStateNodes, missingRootStorageNodes)
err = v.ValidateTrie(stateRoot) 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() { It("Returns an error if the state trie is missing node(s)", 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(append(missingNodeStateNodes, mockCode), trieStorageNodes)
loadTrie(missingNodeStateNodes, trieStorageNodes)
err = v.ValidateTrie(stateRoot) 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() { It("Returns an error if the storage trie is missing node(s)", 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(append(trieStateNodes, mockCode), missingNodeStorageNodes)
loadTrie(trieStateNodes, missingNodeStorageNodes)
err = v.ValidateTrie(stateRoot) 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() { 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) err = v.ValidateTrie(stateRoot)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
}) })