code referenced by codehash in contract accounts needs to be present in kv dstore for the trie to be considered complete by the state node iterator
This commit is contained in:
parent
d26bb68995
commit
00223269f8
@ -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)
|
||||
|
@ -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())
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user