From 57d92f100b38619146f81690a8132848180e5937 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 22 May 2024 19:43:16 -0600 Subject: [PATCH 1/3] core: create MessageReplayMode and make argument required in TransactionToMessage --- cmd/evm/internal/t8ntool/execution.go | 2 +- core/state_prefetcher.go | 2 +- core/state_processor.go | 4 ++-- core/state_transition.go | 5 ++++- eth/state_accessor.go | 2 +- eth/tracers/api.go | 12 ++++++------ eth/tracers/api_test.go | 2 +- eth/tracers/internal/tracetest/calltrace_test.go | 4 ++-- .../internal/tracetest/flat_calltrace_test.go | 2 +- eth/tracers/internal/tracetest/prestate_test.go | 2 +- eth/tracers/tracers_test.go | 2 +- internal/ethapi/api.go | 2 +- 12 files changed, 22 insertions(+), 19 deletions(-) diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 01df64ed6..59296c0e1 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 ff867309d..572b71550 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 234f23bd2..f109f3641 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, MessageCommitMode) if err != nil { return nil, nil, err } diff --git a/core/state_transition.go b/core/state_transition.go index c3334c13c..3613ebb9b 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -165,11 +165,14 @@ const ( MessageCommitMode MessageRunMode = iota MessageGasEstimationMode MessageEthcallMode + 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 439d88c2d..3e76c01c8 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 3352ee9ef..e6c7adade 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 94722ee37..18e915337 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 fe694881f..a43ea1ff8 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 b318548bc..124cc9b38 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 666a5fda7..b8c239d0d 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 b10f3503e..09aa5010c 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 1223441b9..b325a96ec 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, core.MessageReplayMode) if err != nil { return nil, err } From a19d794fbc7ebe21669a31ad31bdbca208c5597c Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 22 May 2024 20:14:22 -0600 Subject: [PATCH 2/3] add ExecutedOnChain func for RunMode --- core/state_transition.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/state_transition.go b/core/state_transition.go index 3613ebb9b..7fbdd797d 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -168,6 +168,11 @@ const ( 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, runmode MessageRunMode) (*Message, error) { msg := &Message{ From de513a2b2c8e9e1239190992fcdaccef81cd387c Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 28 May 2024 17:50:10 -0600 Subject: [PATCH 3/3] fixed runmode for two invocations --- core/state_processor.go | 2 +- internal/ethapi/api.go | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/state_processor.go b/core/state_processor.go index f109f3641..af388487a 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -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, MessageCommitMode) + msg, err := TransactionToMessage(tx, types.MakeSigner(config, header.Number, header.Time), header.BaseFee, MessageReplayMode) if err != nil { return nil, nil, err } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index b325a96ec..54d982d70 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, core.MessageReplayMode) + 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() {