refactor(all): rework EVM constructor #30745 (#2065)

This commit is contained in:
Daniel Liu 2026-02-17 17:05:18 +08:00 committed by GitHub
parent 373037032f
commit cfca45a7eb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 241 additions and 137 deletions

View file

@ -777,9 +777,10 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
evmContext := core.NewEVMBlockContext(block, b.blockchain, nil)
// Create a new environment which holds all relevant information
// about the transaction and calling mechanisms.
vmenv := vm.NewEVM(evmContext, txContext, stateDB, nil, b.config, vm.Config{NoBaseFee: true})
evm := vm.NewEVM(evmContext, stateDB, nil, b.config, vm.Config{NoBaseFee: true})
evm.SetTxContext(txContext)
gaspool := new(core.GasPool).AddGas(gomath.MaxUint64)
return core.NewStateTransition(vmenv, msg, gaspool).TransitionDb(common.Address{})
return core.NewStateTransition(evm, msg, gaspool).TransitionDb(common.Address{})
}
// SendTransaction updates the pending block to include the given transaction.

View file

@ -371,7 +371,9 @@ func createBlockFromHeader(bc *core.BlockChain, customHeader *types.Header, txs
var receipts types.Receipts
for i, tx := range txs {
statedb.SetTxContext(tx.Hash(), i)
receipt, _, _, err := core.ApplyTransaction(bc.Config(), nil, bc, &header.Coinbase, gp, statedb, nil, &header, tx, gasUsed, vm.Config{})
blockContext := core.NewEVMBlockContext(&header, bc, &header.Coinbase)
evm := vm.NewEVM(blockContext, statedb, nil, bc.Config(), vm.Config{})
receipt, _, _, err := core.ApplyTransaction(bc.Config(), nil, evm, gp, statedb, &header, tx, gasUsed)
if err != nil {
return nil, fmt.Errorf("%v when applying transaction", err)
}

View file

@ -901,7 +901,9 @@ func createBlockFromHeader(bc *core.BlockChain, customHeader *types.Header, txs
var receipts types.Receipts
for i, tx := range txs {
statedb.SetTxContext(tx.Hash(), i)
receipt, _, _, err := core.ApplyTransaction(bc.Config(), nil, bc, &header.Coinbase, gp, statedb, nil, &header, tx, gasUsed, vm.Config{})
blockContext := core.NewEVMBlockContext(&header, bc, &header.Coinbase)
evm := vm.NewEVM(blockContext, statedb, nil, bc.Config(), vm.Config{})
receipt, _, _, err := core.ApplyTransaction(bc.Config(), nil, evm, gp, statedb, &header, tx, gasUsed)
if err != nil {
return nil, fmt.Errorf("%v when applying transaction", err)
}

View file

@ -87,7 +87,9 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
}
feeCapacity := b.statedb.GetTRC21FeeCapacityFromState()
b.statedb.SetTxContext(tx.Hash(), len(b.txs))
receipt, gas, tokenFeeUsed, err := ApplyTransaction(b.config, feeCapacity, bc, &b.header.Coinbase, b.gasPool, b.statedb, nil, b.header, tx, &b.header.GasUsed, vmConfig)
blockContext := NewEVMBlockContext(b.header, bc, &b.header.Coinbase)
evm := vm.NewEVM(blockContext, b.statedb, nil, b.config, vmConfig)
receipt, gas, tokenFeeUsed, err := ApplyTransaction(b.config, feeCapacity, evm, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed)
if err != nil {
panic(err)
}
@ -235,7 +237,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
if config.IsPrague(b.header.Number) {
// EIP-2935
blockContext := NewEVMBlockContext(b.header, chainReader, &b.header.Coinbase)
evm := vm.NewEVM(blockContext, vm.TxContext{}, statedb, nil, config, vm.Config{})
evm := vm.NewEVM(blockContext, statedb, nil, config, vm.Config{})
ProcessParentBlockHash(b.header.ParentHash, evm, statedb)
}

View file

@ -53,7 +53,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
header = block.Header()
gaspool = new(GasPool).AddGas(block.GasLimit())
blockContext = NewEVMBlockContext(header, p.bc, nil)
evm = vm.NewEVM(blockContext, vm.TxContext{}, statedb, nil, p.config, cfg)
evm = vm.NewEVM(blockContext, statedb, nil, p.config, cfg)
signer = types.MakeSigner(p.config, header.Number)
)
// Iterate over and process the individual transactions
@ -69,7 +69,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
return // Also invalid block, bail out
}
statedb.SetTxContext(tx.Hash(), i)
if err := precacheTransaction(msg, p.config, gaspool, statedb, header, evm); err != nil {
if err := precacheTransaction(msg, gaspool, evm); err != nil {
return // Ugh, something went horribly wrong, bail out
}
// If we're pre-byzantium, pre-load trie nodes for the intermediate root
@ -86,9 +86,9 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
// precacheTransaction attempts to apply a transaction to the given state database
// and uses the input parameters for its environment. The goal is not to execute
// the transaction successfully, rather to warm up touched data slots.
func precacheTransaction(msg *Message, config *params.ChainConfig, gaspool *GasPool, statedb *state.StateDB, header *types.Header, evm *vm.EVM) error {
func precacheTransaction(msg *Message, gaspool *GasPool, evm *vm.EVM) error {
// Update the evm with the new transaction context.
evm.Reset(NewEVMTxContext(msg), statedb)
evm.SetTxContext(NewEVMTxContext(msg))
// Add addresses to access list if applicable
_, err := ApplyMessage(evm, msg, gaspool, common.Address{})
return err

View file

@ -97,13 +97,13 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, tra
totalFeeUsed := big.NewInt(0)
// Apply pre-execution system calls.
blockContext := NewEVMBlockContext(header, p.bc, nil)
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, tracingStateDB, tradingState, p.config, cfg)
context := NewEVMBlockContext(header, p.bc, nil)
evm := vm.NewEVM(context, tracingStateDB, tradingState, p.config, cfg)
signer := types.MakeSigner(p.config, blockNumber)
coinbaseOwner := getCoinbaseOwner(p.bc, statedb, header, nil)
if p.config.IsPrague(block.Number()) {
ProcessParentBlockHash(block.ParentHash(), vmenv, tracingStateDB)
ProcessParentBlockHash(block.ParentHash(), evm, tracingStateDB)
}
// Iterate over and process the individual transactions
@ -146,7 +146,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, tra
}
statedb.SetTxContext(tx.Hash(), i)
receipt, gas, tokenFeeUsed, err := ApplyTransactionWithEVM(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv, balanceFee, coinbaseOwner)
receipt, gas, tokenFeeUsed, err := ApplyTransactionWithEVM(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, evm, balanceFee, coinbaseOwner)
if err != nil {
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
}
@ -204,13 +204,13 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
}
// Apply pre-execution system calls.
blockContext := NewEVMBlockContext(header, p.bc, nil)
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, tracingStateDB, tradingState, p.config, cfg)
context := NewEVMBlockContext(header, p.bc, nil)
evm := vm.NewEVM(context, tracingStateDB, tradingState, p.config, cfg)
signer := types.MakeSigner(p.config, blockNumber)
coinbaseOwner := getCoinbaseOwner(p.bc, statedb, header, nil)
if p.config.IsPrague(block.Number()) {
ProcessParentBlockHash(block.ParentHash(), vmenv, tracingStateDB)
ProcessParentBlockHash(block.ParentHash(), evm, tracingStateDB)
}
// Iterate over and process the individual transactions
@ -253,7 +253,7 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
}
statedb.SetTxContext(tx.Hash(), i)
receipt, gas, tokenFeeUsed, err := ApplyTransactionWithEVM(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv, balanceFee, coinbaseOwner)
receipt, gas, tokenFeeUsed, err := ApplyTransactionWithEVM(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, evm, balanceFee, coinbaseOwner)
if err != nil {
return nil, nil, 0, err
}
@ -280,11 +280,7 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
// and uses the input parameters for its environment similar to ApplyTransaction. However,
// 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, balanceFee *big.Int, coinbaseOwner common.Address) (receipt *types.Receipt, gasUsed uint64, tokenFeeUsed bool, err error) {
// Initialize tracer at the beginning to ensure all transaction types
// (including non-EVM special transactions) are properly traced.
var tracingStateDB = vm.StateDB(statedb)
if hooks := evm.Config.Tracer; hooks != nil {
tracingStateDB = state.NewHookedState(statedb, hooks)
if hooks.OnTxStart != nil {
hooks.OnTxStart(evm.GetVMContext(), tx, msg.From)
}
@ -314,7 +310,7 @@ func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPo
// Create a new context to be used in the EVM environment
txContext := NewEVMTxContext(msg)
evm.Reset(txContext, tracingStateDB)
evm.SetTxContext(txContext)
// Bypass denylist address
maxBlockNumber := new(big.Int).SetInt64(9147459)
@ -469,7 +465,7 @@ func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPo
// Update the state with pending changes.
var root []byte
if config.IsByzantium(blockNumber) {
tracingStateDB.Finalise(true)
evm.StateDB.Finalise(true)
} else {
root = statedb.IntermediateRoot(config.IsEIP158(blockNumber)).Bytes()
}
@ -524,7 +520,7 @@ func getCoinbaseOwner(bc *BlockChain, statedb *state.StateDB, header *types.Head
// and uses the input parameters for its environment. It returns the receipt
// for the transaction, gas used and an error if the transaction failed,
// indicating the block was invalid.
func ApplyTransaction(config *params.ChainConfig, tokensFee map[common.Address]*big.Int, bc *BlockChain, author *common.Address, gp *GasPool, statedb *state.StateDB, XDCxState *tradingstate.TradingStateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, uint64, bool, error) {
func ApplyTransaction(config *params.ChainConfig, tokensFee map[common.Address]*big.Int, evm *vm.EVM, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64) (*types.Receipt, uint64, bool, error) {
var balanceFee *big.Int
if tx.To() != nil {
if value, ok := tokensFee[*tx.To()]; ok {
@ -532,16 +528,13 @@ func ApplyTransaction(config *params.ChainConfig, tokensFee map[common.Address]*
}
}
// Create a new context to be used in the EVM environment
blockContext := NewEVMBlockContext(header, bc, author)
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, XDCxState, config, cfg)
signer := types.MakeSigner(config, header.Number)
msg, err := TransactionToMessage(tx, signer, balanceFee, header.Number, header.BaseFee)
if err != nil {
return nil, 0, false, err
}
coinbaseOwner := getCoinbaseOwner(bc, statedb, header, author)
return ApplyTransactionWithEVM(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv, balanceFee, coinbaseOwner)
coinbaseOwner := statedb.GetOwner(evm.Context.Coinbase)
return ApplyTransactionWithEVM(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, evm, balanceFee, coinbaseOwner)
}
func ApplySignTransaction(msg *Message, config *params.ChainConfig, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (receipt *types.Receipt, gasUsed uint64, tokenFeeUsed bool, err error) {
@ -726,7 +719,7 @@ func ProcessParentBlockHash(prevHash common.Hash, vmenv *vm.EVM, statedb vm.Stat
To: &params.HistoryStorageAddress,
Data: prevHash.Bytes(),
}
vmenv.Reset(NewEVMTxContext(msg), statedb)
vmenv.SetTxContext(NewEVMTxContext(msg))
statedb.AddAddressToAccessList(params.HistoryStorageAddress)
_, _, err := vmenv.Call(msg.From, *msg.To, msg.Data, 30_000_000, common.U2560)
if err != nil {

View file

@ -467,7 +467,7 @@ func TestApplyTransactionWithEVMTracer(t *testing.T) {
blockHash := genesis.Hash()
vmContext := NewEVMBlockContext(blockchain.CurrentBlock(), blockchain, nil)
evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, nil, blockchain.Config(), vmConfig)
evm := vm.NewEVM(vmContext, statedb, nil, blockchain.Config(), vmConfig)
// Apply transaction
var usedGas uint64
@ -493,6 +493,81 @@ func TestApplyTransactionWithEVMTracer(t *testing.T) {
}
}
func TestApplyTransactionWithEVMStateChangeHooks(t *testing.T) {
var (
config = &params.ChainConfig{
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
Eip1559Block: big.NewInt(0),
Ethash: new(params.EthashConfig),
}
signer = types.LatestSigner(config)
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
sender = crypto.PubkeyToAddress(testKey.PublicKey)
recipient = common.HexToAddress("0x1234567890123456789012345678901234567890")
hookInvoked bool
)
db := rawdb.NewMemoryDatabase()
gspec := &Genesis{
Config: config,
Alloc: types.GenesisAlloc{
sender: {
Balance: big.NewInt(1000000000000000000),
Nonce: 0,
},
},
}
genesis := gspec.MustCommit(db)
blockchain, _ := NewBlockChain(db, nil, gspec, ethash.NewFaker(), vm.Config{})
defer blockchain.Stop()
statedb, err := blockchain.State()
if err != nil {
t.Fatalf("Failed to get state: %v", err)
}
tx := types.NewTransaction(0, recipient, big.NewInt(1), 21000, big.NewInt(20000000000), nil)
signedTx, err := types.SignTx(tx, signer, testKey)
if err != nil {
t.Fatalf("Failed to sign tx: %v", err)
}
hooks := &tracing.Hooks{
OnBalanceChange: func(addr common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) {
hookInvoked = true
},
}
hookedState := state.NewHookedState(statedb, hooks)
vmContext := NewEVMBlockContext(blockchain.CurrentBlock(), blockchain, nil)
evmenv := vm.NewEVM(vmContext, hookedState, nil, blockchain.Config(), vm.Config{Tracer: hooks})
msg, err := TransactionToMessage(signedTx, signer, nil, big.NewInt(1), nil)
if err != nil {
t.Fatalf("Failed to build message: %v", err)
}
gasPool := new(GasPool).AddGas(1000000)
var usedGas uint64
_, _, _, err = ApplyTransactionWithEVM(msg, config, gasPool, statedb, big.NewInt(1), genesis.Hash(), signedTx, &usedGas, evmenv, nil, common.Address{})
if err != nil {
t.Fatalf("ApplyTransactionWithEVM failed: %v", err)
}
if !hookInvoked {
t.Fatal("expected OnBalanceChange to be invoked, but it was not")
}
}
func TestProcessParentBlockHash(t *testing.T) {
var (
chainConfig = params.MergedTestChainConfig
@ -508,11 +583,11 @@ func TestProcessParentBlockHash(t *testing.T) {
statedb.IntermediateRoot(true)
vmContext := NewEVMBlockContext(header, nil, &coinbase)
evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, nil, chainConfig, vm.Config{})
evm := vm.NewEVM(vmContext, statedb, nil, chainConfig, vm.Config{})
ProcessParentBlockHash(header.ParentHash, evm, statedb)
vmContext = NewEVMBlockContext(parent, nil, &coinbase)
evm = vm.NewEVM(vmContext, vm.TxContext{}, statedb, nil, chainConfig, vm.Config{})
evm = vm.NewEVM(vmContext, statedb, nil, chainConfig, vm.Config{})
ProcessParentBlockHash(parent.ParentHash, evm, statedb)
// make sure that the state is correct
@ -548,8 +623,8 @@ func TestProcessParentBlockHashPragueGuard(t *testing.T) {
BaseFee: nil,
Random: &random,
}
evmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, nil, &config, vm.Config{})
ProcessParentBlockHash(common.Hash{0x01}, evmenv, statedb)
evm := vm.NewEVM(blockContext, statedb, nil, &config, vm.Config{})
ProcessParentBlockHash(common.Hash{0x01}, evm, statedb)
if code := statedb.GetCode(params.HistoryStorageAddress); len(code) != 0 {
t.Fatalf("unexpected history contract code predeploy: %x", code)
@ -586,8 +661,8 @@ func TestProcessParentBlockHashBackfillMissingHistory(t *testing.T) {
BaseFee: nil,
Random: &random,
}
evmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, nil, &config, vm.Config{})
ProcessParentBlockHash(common.Hash{0x01}, evmenv, statedb)
evm := vm.NewEVM(blockContext, statedb, nil, &config, vm.Config{})
ProcessParentBlockHash(common.Hash{0x01}, evm, statedb)
if have := getParentBlockHash(statedb, 1); have != available[1] {
t.Fatalf("expected hash at slot 1, have %v", have)
@ -619,14 +694,14 @@ func TestProcessParentBlockHashCodeMismatchPanics(t *testing.T) {
BaseFee: nil,
Random: &random,
}
evmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, nil, &config, vm.Config{})
evm := vm.NewEVM(blockContext, statedb, nil, &config, vm.Config{})
defer func() {
if recover() == nil {
t.Fatal("expected panic on history storage code mismatch")
}
}()
ProcessParentBlockHash(common.Hash{0x01}, evmenv, statedb)
ProcessParentBlockHash(common.Hash{0x01}, evm, statedb)
}
func getParentBlockHash(statedb *state.StateDB, number uint64) common.Hash {

View file

@ -110,9 +110,10 @@ func CallContractWithState(call ethereum.CallMsg, chain consensus.ChainContext,
// about the transaction and calling mechanisms.
txContext := NewEVMTxContext(msg)
evmContext := NewEVMBlockContext(chain.CurrentHeader(), chain, nil)
vmenv := vm.NewEVM(evmContext, txContext, statedb, nil, chain.Config(), vm.Config{})
evm := vm.NewEVM(evmContext, statedb, nil, chain.Config(), vm.Config{})
evm.SetTxContext(txContext)
gaspool := new(GasPool).AddGas(1000000)
result, err := NewStateTransition(vmenv, msg, gaspool).TransitionDb(common.Address{})
result, err := NewStateTransition(evm, msg, gaspool).TransitionDb(common.Address{})
if err != nil {
return nil, err
}

View file

@ -132,12 +132,13 @@ type EVM struct {
returnData []byte // Last CALL's return data for subsequent reuse
}
// NewEVM returns a new EVM. The returned EVM is not thread safe and should
// only ever be used *once*.
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, tradingStateDB *tradingstate.TradingStateDB, chainConfig *params.ChainConfig, config Config) *EVM {
// NewEVM constructs an EVM instance with the supplied block context, state
// database and several configs. It is meant to be used throughout the entire
// state transition of a block, with the transaction context switched as
// needed by calling evm.SetTxContext.
func NewEVM(blockCtx BlockContext, statedb StateDB, tradingStateDB *tradingstate.TradingStateDB, chainConfig *params.ChainConfig, config Config) *EVM {
evm := &EVM{
Context: blockCtx,
TxContext: txCtx,
StateDB: statedb,
tradingStateDB: tradingStateDB,
Config: config,
@ -198,6 +199,11 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, tradingStat
return evm
}
// SetTracer sets the tracer for following state transition.
func (evm *EVM) SetTracer(tracer *tracing.Hooks) {
evm.Config.Tracer = tracer
}
// SetPrecompiles sets the precompiled contracts for the EVM.
// This method is only used through RPC calls.
// It is not thread-safe.
@ -205,11 +211,10 @@ func (evm *EVM) SetPrecompiles(precompiles PrecompiledContracts) {
evm.precompiles = precompiles
}
// Reset resets the EVM with a new transaction context.Reset
// SetTxContext updates the EVM with a new transaction context.
// This is not threadsafe and should only be done very cautiously.
func (evm *EVM) Reset(txCtx TxContext, statedb StateDB) {
func (evm *EVM) SetTxContext(txCtx TxContext) {
evm.TxContext = txCtx
evm.StateDB = statedb
}
// Cancel cancels any running EVM operation. This may be called concurrently and

View file

@ -96,16 +96,16 @@ func TestEIP2200(t *testing.T) {
CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true },
Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
}
vmenv := NewEVM(vmctx, TxContext{}, statedb, nil, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
evm := NewEVM(vmctx, statedb, nil, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
_, gas, err := vmenv.Call(common.Address{}, address, nil, tt.gaspool, new(uint256.Int))
_, gas, err := evm.Call(common.Address{}, address, nil, tt.gaspool, new(uint256.Int))
if !errors.Is(err, tt.failure) {
t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.failure)
}
if used := tt.gaspool - gas; used != tt.used {
t.Errorf("test %d: gas used mismatch: have %v, want %v", i, used, tt.used)
}
if refund := vmenv.StateDB.GetRefund(); refund != tt.refund {
if refund := evm.StateDB.GetRefund(); refund != tt.refund {
t.Errorf("test %d: gas refund mismatch: have %v, want %v", i, refund, tt.refund)
}
}
@ -151,9 +151,9 @@ func TestCreateGas(t *testing.T) {
config.ExtraEips = []int{3860}
}
vmenv := NewEVM(vmctx, TxContext{}, statedb, nil, params.AllEthashProtocolChanges, config)
evm := NewEVM(vmctx, statedb, nil, params.AllEthashProtocolChanges, config)
var startGas = uint64(testGas)
ret, gas, err := vmenv.Call(common.Address{}, address, nil, startGas, new(uint256.Int))
ret, gas, err := evm.Call(common.Address{}, address, nil, startGas, new(uint256.Int))
if err != nil {
return false
}

View file

@ -98,7 +98,7 @@ func init() {
func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFunc, name string) {
var (
evm = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
evm = NewEVM(BlockContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
pc = uint64(0)
)
@ -196,7 +196,7 @@ func TestSAR(t *testing.T) {
func TestAddMod(t *testing.T) {
var (
evm = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
evm = NewEVM(BlockContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
pc = uint64(0)
)
@ -239,7 +239,7 @@ func TestWriteExpectedValues(t *testing.T) {
// getResult is a convenience function to generate the expected values
getResult := func(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase {
var (
evm = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
evm = NewEVM(BlockContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
pc = uint64(0)
)
@ -289,7 +289,7 @@ func TestJsonTestcases(t *testing.T) {
func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
var (
evm = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
evm = NewEVM(BlockContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
scope = &ScopeContext{nil, stack, nil}
)
@ -526,7 +526,7 @@ func BenchmarkOpIsZero(b *testing.B) {
func TestOpMstore(t *testing.T) {
var (
evm = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
evm = NewEVM(BlockContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
mem = NewMemory()
)
@ -550,7 +550,7 @@ func TestOpMstore(t *testing.T) {
func BenchmarkOpMstore(bench *testing.B) {
var (
evm = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
evm = NewEVM(BlockContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
mem = NewMemory()
)
@ -570,7 +570,7 @@ func BenchmarkOpMstore(bench *testing.B) {
func TestOpTstore(t *testing.T) {
var (
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()))
evm = NewEVM(BlockContext{}, TxContext{}, statedb, nil, params.TestChainConfig, Config{})
evm = NewEVM(BlockContext{}, statedb, nil, params.TestChainConfig, Config{})
stack = newstack()
mem = NewMemory()
caller = common.Address{}
@ -609,7 +609,7 @@ func TestOpTstore(t *testing.T) {
func BenchmarkOpKeccak256(bench *testing.B) {
var (
evm = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
evm = NewEVM(BlockContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
mem = NewMemory()
)
@ -710,7 +710,7 @@ func TestRandom(t *testing.T) {
{name: "hash(0x010203)", random: crypto.Keccak256Hash([]byte{0x01, 0x02, 0x03})},
} {
var (
evm = NewEVM(BlockContext{Random: &tt.random}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
evm = NewEVM(BlockContext{Random: &tt.random}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
pc = uint64(0)
)
@ -750,7 +750,7 @@ func TestBlobHash(t *testing.T) {
{name: "out-of-bounds (nil)", idx: 25, expect: zero, hashes: nil},
} {
var (
evm = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
evm = NewEVM(BlockContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
pc = uint64(0)
)
@ -853,7 +853,7 @@ func TestOpMCopy(t *testing.T) {
},
} {
var (
evm = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
evm = NewEVM(BlockContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
pc = uint64(0)
)
@ -909,7 +909,7 @@ func TestOpMCopy(t *testing.T) {
}
func TestOpCLZ(t *testing.T) {
evm := NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
evm := NewEVM(BlockContext{}, nil, nil, params.TestChainConfig, Config{})
tests := []struct {
inputHex string

View file

@ -39,5 +39,7 @@ func NewEnv(cfg *Config) *vm.EVM {
Random: cfg.Random,
}
return vm.NewEVM(blockContext, txContext, cfg.State, nil, cfg.ChainConfig, cfg.EVMConfig)
evm := vm.NewEVM(blockContext, cfg.State, nil, cfg.ChainConfig, cfg.EVMConfig)
evm.SetTxContext(txContext)
return evm
}

View file

@ -32,7 +32,6 @@ import (
"github.com/XinFinOrg/XDPoSChain/accounts"
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/common/math"
"github.com/XinFinOrg/XDPoSChain/consensus"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
"github.com/XinFinOrg/XDPoSChain/contracts"
@ -40,7 +39,6 @@ import (
"github.com/XinFinOrg/XDPoSChain/core/bloombits"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"github.com/XinFinOrg/XDPoSChain/core/state"
"github.com/XinFinOrg/XDPoSChain/core/tracing"
"github.com/XinFinOrg/XDPoSChain/core/txpool"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/core/vm"
@ -264,20 +262,18 @@ func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
return b.eth.blockchain.GetTdByHash(hash)
}
func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, XDCxState *tradingstate.TradingStateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error, error) {
func (b *EthAPIBackend) GetEVM(ctx context.Context, state *state.StateDB, XDCxState *tradingstate.TradingStateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error, error) {
vmError := func() error { return nil }
if vmConfig == nil {
vmConfig = b.eth.blockchain.GetVMConfig()
}
state.SetBalance(msg.From, math.MaxBig256, tracing.BalanceChangeUnspecified)
txContext := core.NewEVMTxContext(msg)
var context vm.BlockContext
if blockCtx != nil {
context = *blockCtx
} else {
context = core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
}
return vm.NewEVM(context, txContext, state, XDCxState, b.eth.chainConfig, *vmConfig), vmError, nil
return vm.NewEVM(context, state, XDCxState, b.eth.chainConfig, *vmConfig), vmError, nil
}
func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {

View file

@ -176,7 +176,8 @@ func run(ctx context.Context, call *core.Message, opts *Options) (*core.Executio
if msgContext.GasPrice.Sign() == 0 {
evmContext.BaseFee = new(big.Int)
}
evm := vm.NewEVM(evmContext, msgContext, dirtyState, nil, opts.Config, vm.Config{NoBaseFee: true})
evm := vm.NewEVM(evmContext, dirtyState, nil, opts.Config, vm.Config{NoBaseFee: true})
evm.SetTxContext(msgContext)
// Monitor the outer context and interrupt the EVM upon cancellation. To avoid
// a dangling goroutine until the outer estimation finishes, create an internal
// context for the lifetime of this method call.

View file

@ -206,11 +206,11 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
if err != nil {
return nil, vm.BlockContext{}, nil, nil, err
}
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil)
evm := vm.NewEVM(context, statedb, nil, eth.blockchain.Config(), vm.Config{})
// If prague hardfork, insert parent block hash in the state as per EIP-2935.
if eth.blockchain.Config().IsPrague(block.Number()) {
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil)
vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, nil, eth.blockchain.Config(), vm.Config{})
core.ProcessParentBlockHash(block.ParentHash(), vmenv, statedb)
core.ProcessParentBlockHash(block.ParentHash(), evm, statedb)
}
if txIndex == 0 && len(block.Transactions()) == 0 {
return nil, vm.BlockContext{}, statedb, release, nil
@ -219,6 +219,9 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
signer := types.MakeSigner(eth.blockchain.Config(), block.Number())
feeCapacity := statedb.GetTRC21FeeCapacityFromState()
for idx, tx := range block.Transactions() {
if idx == txIndex {
return tx, context, statedb, release, nil
}
var balance *big.Int
if tx.To() != nil {
if value, ok := feeCapacity[*tx.To()]; ok {
@ -228,19 +231,16 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
// Assemble the transaction call message and return if the requested offset
msg, _ := core.TransactionToMessage(tx, signer, balance, block.Number(), block.BaseFee())
txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil)
if idx == txIndex {
return tx, context, statedb, release, nil
}
evm.SetTxContext(txContext)
// Not yet the searched for transaction, execute on top of the current state
vmenv := vm.NewEVM(context, txContext, statedb, nil, eth.blockchain.Config(), vm.Config{})
statedb.SetTxContext(tx.Hash(), idx)
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas()), common.Address{}); err != nil {
if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()), common.Address{}); err != nil {
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
}
// Ensure any modifications are committed to the state
// 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())
}

View file

@ -382,8 +382,8 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
// Insert parent hash in history contract.
if api.backend.ChainConfig().IsPrague(next.Number()) {
context := core.NewEVMBlockContext(next.Header(), api.chainContext(ctx), nil)
vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, nil, api.backend.ChainConfig(), vm.Config{})
core.ProcessParentBlockHash(next.ParentHash(), vmenv, statedb)
evm := vm.NewEVM(context, statedb, nil, api.backend.ChainConfig(), vm.Config{})
core.ProcessParentBlockHash(next.ParentHash(), evm, statedb)
}
// Clean out any pending release functions of trace state. Note this
// step must be done after constructing tracing state, because the
@ -519,8 +519,9 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
)
evm := vm.NewEVM(vmctx, statedb, nil, chainConfig, vm.Config{})
if chainConfig.IsPrague(block.Number()) {
core.ProcessParentBlockHash(block.ParentHash(), vm.NewEVM(vmctx, vm.TxContext{}, statedb, nil, chainConfig, vm.Config{}), statedb)
core.ProcessParentBlockHash(block.ParentHash(), evm, statedb)
}
feeCapacity := statedb.GetTRC21FeeCapacityFromState()
for i, tx := range block.Transactions() {
@ -540,10 +541,10 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
var (
msg, _ = core.TransactionToMessage(tx, signer, balance, block.Number(), block.BaseFee())
txContext = core.NewEVMTxContext(msg)
vmenv = vm.NewEVM(vmctx, txContext, statedb, nil, chainConfig, vm.Config{})
)
evm.SetTxContext(txContext)
statedb.SetTxContext(tx.Hash(), i)
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit), common.Address{}); err != nil {
if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit), common.Address{}); err != nil {
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
// return the roots. Most likely, the caller already knows that a certain transaction fails to
@ -587,9 +588,9 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
defer release()
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
evm := vm.NewEVM(blockCtx, statedb, nil, api.backend.ChainConfig(), vm.Config{})
if api.backend.ChainConfig().IsPrague(block.Number()) {
vmenv := vm.NewEVM(blockCtx, vm.TxContext{}, statedb, nil, api.backend.ChainConfig(), vm.Config{})
core.ProcessParentBlockHash(block.ParentHash(), vmenv, statedb)
core.ProcessParentBlockHash(block.ParentHash(), evm, statedb)
}
// JS tracers have high overhead. In this case run a parallel
@ -692,6 +693,8 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
feeCapacity := statedb.GetTRC21FeeCapacityFromState()
var failed error
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
evm := vm.NewEVM(blockCtx, statedb, nil, api.backend.ChainConfig(), vm.Config{})
txloop:
for i, tx := range txs {
// Send the trace task over for execution
@ -717,14 +720,14 @@ txloop:
header := block.Header()
msg, _ := core.TransactionToMessage(tx, signer, balance, header.Number, header.BaseFee)
statedb.SetTxContext(tx.Hash(), i)
vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, nil, api.backend.ChainConfig(), vm.Config{})
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit), common.Address{}); err != nil {
evm.SetTxContext(core.NewEVMTxContext(msg))
if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit), common.Address{}); err != nil {
failed = err
break txloop
}
// 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
statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
statedb.Finalise(evm.ChainConfig().IsEIP158(block.Number()))
}
close(jobs)
@ -894,7 +897,8 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
}
}
// The actual TxContext will be created as part of ApplyTransactionWithEVM.
vmenv := vm.NewEVM(vmctx, vm.TxContext{GasPrice: message.GasPrice}, statedb, nil, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true})
evm := vm.NewEVM(vmctx, statedb, nil, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true})
evm.SetTxContext(vm.TxContext{GasPrice: message.GasPrice})
// Define a meaningful timeout of a single transaction trace
if config.Timeout != nil {
@ -908,7 +912,7 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
if errors.Is(deadlineCtx.Err(), context.DeadlineExceeded) {
tracer.Stop(errors.New("execution timeout"))
// Stop evm execution. Note cancellation is not necessarily immediate.
vmenv.Cancel()
evm.Cancel()
}
}()
defer cancel()
@ -923,7 +927,7 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
// Call SetTxContext to clear out the statedb access list
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, balance, common.Address{})
_, _, _, err = core.ApplyTransactionWithEVM(message, api.backend.ChainConfig(), new(core.GasPool).AddGas(message.GasLimit), statedb, vmctx.BlockNumber, txctx.BlockHash, tx, &usedGas, evm, balance, common.Address{})
if err != nil {
return nil, fmt.Errorf("tracing failed: %w", err)
}

View file

@ -174,18 +174,19 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block
}
// Recompute transactions up to the target index.
signer := types.MakeSigner(b.chainConfig, block.Number())
context := core.NewEVMBlockContext(block.Header(), b.chain, nil)
evm := vm.NewEVM(context, statedb, nil, b.chainConfig, vm.Config{})
for idx, tx := range block.Transactions() {
msg, _ := core.TransactionToMessage(tx, signer, nil, block.Number(), block.BaseFee())
txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(block.Header(), b.chain, nil)
if idx == txIndex {
return tx, context, statedb, release, nil
}
vmenv := vm.NewEVM(context, txContext, statedb, nil, b.chainConfig, vm.Config{})
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas()), common.Address{}); err != nil {
msg, _ := core.TransactionToMessage(tx, signer, nil, block.Number(), block.BaseFee())
txContext := core.NewEVMTxContext(msg)
evm.SetTxContext(txContext)
if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()), common.Address{}); err != nil {
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())
}

View file

@ -142,7 +142,8 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
}
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), logState, nil, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
evm := vm.NewEVM(context, logState, nil, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
evm.SetTxContext(core.NewEVMTxContext(msg))
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()), common.Address{})
if err != nil {
@ -228,13 +229,17 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
state := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc)
b.ReportAllocs()
evm := vm.NewEVM(context, state, nil, test.Genesis.Config, vm.Config{})
evm.SetTxContext(txContext)
for b.Loop() {
snap := state.Snapshot()
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, nil, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
snap := state.Snapshot()
evm.Config.Tracer = tracer.Hooks
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if _, err = st.TransitionDb(common.Address{}); err != nil {
b.Fatalf("failed to execute transaction: %v", err)
@ -379,7 +384,8 @@ func TestInternals(t *testing.T) {
Origin: origin,
GasPrice: tx.GasPrice(),
}
evm := vm.NewEVM(context, txContext, logState, nil, config, vm.Config{Tracer: tc.tracer.Hooks})
evm := vm.NewEVM(context, logState, nil, config, vm.Config{Tracer: tc.tracer.Hooks})
evm.SetTxContext(txContext)
msg, err := core.TransactionToMessage(tx, signer, nil, nil, big.NewInt(0))
if err != nil {
t.Fatalf("test %v: failed to create message: %v", tc.name, err)
@ -459,7 +465,8 @@ func testContractTracer(tracerName string, dirPath string, t *testing.T) {
if err != nil {
t.Fatalf("failed to create call tracer: %v", err)
}
evm := vm.NewEVM(context, txContext, state, nil, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
evm := vm.NewEVM(context, state, nil, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
evm.SetTxContext(txContext)
msg, err := core.TransactionToMessage(tx, signer, nil, nil, nil)
if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err)

View file

@ -105,7 +105,8 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
if err != nil {
return fmt.Errorf("failed to prepare transaction for tracing: %v", err)
}
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), state, nil, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
evm := vm.NewEVM(context, state, nil, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
evm.SetTxContext(core.NewEVMTxContext(msg))
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()), common.Address{})
if err != nil {

View file

@ -114,7 +114,8 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
}
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), state, nil, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
evm := vm.NewEVM(context, state, nil, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
evm.SetTxContext(core.NewEVMTxContext(msg))
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()), common.Address{})
if err != nil {

View file

@ -51,12 +51,13 @@ func testCtx() *vmContext {
func runTrace(tracer *tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig, contractCode []byte) (json.RawMessage, error) {
var (
evm = vm.NewEVM(vmctx.ctx, vmctx.txContext, &dummyStatedb{}, nil, chaincfg, vm.Config{Tracer: tracer.Hooks})
evm = vm.NewEVM(vmctx.ctx, &dummyStatedb{}, nil, chaincfg, vm.Config{Tracer: tracer.Hooks})
gasLimit uint64 = 31000
startGas uint64 = 10000
value = new(uint256.Int)
contract = vm.NewContract(common.Address{}, common.Address{}, value, startGas, nil)
)
evm.SetTxContext(vmctx.txContext)
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
if contractCode != nil {
contract.Code = contractCode
@ -178,8 +179,9 @@ func TestHaltBetweenSteps(t *testing.T) {
scope := &vm.ScopeContext{
Contract: vm.NewContract(common.Address{}, common.Address{}, new(uint256.Int), 0, nil),
}
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(1)}, &dummyStatedb{}, nil, chainConfig, vm.Config{Tracer: tracer.Hooks})
tracer.OnTxStart(env.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{})
evm := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, nil, chainConfig, vm.Config{Tracer: tracer.Hooks})
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.OnOpcode(0, 0, 0, 0, scope, nil, 0, nil)
timeout := errors.New("stahp")
@ -201,8 +203,9 @@ func TestNoStepExec(t *testing.T) {
if err != nil {
t.Fatal(err)
}
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100)}, &dummyStatedb{}, nil, chainConfig, vm.Config{Tracer: tracer.Hooks})
tracer.OnTxStart(env.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{})
evm := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, nil, chainConfig, vm.Config{Tracer: tracer.Hooks})
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.OnExit(0, nil, 0, nil, false)
ret, err := tracer.GetResult()

View file

@ -42,7 +42,7 @@ func (*dummyStatedb) SetState(_ common.Address, _ common.Hash, _ common.Hash) co
func TestStoreCapture(t *testing.T) {
var (
logger = NewStructLogger(nil)
evm = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, &dummyStatedb{}, nil, params.TestChainConfig, vm.Config{Tracer: logger.Hooks()})
evm = vm.NewEVM(vm.BlockContext{}, &dummyStatedb{}, nil, params.TestChainConfig, vm.Config{Tracer: logger.Hooks()})
contract = vm.NewContract(common.Address{}, common.Address{}, new(uint256.Int), 100000, nil)
)
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)}

View file

@ -88,7 +88,8 @@ func BenchmarkTransactionTrace(b *testing.B) {
//EnableMemory: false,
//EnableReturnData: false,
})
evm := vm.NewEVM(context, txContext, state, nil, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer.Hooks()})
evm := vm.NewEVM(context, state, nil, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer.Hooks()})
evm.SetTxContext(txContext)
msg, err := core.TransactionToMessage(tx, signer, nil, nil, context.BaseFee)
if err != nil {
b.Fatalf("failed to prepare transaction for tracing: %v", err)

View file

@ -1274,7 +1274,8 @@ func applyMessage(ctx context.Context, b Backend, args TransactionArgs, state *s
if msg.GasPrice.Sign() == 0 {
blockContext.BaseFee = new(big.Int)
}
evm, vmError, err := b.GetEVM(ctx, msg, state, XDCxState, header, vmConfig, blockContext)
state.SetBalance(msg.From, math.MaxBig256, tracing.BalanceChangeUnspecified)
evm, vmError, err := b.GetEVM(ctx, state, XDCxState, header, vmConfig, blockContext)
if err != nil {
return nil, err
}
@ -1284,7 +1285,7 @@ func applyMessage(ctx context.Context, b Backend, args TransactionArgs, state *s
if precompiles != nil {
evm.SetPrecompiles(precompiles)
}
evm.SetTxContext(core.NewEVMTxContext(msg))
res, err := applyMessageWithEVM(ctx, evm, msg, timeout, gp)
// 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"
@ -1888,16 +1889,18 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
// Apply the transaction with the access list tracer
tracer := logger.NewAccessListTracer(accessList, args.from(), to, precompiles)
config := vm.Config{Tracer: tracer.Hooks(), NoBaseFee: true}
vmenv, _, err := b.GetEVM(ctx, msg, statedb, XDCxState, header, &config, nil)
statedb.SetBalance(msg.From, math.MaxBig256, tracing.BalanceChangeUnspecified)
evm, _, err := b.GetEVM(ctx, statedb, XDCxState, header, &config, nil)
if err != nil {
return nil, 0, nil, err
}
// Lower the basefee to 0 to avoid breaking EVM
// invariants (basefee < feecap).
if msg.GasPrice.Sign() == 0 {
vmenv.Context.BaseFee = new(big.Int)
evm.Context.BaseFee = new(big.Int)
}
res, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit), common.Address{})
evm.SetTxContext(core.NewEVMTxContext(msg))
res, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit), common.Address{})
if err != nil {
return nil, 0, nil, fmt.Errorf("failed to apply transaction: %v err: %v", args.ToTransaction(types.LegacyTxType).Hash(), err)
}

View file

@ -75,7 +75,7 @@ type Backend interface {
PendingBlockAndReceipts() (*types.Block, types.Receipts)
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
GetTd(ctx context.Context, hash common.Hash) *big.Int
GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, XDCxState *tradingstate.TradingStateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error, error)
GetEVM(ctx context.Context, state *state.StateDB, XDCxState *tradingstate.TradingStateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error, error)
SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription

View file

@ -175,12 +175,12 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
NoBaseFee: !sim.validate,
Tracer: tracer.Hooks(),
}
evm = vm.NewEVM(blockContext, vm.TxContext{GasPrice: new(big.Int)}, sim.state, nil, sim.chainConfig, *vmConfig)
)
var tracingStateDB = vm.StateDB(sim.state)
if hooks := tracer.Hooks(); hooks != nil {
tracingStateDB = state.NewHookedState(sim.state, hooks)
}
evm := vm.NewEVM(blockContext, tracingStateDB, nil, sim.chainConfig, *vmConfig)
// It is possible to override precompiles with EVM bytecode, or
// move them to another address.
if precompiles != nil {
@ -198,7 +198,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
tracer.reset(tx.Hash(), uint(i))
// EoA check is always skipped, even in validation mode.
msg := call.ToMessage(sim.b, 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)
if err != nil {
txErr := txValidationError(err)

View file

@ -349,7 +349,7 @@ func (b *backendMock) GetTd(ctx context.Context, hash common.Hash) *big.Int {
return nil
}
func (b *backendMock) GetEVM(context.Context, *core.Message, *state.StateDB, *tradingstate.TradingStateDB, *types.Header, *vm.Config, *vm.BlockContext) (*vm.EVM, func() error, error) {
func (b *backendMock) GetEVM(context.Context, *state.StateDB, *tradingstate.TradingStateDB, *types.Header, *vm.Config, *vm.BlockContext) (*vm.EVM, func() error, error) {
return nil, nil, nil
}

View file

@ -86,14 +86,15 @@ type Agent interface {
type Work struct {
config *params.ChainConfig
signer types.Signer
state *state.StateDB // apply state changes here
tcount int // tx count in cycle
evm *vm.EVM
state *state.StateDB // apply state changes here
parentState *state.StateDB
tradingState *tradingstate.TradingStateDB
lendingState *lendingstate.LendingStateDB
ancestors mapset.Set[common.Hash] // ancestor set (used for checking uncle parent validity)
family mapset.Set[common.Hash] // family set (used for checking uncle invalidity)
tcount int // tx count in cycle
Block *types.Block // the new block
@ -636,6 +637,7 @@ func (w *worker) makeCurrent(parent *types.Block, header *types.Header) error {
ancestors: mapset.NewSet[common.Hash](),
family: mapset.NewSet[common.Hash](),
header: header,
evm: vm.NewEVM(core.NewEVMBlockContext(header, w.chain, &header.Coinbase), state, XDCxState, w.config, vm.Config{}),
uncles: make(map[common.Hash]*types.Header),
createdAt: time.Now(),
}
@ -788,9 +790,7 @@ func (w *worker) commitNewWork() {
work.state.DeleteAddress(common.BlockSignersBinary)
}
if w.config.IsPrague(header.Number) {
context := core.NewEVMBlockContext(header, w.chain, nil)
vmenv := vm.NewEVM(context, vm.TxContext{}, w.current.state, nil, w.config, vm.Config{})
core.ProcessParentBlockHash(header.ParentHash, vmenv, w.current.state)
core.ProcessParentBlockHash(header.ParentHash, work.evm, work.state)
}
// won't grasp txs at checkpoint
var (
@ -1049,7 +1049,7 @@ func (w *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Addr
log.Trace("Skipping account with special transaction invalid nonce", "sender", from, "nonce", nonce, "tx nonce ", tx.Nonce(), "to", to)
continue
}
logs, tokenFeeUsed, gas, err := w.commitTransaction(balanceFee, tx, bc, coinbase, gp)
logs, tokenFeeUsed, gas, err := w.commitTransaction(balanceFee, tx, gp)
switch {
case errors.Is(err, core.ErrNonceTooLow):
// New head notification data race between the transaction pool and miner, shift
@ -1159,7 +1159,7 @@ func (w *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Addr
txs.Pop()
continue
}
logs, tokenFeeUsed, gas, err := w.commitTransaction(balanceFee, tx, bc, coinbase, gp)
logs, tokenFeeUsed, gas, err := w.commitTransaction(balanceFee, tx, gp)
switch {
case errors.Is(err, core.ErrGasLimitReached):
// Pop the current out-of-gas transaction without shifting in the next from the account
@ -1222,10 +1222,10 @@ func (w *Work) commitTransactions(mux *event.TypeMux, balanceFee map[common.Addr
}
}
func (w *Work) commitTransaction(balanceFee map[common.Address]*big.Int, tx *types.Transaction, bc *core.BlockChain, coinbase common.Address, gp *core.GasPool) ([]*types.Log, bool, uint64, error) {
func (w *Work) commitTransaction(balanceFee map[common.Address]*big.Int, tx *types.Transaction, gp *core.GasPool) ([]*types.Log, bool, uint64, error) {
snap := w.state.Snapshot()
receipt, gas, tokenFeeUsed, err := core.ApplyTransaction(w.config, balanceFee, bc, &coinbase, gp, w.state, w.tradingState, w.header, tx, &w.header.GasUsed, vm.Config{})
receipt, gas, tokenFeeUsed, err := core.ApplyTransaction(w.config, balanceFee, w.evm, gp, w.state, w.header, tx, &w.header.GasUsed)
if err != nil {
w.state.RevertToSnapshot(snap)
return nil, false, 0, err

View file

@ -182,7 +182,8 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config) (*state.StateD
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
context.GetHash = vmTestBlockHash
context.BaseFee = baseFee
evm := vm.NewEVM(context, txContext, statedb, nil, config, vmconfig)
evm := vm.NewEVM(context, statedb, nil, config, vmconfig)
evm.SetTxContext(txContext)
// Execute the message.
snapshot := statedb.Snapshot()

View file

@ -148,7 +148,9 @@ func (t *VMTest) newEVM(statedb *state.StateDB, vmconfig vm.Config) *vm.EVM {
GasLimit: t.json.Env.GasLimit,
Difficulty: t.json.Env.Difficulty,
}
return vm.NewEVM(context, txContext, statedb, nil, params.MainnetChainConfig, vmconfig)
evm := vm.NewEVM(context, statedb, nil, params.MainnetChainConfig, vmconfig)
evm.SetTxContext(txContext)
return evm
}
func vmTestBlockHash(n uint64) common.Hash {