diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index bf6b6ef3c7..bc807f7af6 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -197,16 +197,12 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb) } if pre.Env.BlockHashes != nil && chainConfig.IsPrague(new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) { - // insert all parent hashes in the contract - for i, h := range pre.Env.BlockHashes { - n := uint64(i) - if n >= pre.Env.Number || pre.Env.Number > (n+params.HistoryServeWindow) { - continue - } - core.ProcessParentBlockHash(statedb, n, h) - } + var ( + prevNumber = pre.Env.Number - 1 + prevHash = pre.Env.BlockHashes[math.HexOrDecimal64(prevNumber)] + ) + core.ProcessParentBlockHash(statedb, prevHash, prevNumber) } - for i := 0; txIt.Next(); i++ { tx, err := txIt.Tx() if err != nil { diff --git a/core/state_processor.go b/core/state_processor.go index 5bc24c6386..66c10c627c 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -82,7 +82,8 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb) } if p.config.IsPrague(block.Number(), block.Time()) { - ProcessBlockHashHistory(statedb, block.Header(), p.config, p.bc) + // This should not underflow as genesis block is not processed. + ProcessParentBlockHash(statedb, block.ParentHash(), block.NumberU64()-1) } // Iterate over and process the individual transactions for i, tx := range block.Transactions() { @@ -214,34 +215,9 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb *stat statedb.Finalise(true) } -// ProcessBlockHashHistory is called at every block to insert the parent block hash -// in the history storage contract as per EIP-2935. At the EIP-2935 fork block, it -// populates the whole buffer with block hashes. -func ProcessBlockHashHistory(statedb *state.StateDB, header *types.Header, chainConfig *params.ChainConfig, chain consensus.ChainHeaderReader) { - var ( - prevHash = header.ParentHash - parent = chain.GetHeaderByHash(prevHash) - number = header.Number.Uint64() - prevNumber = parent.Number.Uint64() - ) - ProcessParentBlockHash(statedb, prevNumber, prevHash) - // History already inserted. - if chainConfig.IsPrague(parent.Number, parent.Time) || prevNumber == 0 { - return - } - var low uint64 - if number > params.HistoryServeWindow { - low = number - params.HistoryServeWindow - } - for i := prevNumber; i > low; i-- { - ProcessParentBlockHash(statedb, i-1, parent.ParentHash) - parent = chain.GetHeader(parent.ParentHash, i-1) - } -} - // ProcessParentBlockHash stores the parent block hash in the history storage contract // as per EIP-2935. -func ProcessParentBlockHash(statedb *state.StateDB, prevNumber uint64, prevHash common.Hash) { +func ProcessParentBlockHash(statedb *state.StateDB, prevHash common.Hash, prevNumber uint64) { ringIndex := prevNumber % params.HistoryServeWindow var key common.Hash binary.BigEndian.PutUint64(key[24:], ringIndex) diff --git a/core/state_processor_test.go b/core/state_processor_test.go index 2caea37ecd..e8da524982 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -552,21 +552,18 @@ 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 +func TestProcessParentBlockHash(t *testing.T) { + var ( + statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewDatabase(memorydb.New())), nil) + hashA = common.Hash{0x01} + hashB = common.Hash{0x02} + header = &types.Header{ParentHash: hashA, Number: big.NewInt(2)} + parent = &types.Header{ParentHash: hashB, Number: big.NewInt(1)} + genesis = &types.Header{ParentHash: common.Hash{}, Number: big.NewInt(0)} + ) - ProcessBlockHashHistory(statedb, header, chainConfig, chain) + ProcessParentBlockHash(statedb, header.ParentHash, parent.Number.Uint64()) + ProcessParentBlockHash(statedb, parent.ParentHash, genesis.Number.Uint64()) // make sure that the state is correct if have := getParentBlockHash(statedb, 1); have != hashA { diff --git a/core/vm/instructions.go b/core/vm/instructions.go index fb82dc1509..9330c5f2e5 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -17,7 +17,6 @@ package vm import ( - "encoding/binary" "math" "github.com/ethereum/go-ethereum/common" @@ -435,27 +434,15 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ( num.Clear() return nil, nil } - historySize := uint64(256) - isPrague := interpreter.evm.ChainConfig().IsPrague(interpreter.evm.Context.BlockNumber, interpreter.evm.Context.Time) - // EIP-2935 extends the observable history window. - if isPrague { - historySize = params.HistoryServeWindow - } var upper, lower uint64 upper = interpreter.evm.Context.BlockNumber.Uint64() - if upper < historySize+1 { + if upper < 257 { lower = 0 } else { - lower = upper - historySize + lower = upper - 256 } if num64 >= lower && num64 < upper { - if isPrague { - var key common.Hash - binary.BigEndian.PutUint64(key[24:], num64 % params.HistoryServeWindow) - num.SetBytes(interpreter.evm.StateDB.GetState(params.HistoryStorageAddress, key).Bytes()) - } else { - num.SetBytes(interpreter.evm.Context.GetHash(num64).Bytes()) - } + num.SetBytes(interpreter.evm.Context.GetHash(num64).Bytes()) } else { num.Clear() } diff --git a/miner/worker.go b/miner/worker.go index 91c4836e53..da72685422 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -201,7 +201,7 @@ func (miner *Miner) prepareWork(genParams *generateParams) (*environment, error) core.ProcessBeaconBlockRoot(*header.ParentBeaconRoot, vmenv, env.state) } if miner.chainConfig.IsPrague(header.Number, header.Time) { - core.ProcessBlockHashHistory(env.state, header, miner.chainConfig, miner.chain) + core.ProcessParentBlockHash(env.state, header.ParentHash, header.Number.Uint64()-1) } return env, nil } diff --git a/tests/testdata b/tests/testdata index fa51c5c164..faf33b4714 160000 --- a/tests/testdata +++ b/tests/testdata @@ -1 +1 @@ -Subproject commit fa51c5c164f79140730ccb8fe26a46c3d3994338 +Subproject commit faf33b471465d3c6cdc3d04fbd690895f78d33f2