diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 824cc0f92e..15973e934d 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -230,17 +230,16 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, misc.ApplyDAOHardFork(statedb) } evm := vm.NewEVM(vmContext, statedb, chainConfig, vmConfig) - - var ( - prevNumber uint64 - prevHash common.Hash - ) - if pre.Env.BlockHashes != nil && chainConfig.IsPrague(new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) { - prevNumber = pre.Env.Number - 1 - prevHash = pre.Env.BlockHashes[math.HexOrDecimal64(prevNumber)] + if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil { + core.ProcessBeaconBlockRoot(*beaconRoot, evm) + } + if pre.Env.BlockHashes != nil && chainConfig.IsPrague(new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) { + var ( + prevNumber = pre.Env.Number - 1 + prevHash = pre.Env.BlockHashes[math.HexOrDecimal64(prevNumber)] + ) + core.ProcessParentBlockHash(prevHash, evm) } - core.PreExecution(context.Background(), pre.Env.ParentBeaconBlockRoot, prevHash, chainConfig, evm, vmContext.BlockNumber, vmContext.Time) - for i := 0; txIt.Next(); i++ { tx, err := txIt.Tx() if err != nil { diff --git a/core/chain_makers.go b/core/chain_makers.go index a3cdf45bd0..7474d892b1 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -315,15 +315,14 @@ func (b *BlockGen) collectRequests(readonly bool) (requests [][]byte) { // off the statedb before executing the system calls. statedb = statedb.Copy() } - // EIP-6110 deposits var blockLogs []*types.Log for _, r := range b.receipts { blockLogs = append(blockLogs, r.Logs...) } - // TODO(rjl493456442) the EVM instance should be shared across the entire - // generation life cycle. + // TODO use the shared EVM throughout the entire generation cycle blockContext := NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase) evm := vm.NewEVM(blockContext, statedb, b.cm.config, vm.Config{}) + requests, err := PostExecution(context.Background(), b.cm.config, b.header.Number, b.header.Time, blockLogs, evm) if err != nil { panic(fmt.Sprintf("failed to run post-execution: %v", err)) diff --git a/core/state_processor.go b/core/state_processor.go index 78d88875aa..06dafaa4b3 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -75,7 +75,6 @@ func (p *StateProcessor) Process(ctx context.Context, block *types.Block, stated if hooks := cfg.Tracer; hooks != nil { tracingStateDB = state.NewHookedState(statedb, hooks) } - // Mutate the block and state according to any hard-fork specs if config.DAOForkSupport && config.DAOForkBlock != nil && config.DAOForkBlock.Cmp(block.Number()) == 0 { misc.ApplyDAOHardFork(tracingStateDB) @@ -87,8 +86,9 @@ func (p *StateProcessor) Process(ctx context.Context, block *types.Block, stated ) defer evm.Release() // Run the pre-execution system calls - PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), config, evm, block.Number(), block.Time()) - + if err := PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), config, evm, block.Number(), block.Time()); err != nil { + return nil, err + } // Iterate over and process the individual transactions for i, tx := range block.Transactions() { msg, err := TransactionToMessage(tx, signer, header.BaseFee) @@ -127,16 +127,20 @@ func (p *StateProcessor) Process(ctx context.Context, block *types.Block, stated } // PreExecution processes pre-execution system calls. -func PreExecution(ctx context.Context, beaconRoot *common.Hash, parent common.Hash, config *params.ChainConfig, evm *vm.EVM, number *big.Int, time uint64) { +func PreExecution(ctx context.Context, beaconRoot *common.Hash, parent common.Hash, config *params.ChainConfig, evm *vm.EVM, number *big.Int, time uint64) error { _, _, spanEnd := telemetry.StartSpan(ctx, "core.preExecution") defer spanEnd(nil) + // EIP-4788 + // TODO(rjl) it should be enforced if cancun is enabled if beaconRoot != nil { ProcessBeaconBlockRoot(*beaconRoot, evm) } + // EIP-2935 if config.IsPrague(number, time) || config.IsUBT(number, time) { ProcessParentBlockHash(parent, evm) } + return nil } // PostExecution processes post-execution system calls when Prague is enabled. diff --git a/eth/state_accessor.go b/eth/state_accessor.go index 53dfb7d458..7042b9b1c1 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -250,8 +250,10 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, defer evm.Release() // Run pre-execution system calls - core.PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), eth.blockchain.Config(), evm, block.Number(), block.Time()) + if err := core.PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), eth.blockchain.Config(), evm, block.Number(), block.Time()); err != nil { + return nil, vm.BlockContext{}, nil, nil, err + } if txIndex == 0 && len(block.Transactions()) == 0 { return nil, context, statedb, release, nil } diff --git a/eth/tracers/api.go b/eth/tracers/api.go index ab76758191..35fff88ddc 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -373,12 +373,9 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed context := core.NewEVMBlockContext(next.Header(), api.chainContext(ctx), nil) evm := vm.NewEVM(context, statedb, api.backend.ChainConfig(), vm.Config{}) - if beaconRoot := next.BeaconRoot(); beaconRoot != nil { - core.ProcessBeaconBlockRoot(*beaconRoot, evm) - } - // Insert parent hash in history contract. - if api.backend.ChainConfig().IsPrague(next.Number(), next.Time()) { - core.ProcessParentBlockHash(next.ParentHash(), evm) + if err := core.PreExecution(ctx, next.BeaconRoot(), next.ParentHash(), api.backend.ChainConfig(), evm, next.Number(), next.Time()); err != nil { + failed = err + break } evm.Release() // Clean out any pending release functions of trace state. Note this @@ -495,8 +492,8 @@ func (api *API) StandardTraceBlockToFile(ctx context.Context, hash common.Hash, return api.standardTraceBlockToFile(ctx, block, config) } -// IntermediateRoots executes a block (bad- or canon- or side-), and returns a list -// of intermediate roots: the stateroot after each transaction. +// IntermediateRoots executes a block, and returns a list of intermediate roots: +// the stateroot after each transaction. func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config *TraceConfig) ([]common.Hash, error) { block, _ := api.blockByHash(ctx, hash) if block == nil { @@ -518,20 +515,20 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config return nil, err } defer release() + var ( roots []common.Hash signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) chainConfig = api.backend.ChainConfig() vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) deleteEmptyObjects = chainConfig.IsEIP158(block.Number()) + evm = vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{}) + logs []*types.Log ) - evm := vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{}) defer evm.Release() - if beaconRoot := block.BeaconRoot(); beaconRoot != nil { - core.ProcessBeaconBlockRoot(*beaconRoot, evm) - } - if chainConfig.IsPrague(block.Number(), block.Time()) { - core.ProcessParentBlockHash(block.ParentHash(), evm) + // Run pre-execution system calls + if err := core.PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), chainConfig, evm, block.Number(), block.Time()); err != nil { + return nil, err } for i, tx := range block.Transactions() { if err := ctx.Err(); err != nil { @@ -549,10 +546,15 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config // N.B: This should never happen while tracing canon blocks, only when tracing bad blocks. return roots, nil } - // calling IntermediateRoot will internally call Finalize on the state + // Calling IntermediateRoot will internally call Finalize on the state // so any modifications are written to the trie roots = append(roots, statedb.IntermediateRoot(deleteEmptyObjects)) + logs = append(logs, statedb.GetLogs(tx.Hash(), block.NumberU64(), block.Hash(), block.Time())...) } + // TODO(rjl) it's a behavioral change, need to discuss with team + // Run post-execution system calls + // core.PostExecution(ctx, chainConfig, block.Number(), block.Time(), logs, evm) + // roots = append(roots, statedb.IntermediateRoot(deleteEmptyObjects)) return roots, nil } @@ -588,13 +590,11 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) evm := vm.NewEVM(blockCtx, statedb, api.backend.ChainConfig(), vm.Config{}) defer evm.Release() - if beaconRoot := block.BeaconRoot(); beaconRoot != nil { - core.ProcessBeaconBlockRoot(*beaconRoot, evm) - } - if api.backend.ChainConfig().IsPrague(block.Number(), block.Time()) { - core.ProcessParentBlockHash(block.ParentHash(), evm) - } + // Run pre-execution system calls + if err := core.PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), api.backend.ChainConfig(), evm, block.Number(), block.Time()); err != nil { + return nil, err + } // JS tracers have high overhead. In this case run a parallel // process that generates states in one thread and traces txes // in separate worker threads. @@ -761,14 +761,12 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block // Note: This copies the config, to not screw up the main config chainConfig, canon = overrideConfig(chainConfig, config.Overrides) } - evm := vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{}) defer evm.Release() - if beaconRoot := block.BeaconRoot(); beaconRoot != nil { - core.ProcessBeaconBlockRoot(*beaconRoot, evm) - } - if chainConfig.IsPrague(block.Number(), block.Time()) { - core.ProcessParentBlockHash(block.ParentHash(), evm) + + // Run pre-execution system calls + if err := core.PreExecution(ctx, block.BeaconRoot(), block.ParentHash(), chainConfig, evm, block.Number(), block.Time()); err != nil { + return nil, err } for i, tx := range block.Transactions() { // Prepare the transaction for un-traced execution @@ -796,6 +794,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block return nil, err } dumps = append(dumps, dump.Name()) + // Set up the tracer and EVM for the transaction. var ( writer = bufio.NewWriter(dump) diff --git a/internal/ethapi/simulate.go b/internal/ethapi/simulate.go index 170104fbdf..8efb626374 100644 --- a/internal/ethapi/simulate.go +++ b/internal/ethapi/simulate.go @@ -319,8 +319,9 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header, evm.SetPrecompiles(precompiles) } // Run pre-execution system calls - core.PreExecution(ctx, header.ParentBeaconRoot, header.ParentHash, sim.chainConfig, evm, header.Number, header.Time) - + if err := core.PreExecution(ctx, header.ParentBeaconRoot, header.ParentHash, sim.chainConfig, evm, header.Number, header.Time); err != nil { + return nil, nil, nil, err + } var allLogs []*types.Log for i, call := range block.Calls { // Terminate if the context is cancelled diff --git a/miner/worker.go b/miner/worker.go index ccafa20b29..71cfabb6b4 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -318,7 +318,9 @@ func (miner *Miner) prepareWork(ctx context.Context, genParams *generateParams, return nil, err } // Run pre-execution system calls - core.PreExecution(ctx, header.ParentBeaconRoot, header.ParentHash, miner.chainConfig, env.evm, header.Number, header.Time) + if err := core.PreExecution(ctx, header.ParentBeaconRoot, header.ParentHash, miner.chainConfig, env.evm, header.Number, header.Time); err != nil { + return nil, err + } return env, nil }