core, eth, internal, cmd: rework EVM constructor (#30745)
This pull request refactors the EVM constructor by removing the TxContext parameter. The EVM object is frequently overused. Ideally, only a single EVM instance should be created and reused throughout the entire state transition of a block, with the transaction context switched as needed by calling evm.SetTxContext. Unfortunately, in some parts of the code, the EVM object is repeatedly created, resulting in unnecessary complexity. This pull request is the first step towards gradually improving and simplifying this setup. --------- Co-authored-by: Martin Holst Swende <martin@swende.se>
This commit is contained in:
parent
6d3d252a5e
commit
e3d61e6db0
|
@ -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 {
|
chainConfig.DAOForkBlock.Cmp(new(big.Int).SetUint64(pre.Env.Number)) == 0 {
|
||||||
misc.ApplyDAOHardFork(statedb)
|
misc.ApplyDAOHardFork(statedb)
|
||||||
}
|
}
|
||||||
|
evm := vm.NewEVM(vmContext, statedb, chainConfig, vmConfig)
|
||||||
if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil {
|
if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil {
|
||||||
evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig)
|
|
||||||
core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb)
|
core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb)
|
||||||
}
|
}
|
||||||
if pre.Env.BlockHashes != nil && chainConfig.IsPrague(new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) {
|
if pre.Env.BlockHashes != nil && chainConfig.IsPrague(new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) {
|
||||||
var (
|
var (
|
||||||
prevNumber = pre.Env.Number - 1
|
prevNumber = pre.Env.Number - 1
|
||||||
prevHash = pre.Env.BlockHashes[math.HexOrDecimal64(prevNumber)]
|
prevHash = pre.Env.BlockHashes[math.HexOrDecimal64(prevNumber)]
|
||||||
evm = vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vmConfig)
|
|
||||||
)
|
)
|
||||||
core.ProcessParentBlockHash(prevHash, evm, statedb)
|
core.ProcessParentBlockHash(prevHash, evm, statedb)
|
||||||
}
|
}
|
||||||
|
@ -246,8 +245,10 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
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.
|
||||||
if tracer != nil {
|
if tracer != nil {
|
||||||
vmConfig.Tracer = tracer.Hooks
|
evm.SetTracer(tracer.Hooks)
|
||||||
}
|
}
|
||||||
statedb.SetTxContext(tx.Hash(), txIndex)
|
statedb.SetTxContext(tx.Hash(), txIndex)
|
||||||
|
|
||||||
|
@ -256,12 +257,12 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
snapshot = statedb.Snapshot()
|
snapshot = statedb.Snapshot()
|
||||||
prevGas = gaspool.Gas()
|
prevGas = gaspool.Gas()
|
||||||
)
|
)
|
||||||
evm := vm.NewEVM(vmContext, txContext, statedb, chainConfig, vmConfig)
|
|
||||||
|
|
||||||
if tracer != nil && tracer.OnTxStart != nil {
|
if tracer != nil && tracer.OnTxStart != nil {
|
||||||
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
||||||
}
|
}
|
||||||
// (ret []byte, usedGas uint64, failed bool, err error)
|
// (ret []byte, usedGas uint64, failed bool, err error)
|
||||||
|
|
||||||
|
evm.SetTxContext(txContext)
|
||||||
msgResult, err := core.ApplyMessage(evm, msg, gaspool)
|
msgResult, err := core.ApplyMessage(evm, msg, gaspool)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
statedb.RevertToSnapshot(snapshot)
|
statedb.RevertToSnapshot(snapshot)
|
||||||
|
@ -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))
|
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not parse requests logs: %v", err))
|
||||||
}
|
}
|
||||||
requests = append(requests, depositRequests)
|
requests = append(requests, depositRequests)
|
||||||
// create EVM for system calls
|
|
||||||
vmenv := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vm.Config{})
|
|
||||||
// EIP-7002 withdrawals
|
// EIP-7002 withdrawals
|
||||||
requests = append(requests, core.ProcessWithdrawalQueue(vmenv, statedb))
|
requests = append(requests, core.ProcessWithdrawalQueue(evm, statedb))
|
||||||
// EIP-7251 consolidations
|
// EIP-7251 consolidations
|
||||||
requests = append(requests, core.ProcessConsolidationQueue(vmenv, statedb))
|
requests = append(requests, core.ProcessConsolidationQueue(evm, statedb))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit block
|
// Commit block
|
||||||
|
|
|
@ -100,9 +100,9 @@ func (b *BlockGen) SetParentBeaconRoot(root common.Hash) {
|
||||||
b.header.ParentBeaconRoot = &root
|
b.header.ParentBeaconRoot = &root
|
||||||
var (
|
var (
|
||||||
blockContext = NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase)
|
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
|
// addTx adds a transaction to the generated block. If no coinbase has
|
||||||
|
@ -116,8 +116,12 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
|
||||||
if b.gasPool == nil {
|
if b.gasPool == nil {
|
||||||
b.SetCoinbase(common.Address{})
|
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))
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -360,12 +364,12 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||||
requests = append(requests, depositRequests)
|
requests = append(requests, depositRequests)
|
||||||
// create EVM for system calls
|
// create EVM for system calls
|
||||||
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
|
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
|
// EIP-7002 withdrawals
|
||||||
withdrawalRequests := ProcessWithdrawalQueue(vmenv, statedb)
|
withdrawalRequests := ProcessWithdrawalQueue(evm, statedb)
|
||||||
requests = append(requests, withdrawalRequests)
|
requests = append(requests, withdrawalRequests)
|
||||||
// EIP-7251 consolidations
|
// EIP-7251 consolidations
|
||||||
consolidationRequests := ProcessConsolidationQueue(vmenv, statedb)
|
consolidationRequests := ProcessConsolidationQueue(evm, statedb)
|
||||||
requests = append(requests, consolidationRequests)
|
requests = append(requests, consolidationRequests)
|
||||||
}
|
}
|
||||||
if requests != nil {
|
if requests != nil {
|
||||||
|
@ -466,8 +470,8 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
|
||||||
if config.IsPrague(b.header.Number, b.header.Time) {
|
if config.IsPrague(b.header.Number, b.header.Time) {
|
||||||
// EIP-2935
|
// EIP-2935
|
||||||
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
|
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{})
|
||||||
ProcessParentBlockHash(b.header.ParentHash, vmenv, statedb)
|
ProcessParentBlockHash(b.header.ParentHash, evm, statedb)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute any user modifications to the block.
|
// Execute any user modifications to the block.
|
||||||
|
|
|
@ -49,7 +49,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
|
||||||
header = block.Header()
|
header = block.Header()
|
||||||
gaspool = new(GasPool).AddGas(block.GasLimit())
|
gaspool = new(GasPool).AddGas(block.GasLimit())
|
||||||
blockContext = NewEVMBlockContext(header, p.chain, nil)
|
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)
|
signer = types.MakeSigner(p.config, header.Number, header.Time)
|
||||||
)
|
)
|
||||||
// Iterate over and process the individual transactions
|
// Iterate over and process the individual transactions
|
||||||
|
@ -65,7 +65,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
|
||||||
return // Also invalid block, bail out
|
return // Also invalid block, bail out
|
||||||
}
|
}
|
||||||
statedb.SetTxContext(tx.Hash(), i)
|
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
|
return // Ugh, something went horribly wrong, bail out
|
||||||
}
|
}
|
||||||
// If we're pre-byzantium, pre-load trie nodes for the intermediate root
|
// If we're pre-byzantium, pre-load trie nodes for the intermediate root
|
||||||
|
@ -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
|
// 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
|
// and uses the input parameters for its environment. The goal is not to execute
|
||||||
// the transaction successfully, rather to warm up touched data slots.
|
// 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.
|
// Update the evm with the new transaction context.
|
||||||
evm.Reset(NewEVMTxContext(msg), statedb)
|
evm.SetTxContext(NewEVMTxContext(msg))
|
||||||
// Add addresses to access list if applicable
|
// Add addresses to access list if applicable
|
||||||
_, err := ApplyMessage(evm, msg, gaspool)
|
_, err := ApplyMessage(evm, msg, gaspool)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -74,18 +74,18 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
)
|
)
|
||||||
|
|
||||||
// Apply pre-execution system calls.
|
// 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)
|
var tracingStateDB = vm.StateDB(statedb)
|
||||||
if hooks := cfg.Tracer; hooks != nil {
|
if hooks := cfg.Tracer; hooks != nil {
|
||||||
tracingStateDB = state.NewHookedState(statedb, hooks)
|
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 {
|
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
||||||
ProcessBeaconBlockRoot(*beaconRoot, vmenv, tracingStateDB)
|
ProcessBeaconBlockRoot(*beaconRoot, evm, tracingStateDB)
|
||||||
}
|
}
|
||||||
if p.config.IsPrague(block.Number(), block.Time()) {
|
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
|
// Iterate over and process the individual transactions
|
||||||
|
@ -96,7 +96,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
}
|
}
|
||||||
statedb.SetTxContext(tx.Hash(), i)
|
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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
||||||
}
|
}
|
||||||
|
@ -113,10 +113,10 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
}
|
}
|
||||||
requests = append(requests, depositRequests)
|
requests = append(requests, depositRequests)
|
||||||
// EIP-7002 withdrawals
|
// EIP-7002 withdrawals
|
||||||
withdrawalRequests := ProcessWithdrawalQueue(vmenv, tracingStateDB)
|
withdrawalRequests := ProcessWithdrawalQueue(evm, tracingStateDB)
|
||||||
requests = append(requests, withdrawalRequests)
|
requests = append(requests, withdrawalRequests)
|
||||||
// EIP-7251 consolidations
|
// EIP-7251 consolidations
|
||||||
consolidationRequests := ProcessConsolidationQueue(vmenv, tracingStateDB)
|
consolidationRequests := ProcessConsolidationQueue(evm, tracingStateDB)
|
||||||
requests = append(requests, consolidationRequests)
|
requests = append(requests, consolidationRequests)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,9 +135,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
// and uses the input parameters for its environment similar to ApplyTransaction. However,
|
// and uses the input parameters for its environment similar to ApplyTransaction. However,
|
||||||
// this method takes an already created EVM instance as input.
|
// this method takes an already created EVM instance as input.
|
||||||
func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (receipt *types.Receipt, err error) {
|
func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (receipt *types.Receipt, err error) {
|
||||||
var tracingStateDB = vm.StateDB(statedb)
|
|
||||||
if hooks := evm.Config.Tracer; hooks != nil {
|
if hooks := evm.Config.Tracer; hooks != nil {
|
||||||
tracingStateDB = state.NewHookedState(statedb, hooks)
|
|
||||||
if hooks.OnTxStart != nil {
|
if hooks.OnTxStart != nil {
|
||||||
hooks.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
hooks.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
||||||
}
|
}
|
||||||
|
@ -148,7 +146,7 @@ func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPo
|
||||||
|
|
||||||
// Create a new context to be used in the EVM environment.
|
// Create a new context to be used in the EVM environment.
|
||||||
txContext := NewEVMTxContext(msg)
|
txContext := NewEVMTxContext(msg)
|
||||||
evm.Reset(txContext, tracingStateDB)
|
evm.SetTxContext(txContext)
|
||||||
|
|
||||||
// Apply the transaction to the current state (included in the env).
|
// Apply the transaction to the current state (included in the env).
|
||||||
result, err := ApplyMessage(evm, msg, gp)
|
result, err := ApplyMessage(evm, msg, gp)
|
||||||
|
@ -159,7 +157,7 @@ func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPo
|
||||||
// Update the state with pending changes.
|
// Update the state with pending changes.
|
||||||
var root []byte
|
var root []byte
|
||||||
if config.IsByzantium(blockNumber) {
|
if config.IsByzantium(blockNumber) {
|
||||||
tracingStateDB.Finalise(true)
|
evm.StateDB.Finalise(true)
|
||||||
} else {
|
} else {
|
||||||
root = statedb.IntermediateRoot(config.IsEIP158(blockNumber)).Bytes()
|
root = statedb.IntermediateRoot(config.IsEIP158(blockNumber)).Bytes()
|
||||||
}
|
}
|
||||||
|
@ -210,16 +208,13 @@ func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, b
|
||||||
// and uses the input parameters for its environment. It returns the receipt
|
// and uses the input parameters for its environment. It returns the receipt
|
||||||
// for the transaction, gas used and an error if the transaction failed,
|
// for the transaction, gas used and an error if the transaction failed,
|
||||||
// indicating the block was invalid.
|
// 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)
|
msg, err := TransactionToMessage(tx, types.MakeSigner(config, header.Number, header.Time), header.BaseFee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Create a new context to be used in the EVM environment
|
// Create a new context to be used in the EVM environment
|
||||||
blockContext := NewEVMBlockContext(header, bc, author)
|
return ApplyTransactionWithEVM(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, evm)
|
||||||
txContext := NewEVMTxContext(msg)
|
|
||||||
vmenv := vm.NewEVM(blockContext, txContext, statedb, config, cfg)
|
|
||||||
return ApplyTransactionWithEVM(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root
|
// ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root
|
||||||
|
@ -242,7 +237,7 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb vm.St
|
||||||
To: ¶ms.BeaconRootsAddress,
|
To: ¶ms.BeaconRootsAddress,
|
||||||
Data: beaconRoot[:],
|
Data: beaconRoot[:],
|
||||||
}
|
}
|
||||||
vmenv.Reset(NewEVMTxContext(msg), statedb)
|
vmenv.SetTxContext(NewEVMTxContext(msg))
|
||||||
statedb.AddAddressToAccessList(params.BeaconRootsAddress)
|
statedb.AddAddressToAccessList(params.BeaconRootsAddress)
|
||||||
_, _, _ = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560)
|
_, _, _ = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560)
|
||||||
statedb.Finalise(true)
|
statedb.Finalise(true)
|
||||||
|
@ -268,7 +263,7 @@ func ProcessParentBlockHash(prevHash common.Hash, vmenv *vm.EVM, statedb vm.Stat
|
||||||
To: ¶ms.HistoryStorageAddress,
|
To: ¶ms.HistoryStorageAddress,
|
||||||
Data: prevHash.Bytes(),
|
Data: prevHash.Bytes(),
|
||||||
}
|
}
|
||||||
vmenv.Reset(NewEVMTxContext(msg), statedb)
|
vmenv.SetTxContext(NewEVMTxContext(msg))
|
||||||
statedb.AddAddressToAccessList(params.HistoryStorageAddress)
|
statedb.AddAddressToAccessList(params.HistoryStorageAddress)
|
||||||
_, _, _ = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560)
|
_, _, _ = vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560)
|
||||||
statedb.Finalise(true)
|
statedb.Finalise(true)
|
||||||
|
@ -304,7 +299,7 @@ func processRequestsSystemCall(vmenv *vm.EVM, statedb vm.StateDB, requestType by
|
||||||
GasTipCap: common.Big0,
|
GasTipCap: common.Big0,
|
||||||
To: &addr,
|
To: &addr,
|
||||||
}
|
}
|
||||||
vmenv.Reset(NewEVMTxContext(msg), statedb)
|
vmenv.SetTxContext(NewEVMTxContext(msg))
|
||||||
statedb.AddAddressToAccessList(addr)
|
statedb.AddAddressToAccessList(addr)
|
||||||
ret, _, _ := vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560)
|
ret, _, _ := vmenv.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560)
|
||||||
statedb.Finalise(true)
|
statedb.Finalise(true)
|
||||||
|
|
|
@ -225,7 +225,7 @@ func TestProcessParentBlockHash(t *testing.T) {
|
||||||
for i := 1; i <= num; i++ {
|
for i := 1; i <= num; i++ {
|
||||||
header := &types.Header{ParentHash: common.Hash{byte(i)}, Number: big.NewInt(int64(i)), Difficulty: new(big.Int)}
|
header := &types.Header{ParentHash: common.Hash{byte(i)}, Number: big.NewInt(int64(i)), Difficulty: new(big.Int)}
|
||||||
vmContext := NewEVMBlockContext(header, nil, new(common.Address))
|
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)
|
ProcessParentBlockHash(header.ParentHash, evm, statedb)
|
||||||
}
|
}
|
||||||
// Read block hashes for block 0 .. num-1
|
// Read block hashes for block 0 .. num-1
|
||||||
|
|
|
@ -116,12 +116,13 @@ type EVM struct {
|
||||||
precompiles map[common.Address]PrecompiledContract
|
precompiles map[common.Address]PrecompiledContract
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEVM returns a new EVM. The returned EVM is not thread safe and should
|
// NewEVM constructs an EVM instance with the supplied block context, state
|
||||||
// only ever be used *once*.
|
// database and several configs. It meant to be used throughout the entire
|
||||||
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM {
|
// 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{
|
evm := &EVM{
|
||||||
Context: blockCtx,
|
Context: blockCtx,
|
||||||
TxContext: txCtx,
|
|
||||||
StateDB: statedb,
|
StateDB: statedb,
|
||||||
Config: config,
|
Config: config,
|
||||||
chainConfig: chainConfig,
|
chainConfig: chainConfig,
|
||||||
|
@ -132,6 +133,11 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig
|
||||||
return evm
|
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.
|
// SetPrecompiles sets the precompiled contracts for the EVM.
|
||||||
// This method is only used through RPC calls.
|
// This method is only used through RPC calls.
|
||||||
// It is not thread-safe.
|
// It is not thread-safe.
|
||||||
|
@ -139,14 +145,13 @@ func (evm *EVM) SetPrecompiles(precompiles PrecompiledContracts) {
|
||||||
evm.precompiles = precompiles
|
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.
|
// 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 {
|
if evm.chainRules.IsEIP4762 {
|
||||||
txCtx.AccessEvents = state.NewAccessEvents(statedb.PointCache())
|
txCtx.AccessEvents = state.NewAccessEvents(evm.StateDB.PointCache())
|
||||||
}
|
}
|
||||||
evm.TxContext = txCtx
|
evm.TxContext = txCtx
|
||||||
evm.StateDB = statedb
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cancel cancels any running EVM operation. This may be called concurrently and
|
// Cancel cancels any running EVM operation. This may be called concurrently and
|
||||||
|
|
|
@ -95,16 +95,16 @@ func TestEIP2200(t *testing.T) {
|
||||||
CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true },
|
CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true },
|
||||||
Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
|
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) {
|
if !errors.Is(err, tt.failure) {
|
||||||
t.Errorf("test %d: failure mismatch: have %v, want %v", i, 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 {
|
if used := tt.gaspool - gas; used != tt.used {
|
||||||
t.Errorf("test %d: gas used mismatch: have %v, want %v", i, 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)
|
t.Errorf("test %d: gas refund mismatch: have %v, want %v", i, refund, tt.refund)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,9 +151,9 @@ func TestCreateGas(t *testing.T) {
|
||||||
config.ExtraEips = []int{3860}
|
config.ExtraEips = []int{3860}
|
||||||
}
|
}
|
||||||
|
|
||||||
vmenv := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, config)
|
evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, config)
|
||||||
var startGas = uint64(testGas)
|
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 {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,10 +104,9 @@ func init() {
|
||||||
|
|
||||||
func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFunc, name string) {
|
func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFunc, name string) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
pc = uint64(0)
|
pc = uint64(0)
|
||||||
evmInterpreter = env.interpreter
|
|
||||||
)
|
)
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
|
@ -116,7 +115,7 @@ func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFu
|
||||||
expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Expected))
|
expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Expected))
|
||||||
stack.push(x)
|
stack.push(x)
|
||||||
stack.push(y)
|
stack.push(y)
|
||||||
opFn(&pc, evmInterpreter, &ScopeContext{nil, stack, nil})
|
opFn(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
|
||||||
if len(stack.data) != 1 {
|
if len(stack.data) != 1 {
|
||||||
t.Errorf("Expected one item on stack after %v, got %d: ", name, len(stack.data))
|
t.Errorf("Expected one item on stack after %v, got %d: ", name, len(stack.data))
|
||||||
}
|
}
|
||||||
|
@ -203,10 +202,9 @@ func TestSAR(t *testing.T) {
|
||||||
|
|
||||||
func TestAddMod(t *testing.T) {
|
func TestAddMod(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
evmInterpreter = NewEVMInterpreter(env)
|
pc = uint64(0)
|
||||||
pc = uint64(0)
|
|
||||||
)
|
)
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
x string
|
x string
|
||||||
|
@ -231,7 +229,7 @@ func TestAddMod(t *testing.T) {
|
||||||
stack.push(z)
|
stack.push(z)
|
||||||
stack.push(y)
|
stack.push(y)
|
||||||
stack.push(x)
|
stack.push(x)
|
||||||
opAddmod(&pc, evmInterpreter, &ScopeContext{nil, stack, nil})
|
opAddmod(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
|
||||||
actual := stack.pop()
|
actual := stack.pop()
|
||||||
if actual.Cmp(expected) != 0 {
|
if actual.Cmp(expected) != 0 {
|
||||||
t.Errorf("Testcase %d, expected %x, got %x", i, expected, actual)
|
t.Errorf("Testcase %d, expected %x, got %x", i, expected, actual)
|
||||||
|
@ -247,10 +245,9 @@ func TestWriteExpectedValues(t *testing.T) {
|
||||||
// getResult is a convenience function to generate the expected values
|
// getResult is a convenience function to generate the expected values
|
||||||
getResult := func(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase {
|
getResult := func(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
pc = uint64(0)
|
pc = uint64(0)
|
||||||
interpreter = env.interpreter
|
|
||||||
)
|
)
|
||||||
result := make([]TwoOperandTestcase, len(args))
|
result := make([]TwoOperandTestcase, len(args))
|
||||||
for i, param := range args {
|
for i, param := range args {
|
||||||
|
@ -258,7 +255,7 @@ func TestWriteExpectedValues(t *testing.T) {
|
||||||
y := new(uint256.Int).SetBytes(common.Hex2Bytes(param.y))
|
y := new(uint256.Int).SetBytes(common.Hex2Bytes(param.y))
|
||||||
stack.push(x)
|
stack.push(x)
|
||||||
stack.push(y)
|
stack.push(y)
|
||||||
opFn(&pc, interpreter, &ScopeContext{nil, stack, nil})
|
opFn(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
|
||||||
actual := stack.pop()
|
actual := stack.pop()
|
||||||
result[i] = TwoOperandTestcase{param.x, param.y, fmt.Sprintf("%064x", actual)}
|
result[i] = TwoOperandTestcase{param.x, param.y, fmt.Sprintf("%064x", actual)}
|
||||||
}
|
}
|
||||||
|
@ -292,13 +289,10 @@ func TestJsonTestcases(t *testing.T) {
|
||||||
|
|
||||||
func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
|
func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
scope = &ScopeContext{nil, stack, nil}
|
scope = &ScopeContext{nil, stack, nil}
|
||||||
evmInterpreter = NewEVMInterpreter(env)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
env.interpreter = evmInterpreter
|
|
||||||
// convert args
|
// convert args
|
||||||
intArgs := make([]*uint256.Int, len(args))
|
intArgs := make([]*uint256.Int, len(args))
|
||||||
for i, arg := range args {
|
for i, arg := range args {
|
||||||
|
@ -310,7 +304,7 @@ func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
|
||||||
for _, arg := range intArgs {
|
for _, arg := range intArgs {
|
||||||
stack.push(arg)
|
stack.push(arg)
|
||||||
}
|
}
|
||||||
op(&pc, evmInterpreter, scope)
|
op(&pc, evm.interpreter, scope)
|
||||||
stack.pop()
|
stack.pop()
|
||||||
}
|
}
|
||||||
bench.StopTimer()
|
bench.StopTimer()
|
||||||
|
@ -533,25 +527,22 @@ func BenchmarkOpIsZero(b *testing.B) {
|
||||||
|
|
||||||
func TestOpMstore(t *testing.T) {
|
func TestOpMstore(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
mem = NewMemory()
|
mem = NewMemory()
|
||||||
evmInterpreter = NewEVMInterpreter(env)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
env.interpreter = evmInterpreter
|
|
||||||
mem.Resize(64)
|
mem.Resize(64)
|
||||||
pc := uint64(0)
|
pc := uint64(0)
|
||||||
v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700"
|
v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700"
|
||||||
stack.push(new(uint256.Int).SetBytes(common.Hex2Bytes(v)))
|
stack.push(new(uint256.Int).SetBytes(common.Hex2Bytes(v)))
|
||||||
stack.push(new(uint256.Int))
|
stack.push(new(uint256.Int))
|
||||||
opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil})
|
opMstore(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
|
||||||
if got := common.Bytes2Hex(mem.GetCopy(0, 32)); got != v {
|
if got := common.Bytes2Hex(mem.GetCopy(0, 32)); got != v {
|
||||||
t.Fatalf("Mstore fail, got %v, expected %v", got, v)
|
t.Fatalf("Mstore fail, got %v, expected %v", got, v)
|
||||||
}
|
}
|
||||||
stack.push(new(uint256.Int).SetUint64(0x1))
|
stack.push(new(uint256.Int).SetUint64(0x1))
|
||||||
stack.push(new(uint256.Int))
|
stack.push(new(uint256.Int))
|
||||||
opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil})
|
opMstore(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
|
||||||
if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" {
|
if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" {
|
||||||
t.Fatalf("Mstore failed to overwrite previous value")
|
t.Fatalf("Mstore failed to overwrite previous value")
|
||||||
}
|
}
|
||||||
|
@ -559,13 +550,10 @@ func TestOpMstore(t *testing.T) {
|
||||||
|
|
||||||
func BenchmarkOpMstore(bench *testing.B) {
|
func BenchmarkOpMstore(bench *testing.B) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
mem = NewMemory()
|
mem = NewMemory()
|
||||||
evmInterpreter = NewEVMInterpreter(env)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
env.interpreter = evmInterpreter
|
|
||||||
mem.Resize(64)
|
mem.Resize(64)
|
||||||
pc := uint64(0)
|
pc := uint64(0)
|
||||||
memStart := new(uint256.Int)
|
memStart := new(uint256.Int)
|
||||||
|
@ -575,43 +563,41 @@ func BenchmarkOpMstore(bench *testing.B) {
|
||||||
for i := 0; i < bench.N; i++ {
|
for i := 0; i < bench.N; i++ {
|
||||||
stack.push(value)
|
stack.push(value)
|
||||||
stack.push(memStart)
|
stack.push(memStart)
|
||||||
opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil})
|
opMstore(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOpTstore(t *testing.T) {
|
func TestOpTstore(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, statedb, params.TestChainConfig, Config{})
|
evm = NewEVM(BlockContext{}, statedb, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
mem = NewMemory()
|
mem = NewMemory()
|
||||||
evmInterpreter = NewEVMInterpreter(env)
|
caller = common.Address{}
|
||||||
caller = common.Address{}
|
to = common.Address{1}
|
||||||
to = common.Address{1}
|
contractRef = contractRef{caller}
|
||||||
contractRef = contractRef{caller}
|
contract = NewContract(contractRef, AccountRef(to), new(uint256.Int), 0)
|
||||||
contract = NewContract(contractRef, AccountRef(to), new(uint256.Int), 0)
|
scopeContext = ScopeContext{mem, stack, contract}
|
||||||
scopeContext = ScopeContext{mem, stack, contract}
|
value = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700")
|
||||||
value = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Add a stateObject for the caller and the contract being called
|
// Add a stateObject for the caller and the contract being called
|
||||||
statedb.CreateAccount(caller)
|
statedb.CreateAccount(caller)
|
||||||
statedb.CreateAccount(to)
|
statedb.CreateAccount(to)
|
||||||
|
|
||||||
env.interpreter = evmInterpreter
|
|
||||||
pc := uint64(0)
|
pc := uint64(0)
|
||||||
// push the value to the stack
|
// push the value to the stack
|
||||||
stack.push(new(uint256.Int).SetBytes(value))
|
stack.push(new(uint256.Int).SetBytes(value))
|
||||||
// push the location to the stack
|
// push the location to the stack
|
||||||
stack.push(new(uint256.Int))
|
stack.push(new(uint256.Int))
|
||||||
opTstore(&pc, evmInterpreter, &scopeContext)
|
opTstore(&pc, evm.interpreter, &scopeContext)
|
||||||
// there should be no elements on the stack after TSTORE
|
// there should be no elements on the stack after TSTORE
|
||||||
if stack.len() != 0 {
|
if stack.len() != 0 {
|
||||||
t.Fatal("stack wrong size")
|
t.Fatal("stack wrong size")
|
||||||
}
|
}
|
||||||
// push the location to the stack
|
// push the location to the stack
|
||||||
stack.push(new(uint256.Int))
|
stack.push(new(uint256.Int))
|
||||||
opTload(&pc, evmInterpreter, &scopeContext)
|
opTload(&pc, evm.interpreter, &scopeContext)
|
||||||
// there should be one element on the stack after TLOAD
|
// there should be one element on the stack after TLOAD
|
||||||
if stack.len() != 1 {
|
if stack.len() != 1 {
|
||||||
t.Fatal("stack wrong size")
|
t.Fatal("stack wrong size")
|
||||||
|
@ -624,12 +610,10 @@ func TestOpTstore(t *testing.T) {
|
||||||
|
|
||||||
func BenchmarkOpKeccak256(bench *testing.B) {
|
func BenchmarkOpKeccak256(bench *testing.B) {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
mem = NewMemory()
|
mem = NewMemory()
|
||||||
evmInterpreter = NewEVMInterpreter(env)
|
|
||||||
)
|
)
|
||||||
env.interpreter = evmInterpreter
|
|
||||||
mem.Resize(32)
|
mem.Resize(32)
|
||||||
pc := uint64(0)
|
pc := uint64(0)
|
||||||
start := new(uint256.Int)
|
start := new(uint256.Int)
|
||||||
|
@ -638,7 +622,7 @@ func BenchmarkOpKeccak256(bench *testing.B) {
|
||||||
for i := 0; i < bench.N; i++ {
|
for i := 0; i < bench.N; i++ {
|
||||||
stack.push(uint256.NewInt(32))
|
stack.push(uint256.NewInt(32))
|
||||||
stack.push(start)
|
stack.push(start)
|
||||||
opKeccak256(&pc, evmInterpreter, &ScopeContext{mem, stack, nil})
|
opKeccak256(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,12 +712,11 @@ func TestRandom(t *testing.T) {
|
||||||
{name: "hash(0x010203)", random: crypto.Keccak256Hash([]byte{0x01, 0x02, 0x03})},
|
{name: "hash(0x010203)", random: crypto.Keccak256Hash([]byte{0x01, 0x02, 0x03})},
|
||||||
} {
|
} {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{Random: &tt.random}, TxContext{}, nil, params.TestChainConfig, Config{})
|
evm = NewEVM(BlockContext{Random: &tt.random}, nil, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
pc = uint64(0)
|
pc = uint64(0)
|
||||||
evmInterpreter = env.interpreter
|
|
||||||
)
|
)
|
||||||
opRandom(&pc, evmInterpreter, &ScopeContext{nil, stack, nil})
|
opRandom(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
|
||||||
if len(stack.data) != 1 {
|
if len(stack.data) != 1 {
|
||||||
t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data))
|
t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data))
|
||||||
}
|
}
|
||||||
|
@ -769,13 +752,13 @@ func TestBlobHash(t *testing.T) {
|
||||||
{name: "out-of-bounds (nil)", idx: 25, expect: zero, hashes: nil},
|
{name: "out-of-bounds (nil)", idx: 25, expect: zero, hashes: nil},
|
||||||
} {
|
} {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{BlobHashes: tt.hashes}, nil, params.TestChainConfig, Config{})
|
evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
pc = uint64(0)
|
pc = uint64(0)
|
||||||
evmInterpreter = env.interpreter
|
|
||||||
)
|
)
|
||||||
|
evm.SetTxContext(TxContext{BlobHashes: tt.hashes})
|
||||||
stack.push(uint256.NewInt(tt.idx))
|
stack.push(uint256.NewInt(tt.idx))
|
||||||
opBlobHash(&pc, evmInterpreter, &ScopeContext{nil, stack, nil})
|
opBlobHash(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
|
||||||
if len(stack.data) != 1 {
|
if len(stack.data) != 1 {
|
||||||
t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data))
|
t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data))
|
||||||
}
|
}
|
||||||
|
@ -872,10 +855,9 @@ func TestOpMCopy(t *testing.T) {
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
var (
|
var (
|
||||||
env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
|
evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
pc = uint64(0)
|
pc = uint64(0)
|
||||||
evmInterpreter = env.interpreter
|
|
||||||
)
|
)
|
||||||
data := common.FromHex(strings.ReplaceAll(tc.pre, " ", ""))
|
data := common.FromHex(strings.ReplaceAll(tc.pre, " ", ""))
|
||||||
// Set pre
|
// Set pre
|
||||||
|
@ -906,7 +888,7 @@ func TestOpMCopy(t *testing.T) {
|
||||||
}
|
}
|
||||||
// and the dynamic cost
|
// and the dynamic cost
|
||||||
var haveGas uint64
|
var haveGas uint64
|
||||||
if dynamicCost, err := gasMcopy(env, nil, stack, mem, memorySize); err != nil {
|
if dynamicCost, err := gasMcopy(evm, nil, stack, mem, memorySize); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
} else {
|
} else {
|
||||||
haveGas = GasFastestStep + dynamicCost
|
haveGas = GasFastestStep + dynamicCost
|
||||||
|
@ -916,7 +898,7 @@ func TestOpMCopy(t *testing.T) {
|
||||||
mem.Resize(memorySize)
|
mem.Resize(memorySize)
|
||||||
}
|
}
|
||||||
// Do the copy
|
// Do the copy
|
||||||
opMcopy(&pc, evmInterpreter, &ScopeContext{mem, stack, nil})
|
opMcopy(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
|
||||||
want := common.FromHex(strings.ReplaceAll(tc.want, " ", ""))
|
want := common.FromHex(strings.ReplaceAll(tc.want, " ", ""))
|
||||||
if have := mem.store; !bytes.Equal(want, have) {
|
if have := mem.store; !bytes.Equal(want, have) {
|
||||||
t.Errorf("case %d: \nwant: %#x\nhave: %#x\n", i, want, have)
|
t.Errorf("case %d: \nwant: %#x\nhave: %#x\n", i, want, have)
|
||||||
|
|
|
@ -47,7 +47,7 @@ func TestLoopInterrupt(t *testing.T) {
|
||||||
statedb.SetCode(address, common.Hex2Bytes(tt))
|
statedb.SetCode(address, common.Hex2Bytes(tt))
|
||||||
statedb.Finalise(true)
|
statedb.Finalise(true)
|
||||||
|
|
||||||
evm := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, Config{})
|
evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{})
|
||||||
|
|
||||||
errChannel := make(chan error)
|
errChannel := make(chan error)
|
||||||
timeout := make(chan bool)
|
timeout := make(chan bool)
|
||||||
|
|
|
@ -42,5 +42,7 @@ func NewEnv(cfg *Config) *vm.EVM {
|
||||||
Random: cfg.Random,
|
Random: cfg.Random,
|
||||||
}
|
}
|
||||||
|
|
||||||
return vm.NewEVM(blockContext, txContext, cfg.State, cfg.ChainConfig, cfg.EVMConfig)
|
evm := vm.NewEVM(blockContext, cfg.State, cfg.ChainConfig, cfg.EVMConfig)
|
||||||
|
evm.SetTxContext(txContext)
|
||||||
|
return evm
|
||||||
}
|
}
|
||||||
|
|
|
@ -249,18 +249,17 @@ func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM {
|
func (b *EthAPIBackend) GetEVM(ctx context.Context, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM {
|
||||||
if vmConfig == nil {
|
if vmConfig == nil {
|
||||||
vmConfig = b.eth.blockchain.GetVMConfig()
|
vmConfig = b.eth.blockchain.GetVMConfig()
|
||||||
}
|
}
|
||||||
txContext := core.NewEVMTxContext(msg)
|
|
||||||
var context vm.BlockContext
|
var context vm.BlockContext
|
||||||
if blockCtx != nil {
|
if blockCtx != nil {
|
||||||
context = *blockCtx
|
context = *blockCtx
|
||||||
} else {
|
} else {
|
||||||
context = core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
|
context = core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
|
||||||
}
|
}
|
||||||
return vm.NewEVM(context, txContext, state, b.ChainConfig(), *vmConfig)
|
return vm.NewEVM(context, state, b.ChainConfig(), *vmConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
|
func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
|
||||||
|
|
|
@ -230,7 +230,8 @@ func run(ctx context.Context, call *core.Message, opts *Options) (*core.Executio
|
||||||
if msgContext.BlobFeeCap != nil && msgContext.BlobFeeCap.BitLen() == 0 {
|
if msgContext.BlobFeeCap != nil && msgContext.BlobFeeCap.BitLen() == 0 {
|
||||||
evmContext.BlobBaseFee = new(big.Int)
|
evmContext.BlobBaseFee = new(big.Int)
|
||||||
}
|
}
|
||||||
evm := vm.NewEVM(evmContext, msgContext, dirtyState, opts.Config, vm.Config{NoBaseFee: true})
|
evm := vm.NewEVM(evmContext, dirtyState, opts.Config, vm.Config{NoBaseFee: true})
|
||||||
|
evm.SetTxContext(msgContext)
|
||||||
// Monitor the outer context and interrupt the EVM upon cancellation. To avoid
|
// Monitor the outer context and interrupt the EVM upon cancellation. To avoid
|
||||||
// a dangling goroutine until the outer estimation finishes, create an internal
|
// a dangling goroutine until the outer estimation finishes, create an internal
|
||||||
// context for the lifetime of this method call.
|
// context for the lifetime of this method call.
|
||||||
|
|
|
@ -235,16 +235,14 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
|
||||||
return nil, vm.BlockContext{}, nil, nil, err
|
return nil, vm.BlockContext{}, nil, nil, err
|
||||||
}
|
}
|
||||||
// Insert parent beacon block root in the state as per EIP-4788.
|
// Insert parent beacon block root in the state as per EIP-4788.
|
||||||
|
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil)
|
||||||
|
evm := vm.NewEVM(context, statedb, eth.blockchain.Config(), vm.Config{})
|
||||||
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
||||||
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil)
|
core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb)
|
||||||
vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, eth.blockchain.Config(), vm.Config{})
|
|
||||||
core.ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
|
|
||||||
}
|
}
|
||||||
// If prague hardfork, insert parent block hash in the state as per EIP-2935.
|
// If prague hardfork, insert parent block hash in the state as per EIP-2935.
|
||||||
if eth.blockchain.Config().IsPrague(block.Number(), block.Time()) {
|
if eth.blockchain.Config().IsPrague(block.Number(), block.Time()) {
|
||||||
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil)
|
core.ProcessParentBlockHash(block.ParentHash(), evm, statedb)
|
||||||
vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, eth.blockchain.Config(), vm.Config{})
|
|
||||||
core.ProcessParentBlockHash(block.ParentHash(), vmenv, statedb)
|
|
||||||
}
|
}
|
||||||
if txIndex == 0 && len(block.Transactions()) == 0 {
|
if txIndex == 0 && len(block.Transactions()) == 0 {
|
||||||
return nil, vm.BlockContext{}, statedb, release, nil
|
return nil, vm.BlockContext{}, statedb, release, nil
|
||||||
|
@ -252,22 +250,22 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
|
||||||
// Recompute transactions up to the target index.
|
// Recompute transactions up to the target index.
|
||||||
signer := types.MakeSigner(eth.blockchain.Config(), block.Number(), block.Time())
|
signer := types.MakeSigner(eth.blockchain.Config(), block.Number(), block.Time())
|
||||||
for idx, tx := range block.Transactions() {
|
for idx, tx := range block.Transactions() {
|
||||||
// Assemble the transaction call message and return if the requested offset
|
|
||||||
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
|
|
||||||
txContext := core.NewEVMTxContext(msg)
|
|
||||||
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil)
|
|
||||||
if idx == txIndex {
|
if idx == txIndex {
|
||||||
return tx, context, statedb, release, nil
|
return tx, context, statedb, release, nil
|
||||||
}
|
}
|
||||||
|
// Assemble the transaction call message and return if the requested offset
|
||||||
|
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
|
||||||
|
txContext := core.NewEVMTxContext(msg)
|
||||||
|
evm.SetTxContext(txContext)
|
||||||
|
|
||||||
// Not yet the searched for transaction, execute on top of the current state
|
// Not yet the searched for transaction, execute on top of the current state
|
||||||
vmenv := vm.NewEVM(context, txContext, statedb, eth.blockchain.Config(), vm.Config{})
|
|
||||||
statedb.SetTxContext(tx.Hash(), idx)
|
statedb.SetTxContext(tx.Hash(), idx)
|
||||||
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
|
if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
|
||||||
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
|
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
|
||||||
}
|
}
|
||||||
// Ensure any modifications are committed to the state
|
// Ensure any modifications are committed to the state
|
||||||
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
||||||
statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
|
statedb.Finalise(evm.ChainConfig().IsEIP158(block.Number()))
|
||||||
}
|
}
|
||||||
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
|
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
|
||||||
}
|
}
|
||||||
|
|
|
@ -378,16 +378,14 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
|
||||||
}
|
}
|
||||||
// Insert block's parent beacon block root in the state
|
// Insert block's parent beacon block root in the state
|
||||||
// as per EIP-4788.
|
// as per EIP-4788.
|
||||||
|
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 {
|
if beaconRoot := next.BeaconRoot(); beaconRoot != nil {
|
||||||
context := core.NewEVMBlockContext(next.Header(), api.chainContext(ctx), nil)
|
core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb)
|
||||||
vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, api.backend.ChainConfig(), vm.Config{})
|
|
||||||
core.ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
|
|
||||||
}
|
}
|
||||||
// Insert parent hash in history contract.
|
// Insert parent hash in history contract.
|
||||||
if api.backend.ChainConfig().IsPrague(next.Number(), next.Time()) {
|
if api.backend.ChainConfig().IsPrague(next.Number(), next.Time()) {
|
||||||
context := core.NewEVMBlockContext(next.Header(), api.chainContext(ctx), nil)
|
core.ProcessParentBlockHash(next.ParentHash(), evm, statedb)
|
||||||
vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, api.backend.ChainConfig(), vm.Config{})
|
|
||||||
core.ProcessParentBlockHash(next.ParentHash(), vmenv, statedb)
|
|
||||||
}
|
}
|
||||||
// Clean out any pending release functions of trace state. Note this
|
// Clean out any pending release functions of trace state. Note this
|
||||||
// step must be done after constructing tracing state, because the
|
// step must be done after constructing tracing state, because the
|
||||||
|
@ -537,12 +535,12 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
|
||||||
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
||||||
deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
|
deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
|
||||||
)
|
)
|
||||||
|
evm := vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{})
|
||||||
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
||||||
vmenv := vm.NewEVM(vmctx, vm.TxContext{}, statedb, chainConfig, vm.Config{})
|
core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb)
|
||||||
core.ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
|
|
||||||
}
|
}
|
||||||
if chainConfig.IsPrague(block.Number(), block.Time()) {
|
if chainConfig.IsPrague(block.Number(), block.Time()) {
|
||||||
core.ProcessParentBlockHash(block.ParentHash(), vm.NewEVM(vmctx, vm.TxContext{}, statedb, chainConfig, vm.Config{}), statedb)
|
core.ProcessParentBlockHash(block.ParentHash(), evm, statedb)
|
||||||
}
|
}
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
if err := ctx.Err(); err != nil {
|
if err := ctx.Err(); err != nil {
|
||||||
|
@ -551,10 +549,10 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
|
||||||
var (
|
var (
|
||||||
msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee())
|
msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee())
|
||||||
txContext = core.NewEVMTxContext(msg)
|
txContext = core.NewEVMTxContext(msg)
|
||||||
vmenv = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{})
|
|
||||||
)
|
)
|
||||||
|
evm.SetTxContext(txContext)
|
||||||
statedb.SetTxContext(tx.Hash(), i)
|
statedb.SetTxContext(tx.Hash(), i)
|
||||||
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil {
|
if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil {
|
||||||
log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err)
|
log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err)
|
||||||
// We intentionally don't return the error here: if we do, then the RPC server will not
|
// We intentionally don't return the error here: if we do, then the RPC server will not
|
||||||
// return the roots. Most likely, the caller already knows that a certain transaction fails to
|
// return the roots. Most likely, the caller already knows that a certain transaction fails to
|
||||||
|
@ -605,13 +603,12 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
|
||||||
defer release()
|
defer release()
|
||||||
|
|
||||||
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
||||||
|
evm := vm.NewEVM(blockCtx, statedb, api.backend.ChainConfig(), vm.Config{})
|
||||||
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
||||||
vmenv := vm.NewEVM(blockCtx, vm.TxContext{}, statedb, api.backend.ChainConfig(), vm.Config{})
|
core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb)
|
||||||
core.ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
|
|
||||||
}
|
}
|
||||||
if api.backend.ChainConfig().IsPrague(block.Number(), block.Time()) {
|
if api.backend.ChainConfig().IsPrague(block.Number(), block.Time()) {
|
||||||
vmenv := vm.NewEVM(blockCtx, vm.TxContext{}, statedb, api.backend.ChainConfig(), vm.Config{})
|
core.ProcessParentBlockHash(block.ParentHash(), evm, statedb)
|
||||||
core.ProcessParentBlockHash(block.ParentHash(), vmenv, statedb)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// JS tracers have high overhead. In this case run a parallel
|
// JS tracers have high overhead. In this case run a parallel
|
||||||
|
@ -695,6 +692,8 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
|
||||||
// Feed the transactions into the tracers and return
|
// Feed the transactions into the tracers and return
|
||||||
var failed error
|
var failed error
|
||||||
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
||||||
|
evm := vm.NewEVM(blockCtx, statedb, api.backend.ChainConfig(), vm.Config{})
|
||||||
|
|
||||||
txloop:
|
txloop:
|
||||||
for i, tx := range txs {
|
for i, tx := range txs {
|
||||||
// Send the trace task over for execution
|
// Send the trace task over for execution
|
||||||
|
@ -709,14 +708,14 @@ txloop:
|
||||||
// Generate the next state snapshot fast without tracing
|
// Generate the next state snapshot fast without tracing
|
||||||
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
|
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
|
||||||
statedb.SetTxContext(tx.Hash(), i)
|
statedb.SetTxContext(tx.Hash(), i)
|
||||||
vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, api.backend.ChainConfig(), vm.Config{})
|
evm.SetTxContext(core.NewEVMTxContext(msg))
|
||||||
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil {
|
if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil {
|
||||||
failed = err
|
failed = err
|
||||||
break txloop
|
break txloop
|
||||||
}
|
}
|
||||||
// Finalize the state so any modifications are written to the trie
|
// Finalize the state so any modifications are written to the trie
|
||||||
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
||||||
statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
|
statedb.Finalise(evm.ChainConfig().IsEIP158(block.Number()))
|
||||||
}
|
}
|
||||||
|
|
||||||
close(jobs)
|
close(jobs)
|
||||||
|
@ -783,13 +782,12 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
||||||
// Note: This copies the config, to not screw up the main config
|
// Note: This copies the config, to not screw up the main config
|
||||||
chainConfig, canon = overrideConfig(chainConfig, config.Overrides)
|
chainConfig, canon = overrideConfig(chainConfig, config.Overrides)
|
||||||
}
|
}
|
||||||
|
evm := vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{})
|
||||||
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
||||||
vmenv := vm.NewEVM(vmctx, vm.TxContext{}, statedb, chainConfig, vm.Config{})
|
core.ProcessBeaconBlockRoot(*beaconRoot, evm, statedb)
|
||||||
core.ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
|
|
||||||
}
|
}
|
||||||
if chainConfig.IsPrague(block.Number(), block.Time()) {
|
if chainConfig.IsPrague(block.Number(), block.Time()) {
|
||||||
vmenv := vm.NewEVM(vmctx, vm.TxContext{}, statedb, chainConfig, vm.Config{})
|
core.ProcessParentBlockHash(block.ParentHash(), evm, statedb)
|
||||||
core.ProcessParentBlockHash(block.ParentHash(), vmenv, statedb)
|
|
||||||
}
|
}
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
// Prepare the transaction for un-traced execution
|
// Prepare the transaction for un-traced execution
|
||||||
|
@ -822,12 +820,12 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Execute the transaction and flush any traces to disk
|
// Execute the transaction and flush any traces to disk
|
||||||
vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf)
|
evm.SetTxContext(txContext)
|
||||||
statedb.SetTxContext(tx.Hash(), i)
|
statedb.SetTxContext(tx.Hash(), i)
|
||||||
if vmConf.Tracer.OnTxStart != nil {
|
if vmConf.Tracer.OnTxStart != nil {
|
||||||
vmConf.Tracer.OnTxStart(vmenv.GetVMContext(), tx, msg.From)
|
vmConf.Tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
||||||
}
|
}
|
||||||
vmRet, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit))
|
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit))
|
||||||
if vmConf.Tracer.OnTxEnd != nil {
|
if vmConf.Tracer.OnTxEnd != nil {
|
||||||
vmConf.Tracer.OnTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas}, err)
|
vmConf.Tracer.OnTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas}, err)
|
||||||
}
|
}
|
||||||
|
@ -843,7 +841,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
||||||
}
|
}
|
||||||
// Finalize the state so any modifications are written to the trie
|
// Finalize the state so any modifications are written to the trie
|
||||||
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
||||||
statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
|
statedb.Finalise(evm.ChainConfig().IsEIP158(block.Number()))
|
||||||
|
|
||||||
// If we've traced the transaction we were looking for, abort
|
// If we've traced the transaction we were looking for, abort
|
||||||
if tx.Hash() == txHash {
|
if tx.Hash() == txHash {
|
||||||
|
@ -1017,7 +1015,8 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// The actual TxContext will be created as part of ApplyTransactionWithEVM.
|
// The actual TxContext will be created as part of ApplyTransactionWithEVM.
|
||||||
vmenv := vm.NewEVM(vmctx, vm.TxContext{GasPrice: message.GasPrice, BlobFeeCap: message.BlobGasFeeCap}, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true})
|
evm := vm.NewEVM(vmctx, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true})
|
||||||
|
evm.SetTxContext(vm.TxContext{GasPrice: message.GasPrice, BlobFeeCap: message.BlobGasFeeCap})
|
||||||
|
|
||||||
// Define a meaningful timeout of a single transaction trace
|
// Define a meaningful timeout of a single transaction trace
|
||||||
if config.Timeout != nil {
|
if config.Timeout != nil {
|
||||||
|
@ -1031,14 +1030,14 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
|
||||||
if errors.Is(deadlineCtx.Err(), context.DeadlineExceeded) {
|
if errors.Is(deadlineCtx.Err(), context.DeadlineExceeded) {
|
||||||
tracer.Stop(errors.New("execution timeout"))
|
tracer.Stop(errors.New("execution timeout"))
|
||||||
// Stop evm execution. Note cancellation is not necessarily immediate.
|
// Stop evm execution. Note cancellation is not necessarily immediate.
|
||||||
vmenv.Cancel()
|
evm.Cancel()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Call Prepare to clear out the statedb access list
|
// Call Prepare to clear out the statedb access list
|
||||||
statedb.SetTxContext(txctx.TxHash, txctx.TxIndex)
|
statedb.SetTxContext(txctx.TxHash, txctx.TxIndex)
|
||||||
_, err = core.ApplyTransactionWithEVM(message, api.backend.ChainConfig(), new(core.GasPool).AddGas(message.GasLimit), statedb, vmctx.BlockNumber, txctx.BlockHash, tx, &usedGas, vmenv)
|
_, err = core.ApplyTransactionWithEVM(message, api.backend.ChainConfig(), new(core.GasPool).AddGas(message.GasLimit), statedb, vmctx.BlockNumber, txctx.BlockHash, tx, &usedGas, evm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("tracing failed: %w", err)
|
return nil, fmt.Errorf("tracing failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,18 +170,19 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block
|
||||||
}
|
}
|
||||||
// Recompute transactions up to the target index.
|
// Recompute transactions up to the target index.
|
||||||
signer := types.MakeSigner(b.chainConfig, block.Number(), block.Time())
|
signer := types.MakeSigner(b.chainConfig, block.Number(), block.Time())
|
||||||
|
context := core.NewEVMBlockContext(block.Header(), b.chain, nil)
|
||||||
|
evm := vm.NewEVM(context, statedb, b.chainConfig, vm.Config{})
|
||||||
for idx, tx := range block.Transactions() {
|
for idx, tx := range block.Transactions() {
|
||||||
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
|
|
||||||
txContext := core.NewEVMTxContext(msg)
|
|
||||||
context := core.NewEVMBlockContext(block.Header(), b.chain, nil)
|
|
||||||
if idx == txIndex {
|
if idx == txIndex {
|
||||||
return tx, context, statedb, release, nil
|
return tx, context, statedb, release, nil
|
||||||
}
|
}
|
||||||
vmenv := vm.NewEVM(context, txContext, statedb, b.chainConfig, vm.Config{})
|
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
|
||||||
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
|
txContext := core.NewEVMTxContext(msg)
|
||||||
|
evm.SetTxContext(txContext)
|
||||||
|
if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
|
||||||
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
|
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
|
||||||
}
|
}
|
||||||
statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
|
statedb.Finalise(evm.ChainConfig().IsEIP158(block.Number()))
|
||||||
}
|
}
|
||||||
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
|
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,8 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||||
}
|
}
|
||||||
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), logState, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
|
evm := vm.NewEVM(context, logState, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
|
||||||
|
evm.SetTxContext(core.NewEVMTxContext(msg))
|
||||||
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
||||||
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -220,12 +221,15 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
|
||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
||||||
|
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), nil, test.Genesis.Config)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatalf("failed to create call tracer: %v", err)
|
||||||
|
}
|
||||||
|
evm := vm.NewEVM(context, state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
|
||||||
|
evm.SetTxContext(txContext)
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), nil, test.Genesis.Config)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatalf("failed to create call tracer: %v", err)
|
|
||||||
}
|
|
||||||
evm := vm.NewEVM(context, txContext, state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
|
|
||||||
snap := state.StateDB.Snapshot()
|
snap := state.StateDB.Snapshot()
|
||||||
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
||||||
if _, err = st.TransitionDb(); err != nil {
|
if _, err = st.TransitionDb(); err != nil {
|
||||||
|
@ -372,7 +376,8 @@ func TestInternals(t *testing.T) {
|
||||||
Origin: origin,
|
Origin: origin,
|
||||||
GasPrice: tx.GasPrice(),
|
GasPrice: tx.GasPrice(),
|
||||||
}
|
}
|
||||||
evm := vm.NewEVM(context, txContext, logState, config, vm.Config{Tracer: tc.tracer.Hooks})
|
evm := vm.NewEVM(context, logState, config, vm.Config{Tracer: tc.tracer.Hooks})
|
||||||
|
evm.SetTxContext(txContext)
|
||||||
msg, err := core.TransactionToMessage(tx, signer, big.NewInt(0))
|
msg, err := core.TransactionToMessage(tx, signer, big.NewInt(0))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("test %v: failed to create message: %v", tc.name, err)
|
t.Fatalf("test %v: failed to create message: %v", tc.name, err)
|
||||||
|
|
|
@ -98,7 +98,8 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to prepare transaction for tracing: %v", err)
|
return fmt.Errorf("failed to prepare transaction for tracing: %v", err)
|
||||||
}
|
}
|
||||||
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
|
evm := vm.NewEVM(context, state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
|
||||||
|
evm.SetTxContext(core.NewEVMTxContext(msg))
|
||||||
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
||||||
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -106,7 +106,8 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||||
}
|
}
|
||||||
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
|
evm := vm.NewEVM(context, state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
|
||||||
|
evm.SetTxContext(core.NewEVMTxContext(msg))
|
||||||
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
||||||
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -64,20 +64,21 @@ func testCtx() *vmContext {
|
||||||
|
|
||||||
func runTrace(tracer *tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig, contractCode []byte) (json.RawMessage, error) {
|
func runTrace(tracer *tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig, contractCode []byte) (json.RawMessage, error) {
|
||||||
var (
|
var (
|
||||||
env = vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Tracer: tracer.Hooks})
|
evm = vm.NewEVM(vmctx.blockCtx, &dummyStatedb{}, chaincfg, vm.Config{Tracer: tracer.Hooks})
|
||||||
gasLimit uint64 = 31000
|
gasLimit uint64 = 31000
|
||||||
startGas uint64 = 10000
|
startGas uint64 = 10000
|
||||||
value = uint256.NewInt(0)
|
value = uint256.NewInt(0)
|
||||||
contract = vm.NewContract(account{}, account{}, value, startGas)
|
contract = vm.NewContract(account{}, account{}, value, startGas)
|
||||||
)
|
)
|
||||||
|
evm.SetTxContext(vmctx.txCtx)
|
||||||
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
|
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
|
||||||
if contractCode != nil {
|
if contractCode != nil {
|
||||||
contract.Code = contractCode
|
contract.Code = contractCode
|
||||||
}
|
}
|
||||||
|
|
||||||
tracer.OnTxStart(env.GetVMContext(), types.NewTx(&types.LegacyTx{Gas: gasLimit}), contract.Caller())
|
tracer.OnTxStart(evm.GetVMContext(), types.NewTx(&types.LegacyTx{Gas: gasLimit}), contract.Caller())
|
||||||
tracer.OnEnter(0, byte(vm.CALL), contract.Caller(), contract.Address(), []byte{}, startGas, value.ToBig())
|
tracer.OnEnter(0, byte(vm.CALL), contract.Caller(), contract.Address(), []byte{}, startGas, value.ToBig())
|
||||||
ret, err := env.Interpreter().Run(contract, []byte{}, false)
|
ret, err := evm.Interpreter().Run(contract, []byte{}, false)
|
||||||
tracer.OnExit(0, ret, startGas-contract.Gas, err, true)
|
tracer.OnExit(0, ret, startGas-contract.Gas, err, true)
|
||||||
// Rest gas assumes no refund
|
// Rest gas assumes no refund
|
||||||
tracer.OnTxEnd(&types.Receipt{GasUsed: gasLimit - contract.Gas}, nil)
|
tracer.OnTxEnd(&types.Receipt{GasUsed: gasLimit - contract.Gas}, nil)
|
||||||
|
@ -191,8 +192,9 @@ func TestHaltBetweenSteps(t *testing.T) {
|
||||||
scope := &vm.ScopeContext{
|
scope := &vm.ScopeContext{
|
||||||
Contract: vm.NewContract(&account{}, &account{}, uint256.NewInt(0), 0),
|
Contract: vm.NewContract(&account{}, &account{}, uint256.NewInt(0), 0),
|
||||||
}
|
}
|
||||||
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(1)}, &dummyStatedb{}, chainConfig, vm.Config{Tracer: tracer.Hooks})
|
evm := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, chainConfig, vm.Config{Tracer: tracer.Hooks})
|
||||||
tracer.OnTxStart(env.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{})
|
evm.SetTxContext(vm.TxContext{GasPrice: big.NewInt(1)})
|
||||||
|
tracer.OnTxStart(evm.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{})
|
||||||
tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, []byte{}, 0, big.NewInt(0))
|
tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, []byte{}, 0, big.NewInt(0))
|
||||||
tracer.OnOpcode(0, 0, 0, 0, scope, nil, 0, nil)
|
tracer.OnOpcode(0, 0, 0, 0, scope, nil, 0, nil)
|
||||||
timeout := errors.New("stahp")
|
timeout := errors.New("stahp")
|
||||||
|
@ -214,8 +216,9 @@ func TestNoStepExec(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100)}, &dummyStatedb{}, chainConfig, vm.Config{Tracer: tracer.Hooks})
|
evm := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, chainConfig, vm.Config{Tracer: tracer.Hooks})
|
||||||
tracer.OnTxStart(env.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{})
|
evm.SetTxContext(vm.TxContext{GasPrice: big.NewInt(100)})
|
||||||
|
tracer.OnTxStart(evm.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{})
|
||||||
tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, []byte{}, 1000, big.NewInt(0))
|
tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, []byte{}, 1000, big.NewInt(0))
|
||||||
tracer.OnExit(0, nil, 0, nil, false)
|
tracer.OnExit(0, nil, 0, nil, false)
|
||||||
ret, err := tracer.GetResult()
|
ret, err := tracer.GetResult()
|
||||||
|
|
|
@ -58,13 +58,13 @@ func (*dummyStatedb) SetState(_ common.Address, _ common.Hash, _ common.Hash) co
|
||||||
func TestStoreCapture(t *testing.T) {
|
func TestStoreCapture(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
logger = NewStructLogger(nil)
|
logger = NewStructLogger(nil)
|
||||||
env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: logger.Hooks()})
|
evm = vm.NewEVM(vm.BlockContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: logger.Hooks()})
|
||||||
contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(uint256.Int), 100000)
|
contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(uint256.Int), 100000)
|
||||||
)
|
)
|
||||||
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)}
|
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)}
|
||||||
var index common.Hash
|
var index common.Hash
|
||||||
logger.OnTxStart(env.GetVMContext(), nil, common.Address{})
|
logger.OnTxStart(evm.GetVMContext(), nil, common.Address{})
|
||||||
_, err := env.Interpreter().Run(contract, []byte{}, false)
|
_, err := evm.Interpreter().Run(contract, []byte{}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,8 @@ func BenchmarkTransactionTrace(b *testing.B) {
|
||||||
//EnableMemory: false,
|
//EnableMemory: false,
|
||||||
//EnableReturnData: false,
|
//EnableReturnData: false,
|
||||||
})
|
})
|
||||||
evm := vm.NewEVM(context, txContext, state.StateDB, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer.Hooks()})
|
evm := vm.NewEVM(context, state.StateDB, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer.Hooks()})
|
||||||
|
evm.SetTxContext(txContext)
|
||||||
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
|
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("failed to prepare transaction for tracing: %v", err)
|
b.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||||
|
|
|
@ -864,10 +864,11 @@ func applyMessage(ctx context.Context, b Backend, args TransactionArgs, state *s
|
||||||
if msg.BlobGasFeeCap != nil && msg.BlobGasFeeCap.BitLen() == 0 {
|
if msg.BlobGasFeeCap != nil && msg.BlobGasFeeCap.BitLen() == 0 {
|
||||||
blockContext.BlobBaseFee = new(big.Int)
|
blockContext.BlobBaseFee = new(big.Int)
|
||||||
}
|
}
|
||||||
evm := b.GetEVM(ctx, msg, state, header, vmConfig, blockContext)
|
evm := b.GetEVM(ctx, state, header, vmConfig, blockContext)
|
||||||
if precompiles != nil {
|
if precompiles != nil {
|
||||||
evm.SetPrecompiles(precompiles)
|
evm.SetPrecompiles(precompiles)
|
||||||
}
|
}
|
||||||
|
evm.SetTxContext(core.NewEVMTxContext(msg))
|
||||||
res, err := applyMessageWithEVM(ctx, evm, msg, timeout, gp)
|
res, err := applyMessageWithEVM(ctx, evm, msg, timeout, gp)
|
||||||
// If an internal state error occurred, let that have precedence. Otherwise,
|
// If an internal state error occurred, let that have precedence. Otherwise,
|
||||||
// a "trie root missing" type of error will masquerade as e.g. "insufficient gas"
|
// a "trie root missing" type of error will masquerade as e.g. "insufficient gas"
|
||||||
|
@ -1331,7 +1332,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
|
||||||
// Apply the transaction with the access list tracer
|
// Apply the transaction with the access list tracer
|
||||||
tracer := logger.NewAccessListTracer(accessList, args.from(), to, precompiles)
|
tracer := logger.NewAccessListTracer(accessList, args.from(), to, precompiles)
|
||||||
config := vm.Config{Tracer: tracer.Hooks(), NoBaseFee: true}
|
config := vm.Config{Tracer: tracer.Hooks(), NoBaseFee: true}
|
||||||
vmenv := b.GetEVM(ctx, msg, statedb, header, &config, nil)
|
vmenv := b.GetEVM(ctx, statedb, header, &config, nil)
|
||||||
// Lower the basefee to 0 to avoid breaking EVM
|
// Lower the basefee to 0 to avoid breaking EVM
|
||||||
// invariants (basefee < feecap).
|
// invariants (basefee < feecap).
|
||||||
if msg.GasPrice.Sign() == 0 {
|
if msg.GasPrice.Sign() == 0 {
|
||||||
|
@ -1340,6 +1341,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
|
||||||
if msg.BlobGasFeeCap != nil && msg.BlobGasFeeCap.BitLen() == 0 {
|
if msg.BlobGasFeeCap != nil && msg.BlobGasFeeCap.BitLen() == 0 {
|
||||||
vmenv.Context.BlobBaseFee = new(big.Int)
|
vmenv.Context.BlobBaseFee = new(big.Int)
|
||||||
}
|
}
|
||||||
|
vmenv.SetTxContext(core.NewEVMTxContext(msg))
|
||||||
res, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit))
|
res, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, nil, fmt.Errorf("failed to apply transaction: %v err: %v", args.ToTransaction(types.LegacyTxType).Hash(), err)
|
return nil, 0, nil, fmt.Errorf("failed to apply transaction: %v err: %v", args.ToTransaction(types.LegacyTxType).Hash(), err)
|
||||||
|
|
|
@ -570,16 +570,15 @@ func (b testBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
|
||||||
}
|
}
|
||||||
return big.NewInt(1)
|
return big.NewInt(1)
|
||||||
}
|
}
|
||||||
func (b testBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockContext *vm.BlockContext) *vm.EVM {
|
func (b testBackend) GetEVM(ctx context.Context, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockContext *vm.BlockContext) *vm.EVM {
|
||||||
if vmConfig == nil {
|
if vmConfig == nil {
|
||||||
vmConfig = b.chain.GetVMConfig()
|
vmConfig = b.chain.GetVMConfig()
|
||||||
}
|
}
|
||||||
txContext := core.NewEVMTxContext(msg)
|
|
||||||
context := core.NewEVMBlockContext(header, b.chain, nil)
|
context := core.NewEVMBlockContext(header, b.chain, nil)
|
||||||
if blockContext != nil {
|
if blockContext != nil {
|
||||||
context = *blockContext
|
context = *blockContext
|
||||||
}
|
}
|
||||||
return vm.NewEVM(context, txContext, state, b.chain.Config(), *vmConfig)
|
return vm.NewEVM(context, state, b.chain.Config(), *vmConfig)
|
||||||
}
|
}
|
||||||
func (b testBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
|
func (b testBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
|
|
|
@ -68,7 +68,7 @@ type Backend interface {
|
||||||
StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error)
|
StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error)
|
||||||
Pending() (*types.Block, types.Receipts, *state.StateDB)
|
Pending() (*types.Block, types.Receipts, *state.StateDB)
|
||||||
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
|
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
|
||||||
GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM
|
GetEVM(ctx context.Context, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM
|
||||||
SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription
|
SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription
|
||||||
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
|
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
|
||||||
|
|
||||||
|
|
|
@ -185,12 +185,12 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
|
||||||
NoBaseFee: !sim.validate,
|
NoBaseFee: !sim.validate,
|
||||||
Tracer: tracer.Hooks(),
|
Tracer: tracer.Hooks(),
|
||||||
}
|
}
|
||||||
evm = vm.NewEVM(blockContext, vm.TxContext{GasPrice: new(big.Int)}, sim.state, sim.chainConfig, *vmConfig)
|
|
||||||
)
|
)
|
||||||
var tracingStateDB = vm.StateDB(sim.state)
|
var tracingStateDB = vm.StateDB(sim.state)
|
||||||
if hooks := tracer.Hooks(); hooks != nil {
|
if hooks := tracer.Hooks(); hooks != nil {
|
||||||
tracingStateDB = state.NewHookedState(sim.state, hooks)
|
tracingStateDB = state.NewHookedState(sim.state, hooks)
|
||||||
}
|
}
|
||||||
|
evm := vm.NewEVM(blockContext, tracingStateDB, sim.chainConfig, *vmConfig)
|
||||||
// It is possible to override precompiles with EVM bytecode, or
|
// It is possible to override precompiles with EVM bytecode, or
|
||||||
// move them to another address.
|
// move them to another address.
|
||||||
if precompiles != nil {
|
if precompiles != nil {
|
||||||
|
@ -208,7 +208,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
|
||||||
tracer.reset(tx.Hash(), uint(i))
|
tracer.reset(tx.Hash(), uint(i))
|
||||||
// EoA check is always skipped, even in validation mode.
|
// EoA check is always skipped, even in validation mode.
|
||||||
msg := call.ToMessage(header.BaseFee, !sim.validate, true)
|
msg := call.ToMessage(header.BaseFee, !sim.validate, true)
|
||||||
evm.Reset(core.NewEVMTxContext(msg), tracingStateDB)
|
evm.SetTxContext(core.NewEVMTxContext(msg))
|
||||||
result, err := applyMessageWithEVM(ctx, evm, msg, timeout, sim.gp)
|
result, err := applyMessageWithEVM(ctx, evm, msg, timeout, sim.gp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
txErr := txValidationError(err)
|
txErr := txValidationError(err)
|
||||||
|
|
|
@ -370,7 +370,7 @@ func (b *backendMock) GetLogs(ctx context.Context, blockHash common.Hash, number
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
func (b *backendMock) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil }
|
func (b *backendMock) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil }
|
||||||
func (b *backendMock) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM {
|
func (b *backendMock) GetEVM(ctx context.Context, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (b *backendMock) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { return nil }
|
func (b *backendMock) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { return nil }
|
||||||
|
|
|
@ -51,6 +51,7 @@ type environment struct {
|
||||||
tcount int // tx count in cycle
|
tcount int // tx count in cycle
|
||||||
gasPool *core.GasPool // available gas used to pack transactions
|
gasPool *core.GasPool // available gas used to pack transactions
|
||||||
coinbase common.Address
|
coinbase common.Address
|
||||||
|
evm *vm.EVM
|
||||||
|
|
||||||
header *types.Header
|
header *types.Header
|
||||||
txs []*types.Transaction
|
txs []*types.Transaction
|
||||||
|
@ -126,14 +127,11 @@ func (miner *Miner) generateWork(params *generateParams, witness bool) *newPaylo
|
||||||
return &newPayloadResult{err: err}
|
return &newPayloadResult{err: err}
|
||||||
}
|
}
|
||||||
requests = append(requests, depositRequests)
|
requests = append(requests, depositRequests)
|
||||||
// create EVM for system calls
|
|
||||||
blockContext := core.NewEVMBlockContext(work.header, miner.chain, &work.header.Coinbase)
|
|
||||||
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, work.state, miner.chainConfig, vm.Config{})
|
|
||||||
// EIP-7002 withdrawals
|
// EIP-7002 withdrawals
|
||||||
withdrawalRequests := core.ProcessWithdrawalQueue(vmenv, work.state)
|
withdrawalRequests := core.ProcessWithdrawalQueue(work.evm, work.state)
|
||||||
requests = append(requests, withdrawalRequests)
|
requests = append(requests, withdrawalRequests)
|
||||||
// EIP-7251 consolidations
|
// EIP-7251 consolidations
|
||||||
consolidationRequests := core.ProcessConsolidationQueue(vmenv, work.state)
|
consolidationRequests := core.ProcessConsolidationQueue(work.evm, work.state)
|
||||||
requests = append(requests, consolidationRequests)
|
requests = append(requests, consolidationRequests)
|
||||||
}
|
}
|
||||||
if requests != nil {
|
if requests != nil {
|
||||||
|
@ -233,14 +231,10 @@ func (miner *Miner) prepareWork(genParams *generateParams, witness bool) (*envir
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if header.ParentBeaconRoot != nil {
|
if header.ParentBeaconRoot != nil {
|
||||||
context := core.NewEVMBlockContext(header, miner.chain, nil)
|
core.ProcessBeaconBlockRoot(*header.ParentBeaconRoot, env.evm, env.state)
|
||||||
vmenv := vm.NewEVM(context, vm.TxContext{}, env.state, miner.chainConfig, vm.Config{})
|
|
||||||
core.ProcessBeaconBlockRoot(*header.ParentBeaconRoot, vmenv, env.state)
|
|
||||||
}
|
}
|
||||||
if miner.chainConfig.IsPrague(header.Number, header.Time) {
|
if miner.chainConfig.IsPrague(header.Number, header.Time) {
|
||||||
context := core.NewEVMBlockContext(header, miner.chain, nil)
|
core.ProcessParentBlockHash(header.ParentHash, env.evm, env.state)
|
||||||
vmenv := vm.NewEVM(context, vm.TxContext{}, env.state, miner.chainConfig, vm.Config{})
|
|
||||||
core.ProcessParentBlockHash(header.ParentHash, vmenv, env.state)
|
|
||||||
}
|
}
|
||||||
return env, nil
|
return env, nil
|
||||||
}
|
}
|
||||||
|
@ -266,6 +260,7 @@ func (miner *Miner) makeEnv(parent *types.Header, header *types.Header, coinbase
|
||||||
coinbase: coinbase,
|
coinbase: coinbase,
|
||||||
header: header,
|
header: header,
|
||||||
witness: state.Witness(),
|
witness: state.Witness(),
|
||||||
|
evm: vm.NewEVM(core.NewEVMBlockContext(header, miner.chain, &coinbase), state, miner.chainConfig, vm.Config{}),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,7 +309,7 @@ func (miner *Miner) applyTransaction(env *environment, tx *types.Transaction) (*
|
||||||
snap = env.state.Snapshot()
|
snap = env.state.Snapshot()
|
||||||
gp = env.gasPool.Gas()
|
gp = env.gasPool.Gas()
|
||||||
)
|
)
|
||||||
receipt, err := core.ApplyTransaction(miner.chainConfig, miner.chain, &env.coinbase, env.gasPool, env.state, env.header, tx, &env.header.GasUsed, vm.Config{})
|
receipt, err := core.ApplyTransaction(miner.chainConfig, env.evm, env.gasPool, env.state, env.header, tx, &env.header.GasUsed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
env.state.RevertToSnapshot(snap)
|
env.state.RevertToSnapshot(snap)
|
||||||
env.gasPool.SetGas(gp)
|
env.gasPool.SetGas(gp)
|
||||||
|
|
|
@ -302,7 +302,8 @@ func runBenchmark(b *testing.B, t *StateTest) {
|
||||||
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
|
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
|
||||||
context.GetHash = vmTestBlockHash
|
context.GetHash = vmTestBlockHash
|
||||||
context.BaseFee = baseFee
|
context.BaseFee = baseFee
|
||||||
evm := vm.NewEVM(context, txContext, state.StateDB, config, vmconfig)
|
evm := vm.NewEVM(context, state.StateDB, config, vmconfig)
|
||||||
|
evm.SetTxContext(txContext)
|
||||||
|
|
||||||
// Create "contract" for sender to cache code analysis.
|
// Create "contract" for sender to cache code analysis.
|
||||||
sender := vm.NewContract(vm.AccountRef(msg.From), vm.AccountRef(msg.From),
|
sender := vm.NewContract(vm.AccountRef(msg.From), vm.AccountRef(msg.From),
|
||||||
|
|
|
@ -293,7 +293,8 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
|
||||||
if config.IsCancun(new(big.Int), block.Time()) && t.json.Env.ExcessBlobGas != nil {
|
if config.IsCancun(new(big.Int), block.Time()) && t.json.Env.ExcessBlobGas != nil {
|
||||||
context.BlobBaseFee = eip4844.CalcBlobFee(*t.json.Env.ExcessBlobGas)
|
context.BlobBaseFee = eip4844.CalcBlobFee(*t.json.Env.ExcessBlobGas)
|
||||||
}
|
}
|
||||||
evm := vm.NewEVM(context, txContext, st.StateDB, config, vmconfig)
|
evm := vm.NewEVM(context, st.StateDB, config, vmconfig)
|
||||||
|
evm.SetTxContext(txContext)
|
||||||
|
|
||||||
if tracer := vmconfig.Tracer; tracer != nil && tracer.OnTxStart != nil {
|
if tracer := vmconfig.Tracer; tracer != nil && tracer.OnTxStart != nil {
|
||||||
tracer.OnTxStart(evm.GetVMContext(), nil, msg.From)
|
tracer.OnTxStart(evm.GetVMContext(), nil, msg.From)
|
||||||
|
|
Loading…
Reference in New Issue