Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions cmd/evm/internal/t8ntool/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,15 +201,14 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
chainConfig.DAOForkBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 {
misc.ApplyDAOHardFork(statedb)
}
evm := vm.NewEVM(vmContext, statedb, chainConfig, vmConfig)
if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil {
evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig)
core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb)
}
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)]
evm = vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig)
)
core.ProcessParentBlockHash(prevHash, evm, statedb)
}
Expand Down Expand Up @@ -246,8 +245,10 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
if err != nil {
return nil, nil, nil, err
}
// TODO (rjl493456442) it's a bit weird to reset the tracer in the
// middle of block execution, please improve it somehow.
Comment on lines +248 to +249
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, the tracer can be set earlier, on the vmconfig before it is passed to the evm. The thing that changes between transactions is the traceOutput. So we would need to split up getTracerFn. I'll take a look

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, yeah it's not quite that simple. Maybe let's leave it for a different PR

if tracer != nil {
vmConfig.Tracer = tracer.Hooks
evm.SetTracer(tracer.Hooks)
}
statedb.SetTxContext(tx.Hash(), txIndex)

Expand All @@ -256,12 +257,12 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
snapshot = statedb.Snapshot()
prevGas = gaspool.Gas()
)
evm := vm.NewEVM(vmContext, txContext, statedb, chainConfig, vmConfig)

if tracer != nil && tracer.OnTxStart != nil {
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
}
// (ret []byte, usedGas uint64, failed bool, err error)

evm.SetTxContext(txContext)
msgResult, err := core.ApplyMessage(evm, msg, gaspool)
if err != nil {
statedb.RevertToSnapshot(snapshot)
Expand Down Expand Up @@ -375,12 +376,11 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not parse requests logs: %v", err))
}
requests = append(requests, depositRequests)
// create EVM for system calls
vmenv := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vm.Config{})

// EIP-7002 withdrawals
requests = append(requests, core.ProcessWithdrawalQueue(vmenv, statedb))
requests = append(requests, core.ProcessWithdrawalQueue(evm, statedb))
// EIP-7251 consolidations
requests = append(requests, core.ProcessConsolidationQueue(vmenv, statedb))
requests = append(requests, core.ProcessConsolidationQueue(evm, statedb))
}

// Commit block
Expand Down
20 changes: 12 additions & 8 deletions core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ func (b *BlockGen) SetParentBeaconRoot(root common.Hash) {
b.header.ParentBeaconRoot = &root
var (
blockContext = NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase)
vmenv = vm.NewEVM(blockContext, vm.TxContext{}, b.statedb, b.cm.config, vm.Config{})
evm = vm.NewEVM(blockContext, b.statedb, b.cm.config, vm.Config{})
)
ProcessBeaconBlockRoot(root, vmenv, b.statedb)
ProcessBeaconBlockRoot(root, evm, b.statedb)
}

// addTx adds a transaction to the generated block. If no coinbase has
Expand All @@ -116,8 +116,12 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
if b.gasPool == nil {
b.SetCoinbase(common.Address{})
}
var (
blockContext = NewEVMBlockContext(b.header, bc, &b.header.Coinbase)
evm = vm.NewEVM(blockContext, b.statedb, b.cm.config, vmConfig)
)
b.statedb.SetTxContext(tx.Hash(), len(b.txs))
receipt, err := ApplyTransaction(b.cm.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vmConfig)
receipt, err := ApplyTransaction(b.cm.config, evm, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed)
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -360,12 +364,12 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
requests = append(requests, depositRequests)
// create EVM for system calls
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, cm.config, vm.Config{})
evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
// EIP-7002 withdrawals
withdrawalRequests := ProcessWithdrawalQueue(vmenv, statedb)
withdrawalRequests := ProcessWithdrawalQueue(evm, statedb)
requests = append(requests, withdrawalRequests)
// EIP-7251 consolidations
consolidationRequests := ProcessConsolidationQueue(vmenv, statedb)
consolidationRequests := ProcessConsolidationQueue(evm, statedb)
requests = append(requests, consolidationRequests)
}
if requests != nil {
Expand Down Expand Up @@ -466,8 +470,8 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
if config.IsPrague(b.header.Number, b.header.Time) {
// EIP-2935
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, cm.config, vm.Config{})
ProcessParentBlockHash(b.header.ParentHash, vmenv, statedb)
evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
ProcessParentBlockHash(b.header.ParentHash, evm, statedb)
}

// Execute any user modifications to the block.
Expand Down
8 changes: 4 additions & 4 deletions core/state_prefetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
header = block.Header()
gaspool = new(GasPool).AddGas(block.GasLimit())
blockContext = NewEVMBlockContext(header, p.chain, nil)
evm = vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
evm = vm.NewEVM(blockContext, statedb, p.config, cfg)
signer = types.MakeSigner(p.config, header.Number, header.Time)
)
// Iterate over and process the individual transactions
Expand All @@ -65,7 +65,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
return // Also invalid block, bail out
}
statedb.SetTxContext(tx.Hash(), i)
if err := precacheTransaction(msg, p.config, gaspool, statedb, header, evm); err != nil {
if err := precacheTransaction(msg, gaspool, evm); err != nil {
return // Ugh, something went horribly wrong, bail out
}
// If we're pre-byzantium, pre-load trie nodes for the intermediate root
Expand All @@ -82,9 +82,9 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
// precacheTransaction attempts to apply a transaction to the given state database
// and uses the input parameters for its environment. The goal is not to execute
// the transaction successfully, rather to warm up touched data slots.
func precacheTransaction(msg *Message, config *params.ChainConfig, gaspool *GasPool, statedb *state.StateDB, header *types.Header, evm *vm.EVM) error {
func precacheTransaction(msg *Message, gaspool *GasPool, evm *vm.EVM) error {
// Update the evm with the new transaction context.
evm.Reset(NewEVMTxContext(msg), statedb)
evm.SetTxContext(NewEVMTxContext(msg))
// Add addresses to access list if applicable
_, err := ApplyMessage(evm, msg, gaspool)
return err
Expand Down
31 changes: 14 additions & 17 deletions core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,18 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
)

// Apply pre-execution system calls.
context = NewEVMBlockContext(header, p.chain, nil)

vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg)
var tracingStateDB = vm.StateDB(statedb)
if hooks := cfg.Tracer; hooks != nil {
tracingStateDB = state.NewHookedState(statedb, hooks)
}
context = NewEVMBlockContext(header, p.chain, nil)
evm := vm.NewEVM(context, tracingStateDB, p.config, cfg)

if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
ProcessBeaconBlockRoot(*beaconRoot, vmenv, tracingStateDB)
ProcessBeaconBlockRoot(*beaconRoot, evm, tracingStateDB)
}
if p.config.IsPrague(block.Number(), block.Time()) {
ProcessParentBlockHash(block.ParentHash(), vmenv, tracingStateDB)
ProcessParentBlockHash(block.ParentHash(), evm, tracingStateDB)
}

// Iterate over and process the individual transactions
Expand All @@ -96,7 +96,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
}
statedb.SetTxContext(tx.Hash(), i)

receipt, err := ApplyTransactionWithEVM(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv)
receipt, err := ApplyTransactionWithEVM(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, evm)
if err != nil {
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
}
Expand All @@ -113,10 +113,10 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
}
requests = append(requests, depositRequests)
// EIP-7002 withdrawals
withdrawalRequests := ProcessWithdrawalQueue(vmenv, tracingStateDB)
withdrawalRequests := ProcessWithdrawalQueue(evm, tracingStateDB)
requests = append(requests, withdrawalRequests)
// EIP-7251 consolidations
consolidationRequests := ProcessConsolidationQueue(vmenv, tracingStateDB)
consolidationRequests := ProcessConsolidationQueue(evm, tracingStateDB)
requests = append(requests, consolidationRequests)
}

Expand Down Expand Up @@ -148,7 +148,7 @@ func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPo

// Create a new context to be used in the EVM environment.
txContext := NewEVMTxContext(msg)
evm.Reset(txContext, tracingStateDB)
evm.SetTxContext(txContext)

// Apply the transaction to the current state (included in the env).
result, err := ApplyMessage(evm, msg, gp)
Expand Down Expand Up @@ -210,16 +210,13 @@ func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, b
// and uses the input parameters for its environment. It returns the receipt
// for the transaction, gas used and an error if the transaction failed,
// indicating the block was invalid.
func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) {
func ApplyTransaction(config *params.ChainConfig, evm *vm.EVM, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64) (*types.Receipt, error) {
msg, err := TransactionToMessage(tx, types.MakeSigner(config, header.Number, header.Time), header.BaseFee)
if err != nil {
return nil, err
}
// Create a new context to be used in the EVM environment
blockContext := NewEVMBlockContext(header, bc, author)
txContext := NewEVMTxContext(msg)
vmenv := vm.NewEVM(blockContext, txContext, statedb, config, cfg)
return ApplyTransactionWithEVM(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv)
return ApplyTransactionWithEVM(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, evm)
}

// ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root
Expand All @@ -242,7 +239,7 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb vm.St
To: &params.BeaconRootsAddress,
Data: beaconRoot[:],
}
vmenv.Reset(NewEVMTxContext(msg), statedb)
vmenv.SetTxContext(NewEVMTxContext(msg))
statedb.AddAddressToAccessList(params.BeaconRootsAddress)
_, _, _ = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560)
statedb.Finalise(true)
Expand All @@ -268,7 +265,7 @@ func ProcessParentBlockHash(prevHash common.Hash, vmenv *vm.EVM, statedb vm.Stat
To: &params.HistoryStorageAddress,
Data: prevHash.Bytes(),
}
vmenv.Reset(NewEVMTxContext(msg), statedb)
vmenv.SetTxContext(NewEVMTxContext(msg))
statedb.AddAddressToAccessList(params.HistoryStorageAddress)
_, _, _ = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560)
statedb.Finalise(true)
Expand Down Expand Up @@ -304,7 +301,7 @@ func processRequestsSystemCall(vmenv *vm.EVM, statedb vm.StateDB, requestType by
GasTipCap: common.Big0,
To: &addr,
}
vmenv.Reset(NewEVMTxContext(msg), statedb)
vmenv.SetTxContext(NewEVMTxContext(msg))
statedb.AddAddressToAccessList(addr)
ret, _, _ := vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560)
statedb.Finalise(true)
Expand Down
2 changes: 1 addition & 1 deletion core/verkle_witness_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ func TestProcessParentBlockHash(t *testing.T) {
for i := 1; i <= num; i++ {
header := &types.Header{ParentHash: common.Hash{byte(i)}, Number: big.NewInt(int64(i)), Difficulty: new(big.Int)}
vmContext := NewEVMBlockContext(header, nil, new(common.Address))
evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, params.MergedTestChainConfig, vm.Config{})
evm := vm.NewEVM(vmContext, statedb, params.MergedTestChainConfig, vm.Config{})
ProcessParentBlockHash(header.ParentHash, evm, statedb)
}
// Read block hashes for block 0 .. num-1
Expand Down
21 changes: 13 additions & 8 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,13 @@ type EVM struct {
precompiles map[common.Address]PrecompiledContract
}

// NewEVM returns a new EVM. The returned EVM is not thread safe and should
// only ever be used *once*.
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM {
// NewEVM constructs an EVM instance with the supplied block context, state
// database and several configs. It meant to be used throughout the entire
// state transition of a block, with the transaction context switched as
// needed by calling evm.SetTxContext.
func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM {
evm := &EVM{
Context: blockCtx,
TxContext: txCtx,
StateDB: statedb,
Config: config,
chainConfig: chainConfig,
Expand All @@ -132,21 +133,25 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig
return evm
}

// SetTracer sets the tracer for following state transition.
func (evm *EVM) SetTracer(tracer *tracing.Hooks) {
evm.Config.Tracer = tracer
}

// SetPrecompiles sets the precompiled contracts for the EVM.
// This method is only used through RPC calls.
// It is not thread-safe.
func (evm *EVM) SetPrecompiles(precompiles PrecompiledContracts) {
evm.precompiles = precompiles
}

// Reset resets the EVM with a new transaction context.Reset
// SetTxContext resets the EVM with a new transaction context.
// This is not threadsafe and should only be done very cautiously.
func (evm *EVM) Reset(txCtx TxContext, statedb StateDB) {
func (evm *EVM) SetTxContext(txCtx TxContext) {
if evm.chainRules.IsEIP4762 {
txCtx.AccessEvents = state.NewAccessEvents(statedb.PointCache())
txCtx.AccessEvents = state.NewAccessEvents(evm.StateDB.PointCache())
}
evm.TxContext = txCtx
evm.StateDB = statedb
}

// Cancel cancels any running EVM operation. This may be called concurrently and
Expand Down
10 changes: 5 additions & 5 deletions core/vm/gas_table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,16 @@ func TestEIP2200(t *testing.T) {
CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true },
Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
}
vmenv := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})

_, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(uint256.Int))
_, gas, err := evm.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(uint256.Int))
if !errors.Is(err, tt.failure) {
t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.failure)
}
if used := tt.gaspool - gas; used != tt.used {
t.Errorf("test %d: gas used mismatch: have %v, want %v", i, used, tt.used)
}
if refund := vmenv.StateDB.GetRefund(); refund != tt.refund {
if refund := evm.StateDB.GetRefund(); refund != tt.refund {
t.Errorf("test %d: gas refund mismatch: have %v, want %v", i, refund, tt.refund)
}
}
Expand Down Expand Up @@ -151,9 +151,9 @@ func TestCreateGas(t *testing.T) {
config.ExtraEips = []int{3860}
}

vmenv := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, config)
evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, config)
var startGas = uint64(testGas)
ret, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, startGas, new(uint256.Int))
ret, gas, err := evm.Call(AccountRef(common.Address{}), address, nil, startGas, new(uint256.Int))
if err != nil {
return false
}
Expand Down
Loading