all: split vm.Context into BlockContext and TxContext (#21672)

This commit is contained in:
Daniel Liu 2024-09-16 15:52:59 +08:00 committed by Daniel Liu
parent 05e52efbad
commit 5470485450
23 changed files with 231 additions and 156 deletions

View file

@ -379,10 +379,12 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call XDPoSChain.Cal
msg.CallMsg.BalanceTokenFee = value
}
}
evmContext := core.NewEVMContext(msg, block.Header(), b.blockchain, nil)
txContext := core.NewEVMTxContext(msg)
evmContext := core.NewEVMBlockContext(block.Header(), b.blockchain, nil)
// Create a new environment which holds all relevant information
// about the transaction and calling mechanisms.
vmenv := vm.NewEVM(evmContext, statedb, nil, b.config, vm.Config{})
vmenv := vm.NewEVM(evmContext, txContext, statedb, nil, b.config, vm.Config{})
gaspool := new(core.GasPool).AddGas(math.MaxUint64)
owner := common.Address{}
ret, usedGas, failed, err, _ = core.NewStateTransition(vmenv, msg, gaspool).TransitionDb(owner)

View file

@ -26,8 +26,8 @@ import (
"github.com/XinFinOrg/XDPoSChain/crypto"
)
// NewEVMContext creates a new context for use in the EVM.
func NewEVMContext(msg Message, header *types.Header, chain consensus.ChainContext, author *common.Address) vm.Context {
// NewEVMBlockContext creates a new context for use in the EVM.
func NewEVMBlockContext(header *types.Header, chain consensus.ChainContext, author *common.Address) vm.BlockContext {
// If we don't have an explicit author (i.e. not mining), extract from the header
var (
beneficiary common.Address
@ -40,21 +40,27 @@ func NewEVMContext(msg Message, header *types.Header, chain consensus.ChainConte
}
// since xdpos chain do not use difficulty and mixdigest, we use hash of the block number as random
random = crypto.Keccak256Hash(header.Number.Bytes())
return vm.Context{
return vm.BlockContext{
CanTransfer: CanTransfer,
Transfer: Transfer,
GetHash: GetHashFn(header, chain),
Origin: msg.From(),
Coinbase: beneficiary,
BlockNumber: new(big.Int).Set(header.Number),
Time: new(big.Int).Set(header.Time),
Difficulty: new(big.Int).Set(header.Difficulty),
GasLimit: header.GasLimit,
GasPrice: new(big.Int).Set(msg.GasPrice()),
Random: &random,
}
}
// NewEVMTxContext creates a new transaction context for a single transaction.
func NewEVMTxContext(msg Message) vm.TxContext {
return vm.TxContext{
Origin: msg.From(),
GasPrice: new(big.Int).Set(msg.GasPrice()),
}
}
// GetHashFn returns a GetHashFunc which retrieves header hashes by number
func GetHashFn(ref *types.Header, chain consensus.ChainContext) func(n uint64) common.Hash {
// Cache will initially contain [refHash.parent],

View file

@ -86,6 +86,9 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, tra
InitSignerInTransactions(p.config, header, block.Transactions())
balanceUpdated := map[common.Address]*big.Int{}
totalFeeUsed := big.NewInt(0)
blockContext := NewEVMBlockContext(header, p.bc, nil)
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, tradingState, p.config, cfg)
// Iterate over and process the individual transactions
for i, tx := range block.Transactions() {
// check black-list txs after hf
if (block.Number().Uint64() >= common.BlackListHFNumber) && !common.IsTestnet {
@ -113,7 +116,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, tra
}
}
statedb.Prepare(tx.Hash(), block.Hash(), i)
receipt, gas, err, tokenFeeUsed := ApplyTransaction(p.config, balanceFee, p.bc, nil, gp, statedb, tradingState, header, tx, usedGas, cfg)
receipt, gas, err, tokenFeeUsed := applyTransaction(p.config, balanceFee, p.bc, nil, gp, statedb, tradingState, header, tx, usedGas, vmenv)
if err != nil {
return nil, nil, 0, err
}
@ -159,6 +162,8 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
if cBlock.stop {
return nil, nil, 0, ErrStopPreparingBlock
}
blockContext := NewEVMBlockContext(header, p.bc, nil)
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, tradingState, p.config, cfg)
// Iterate over and process the individual transactions
receipts = make([]*types.Receipt, block.Transactions().Len())
for i, tx := range block.Transactions() {
@ -188,7 +193,7 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
}
}
statedb.Prepare(tx.Hash(), block.Hash(), i)
receipt, gas, err, tokenFeeUsed := ApplyTransaction(p.config, balanceFee, p.bc, nil, gp, statedb, tradingState, header, tx, usedGas, cfg)
receipt, gas, err, tokenFeeUsed := applyTransaction(p.config, balanceFee, p.bc, nil, gp, statedb, tradingState, header, tx, usedGas, vmenv)
if err != nil {
return nil, nil, 0, err
}
@ -210,11 +215,7 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
return receipts, allLogs, *usedGas, nil
}
// ApplyTransaction attempts to apply a transaction to the given state database
// 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, error, bool) {
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, evm *vm.EVM) (*types.Receipt, uint64, error, bool) {
to := tx.To()
if to != nil && *to == common.BlockSignersBinary && config.IsTIPSigning(header.Number) {
return ApplySignTransaction(config, statedb, header, tx, usedGas)
@ -243,11 +244,12 @@ func ApplyTransaction(config *params.ChainConfig, tokensFee map[common.Address]*
if err != nil {
return nil, 0, err, false
}
// Create a new context to be used in the EVM environment.
context := NewEVMContext(msg, header, bc, author)
// Create a new environment which holds all relevant information
// about the transaction and calling mechanisms.
vmenv := vm.NewEVM(context, statedb, XDCxState, config, cfg)
// Create a new context to be used in the EVM environment
txContext := NewEVMTxContext(msg)
// Update the evm with the new transaction context.
evm.Reset(txContext, statedb)
// If we don't have an explicit author (i.e. not mining), extract from the header
var beneficiary common.Address
@ -404,7 +406,7 @@ func ApplyTransaction(config *params.ChainConfig, tokensFee map[common.Address]*
// End Bypass blacklist address
// Apply the transaction to the current state (included in the env)
_, gas, failed, err, _ := ApplyMessage(vmenv, msg, gp, coinbaseOwner)
_, gas, failed, err, _ := ApplyMessage(evm, msg, gp, coinbaseOwner)
if err != nil {
return nil, 0, err, false
@ -432,7 +434,7 @@ func ApplyTransaction(config *params.ChainConfig, tokensFee map[common.Address]*
// If the transaction created a contract, store the creation address in the receipt.
if msg.To() == nil {
receipt.ContractAddress = crypto.CreateAddress(vmenv.Context.Origin, tx.Nonce())
receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
}
// Set the receipt logs and create the bloom filter.
@ -447,6 +449,17 @@ func ApplyTransaction(config *params.ChainConfig, tokensFee map[common.Address]*
return receipt, gas, err, balanceFee != nil
}
// ApplyTransaction attempts to apply a transaction to the given state database
// 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, error, bool) {
// 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)
return applyTransaction(config, tokensFee, bc, author, gp, statedb, XDCxState, header, tx , usedGas, vmenv)
}
func ApplySignTransaction(config *params.ChainConfig, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64) (*types.Receipt, uint64, error, bool) {
// Update the state with pending changes
var root []byte

View file

@ -216,16 +216,37 @@ func (st *StateTransition) preCheck() error {
}
// TransitionDb will transition the state by applying the current message and
// returning the result including the the used gas. It returns an error if it
// failed. An error indicates a consensus issue.
// returning the evm execution result with following fields.
//
// - used gas:
// total gas used (including gas being refunded)
// - returndata:
// the returned data from evm
// - concrete execution error:
// various **EVM** error which aborts the execution,
// e.g. ErrOutOfGas, ErrExecutionReverted
//
// However if any consensus issue encountered, return the error directly with
// nil evm execution result.
func (st *StateTransition) TransitionDb(owner common.Address) (ret []byte, usedGas uint64, failed bool, err error, vmErr error) {
// First check this message satisfies all consensus rules before
// applying the message. The rules include these clauses
//
// 1. the nonce of the message caller is correct
// 2. caller has enough balance to cover transaction fee(gaslimit * gasprice)
// 3. the amount of gas required is available in the block
// 4. the purchased gas is enough to cover intrinsic usage
// 5. there is no overflow when calculating intrinsic gas
// 6. caller has enough balance to cover asset transfer for **topmost** call
// Check clauses 1-3, buy gas if everything is correct
if err = st.preCheck(); err != nil {
return
}
msg := st.msg
sender := st.from() // err checked in preCheck
homestead := st.evm.ChainConfig().IsHomestead(st.evm.BlockNumber)
homestead := st.evm.ChainConfig().IsHomestead(st.evm.Context.BlockNumber)
contractCreation := msg.To() == nil
// Pay intrinsic gas
@ -274,12 +295,12 @@ func (st *StateTransition) TransitionDb(owner common.Address) (ret []byte, usedG
}
st.refundGas()
if st.evm.BlockNumber.Cmp(common.TIPTRC21Fee) > 0 {
if st.evm.Context.BlockNumber.Cmp(common.TIPTRC21Fee) > 0 {
if (owner != common.Address{}) {
st.state.AddBalance(owner, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
}
} else {
st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
st.state.AddBalance(st.evm.Context.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
}
return ret, st.gasUsed(), vmerr != nil, nil, vmerr

View file

@ -108,10 +108,11 @@ func CallContractWithState(call ethereum.CallMsg, chain consensus.ChainContext,
msg.CallMsg.BalanceTokenFee = value
}
}
evmContext := NewEVMContext(msg, chain.CurrentHeader(), chain, nil)
txContext := NewEVMTxContext(msg)
evmContext := NewEVMBlockContext(chain.CurrentHeader(), chain, nil)
// Create a new environment which holds all relevant information
// about the transaction and calling mechanisms.
vmenv := vm.NewEVM(evmContext, statedb, nil, chain.Config(), vm.Config{})
vmenv := vm.NewEVM(evmContext, txContext, statedb, nil, chain.Config(), vm.Config{})
gaspool := new(GasPool).AddGas(1000000)
owner := common.Address{}
rval, _, _, err, _ := NewStateTransition(vmenv, msg, gaspool).TransitionDb(owner)

View file

@ -519,7 +519,7 @@ func testXDCxPrecompiled(addr string, test precompiledTest, t *testing.T) {
tradingStateDB.SetLastPrice(tradingstate.GetTradingOrderBookHash(common.HexToAddress(BTCAddress), common.HexToAddress(USDTAddress)), BTCUSDTLastPrice)
tradingStateDB.SetMediumPriceBeforeEpoch(tradingstate.GetTradingOrderBookHash(common.HexToAddress(BTCAddress), common.HexToAddress(USDTAddress)), BTCUSDTEpochPrice)
evm := NewEVM(Context{BlockNumber: common.Big1}, nil, tradingStateDB, &params.ChainConfig{ByzantiumBlock: common.Big0}, Config{})
evm := NewEVM(BlockContext{BlockNumber: common.Big1}, TxContext{}, nil, tradingStateDB, &params.ChainConfig{ByzantiumBlock: common.Big0}, Config{})
contractAddr := common.HexToAddress(addr)
p := PrecompiledContractsByzantium[contractAddr]
in := common.Hex2Bytes(test.input)
@ -536,7 +536,7 @@ func testXDCxPrecompiled(addr string, test precompiledTest, t *testing.T) {
}
func testPrecompiledWithEmptyTradingState(addr string, test precompiledTest, t *testing.T) {
evm := NewEVM(Context{BlockNumber: common.Big1}, nil, nil, &params.ChainConfig{ByzantiumBlock: common.Big0}, Config{})
evm := NewEVM(BlockContext{BlockNumber: common.Big1}, TxContext{}, nil, nil, &params.ChainConfig{ByzantiumBlock: common.Big0}, Config{})
contractAddr := common.HexToAddress(addr)
p := PrecompiledContractsByzantium[contractAddr]

View file

@ -63,7 +63,7 @@ func (evm *EVM) precompile2(addr common.Address) (PrecompiledContract, bool) {
switch {
case evm.chainRules.IsXDCxDisable:
precompiles = PrecompiledContractsXDCv2
case evm.chainRules.IsIstanbul && evm.ChainConfig().IsTIPXDCXCancellationFee(evm.BlockNumber):
case evm.chainRules.IsIstanbul && evm.ChainConfig().IsTIPXDCXCancellationFee(evm.Context.BlockNumber):
precompiles = PrecompiledContractsIstanbul
case evm.chainRules.IsByzantium:
precompiles = PrecompiledContractsByzantium
@ -78,7 +78,7 @@ func (evm *EVM) precompile2(addr common.Address) (PrecompiledContract, bool) {
func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, error) {
if contract.CodeAddr != nil {
if p, isPrecompile := evm.precompile(*contract.CodeAddr); isPrecompile {
if evm.chainConfig.IsTIPXDCXReceiver(evm.BlockNumber) {
if evm.chainConfig.IsTIPXDCXReceiver(evm.Context.BlockNumber) {
switch p := p.(type) {
case *XDCxEpochPrice:
p.SetTradingState(evm.tradingStateDB)
@ -89,7 +89,7 @@ func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, err
return RunPrecompiledContract(p, input, contract)
}
}
if evm.ChainConfig().IsTIPXDCXCancellationFee(evm.BlockNumber) {
if evm.ChainConfig().IsTIPXDCXCancellationFee(evm.Context.BlockNumber) {
for _, interpreter := range evm.interpreters {
if interpreter.CanRun(contract.Code) {
if evm.interpreter != interpreter {
@ -110,9 +110,9 @@ func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, err
return nil, errors.New("no compatible interpreter")
}
// Context provides the EVM with auxiliary information. Once provided
// BlockContext provides the EVM with auxiliary information. Once provided
// it shouldn't be modified.
type Context struct {
type BlockContext struct {
// CanTransfer returns whether the account contains
// sufficient ether to transfer the value
CanTransfer CanTransferFunc
@ -121,10 +121,6 @@ type Context struct {
// GetHash returns the hash corresponding to n
GetHash GetHashFunc
// Message information
Origin common.Address // Provides information for ORIGIN
GasPrice *big.Int // Provides information for GASPRICE
// Block information
Coinbase common.Address // Provides information for COINBASE
GasLimit uint64 // Provides information for GASLIMIT
@ -134,6 +130,14 @@ type Context struct {
Random *common.Hash // Provides information for PREVRANDAO
}
// TxContext provides the EVM with information about a transaction.
// All fields can change between transactions.
type TxContext struct {
// Message information
Origin common.Address // Provides information for ORIGIN
GasPrice *big.Int // Provides information for GASPRICE
}
// EVM is the Ethereum Virtual Machine base object and provides
// the necessary tools to run a contract on the given state with
// the provided context. It should be noted that any error
@ -144,8 +148,9 @@ type Context struct {
//
// The EVM should never be reused and is not thread safe.
type EVM struct {
// Context provides auxiliary blockchain related information
Context
// BlockContext provides auxiliary blockchain related information
Context BlockContext
TxContext
// StateDB gives access to the underlying state
StateDB StateDB
@ -176,14 +181,15 @@ type EVM struct {
// NewEVM returns a new EVM. The returned EVM is not thread safe and should
// only ever be used *once*.
func NewEVM(ctx Context, statedb StateDB, tradingStateDB *tradingstate.TradingStateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, tradingStateDB *tradingstate.TradingStateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
evm := &EVM{
Context: ctx,
Context: blockCtx,
TxContext: txCtx,
StateDB: statedb,
tradingStateDB: tradingStateDB,
vmConfig: vmConfig,
chainConfig: chainConfig,
chainRules: chainConfig.Rules(ctx.BlockNumber),
chainRules: chainConfig.Rules(blockCtx.BlockNumber),
interpreters: make([]Interpreter, 0, 1),
}
@ -195,6 +201,13 @@ func NewEVM(ctx Context, statedb StateDB, tradingStateDB *tradingstate.TradingSt
return evm
}
// Reset resets the EVM with a new transaction context.Reset
// This is not threadsafe and should only be done very cautiously.
func (evm *EVM) Reset(txCtx TxContext, statedb StateDB) {
evm.TxContext = txCtx
evm.StateDB = statedb
}
// Cancel cancels any running EVM operation. This may be called concurrently and
// it's safe to be called multiple times.
func (evm *EVM) Cancel() {
@ -245,7 +258,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
}
evm.StateDB.CreateAccount(addr)
}
evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
evm.Context.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
// Capture the tracer start/end events in debug mode
if evm.vmConfig.Debug {
@ -390,7 +403,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
contract := NewContract(caller, to, new(big.Int), gas)
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
if evm.ChainConfig().IsTIPXDCXCancellationFee(evm.BlockNumber) {
if evm.ChainConfig().IsTIPXDCXCancellationFee(evm.Context.BlockNumber) {
// We do an AddBalance of zero here, just in order to trigger a touch.
// This doesn't matter on Mainnet, where all empties are gone at the time of Byzantium,
// but is the correct thing to do and matters on other networks, in tests, and potential
@ -409,7 +422,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally
// when we're in Homestead this also counts for code storage gas errors.
ret, err = run(evm, contract, input, evm.ChainConfig().IsTIPXDCXCancellationFee(evm.BlockNumber))
ret, err = run(evm, contract, input, evm.ChainConfig().IsTIPXDCXCancellationFee(evm.Context.BlockNumber))
gas = contract.Gas
if err != nil {
evm.StateDB.RevertToSnapshot(snapshot)
@ -439,7 +452,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
if evm.depth > int(params.CallCreateDepth) {
return nil, common.Address{}, gas, ErrDepth
}
if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
return nil, common.Address{}, gas, ErrInsufficientBalance
}
nonce := evm.StateDB.GetNonce(caller.Address())
@ -463,7 +476,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
if evm.chainRules.IsEIP158 {
evm.StateDB.SetNonce(address, 1)
}
evm.Transfer(evm.StateDB, caller.Address(), address, value)
evm.Context.Transfer(evm.StateDB, caller.Address(), address, value)
// Initialise a new contract and set the code that is to be used by the EVM.
// The contract is a scoped environment for this execution context only.

View file

@ -88,11 +88,11 @@ func TestEIP2200(t *testing.T) {
statedb.SetState(address, common.Hash{}, common.BytesToHash([]byte{tt.original}))
statedb.Finalise(true) // Push the state into the "original" slot
vmctx := Context{
vmctx := BlockContext{
CanTransfer: func(StateDB, common.Address, *big.Int) bool { return true },
Transfer: func(StateDB, common.Address, common.Address, *big.Int) {},
}
vmenv := NewEVM(vmctx, statedb, nil, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
vmenv := NewEVM(vmctx, TxContext{}, statedb, nil, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
_, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(big.Int))
if err != tt.failure {

View file

@ -447,14 +447,14 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
return nil, nil
}
var upper, lower uint64
upper = interpreter.evm.BlockNumber.Uint64()
upper = interpreter.evm.Context.BlockNumber.Uint64()
if upper < 257 {
lower = 0
} else {
lower = upper - 256
}
if num64 >= lower && num64 < upper {
num.SetBytes(interpreter.evm.GetHash(num64).Bytes())
num.SetBytes(interpreter.evm.Context.GetHash(num64).Bytes())
} else {
num.Clear()
}
@ -462,24 +462,24 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
}
func opCoinbase(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.push(new(uint256.Int).SetBytes(interpreter.evm.Coinbase.Bytes()))
scope.Stack.push(new(uint256.Int).SetBytes(interpreter.evm.Context.Coinbase.Bytes()))
return nil, nil
}
func opTimestamp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
v, _ := uint256.FromBig(interpreter.evm.Time)
v, _ := uint256.FromBig(interpreter.evm.Context.Time)
scope.Stack.push(v)
return nil, nil
}
func opNumber(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
v, _ := uint256.FromBig(interpreter.evm.BlockNumber)
v, _ := uint256.FromBig(interpreter.evm.Context.BlockNumber)
scope.Stack.push(v)
return nil, nil
}
func opDifficulty(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
v, _ := uint256.FromBig(interpreter.evm.Difficulty)
v, _ := uint256.FromBig(interpreter.evm.Context.Difficulty)
scope.Stack.push(v)
return nil, nil
}
@ -496,7 +496,7 @@ func opRandom(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
}
func opGasLimit(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.push(new(uint256.Int).SetUint64(interpreter.evm.GasLimit))
scope.Stack.push(new(uint256.Int).SetUint64(interpreter.evm.Context.GasLimit))
return nil, nil
}
@ -851,7 +851,7 @@ func makeLog(size int) executionFunc {
Data: d,
// This is a non-consensus field, but assigned here because
// core/state doesn't know the current block number.
BlockNumber: interpreter.evm.BlockNumber.Uint64(),
BlockNumber: interpreter.evm.Context.BlockNumber.Uint64(),
})
return nil, nil

View file

@ -95,7 +95,7 @@ func init() {
func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFunc, name string) {
var (
env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{})
env = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
pc = uint64(0)
evmInterpreter = env.interpreter.(*EVMInterpreter)
@ -194,7 +194,7 @@ func TestSAR(t *testing.T) {
func TestAddMod(t *testing.T) {
var (
env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{})
env = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
pc = uint64(0)
@ -233,7 +233,7 @@ func TestAddMod(t *testing.T) {
// getResult is a convenience function to generate the expected values
func getResult(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase {
var (
env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{})
env = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
pc = uint64(0)
interpreter = env.interpreter.(*EVMInterpreter)
@ -289,7 +289,7 @@ func TestJsonTestcases(t *testing.T) {
func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
var (
env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{})
env = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
)
@ -523,7 +523,7 @@ func BenchmarkOpIsZero(b *testing.B) {
func TestOpMstore(t *testing.T) {
var (
env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{})
env = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
mem = NewMemory()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
@ -549,7 +549,7 @@ func TestOpMstore(t *testing.T) {
func BenchmarkOpMstore(bench *testing.B) {
var (
env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{})
env = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
mem = NewMemory()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
@ -571,7 +571,7 @@ func BenchmarkOpMstore(bench *testing.B) {
func BenchmarkOpKeccak256(bench *testing.B) {
var (
env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{})
env = NewEVM(BlockContext{}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
mem = NewMemory()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
@ -676,7 +676,7 @@ func TestRandom(t *testing.T) {
{name: "hash(0x010203)", random: crypto.Keccak256Hash([]byte{0x01, 0x02, 0x03})},
} {
var (
env = NewEVM(Context{Random: &tt.random}, nil, nil, params.TestChainConfig, Config{})
env = NewEVM(BlockContext{Random: &tt.random}, TxContext{}, nil, nil, params.TestChainConfig, Config{})
stack = newstack()
pc = uint64(0)
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)

View file

@ -50,7 +50,7 @@ func (*dummyStatedb) GetRefund() uint64 { return 1337 }
func TestStoreCapture(t *testing.T) {
var (
env = NewEVM(Context{}, &dummyStatedb{}, nil, params.TestChainConfig, Config{})
env = NewEVM(BlockContext{}, TxContext{}, &dummyStatedb{}, nil, params.TestChainConfig, Config{})
logger = NewStructLogger(nil)
contract = NewContract(&dummyContractRef{}, &dummyContractRef{}, new(big.Int), 0)
scope = &ScopeContext{

View file

@ -22,18 +22,20 @@ import (
)
func NewEnv(cfg *Config) *vm.EVM {
context := vm.Context{
txContext := vm.TxContext{
Origin: cfg.Origin,
GasPrice: cfg.GasPrice,
}
blockContext := vm.BlockContext{
CanTransfer: core.CanTransfer,
Transfer: core.Transfer,
GetHash: cfg.GetHashFn,
Origin: cfg.Origin,
Coinbase: cfg.Coinbase,
BlockNumber: cfg.BlockNumber,
Time: cfg.Time,
Difficulty: cfg.Difficulty,
GasLimit: cfg.GasLimit,
GasPrice: cfg.GasPrice,
}
return vm.NewEVM(context, cfg.State, nil, cfg.ChainConfig, cfg.EVMConfig)
return vm.NewEVM(blockContext, txContext, cfg.State, nil, cfg.ChainConfig, cfg.EVMConfig)
}

View file

@ -258,8 +258,9 @@ func (b *EthApiBackend) GetEVM(ctx context.Context, msg core.Message, state *sta
vmConfig = b.eth.blockchain.GetVMConfig()
}
state.SetBalance(msg.From(), math.MaxBig256)
context := core.NewEVMContext(msg, header, b.eth.BlockChain(), nil)
return vm.NewEVM(context, state, XDCxState, b.eth.chainConfig, *vmConfig), vmError, nil
txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
return vm.NewEVM(context, txContext, state, XDCxState, b.eth.chainConfig, *vmConfig), vmError, nil
}
func (b *EthApiBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {

View file

@ -232,6 +232,7 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
// Fetch and execute the next block trace tasks
for task := range tasks {
signer := types.MakeSigner(api.config, task.block.Number())
blockCtx := core.NewEVMBlockContext(task.block.Header(), api.eth.blockchain, nil)
feeCapacity := state.GetTRC21FeeCapacityFromState(task.statedb)
// Trace all the transactions contained within
for i, tx := range task.block.Transactions() {
@ -247,9 +248,7 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl
TxIndex: i,
TxHash: tx.Hash(),
}
vmctx := core.NewEVMContext(msg, task.block.Header(), api.eth.blockchain, nil)
res, err := api.traceTx(ctx, msg, txctx, vmctx, task.statedb, config)
res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
if err != nil {
task.results[i] = &txTraceResult{Error: err.Error()}
log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
@ -473,11 +472,11 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
threads = len(txs)
}
blockHash := block.Hash()
blockCtx := core.NewEVMBlockContext(block.Header(), api.eth.blockchain, nil)
for th := 0; th < threads; th++ {
pend.Add(1)
go func() {
defer pend.Done()
// Fetch and execute the next transaction trace tasks
for task := range jobs {
feeCapacity := state.GetTRC21FeeCapacityFromState(task.statedb)
@ -493,9 +492,7 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
TxIndex: task.index,
TxHash: txs[task.index].Hash(),
}
vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
res, err := api.traceTx(ctx, msg, txctx, vmctx, task.statedb, config)
res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
if err != nil {
results[task.index] = &txTraceResult{Error: err.Error()}
continue
@ -522,10 +519,10 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
}
// Generate the next state snapshot fast without tracing
msg, _ := tx.AsMessage(signer, balacne, block.Number())
txContext := core.NewEVMTxContext(msg)
statedb.Prepare(tx.Hash(), block.Hash(), i)
vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
vmenv := vm.NewEVM(vmctx, statedb, XDCxState, api.config, vm.Config{})
vmenv := vm.NewEVM(blockCtx, txContext, statedb, XDCxState, api.config, vm.Config{})
owner := common.Address{}
if _, _, _, err, _ := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()), owner); err != nil {
failed = err
@ -693,7 +690,7 @@ func (api *PrivateDebugAPI) TraceCall(ctx context.Context, args ethapi.Transacti
}
// Execute the trace
msg := args.ToMessage(api.eth.ApiBackend, block.Number(), api.eth.ApiBackend.RPCGasCap())
vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
vmctx := core.NewEVMBlockContext(block.Header(), api.eth.blockchain, nil)
var traceConfig *TraceConfig
if config != nil {
traceConfig = &config.TraceConfig
@ -704,11 +701,12 @@ func (api *PrivateDebugAPI) TraceCall(ctx context.Context, args ethapi.Transacti
// traceTx configures a new tracer according to the provided configuration, and
// executes the given message in the provided environment. The return value will
// be tracer dependent.
func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, txctx *tracers.Context, vmctx vm.Context, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, txctx *tracers.Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
// Assemble the structured logger or the JavaScript tracer
var (
tracer vm.EVMLogger
err error
tracer vm.EVMLogger
err error
txContext = core.NewEVMTxContext(message)
)
switch {
case config == nil:
@ -739,7 +737,7 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, t
tracer = vm.NewStructLogger(config.LogConfig)
}
// Run the transaction with tracing enabled.
vmenv := vm.NewEVM(vmctx, statedb, nil, api.config, vm.Config{Debug: true, Tracer: tracer})
vmenv := vm.NewEVM(vmctx, txContext, statedb, nil, api.config, vm.Config{Debug: true, Tracer: tracer})
// Call Prepare to clear out the statedb access list
statedb.Prepare(txctx.TxHash, txctx.BlockHash, txctx.TxIndex)
@ -768,19 +766,19 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, t
}
// computeTxEnv returns the execution environment of a certain transaction.
func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, reexec uint64) (core.Message, vm.Context, *state.StateDB, error) {
func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error) {
// Create the parent state database
block := api.eth.blockchain.GetBlockByHash(blockHash)
if block == nil {
return nil, vm.Context{}, nil, fmt.Errorf("block %x not found", blockHash)
return nil, vm.BlockContext{}, nil, fmt.Errorf("block %x not found", blockHash)
}
parent := api.eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1)
if parent == nil {
return nil, vm.Context{}, nil, fmt.Errorf("parent %x not found", block.ParentHash())
return nil, vm.BlockContext{}, nil, fmt.Errorf("parent %x not found", block.ParentHash())
}
statedb, XDCxState, err := api.computeStateDB(parent, reexec)
if err != nil {
return nil, vm.Context{}, nil, err
return nil, vm.BlockContext{}, nil, err
}
// Recompute transactions up to the target index.
feeCapacity := state.GetTRC21FeeCapacityFromState(statedb)
@ -804,14 +802,14 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, ree
}
msg, err := tx.AsMessage(types.MakeSigner(api.config, block.Header().Number), balanceFee, block.Number())
if err != nil {
return nil, vm.Context{}, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err)
return nil, vm.BlockContext{}, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err)
}
context := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
context := core.NewEVMBlockContext(block.Header(), api.eth.blockchain, nil)
return msg, context, statedb, nil
}
_, gas, err, tokenFeeUsed := core.ApplyTransaction(api.config, feeCapacity, api.eth.blockchain, nil, gp, statedb, XDCxState, block.Header(), tx, usedGas, vm.Config{})
if err != nil {
return nil, vm.Context{}, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err)
return nil, vm.BlockContext{}, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err)
}
if tokenFeeUsed {
@ -822,5 +820,5 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, ree
}
}
statedb.DeleteSuicides()
return nil, vm.Context{}, nil, fmt.Errorf("tx index %d out of range for block %x", txIndex, blockHash)
return nil, vm.BlockContext{}, nil, fmt.Errorf("tx index %d out of range for block %x", txIndex, blockHash)
}

View file

@ -95,7 +95,11 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
var (
signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)))
origin, _ = signer.Sender(tx)
context = vm.Context{
txContext = vm.TxContext{
Origin: origin,
GasPrice: tx.GasPrice(),
}
context = vm.BlockContext{
CanTransfer: core.CanTransfer,
Transfer: core.Transfer,
Coinbase: test.Context.Miner,
@ -103,8 +107,6 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
Time: new(big.Int).SetUint64(uint64(test.Context.Time)),
Difficulty: (*big.Int)(test.Context.Difficulty),
GasLimit: uint64(test.Context.GasLimit),
Origin: origin,
GasPrice: tx.GasPrice(),
}
statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc)
)
@ -112,7 +114,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
if err != nil {
t.Fatalf("failed to create call tracer: %v", err)
}
evm := vm.NewEVM(context, statedb, nil, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer})
evm := vm.NewEVM(context, txContext, statedb, nil, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer})
msg, err := tx.AsMessage(signer, nil, nil)
if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
@ -204,7 +206,11 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
b.Fatalf("failed to prepare transaction for tracing: %v", err)
}
origin, _ := signer.Sender(tx)
context := vm.Context{
txContext := vm.TxContext{
Origin: origin,
GasPrice: tx.GasPrice(),
}
context := vm.BlockContext{
CanTransfer: core.CanTransfer,
Transfer: core.Transfer,
Coinbase: test.Context.Miner,
@ -212,8 +218,6 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
Time: new(big.Int).SetUint64(uint64(test.Context.Time)),
Difficulty: (*big.Int)(test.Context.Difficulty),
GasLimit: uint64(test.Context.GasLimit),
Origin: origin,
GasPrice: tx.GasPrice(),
}
statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc)
@ -224,7 +228,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
if err != nil {
b.Fatalf("failed to create call tracer: %v", err)
}
evm := vm.NewEVM(context, statedb, nil, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer})
evm := vm.NewEVM(context, txContext, statedb, nil, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer})
snap := statedb.Snapshot()
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if _, _, _, err, _ = st.TransitionDb(common.Address{}); err != nil {

View file

@ -670,7 +670,7 @@ func (jst *JsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Ad
jst.ctx["to"] = to
jst.ctx["input"] = input
jst.ctx["gas"] = gas
jst.ctx["gasPrice"] = env.Context.GasPrice
jst.ctx["gasPrice"] = env.TxContext.GasPrice
jst.ctx["value"] = value
// Initialize the context

View file

@ -51,19 +51,20 @@ func (*dummyStatedb) GetRefund() uint64 { return 1337 }
func (*dummyStatedb) GetBalance(addr common.Address) *big.Int { return new(big.Int) }
type vmContext struct {
ctx vm.Context // future pr should distinguish blockContext and txContext
ctx vm.BlockContext
txContext vm.TxContext
}
func testCtx() *vmContext {
return &vmContext{ctx: vm.Context{BlockNumber: big.NewInt(1), GasPrice: big.NewInt(100000)}}
}
func runTrace(tracer Tracer, vmctx *vmContext, chaincfg *params.ChainConfig) (json.RawMessage, error) {
env := vm.NewEVM(vmctx.ctx, &dummyStatedb{}, nil, chaincfg, vm.Config{Debug: true, Tracer: tracer})
func runTrace(tracer Tracer, blockNumber *big.Int, chaincfg *params.ChainConfig) (json.RawMessage, error) {
var (
startGas uint64 = 10000
value = big.NewInt(0)
startGas uint64 = 10000
value = big.NewInt(0)
ctx = vm.BlockContext{BlockNumber: blockNumber}
txContext = vm.TxContext{GasPrice: big.NewInt(100000)}
)
env := vm.NewEVM(ctx, txContext, &dummyStatedb{}, nil, chaincfg, vm.Config{Debug: true, Tracer: tracer})
contract := vm.NewContract(account{}, account{}, value, startGas)
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
@ -83,7 +84,7 @@ func TestTracer(t *testing.T) {
if err != nil {
t.Fatal(err)
}
ret, err := runTrace(tracer, testCtx(), params.TestChainConfig)
ret, err := runTrace(tracer, big.NewInt(1), params.TestChainConfig)
if err != nil {
return nil, err.Error() // Stringify to allow comparison without nil checks
}
@ -138,7 +139,7 @@ func TestHalt(t *testing.T) {
time.Sleep(1 * time.Second)
tracer.Stop(timeout)
}()
if _, err = runTrace(tracer, testCtx(), params.TestChainConfig); err.Error() != "stahp in server-side tracer function 'step'" {
if _, err = runTrace(tracer, big.NewInt(1), params.TestChainConfig); err.Error() != "stahp in server-side tracer function 'step'" {
t.Errorf("Expected timeout error, got %v", err)
}
}
@ -148,7 +149,7 @@ func TestHaltBetweenSteps(t *testing.T) {
if err != nil {
t.Fatal(err)
}
env := vm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, nil, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{}, &dummyStatedb{}, nil, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
scope := &vm.ScopeContext{
Contract: vm.NewContract(&account{}, &account{}, big.NewInt(0), 0),
}
@ -165,8 +166,10 @@ func TestHaltBetweenSteps(t *testing.T) {
// TestNoStepExec tests a regular value transfer (no exec), and accessing the statedb
// in 'result'
func TestNoStepExec(t *testing.T) {
runEmptyTrace := func(tracer Tracer, vmctx *vmContext) (json.RawMessage, error) {
env := vm.NewEVM(vmctx.ctx, &dummyStatedb{}, nil, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
runEmptyTrace := func(tracer Tracer) (json.RawMessage, error) {
ctx := vm.BlockContext{BlockNumber: big.NewInt(1)}
txContext := vm.TxContext{GasPrice: big.NewInt(100000)}
env := vm.NewEVM(ctx, txContext, &dummyStatedb{}, nil, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
startGas := uint64(10000)
contract := vm.NewContract(account{}, account{}, big.NewInt(0), startGas)
tracer.CaptureStart(env, contract.Caller(), contract.Address(), false, []byte{}, startGas, big.NewInt(0))
@ -179,7 +182,7 @@ func TestNoStepExec(t *testing.T) {
if err != nil {
t.Fatal(err)
}
ret, err := runEmptyTrace(tracer, testCtx())
ret, err := runEmptyTrace(tracer)
if err != nil {
t.Fatal(err)
}
@ -205,12 +208,11 @@ func TestIsPrecompile(t *testing.T) {
chaincfg.ByzantiumBlock = big.NewInt(100)
chaincfg.IstanbulBlock = big.NewInt(200)
chaincfg.BerlinBlock = big.NewInt(300)
ctx := vm.Context{BlockNumber: big.NewInt(150), GasPrice: big.NewInt(100000)}
tracer, err := New("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", new(Context))
if err != nil {
t.Fatal(err)
}
res, err := runTrace(tracer, &vmContext{ctx}, chaincfg)
res, err := runTrace(tracer, big.NewInt(150), chaincfg)
if err != nil {
t.Error(err)
}
@ -219,8 +221,7 @@ func TestIsPrecompile(t *testing.T) {
}
tracer, _ = New("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", new(Context))
ctx = vm.Context{BlockNumber: big.NewInt(250), GasPrice: big.NewInt(100000)}
res, err = runTrace(tracer, &vmContext{ctx}, chaincfg)
res, err = runTrace(tracer, big.NewInt(250), chaincfg)
if err != nil {
t.Error(err)
}
@ -267,7 +268,7 @@ func TestRegressionPanicSlice(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if _, err = runTrace(tracer, testCtx(), params.TestChainConfig); err != nil {
if _, err = runTrace(tracer, big.NewInt(1), params.TestChainConfig); err != nil {
t.Fatal(err)
}
}
@ -278,7 +279,7 @@ func TestRegressionPanicPeek(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if _, err = runTrace(tracer, testCtx(), params.TestChainConfig); err != nil {
if _, err = runTrace(tracer, big.NewInt(1), params.TestChainConfig); err != nil {
t.Fatal(err)
}
}
@ -289,7 +290,7 @@ func TestRegressionPanicGetUint(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if _, err = runTrace(tracer, testCtx(), params.TestChainConfig); err != nil {
if _, err = runTrace(tracer, big.NewInt(1), params.TestChainConfig); err != nil {
t.Fatal(err)
}
}
@ -300,7 +301,7 @@ func TestTracing(t *testing.T) {
t.Fatal(err)
}
ret, err := runTrace(tracer, testCtx(), params.TestChainConfig)
ret, err := runTrace(tracer, big.NewInt(1), params.TestChainConfig)
if err != nil {
t.Fatal(err)
}
@ -315,7 +316,7 @@ func TestStack(t *testing.T) {
t.Fatal(err)
}
ret, err := runTrace(tracer, testCtx(), params.TestChainConfig)
ret, err := runTrace(tracer, big.NewInt(1), params.TestChainConfig)
if err != nil {
t.Fatal(err)
}
@ -330,7 +331,7 @@ func TestOpcodes(t *testing.T) {
t.Fatal(err)
}
ret, err := runTrace(tracer, testCtx(), params.TestChainConfig)
ret, err := runTrace(tracer, big.NewInt(1), params.TestChainConfig)
if err != nil {
t.Fatal(err)
}

View file

@ -118,7 +118,11 @@ func TestZeroValueToNotExitCall(t *testing.T) {
t.Fatalf("err %v", err)
}
origin, _ := signer.Sender(tx)
context := vm.Context{
txContext := vm.TxContext{
Origin: origin,
GasPrice: big.NewInt(1),
}
context := vm.BlockContext{
CanTransfer: core.CanTransfer,
Transfer: core.Transfer,
Coinbase: common.Address{},
@ -126,8 +130,6 @@ func TestZeroValueToNotExitCall(t *testing.T) {
Time: new(big.Int).SetUint64(5),
Difficulty: big.NewInt(0x30000),
GasLimit: uint64(6000000),
Origin: origin,
GasPrice: big.NewInt(1),
}
var code = []byte{
byte(vm.PUSH1), 0x0, byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), // in and outs zero
@ -150,7 +152,7 @@ func TestZeroValueToNotExitCall(t *testing.T) {
if err != nil {
t.Fatalf("failed to create call tracer: %v", err)
}
evm := vm.NewEVM(context, statedb, nil, params.MainnetChainConfig, vm.Config{Debug: true, Tracer: tracer})
evm := vm.NewEVM(context, txContext, statedb, nil, params.MainnetChainConfig, vm.Config{Debug: true, Tracer: tracer})
msg, err := tx.AsMessage(signer, nil, nil)
if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
@ -200,16 +202,18 @@ func TestPrestateTracerCreate2(t *testing.T) {
result: 0x60f3f640a8508fC6a86d45DF051962668E1e8AC7
*/
origin, _ := signer.Sender(tx)
context := vm.Context{
txContext := vm.TxContext{
Origin: origin,
GasPrice: big.NewInt(1),
}
context := vm.BlockContext{
CanTransfer: core.CanTransfer,
Transfer: core.Transfer,
Origin: origin,
Coinbase: common.Address{},
BlockNumber: new(big.Int).SetUint64(8000000),
Time: new(big.Int).SetUint64(5),
Difficulty: big.NewInt(0x30000),
GasLimit: uint64(6000000),
GasPrice: big.NewInt(1),
}
alloc := core.GenesisAlloc{}
@ -233,7 +237,7 @@ func TestPrestateTracerCreate2(t *testing.T) {
if err != nil {
t.Fatalf("failed to create call tracer: %v", err)
}
evm := vm.NewEVM(context, statedb, nil, params.MainnetChainConfig, vm.Config{Debug: true, Tracer: tracer})
evm := vm.NewEVM(context, txContext, statedb, nil, params.MainnetChainConfig, vm.Config{Debug: true, Tracer: tracer})
msg, err := tx.AsMessage(signer, nil, nil)
if err != nil {
@ -291,7 +295,11 @@ func BenchmarkTransactionTrace(b *testing.B) {
if err != nil {
b.Fatal(err)
}
context := vm.Context{
txContext := vm.TxContext{
Origin: from,
GasPrice: tx.GasPrice(),
}
context := vm.BlockContext{
CanTransfer: core.CanTransfer,
Transfer: core.Transfer,
Coinbase: common.Address{},
@ -300,8 +308,6 @@ func BenchmarkTransactionTrace(b *testing.B) {
Difficulty: big.NewInt(0xffffffff),
GasLimit: gas,
// BaseFee: big.NewInt(8),
Origin: from,
GasPrice: tx.GasPrice(),
}
alloc := core.GenesisAlloc{}
// The code pushes 'deadbeef' into memory, then the other params, and calls CREATE2, then returns
@ -329,7 +335,7 @@ func BenchmarkTransactionTrace(b *testing.B) {
//EnableMemory: false,
//EnableReturnData: false,
})
evm := vm.NewEVM(context, statedb, nil, params.AllEthashProtocolChanges, vm.Config{Debug: true, Tracer: tracer})
evm := vm.NewEVM(context, txContext, statedb, nil, params.AllEthashProtocolChanges, vm.Config{Debug: true, Tracer: tracer})
msg, err := tx.AsMessage(signer, nil, nil)
if err != nil {
b.Fatalf("failed to prepare transaction for tracing: %v", err)

View file

@ -184,8 +184,9 @@ func (b *LesApiBackend) GetEVM(ctx context.Context, msg core.Message, state *sta
vmConfig = new(vm.Config)
}
state.SetBalance(msg.From(), math.MaxBig256)
context := core.NewEVMContext(msg, header, b.eth.blockchain, nil)
return vm.NewEVM(context, state, XDCxState, b.eth.chainConfig, *vmConfig), state.Error, nil
txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(header, b.eth.blockchain, nil)
return vm.NewEVM(context, txContext, state, XDCxState, b.eth.chainConfig, *vmConfig), state.Error, nil
}
func (b *LesApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {

View file

@ -135,8 +135,9 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
}
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, nil, false, balanceTokenFee, header.Number)}
context := core.NewEVMContext(msg, header, bc, nil)
vmenv := vm.NewEVM(context, statedb, nil, config, vm.Config{})
context := core.NewEVMBlockContext(header, bc, nil)
txContext := core.NewEVMTxContext(msg)
vmenv := vm.NewEVM(context, txContext, statedb, nil, config, vm.Config{})
//vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxUint64)
@ -154,8 +155,9 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
balanceTokenFee = value
}
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, nil, false, balanceTokenFee, header.Number)}
context := core.NewEVMContext(msg, header, lc, nil)
vmenv := vm.NewEVM(context, statedb, nil, config, vm.Config{})
context := core.NewEVMBlockContext(header, lc, nil)
txContext := core.NewEVMTxContext(msg)
vmenv := vm.NewEVM(context, txContext, statedb, nil, config, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxUint64)
owner := common.Address{}
ret, _, _, _, _ := core.ApplyMessage(vmenv, msg, gp, owner)

View file

@ -185,8 +185,9 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
balanceTokenFee = value
}
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, new(big.Int), data, nil, false, balanceTokenFee, header.Number)}
context := core.NewEVMContext(msg, header, chain, nil)
vmenv := vm.NewEVM(context, st, nil, config, vm.Config{})
txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(header, chain, nil)
vmenv := vm.NewEVM(context, txContext, st, nil, config, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxUint64)
owner := common.Address{}
ret, _, _, _, _ := core.ApplyMessage(vmenv, msg, gp, owner)

View file

@ -137,9 +137,10 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config) (*state.StateD
}
// Prepare the EVM.
context := core.NewEVMContext(msg, block.Header(), nil, &t.json.Env.Coinbase)
txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
context.GetHash = vmTestBlockHash
evm := vm.NewEVM(context, statedb, nil, config, vmconfig)
evm := vm.NewEVM(context, txContext, statedb, nil, config, vmconfig)
// Execute the message.
snapshot := statedb.Snapshot()

View file

@ -132,19 +132,21 @@ func (t *VMTest) newEVM(statedb *state.StateDB, vmconfig vm.Config) *vm.EVM {
return core.CanTransfer(db, address, amount)
}
transfer := func(db vm.StateDB, sender, recipient common.Address, amount *big.Int) {}
context := vm.Context{
txContext := vm.TxContext{
Origin: t.json.Exec.Origin,
GasPrice: t.json.Exec.GasPrice,
}
context := vm.BlockContext{
CanTransfer: canTransfer,
Transfer: transfer,
GetHash: vmTestBlockHash,
Origin: t.json.Exec.Origin,
Coinbase: t.json.Env.Coinbase,
BlockNumber: new(big.Int).SetUint64(t.json.Env.Number),
Time: new(big.Int).SetUint64(t.json.Env.Timestamp),
GasLimit: t.json.Env.GasLimit,
Difficulty: t.json.Env.Difficulty,
GasPrice: t.json.Exec.GasPrice,
}
return vm.NewEVM(context, statedb, nil, params.MainnetChainConfig, vmconfig)
return vm.NewEVM(context, txContext, statedb, nil, params.MainnetChainConfig, vmconfig)
}
func vmTestBlockHash(n uint64) common.Hash {