Skip to content

Commit 9ef1d67

Browse files
rjl493456442s1na
authored andcommitted
core: switch EVM tx context in ApplyMessage (ethereum#30809)
This change relocates the EVM tx context switching to the ApplyMessage function. With this change, we can remove a lot of EVM.SetTxContext calls before message execution. ### Tracing API changes - This PR replaces the `GasPrice` field of the `VMContext` struct with `BaseFee`. Users may instead take the effective gas price from `tx.EffectiveGasTipValue(env.BaseFee)`. --------- Co-authored-by: Sina Mahmoodi <[email protected]>
1 parent c98e558 commit 9ef1d67

File tree

20 files changed

+57
-105
lines changed

20 files changed

+57
-105
lines changed

cmd/evm/internal/t8ntool/execution.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -253,16 +253,13 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
253253
statedb.SetTxContext(tx.Hash(), txIndex)
254254

255255
var (
256-
txContext = core.NewEVMTxContext(msg)
257-
snapshot = statedb.Snapshot()
258-
prevGas = gaspool.Gas()
256+
snapshot = statedb.Snapshot()
257+
prevGas = gaspool.Gas()
259258
)
260259
if tracer != nil && tracer.OnTxStart != nil {
261260
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
262261
}
263262
// (ret []byte, usedGas uint64, failed bool, err error)
264-
265-
evm.SetTxContext(txContext)
266263
msgResult, err := core.ApplyMessage(evm, msg, gaspool)
267264
if err != nil {
268265
statedb.RevertToSnapshot(snapshot)

core/block_validator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
9393
}
9494

9595
// The individual checks for blob validity (version-check + not empty)
96-
// happens in StateTransition.
96+
// happens in state transition.
9797
}
9898

9999
// Check blob gas usage.

core/state_prefetcher.go

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
6565
return // Also invalid block, bail out
6666
}
6767
statedb.SetTxContext(tx.Hash(), i)
68-
if err := precacheTransaction(msg, gaspool, evm); err != nil {
68+
69+
// We attempt to apply a transaction. The goal is not to execute
70+
// the transaction successfully, rather to warm up touched data slots.
71+
if _, err := ApplyMessage(evm, msg, gaspool); err != nil {
6972
return // Ugh, something went horribly wrong, bail out
7073
}
7174
// If we're pre-byzantium, pre-load trie nodes for the intermediate root
@@ -78,14 +81,3 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
7881
statedb.IntermediateRoot(true)
7982
}
8083
}
81-
82-
// precacheTransaction attempts to apply a transaction to the given state database
83-
// and uses the input parameters for its environment. The goal is not to execute
84-
// the transaction successfully, rather to warm up touched data slots.
85-
func precacheTransaction(msg *Message, gaspool *GasPool, evm *vm.EVM) error {
86-
// Update the evm with the new transaction context.
87-
evm.SetTxContext(NewEVMTxContext(msg))
88-
// Add addresses to access list if applicable
89-
_, err := ApplyMessage(evm, msg, gaspool)
90-
return err
91-
}

core/state_processor.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -140,17 +140,11 @@ func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB,
140140
defer func() { hooks.OnTxEnd(receipt, err) }()
141141
}
142142
}
143-
144-
// Create a new context to be used in the EVM environment.
145-
txContext := NewEVMTxContext(msg)
146-
evm.SetTxContext(txContext)
147-
148143
// Apply the transaction to the current state (included in the env).
149144
result, err := ApplyMessage(evm, msg, gp)
150145
if err != nil {
151146
return nil, err
152147
}
153-
154148
// Update the state with pending changes.
155149
var root []byte
156150
if evm.ChainConfig().IsByzantium(blockNumber) {

core/state_transition.go

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -187,10 +187,11 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In
187187
// indicates a core error meaning that the message would always fail for that particular
188188
// state and would never be accepted within a block.
189189
func ApplyMessage(evm *vm.EVM, msg *Message, gp *GasPool) (*ExecutionResult, error) {
190-
return NewStateTransition(evm, msg, gp).TransitionDb()
190+
evm.SetTxContext(NewEVMTxContext(msg))
191+
return newStateTransition(evm, msg, gp).execute()
191192
}
192193

193-
// StateTransition represents a state transition.
194+
// stateTransition represents a state transition.
194195
//
195196
// == The State Transitioning Model
196197
//
@@ -212,7 +213,7 @@ func ApplyMessage(evm *vm.EVM, msg *Message, gp *GasPool) (*ExecutionResult, err
212213
//
213214
// 5. Run Script section
214215
// 6. Derive new state root
215-
type StateTransition struct {
216+
type stateTransition struct {
216217
gp *GasPool
217218
msg *Message
218219
gasRemaining uint64
@@ -221,9 +222,9 @@ type StateTransition struct {
221222
evm *vm.EVM
222223
}
223224

224-
// NewStateTransition initialises and returns a new state transition object.
225-
func NewStateTransition(evm *vm.EVM, msg *Message, gp *GasPool) *StateTransition {
226-
return &StateTransition{
225+
// newStateTransition initialises and returns a new state transition object.
226+
func newStateTransition(evm *vm.EVM, msg *Message, gp *GasPool) *stateTransition {
227+
return &stateTransition{
227228
gp: gp,
228229
evm: evm,
229230
msg: msg,
@@ -232,14 +233,14 @@ func NewStateTransition(evm *vm.EVM, msg *Message, gp *GasPool) *StateTransition
232233
}
233234

234235
// to returns the recipient of the message.
235-
func (st *StateTransition) to() common.Address {
236+
func (st *stateTransition) to() common.Address {
236237
if st.msg == nil || st.msg.To == nil /* contract creation */ {
237238
return common.Address{}
238239
}
239240
return *st.msg.To
240241
}
241242

242-
func (st *StateTransition) buyGas() error {
243+
func (st *stateTransition) buyGas() error {
243244
mgval := new(big.Int).SetUint64(st.msg.GasLimit)
244245
mgval.Mul(mgval, st.msg.GasPrice)
245246
balanceCheck := new(big.Int).Set(mgval)
@@ -283,7 +284,7 @@ func (st *StateTransition) buyGas() error {
283284
return nil
284285
}
285286

286-
func (st *StateTransition) preCheck() error {
287+
func (st *stateTransition) preCheck() error {
287288
// Only check transactions that are not fake
288289
msg := st.msg
289290
if !msg.SkipNonceChecks {
@@ -368,7 +369,7 @@ func (st *StateTransition) preCheck() error {
368369
return st.buyGas()
369370
}
370371

371-
// TransitionDb will transition the state by applying the current message and
372+
// execute will transition the state by applying the current message and
372373
// returning the evm execution result with following fields.
373374
//
374375
// - used gas: total gas used (including gas being refunded)
@@ -378,7 +379,7 @@ func (st *StateTransition) preCheck() error {
378379
//
379380
// However if any consensus issue encountered, return the error directly with
380381
// nil evm execution result.
381-
func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
382+
func (st *stateTransition) execute() (*ExecutionResult, error) {
382383
// First check this message satisfies all consensus rules before
383384
// applying the message. The rules include these clauses
384385
//
@@ -493,7 +494,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
493494
}, nil
494495
}
495496

496-
func (st *StateTransition) refundGas(refundQuotient uint64) uint64 {
497+
func (st *stateTransition) refundGas(refundQuotient uint64) uint64 {
497498
// Apply refund counter, capped to a refund quotient
498499
refund := st.gasUsed() / refundQuotient
499500
if refund > st.state.GetRefund() {
@@ -523,11 +524,11 @@ func (st *StateTransition) refundGas(refundQuotient uint64) uint64 {
523524
}
524525

525526
// gasUsed returns the amount of gas used up by the state transition.
526-
func (st *StateTransition) gasUsed() uint64 {
527+
func (st *stateTransition) gasUsed() uint64 {
527528
return st.initialGas - st.gasRemaining
528529
}
529530

530531
// blobGasUsed returns the amount of blob gas used by the message.
531-
func (st *StateTransition) blobGasUsed() uint64 {
532+
func (st *stateTransition) blobGasUsed() uint64 {
532533
return uint64(len(st.msg.BlobHashes) * params.BlobTxBlobGasPerBlob)
533534
}

core/tracing/hooks.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,8 @@ type VMContext struct {
5555
BlockNumber *big.Int
5656
Time uint64
5757
Random *common.Hash
58-
// Effective tx gas price
59-
GasPrice *big.Int
60-
StateDB StateDB
58+
BaseFee *big.Int
59+
StateDB StateDB
6160
}
6261

6362
// BlockEvent is emitted upon tracing an incoming block.

core/vm/evm.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ func (evm *EVM) GetVMContext() *tracing.VMContext {
605605
BlockNumber: evm.Context.BlockNumber,
606606
Time: evm.Context.Time,
607607
Random: evm.Context.Random,
608-
GasPrice: evm.TxContext.GasPrice,
608+
BaseFee: evm.Context.BaseFee,
609609
StateDB: evm.StateDB,
610610
}
611611
}

eth/gasestimator/gasestimator.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,21 +217,19 @@ func execute(ctx context.Context, call *core.Message, opts *Options, gasLimit ui
217217
func run(ctx context.Context, call *core.Message, opts *Options) (*core.ExecutionResult, error) {
218218
// Assemble the call and the call context
219219
var (
220-
msgContext = core.NewEVMTxContext(call)
221220
evmContext = core.NewEVMBlockContext(opts.Header, opts.Chain, nil)
222-
223221
dirtyState = opts.State.Copy()
224222
)
225223
// Lower the basefee to 0 to avoid breaking EVM
226224
// invariants (basefee < feecap).
227-
if msgContext.GasPrice.Sign() == 0 {
225+
if call.GasPrice.Sign() == 0 {
228226
evmContext.BaseFee = new(big.Int)
229227
}
230-
if msgContext.BlobFeeCap != nil && msgContext.BlobFeeCap.BitLen() == 0 {
228+
if call.BlobGasFeeCap != nil && call.BlobGasFeeCap.BitLen() == 0 {
231229
evmContext.BlobBaseFee = new(big.Int)
232230
}
233231
evm := vm.NewEVM(evmContext, dirtyState, opts.Config, vm.Config{NoBaseFee: true})
234-
evm.SetTxContext(msgContext)
232+
235233
// Monitor the outer context and interrupt the EVM upon cancellation. To avoid
236234
// a dangling goroutine until the outer estimation finishes, create an internal
237235
// context for the lifetime of this method call.

eth/state_accessor.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,6 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
255255
}
256256
// Assemble the transaction call message and return if the requested offset
257257
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
258-
txContext := core.NewEVMTxContext(msg)
259-
evm.SetTxContext(txContext)
260258

261259
// Not yet the searched for transaction, execute on top of the current state
262260
statedb.SetTxContext(tx.Hash(), idx)

eth/tracers/api.go

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -546,11 +546,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
546546
if err := ctx.Err(); err != nil {
547547
return nil, err
548548
}
549-
var (
550-
msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee())
551-
txContext = core.NewEVMTxContext(msg)
552-
)
553-
evm.SetTxContext(txContext)
549+
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
554550
statedb.SetTxContext(tx.Hash(), i)
555551
if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil {
556552
log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err)
@@ -708,7 +704,6 @@ txloop:
708704
// Generate the next state snapshot fast without tracing
709705
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
710706
statedb.SetTxContext(tx.Hash(), i)
711-
evm.SetTxContext(core.NewEVMTxContext(msg))
712707
if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil {
713708
failed = err
714709
break txloop
@@ -792,12 +787,11 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
792787
for i, tx := range block.Transactions() {
793788
// Prepare the transaction for un-traced execution
794789
var (
795-
msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee())
796-
txContext = core.NewEVMTxContext(msg)
797-
vmConf vm.Config
798-
dump *os.File
799-
writer *bufio.Writer
800-
err error
790+
msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee())
791+
vmConf vm.Config
792+
dump *os.File
793+
writer *bufio.Writer
794+
err error
801795
)
802796
// If the transaction needs tracing, swap out the configs
803797
if tx.Hash() == txHash || txHash == (common.Hash{}) {
@@ -820,7 +814,6 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
820814
}
821815
}
822816
// Execute the transaction and flush any traces to disk
823-
evm.SetTxContext(txContext)
824817
statedb.SetTxContext(tx.Hash(), i)
825818
if vmConf.Tracer.OnTxStart != nil {
826819
vmConf.Tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
@@ -1016,7 +1009,6 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
10161009
}
10171010
// The actual TxContext will be created as part of ApplyTransactionWithEVM.
10181011
evm := vm.NewEVM(vmctx, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true})
1019-
evm.SetTxContext(vm.TxContext{GasPrice: message.GasPrice, BlobFeeCap: message.BlobGasFeeCap})
10201012

10211013
// Define a meaningful timeout of a single transaction trace
10221014
if config.Timeout != nil {

0 commit comments

Comments
 (0)