diff --git a/core/state_processor.go b/core/state_processor.go index 79a3f37279da..74531007f57a 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -296,13 +296,10 @@ func ProcessBlockHashHistory(statedb *state.StateDB, header *types.Header, chain var low uint64 if number > params.HistoryServeWindow { low = number - params.HistoryServeWindow - if number < params.HistoryServeWindow { - low = 0 - } } - for i := prevNumber - 1; i >= low; i-- { - ProcessParentBlockHash(statedb, i, parent.ParentHash) - parent = chain.GetHeader(parent.ParentHash, i) + for i := prevNumber; i > low; i-- { + ProcessParentBlockHash(statedb, i-1, parent.ParentHash) + parent = chain.GetHeader(parent.ParentHash, i-1) } } diff --git a/core/state_processor_test.go b/core/state_processor_test.go index e98d27eb92d2..e2f75319987c 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -18,6 +18,7 @@ package core import ( "crypto/ecdsa" + "encoding/binary" "math/big" "testing" @@ -29,9 +30,11 @@ import ( "github.com/ethereum/go-ethereum/consensus/misc/eip1559" "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethdb/memorydb" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" "github.com/holiman/uint256" @@ -528,3 +531,55 @@ func TestProcessVerkle(t *testing.T) { } } } + +type MockChain struct { + chain map[common.Hash]*types.Header +} + +func (m *MockChain) Config() *params.ChainConfig { return nil } + +func (m *MockChain) CurrentHeader() *types.Header { return nil } + +func (m *MockChain) GetHeaderByNumber(number uint64) *types.Header { return nil } + +func (m *MockChain) GetTd(hash common.Hash, number uint64) *big.Int { return nil } + +func (m *MockChain) GetHeaderByHash(hash common.Hash) *types.Header { + return m.chain[hash] +} + +func (m *MockChain) GetHeader(hash common.Hash, number uint64) *types.Header { + return m.chain[hash] +} + +func TestProcessBlockHashHistory(t *testing.T) { + hashA := common.Hash{0x01} + hashB := common.Hash{0x02} + statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil) + header := &types.Header{ParentHash: hashA, Number: big.NewInt(2)} + parent := &types.Header{ParentHash: hashB, Number: big.NewInt(1)} + parentParent := &types.Header{ParentHash: common.Hash{}, Number: big.NewInt(0)} + chainConfig := params.AllDevChainProtocolChanges + chainConfig.PragueTime = nil + chain := new(MockChain) + chain.chain = make(map[common.Hash]*types.Header) + chain.chain[hashA] = parent + chain.chain[hashB] = parentParent + + ProcessBlockHashHistory(statedb, header, chainConfig, chain) + + // make sure that the state is correct + if have := getParentBlockHash(statedb, 1); have != hashA { + t.Fail() + } + if have := getParentBlockHash(statedb, 0); have != hashB { + t.Fail() + } +} + +func getParentBlockHash(statedb *state.StateDB, number uint64) common.Hash { + ringIndex := number % params.HistoryServeWindow + var key common.Hash + binary.BigEndian.PutUint64(key[24:], ringIndex) + return statedb.GetState(params.HistoryStorageAddress, key) +}