commit
d85825c0ab
@ -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