diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 01df64ed6e..59296c0e1c 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -208,7 +208,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, rejectedTxs = append(rejectedTxs, &rejectedTx{i, errMsg}) continue } - msg, err := core.TransactionToMessage(tx, signer, pre.Env.BaseFee) + msg, err := core.TransactionToMessage(tx, signer, pre.Env.BaseFee, core.MessageCommitMode) if err != nil { log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", err) rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go index ff867309de..572b715506 100644 --- a/core/state_prefetcher.go +++ b/core/state_prefetcher.go @@ -63,7 +63,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c return } // Convert the transaction into an executable message and pre-cache its sender - msg, err := TransactionToMessage(tx, signer, header.BaseFee) + msg, err := TransactionToMessage(tx, signer, header.BaseFee, MessageEthcallMode) if err != nil { return // Also invalid block, bail out } diff --git a/core/state_processor.go b/core/state_processor.go index 234f23bd20..af388487ad 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -80,7 +80,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg } // Iterate over and process the individual transactions for i, tx := range block.Transactions() { - msg, err := TransactionToMessage(tx, signer, header.BaseFee) + msg, err := TransactionToMessage(tx, signer, header.BaseFee, MessageCommitMode) if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } @@ -170,7 +170,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo } func ApplyTransactionWithResultFilter(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config, resultFilter func(*ExecutionResult) error) (*types.Receipt, *ExecutionResult, error) { - msg, err := TransactionToMessage(tx, types.MakeSigner(config, header.Number, header.Time), header.BaseFee) + msg, err := TransactionToMessage(tx, types.MakeSigner(config, header.Number, header.Time), header.BaseFee, MessageReplayMode) if err != nil { return nil, nil, err } diff --git a/core/state_transition.go b/core/state_transition.go index c3334c13c4..7fbdd797d5 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -165,11 +165,19 @@ const ( MessageCommitMode MessageRunMode = iota MessageGasEstimationMode MessageEthcallMode + MessageReplayMode ) +// these message modes are executed onchain so cannot make any gas shortcuts +func (m MessageRunMode) ExecutedOnChain() bool { + return m == MessageCommitMode || m == MessageReplayMode +} + // TransactionToMessage converts a transaction into a Message. -func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.Int) (*Message, error) { +func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.Int, runmode MessageRunMode) (*Message, error) { msg := &Message{ + TxRunMode: runmode, + Tx: tx, Nonce: tx.Nonce(), diff --git a/eth/state_accessor.go b/eth/state_accessor.go index 439d88c2d8..3e76c01c83 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -259,7 +259,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, signer := types.MakeSigner(eth.blockchain.Config(), block.Number(), block.Time()) for idx, tx := range block.Transactions() { // Assemble the transaction call message and return if the requested offset - msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) + msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee(), core.MessageReplayMode) txContext := core.NewEVMTxContext(msg) context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil) if idx == txIndex { diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 3352ee9eff..e6c7adadec 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -274,7 +274,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed ) // Trace all the transactions contained within for i, tx := range task.block.Transactions() { - msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee()) + msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee(), core.MessageReplayMode) txctx := &Context{ BlockHash: task.block.Hash(), BlockNumber: task.block.Number(), @@ -535,7 +535,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config return nil, err } var ( - msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee()) + msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee(), core.MessageReplayMode) txContext = core.NewEVMTxContext(msg) vmenv = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{}) ) @@ -609,7 +609,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac ) for i, tx := range txs { // Generate the next state snapshot fast without tracing - msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) + msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee(), core.MessageReplayMode) txctx := &Context{ BlockHash: blockHash, BlockNumber: block.Number(), @@ -652,7 +652,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat defer pend.Done() // Fetch and execute the next transaction trace tasks for task := range jobs { - msg, _ := core.TransactionToMessage(txs[task.index], signer, block.BaseFee()) + msg, _ := core.TransactionToMessage(txs[task.index], signer, block.BaseFee(), core.MessageReplayMode) txctx := &Context{ BlockHash: blockHash, BlockNumber: block.Number(), @@ -683,7 +683,7 @@ txloop: } // Generate the next state snapshot fast without tracing - msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) + msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee(), core.MessageReplayMode) statedb.SetTxContext(tx.Hash(), i) vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, api.backend.ChainConfig(), vm.Config{}) if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil { @@ -763,7 +763,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block for i, tx := range block.Transactions() { // Prepare the transaction for un-traced execution var ( - msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee()) + msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee(), core.MessageReplayMode) txContext = core.NewEVMTxContext(msg) vmConf vm.Config dump *os.File diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index 94722ee372..18e9153374 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -175,7 +175,7 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block // Recompute transactions up to the target index. signer := types.MakeSigner(b.chainConfig, block.Number(), block.Time()) for idx, tx := range block.Transactions() { - msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) + msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee(), core.MessageReplayMode) txContext := core.NewEVMTxContext(msg) context := core.NewEVMBlockContext(block.Header(), b.chain, nil) if idx == txIndex { diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go index fe694881f9..a43ea1ff86 100644 --- a/eth/tracers/internal/tracetest/calltrace_test.go +++ b/eth/tracers/internal/tracetest/calltrace_test.go @@ -152,7 +152,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) { if err != nil { t.Fatalf("failed to create call tracer: %v", err) } - msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) + msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, core.MessageReplayMode) if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } @@ -242,7 +242,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) { Difficulty: (*big.Int)(test.Context.Difficulty), GasLimit: uint64(test.Context.GasLimit), } - msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) + msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, core.MessageReplayMode) if err != nil { b.Fatalf("failed to prepare transaction for tracing: %v", err) } diff --git a/eth/tracers/internal/tracetest/flat_calltrace_test.go b/eth/tracers/internal/tracetest/flat_calltrace_test.go index b318548bc1..124cc9b38a 100644 --- a/eth/tracers/internal/tracetest/flat_calltrace_test.go +++ b/eth/tracers/internal/tracetest/flat_calltrace_test.go @@ -103,7 +103,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string if err != nil { return fmt.Errorf("failed to create call tracer: %v", err) } - msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) + msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, core.MessageReplayMode) if err != nil { return fmt.Errorf("failed to prepare transaction for tracing: %v", err) } diff --git a/eth/tracers/internal/tracetest/prestate_test.go b/eth/tracers/internal/tracetest/prestate_test.go index 666a5fda78..b8c239d0d7 100644 --- a/eth/tracers/internal/tracetest/prestate_test.go +++ b/eth/tracers/internal/tracetest/prestate_test.go @@ -111,7 +111,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) { if err != nil { t.Fatalf("failed to create call tracer: %v", err) } - msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) + msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, core.MessageReplayMode) if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go index b10f3503e0..09aa5010cd 100644 --- a/eth/tracers/tracers_test.go +++ b/eth/tracers/tracers_test.go @@ -90,7 +90,7 @@ func BenchmarkTransactionTrace(b *testing.B) { //EnableReturnData: false, }) evm := vm.NewEVM(context, txContext, statedb, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer}) - msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) + msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, core.MessageReplayMode) if err != nil { b.Fatalf("failed to prepare transaction for tracing: %v", err) } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 1223441b98..54d982d70e 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1155,7 +1155,7 @@ func runScheduledTxes(ctx context.Context, b core.NodeInterfaceBackendAPI, state scheduled := result.ScheduledTxes for runMode == core.MessageGasEstimationMode && len(scheduled) > 0 { // This will panic if the scheduled tx is signed, but we only schedule unsigned ones - msg, err := core.TransactionToMessage(scheduled[0], types.NewArbitrumSigner(nil), header.BaseFee) + msg, err := core.TransactionToMessage(scheduled[0], types.NewArbitrumSigner(nil), header.BaseFee, runMode) if err != nil { return nil, err } @@ -1167,7 +1167,6 @@ func runScheduledTxes(ctx context.Context, b core.NodeInterfaceBackendAPI, state log.Warn("Scheduling tx used less gas than scheduled tx has available", "usedGas", result.UsedGas, "scheduledGas", msg.GasLimit) result.UsedGas = 0 } - msg.TxRunMode = runMode // make a new EVM for the scheduled Tx (an EVM must never be reused) evm := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}, &blockCtx) go func() {