cmd/evm, core/state: fix post-exec dump of state (statetests, blockchaintests) (#28504)
There were several problems related to dumping state. - If a preimage was missing, even if we had set the `OnlyWithAddresses` to `false`, to export them anyway, the way the mapping was constructed (using `common.Address` as key) made the entries get lost anyway. Concerns both state- and blockchain tests. - Blockchain test execution was not configured to store preimages. This changes makes it so that the block test executor takes a callback, just like the state test executor already does. This callback can be used to examine the post-execution state, e.g. to aid debugging of test failures.
This commit is contained in:
+9
-9
@@ -133,7 +133,7 @@ func (api *DebugAPI) GetBadBlocks(ctx context.Context) ([]*BadBlockArgs, error)
|
||||
const AccountRangeMaxResults = 256
|
||||
|
||||
// AccountRange enumerates all accounts in the given block and start point in paging request
|
||||
func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hexutil.Bytes, maxResults int, nocode, nostorage, incompletes bool) (state.IteratorDump, error) {
|
||||
func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hexutil.Bytes, maxResults int, nocode, nostorage, incompletes bool) (state.Dump, error) {
|
||||
var stateDb *state.StateDB
|
||||
var err error
|
||||
|
||||
@@ -144,7 +144,7 @@ func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hex
|
||||
// the miner and operate on those
|
||||
_, stateDb = api.eth.miner.Pending()
|
||||
if stateDb == nil {
|
||||
return state.IteratorDump{}, errors.New("pending state is not available")
|
||||
return state.Dump{}, errors.New("pending state is not available")
|
||||
}
|
||||
} else {
|
||||
var header *types.Header
|
||||
@@ -158,29 +158,29 @@ func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hex
|
||||
default:
|
||||
block := api.eth.blockchain.GetBlockByNumber(uint64(number))
|
||||
if block == nil {
|
||||
return state.IteratorDump{}, fmt.Errorf("block #%d not found", number)
|
||||
return state.Dump{}, fmt.Errorf("block #%d not found", number)
|
||||
}
|
||||
header = block.Header()
|
||||
}
|
||||
if header == nil {
|
||||
return state.IteratorDump{}, fmt.Errorf("block #%d not found", number)
|
||||
return state.Dump{}, fmt.Errorf("block #%d not found", number)
|
||||
}
|
||||
stateDb, err = api.eth.BlockChain().StateAt(header.Root)
|
||||
if err != nil {
|
||||
return state.IteratorDump{}, err
|
||||
return state.Dump{}, err
|
||||
}
|
||||
}
|
||||
} else if hash, ok := blockNrOrHash.Hash(); ok {
|
||||
block := api.eth.blockchain.GetBlockByHash(hash)
|
||||
if block == nil {
|
||||
return state.IteratorDump{}, fmt.Errorf("block %s not found", hash.Hex())
|
||||
return state.Dump{}, fmt.Errorf("block %s not found", hash.Hex())
|
||||
}
|
||||
stateDb, err = api.eth.BlockChain().StateAt(block.Root())
|
||||
if err != nil {
|
||||
return state.IteratorDump{}, err
|
||||
return state.Dump{}, err
|
||||
}
|
||||
} else {
|
||||
return state.IteratorDump{}, errors.New("either block number or block hash must be specified")
|
||||
return state.Dump{}, errors.New("either block number or block hash must be specified")
|
||||
}
|
||||
|
||||
opts := &state.DumpConfig{
|
||||
@@ -193,7 +193,7 @@ func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hex
|
||||
if maxResults > AccountRangeMaxResults || maxResults <= 0 {
|
||||
opts.Max = AccountRangeMaxResults
|
||||
}
|
||||
return stateDb.IteratorDump(opts), nil
|
||||
return stateDb.RawDump(opts), nil
|
||||
}
|
||||
|
||||
// StorageRangeResult is the result of a debug_storageRangeAt API call.
|
||||
|
||||
+13
-12
@@ -21,6 +21,7 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
@@ -35,8 +36,8 @@ import (
|
||||
|
||||
var dumper = spew.ConfigState{Indent: " "}
|
||||
|
||||
func accountRangeTest(t *testing.T, trie *state.Trie, statedb *state.StateDB, start common.Hash, requestedNum int, expectedNum int) state.IteratorDump {
|
||||
result := statedb.IteratorDump(&state.DumpConfig{
|
||||
func accountRangeTest(t *testing.T, trie *state.Trie, statedb *state.StateDB, start common.Hash, requestedNum int, expectedNum int) state.Dump {
|
||||
result := statedb.RawDump(&state.DumpConfig{
|
||||
SkipCode: true,
|
||||
SkipStorage: true,
|
||||
OnlyWithAddresses: false,
|
||||
@@ -47,12 +48,12 @@ func accountRangeTest(t *testing.T, trie *state.Trie, statedb *state.StateDB, st
|
||||
if len(result.Accounts) != expectedNum {
|
||||
t.Fatalf("expected %d results, got %d", expectedNum, len(result.Accounts))
|
||||
}
|
||||
for address := range result.Accounts {
|
||||
if address == (common.Address{}) {
|
||||
t.Fatalf("empty address returned")
|
||||
for addr, acc := range result.Accounts {
|
||||
if strings.HasSuffix(addr, "pre") || acc.Address == nil {
|
||||
t.Fatalf("account without prestate (address) returned: %v", addr)
|
||||
}
|
||||
if !statedb.Exist(address) {
|
||||
t.Fatalf("account not found in state %s", address.Hex())
|
||||
if !statedb.Exist(*acc.Address) {
|
||||
t.Fatalf("account not found in state %s", acc.Address.Hex())
|
||||
}
|
||||
}
|
||||
return result
|
||||
@@ -92,16 +93,16 @@ func TestAccountRange(t *testing.T) {
|
||||
secondResult := accountRangeTest(t, &trie, sdb, common.BytesToHash(firstResult.Next), AccountRangeMaxResults, AccountRangeMaxResults)
|
||||
|
||||
hList := make([]common.Hash, 0)
|
||||
for addr1 := range firstResult.Accounts {
|
||||
// If address is empty, then it makes no sense to compare
|
||||
for addr1, acc := range firstResult.Accounts {
|
||||
// If address is non-available, then it makes no sense to compare
|
||||
// them as they might be two different accounts.
|
||||
if addr1 == (common.Address{}) {
|
||||
if acc.Address == nil {
|
||||
continue
|
||||
}
|
||||
if _, duplicate := secondResult.Accounts[addr1]; duplicate {
|
||||
t.Fatalf("pagination test failed: results should not overlap")
|
||||
}
|
||||
hList = append(hList, crypto.Keccak256Hash(addr1.Bytes()))
|
||||
hList = append(hList, crypto.Keccak256Hash(acc.Address.Bytes()))
|
||||
}
|
||||
// Test to see if it's possible to recover from the middle of the previous
|
||||
// set and get an even split between the first and second sets.
|
||||
@@ -140,7 +141,7 @@ func TestEmptyAccountRange(t *testing.T) {
|
||||
st.Commit(0, true)
|
||||
st, _ = state.New(types.EmptyRootHash, statedb, nil)
|
||||
|
||||
results := st.IteratorDump(&state.DumpConfig{
|
||||
results := st.RawDump(&state.DumpConfig{
|
||||
SkipCode: true,
|
||||
SkipStorage: true,
|
||||
OnlyWithAddresses: true,
|
||||
|
||||
Reference in New Issue
Block a user