commit
d85825c0ab
@ -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)
|
||||||
|
@ -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())
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user