core, all: split vm.Context into BlockContext and TxContext (#21672)
* all: core: split vm.Config into BlockConfig and TxConfig * core: core/vm: reset EVM between tx in block instead of creating new * core/vm: added docs
This commit is contained in:
		
							parent
							
								
									6f4cccf8d2
								
							
						
					
					
						commit
						2045a2bba3
					
				@ -542,10 +542,11 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
 | 
			
		||||
	// Execute the call.
 | 
			
		||||
	msg := callMsg{call}
 | 
			
		||||
 | 
			
		||||
	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, b.config, vm.Config{})
 | 
			
		||||
	vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{})
 | 
			
		||||
	gasPool := new(core.GasPool).AddGas(math.MaxUint64)
 | 
			
		||||
 | 
			
		||||
	return core.NewStateTransition(vmEnv, msg, gasPool).TransitionDb()
 | 
			
		||||
 | 
			
		||||
@ -110,7 +110,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
 | 
			
		||||
		txIndex     = 0
 | 
			
		||||
	)
 | 
			
		||||
	gaspool.AddGas(pre.Env.GasLimit)
 | 
			
		||||
	vmContext := vm.Context{
 | 
			
		||||
	vmContext := vm.BlockContext{
 | 
			
		||||
		CanTransfer: core.CanTransfer,
 | 
			
		||||
		Transfer:    core.Transfer,
 | 
			
		||||
		Coinbase:    pre.Env.Coinbase,
 | 
			
		||||
@ -119,7 +119,6 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
 | 
			
		||||
		Difficulty:  pre.Env.Difficulty,
 | 
			
		||||
		GasLimit:    pre.Env.GasLimit,
 | 
			
		||||
		GetHash:     getHash,
 | 
			
		||||
		// GasPrice and Origin needs to be set per transaction
 | 
			
		||||
	}
 | 
			
		||||
	// If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's
 | 
			
		||||
	// done in StateProcessor.Process(block, ...), right before transactions are applied.
 | 
			
		||||
@ -143,10 +142,9 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
 | 
			
		||||
		vmConfig.Tracer = tracer
 | 
			
		||||
		vmConfig.Debug = (tracer != nil)
 | 
			
		||||
		statedb.Prepare(tx.Hash(), blockHash, txIndex)
 | 
			
		||||
		vmContext.GasPrice = msg.GasPrice()
 | 
			
		||||
		vmContext.Origin = msg.From()
 | 
			
		||||
		txContext := core.NewEVMTxContext(msg)
 | 
			
		||||
 | 
			
		||||
		evm := vm.NewEVM(vmContext, statedb, chainConfig, vmConfig)
 | 
			
		||||
		evm := vm.NewEVM(vmContext, txContext, statedb, chainConfig, vmConfig)
 | 
			
		||||
		if chainConfig.IsYoloV2(vmContext.BlockNumber) {
 | 
			
		||||
			statedb.AddAddressToAccessList(msg.From())
 | 
			
		||||
			if dst := msg.To(); dst != nil {
 | 
			
		||||
@ -185,7 +183,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
 | 
			
		||||
			receipt.GasUsed = msgResult.UsedGas
 | 
			
		||||
			// if the transaction created a contract, store the creation address in the receipt.
 | 
			
		||||
			if msg.To() == nil {
 | 
			
		||||
				receipt.ContractAddress = crypto.CreateAddress(evm.Context.Origin, tx.Nonce())
 | 
			
		||||
				receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
 | 
			
		||||
			}
 | 
			
		||||
			// Set the receipt logs and create a bloom for filtering
 | 
			
		||||
			receipt.Logs = statedb.GetLogs(tx.Hash())
 | 
			
		||||
 | 
			
		||||
@ -671,12 +671,13 @@ func (api *RetestethAPI) AccountRange(ctx context.Context,
 | 
			
		||||
		}
 | 
			
		||||
		// Recompute transactions up to the target index.
 | 
			
		||||
		signer := types.MakeSigner(api.blockchain.Config(), block.Number())
 | 
			
		||||
		context := core.NewEVMBlockContext(block.Header(), api.blockchain, nil)
 | 
			
		||||
		for idx, tx := range block.Transactions() {
 | 
			
		||||
			// Assemble the transaction call message and return if the requested offset
 | 
			
		||||
			msg, _ := tx.AsMessage(signer)
 | 
			
		||||
			context := core.NewEVMContext(msg, block.Header(), api.blockchain, nil)
 | 
			
		||||
			txContext := core.NewEVMTxContext(msg)
 | 
			
		||||
			// Not yet the searched for transaction, execute on top of the current state
 | 
			
		||||
			vmenv := vm.NewEVM(context, statedb, api.blockchain.Config(), vm.Config{})
 | 
			
		||||
			vmenv := vm.NewEVM(context, txContext, statedb, api.blockchain.Config(), vm.Config{})
 | 
			
		||||
			if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
 | 
			
		||||
				return AccountRangeResult{}, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
 | 
			
		||||
			}
 | 
			
		||||
@ -781,12 +782,13 @@ func (api *RetestethAPI) StorageRangeAt(ctx context.Context,
 | 
			
		||||
		}
 | 
			
		||||
		// Recompute transactions up to the target index.
 | 
			
		||||
		signer := types.MakeSigner(api.blockchain.Config(), block.Number())
 | 
			
		||||
		context := core.NewEVMBlockContext(block.Header(), api.blockchain, nil)
 | 
			
		||||
		for idx, tx := range block.Transactions() {
 | 
			
		||||
			// Assemble the transaction call message and return if the requested offset
 | 
			
		||||
			msg, _ := tx.AsMessage(signer)
 | 
			
		||||
			context := core.NewEVMContext(msg, block.Header(), api.blockchain, nil)
 | 
			
		||||
			txContext := core.NewEVMTxContext(msg)
 | 
			
		||||
			// Not yet the searched for transaction, execute on top of the current state
 | 
			
		||||
			vmenv := vm.NewEVM(context, statedb, api.blockchain.Config(), vm.Config{})
 | 
			
		||||
			vmenv := vm.NewEVM(context, txContext, statedb, api.blockchain.Config(), vm.Config{})
 | 
			
		||||
			if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
 | 
			
		||||
				return StorageRangeResult{}, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								core/evm.go
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								core/evm.go
									
									
									
									
									
								
							@ -35,8 +35,8 @@ type ChainContext interface {
 | 
			
		||||
	GetHeader(common.Hash, uint64) *types.Header
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewEVMContext creates a new context for use in the EVM.
 | 
			
		||||
func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author *common.Address) vm.Context {
 | 
			
		||||
// NewEVMBlockContext creates a new context for use in the EVM.
 | 
			
		||||
func NewEVMBlockContext(header *types.Header, chain 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
 | 
			
		||||
	if author == nil {
 | 
			
		||||
@ -44,16 +44,22 @@ func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author
 | 
			
		||||
	} else {
 | 
			
		||||
		beneficiary = *author
 | 
			
		||||
	}
 | 
			
		||||
	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).SetUint64(header.Time),
 | 
			
		||||
		Difficulty:  new(big.Int).Set(header.Difficulty),
 | 
			
		||||
		GasLimit:    header.GasLimit,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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()),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -86,8 +86,9 @@ func precacheTransaction(config *params.ChainConfig, bc ChainContext, author *co
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	// Create the EVM and execute the transaction
 | 
			
		||||
	context := NewEVMContext(msg, header, bc, author)
 | 
			
		||||
	vm := vm.NewEVM(context, statedb, config, cfg)
 | 
			
		||||
	context := NewEVMBlockContext(header, bc, author)
 | 
			
		||||
	txContext := NewEVMTxContext(msg)
 | 
			
		||||
	vm := vm.NewEVM(context, txContext, statedb, config, cfg)
 | 
			
		||||
 | 
			
		||||
	_, err = ApplyMessage(vm, msg, gaspool)
 | 
			
		||||
	return err
 | 
			
		||||
 | 
			
		||||
@ -65,10 +65,16 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
 | 
			
		||||
	if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
 | 
			
		||||
		misc.ApplyDAOHardFork(statedb)
 | 
			
		||||
	}
 | 
			
		||||
	blockContext := NewEVMBlockContext(header, p.bc, nil)
 | 
			
		||||
	vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg)
 | 
			
		||||
	// Iterate over and process the individual transactions
 | 
			
		||||
	for i, tx := range block.Transactions() {
 | 
			
		||||
		msg, err := tx.AsMessage(types.MakeSigner(p.config, header.Number))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, nil, 0, err
 | 
			
		||||
		}
 | 
			
		||||
		statedb.Prepare(tx.Hash(), block.Hash(), i)
 | 
			
		||||
		receipt, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, cfg)
 | 
			
		||||
		receipt, err := applyTransaction(msg, p.config, p.bc, nil, gp, statedb, header, tx, usedGas, vmenv)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, nil, 0, err
 | 
			
		||||
		}
 | 
			
		||||
@ -81,34 +87,25 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
 | 
			
		||||
	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, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) {
 | 
			
		||||
	msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) {
 | 
			
		||||
	// 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, config, cfg)
 | 
			
		||||
 | 
			
		||||
	txContext := NewEVMTxContext(msg)
 | 
			
		||||
	// Add addresses to access list if applicable
 | 
			
		||||
	if config.IsYoloV2(header.Number) {
 | 
			
		||||
		statedb.AddAddressToAccessList(msg.From())
 | 
			
		||||
		if dst := msg.To(); dst != nil {
 | 
			
		||||
			statedb.AddAddressToAccessList(*dst)
 | 
			
		||||
			// If it's a create-tx, the destination will be added inside evm.create
 | 
			
		||||
		}
 | 
			
		||||
		for _, addr := range vmenv.ActivePrecompiles() {
 | 
			
		||||
		for _, addr := range evm.ActivePrecompiles() {
 | 
			
		||||
			statedb.AddAddressToAccessList(addr)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Update the evm with the new transaction context.
 | 
			
		||||
	evm.Reset(txContext, statedb)
 | 
			
		||||
	// Apply the transaction to the current state (included in the env)
 | 
			
		||||
	result, err := ApplyMessage(vmenv, msg, gp)
 | 
			
		||||
	result, err := ApplyMessage(evm, msg, gp)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@ -128,7 +125,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
 | 
			
		||||
	receipt.GasUsed = result.UsedGas
 | 
			
		||||
	// 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 a bloom for filtering
 | 
			
		||||
	receipt.Logs = statedb.GetLogs(tx.Hash())
 | 
			
		||||
@ -139,3 +136,18 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
 | 
			
		||||
 | 
			
		||||
	return receipt, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) {
 | 
			
		||||
	msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	// Create a new context to be used in the EVM environment
 | 
			
		||||
	blockContext := NewEVMBlockContext(header, bc, author)
 | 
			
		||||
	vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg)
 | 
			
		||||
	return applyTransaction(msg, config, bc, author, gp, statedb, header, tx, usedGas, vmenv)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -230,8 +230,8 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
 | 
			
		||||
	}
 | 
			
		||||
	msg := st.msg
 | 
			
		||||
	sender := vm.AccountRef(msg.From())
 | 
			
		||||
	homestead := st.evm.ChainConfig().IsHomestead(st.evm.BlockNumber)
 | 
			
		||||
	istanbul := st.evm.ChainConfig().IsIstanbul(st.evm.BlockNumber)
 | 
			
		||||
	homestead := st.evm.ChainConfig().IsHomestead(st.evm.Context.BlockNumber)
 | 
			
		||||
	istanbul := st.evm.ChainConfig().IsIstanbul(st.evm.Context.BlockNumber)
 | 
			
		||||
	contractCreation := msg.To() == nil
 | 
			
		||||
 | 
			
		||||
	// Check clauses 4-5, subtract intrinsic gas if everything is correct
 | 
			
		||||
@ -245,7 +245,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
 | 
			
		||||
	st.gas -= gas
 | 
			
		||||
 | 
			
		||||
	// Check clause 6
 | 
			
		||||
	if msg.Value().Sign() > 0 && !st.evm.CanTransfer(st.state, msg.From(), msg.Value()) {
 | 
			
		||||
	if msg.Value().Sign() > 0 && !st.evm.Context.CanTransfer(st.state, msg.From(), msg.Value()) {
 | 
			
		||||
		return nil, ErrInsufficientFundsForTransfer
 | 
			
		||||
	}
 | 
			
		||||
	var (
 | 
			
		||||
@ -260,7 +260,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
 | 
			
		||||
		ret, st.gas, vmerr = st.evm.Call(sender, st.to(), st.data, st.gas, st.value)
 | 
			
		||||
	}
 | 
			
		||||
	st.refundGas()
 | 
			
		||||
	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 &ExecutionResult{
 | 
			
		||||
		UsedGas:    st.gasUsed(),
 | 
			
		||||
 | 
			
		||||
@ -91,9 +91,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
 | 
			
		||||
@ -102,10 +102,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
 | 
			
		||||
@ -114,6 +110,14 @@ type Context struct {
 | 
			
		||||
	Difficulty  *big.Int       // Provides information for DIFFICULTY
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
@ -125,7 +129,8 @@ type Context struct {
 | 
			
		||||
// The EVM should never be reused and is not thread safe.
 | 
			
		||||
type EVM struct {
 | 
			
		||||
	// Context provides auxiliary blockchain related information
 | 
			
		||||
	Context
 | 
			
		||||
	Context BlockContext
 | 
			
		||||
	TxContext
 | 
			
		||||
	// StateDB gives access to the underlying state
 | 
			
		||||
	StateDB StateDB
 | 
			
		||||
	// Depth is the current call stack
 | 
			
		||||
@ -153,17 +158,18 @@ 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, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
 | 
			
		||||
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
 | 
			
		||||
	evm := &EVM{
 | 
			
		||||
		Context:      ctx,
 | 
			
		||||
		Context:      blockCtx,
 | 
			
		||||
		TxContext:    txCtx,
 | 
			
		||||
		StateDB:      statedb,
 | 
			
		||||
		vmConfig:     vmConfig,
 | 
			
		||||
		chainConfig:  chainConfig,
 | 
			
		||||
		chainRules:   chainConfig.Rules(ctx.BlockNumber),
 | 
			
		||||
		chainRules:   chainConfig.Rules(blockCtx.BlockNumber),
 | 
			
		||||
		interpreters: make([]Interpreter, 0, 1),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if chainConfig.IsEWASM(ctx.BlockNumber) {
 | 
			
		||||
	if chainConfig.IsEWASM(blockCtx.BlockNumber) {
 | 
			
		||||
		// to be implemented by EVM-C and Wagon PRs.
 | 
			
		||||
		// if vmConfig.EWASMInterpreter != "" {
 | 
			
		||||
		//  extIntOpts := strings.Split(vmConfig.EWASMInterpreter, ":")
 | 
			
		||||
@ -187,6 +193,13 @@ func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmCon
 | 
			
		||||
	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() {
 | 
			
		||||
@ -233,7 +246,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
 | 
			
		||||
		}
 | 
			
		||||
		evm.StateDB.CreateAccount(addr)
 | 
			
		||||
	}
 | 
			
		||||
	evm.Transfer(evm.StateDB, caller.Address(), addr, value)
 | 
			
		||||
	evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value)
 | 
			
		||||
 | 
			
		||||
	// Capture the tracer start/end events in debug mode
 | 
			
		||||
	if evm.vmConfig.Debug && evm.depth == 0 {
 | 
			
		||||
@ -426,7 +439,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())
 | 
			
		||||
@ -447,7 +460,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.
 | 
			
		||||
 | 
			
		||||
@ -87,11 +87,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, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
 | 
			
		||||
		vmenv := NewEVM(vmctx, TxContext{}, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
 | 
			
		||||
 | 
			
		||||
		_, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(big.Int))
 | 
			
		||||
		if err != tt.failure {
 | 
			
		||||
 | 
			
		||||
@ -438,14 +438,14 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx)
 | 
			
		||||
		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()
 | 
			
		||||
	}
 | 
			
		||||
@ -453,30 +453,30 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func opCoinbase(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
 | 
			
		||||
	callContext.stack.push(new(uint256.Int).SetBytes(interpreter.evm.Coinbase.Bytes()))
 | 
			
		||||
	callContext.stack.push(new(uint256.Int).SetBytes(interpreter.evm.Context.Coinbase.Bytes()))
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func opTimestamp(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
 | 
			
		||||
	v, _ := uint256.FromBig(interpreter.evm.Time)
 | 
			
		||||
	v, _ := uint256.FromBig(interpreter.evm.Context.Time)
 | 
			
		||||
	callContext.stack.push(v)
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func opNumber(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
 | 
			
		||||
	v, _ := uint256.FromBig(interpreter.evm.BlockNumber)
 | 
			
		||||
	v, _ := uint256.FromBig(interpreter.evm.Context.BlockNumber)
 | 
			
		||||
	callContext.stack.push(v)
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func opDifficulty(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
 | 
			
		||||
	v, _ := uint256.FromBig(interpreter.evm.Difficulty)
 | 
			
		||||
	v, _ := uint256.FromBig(interpreter.evm.Context.Difficulty)
 | 
			
		||||
	callContext.stack.push(v)
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func opGasLimit(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
 | 
			
		||||
	callContext.stack.push(new(uint256.Int).SetUint64(interpreter.evm.GasLimit))
 | 
			
		||||
	callContext.stack.push(new(uint256.Int).SetUint64(interpreter.evm.Context.GasLimit))
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -842,7 +842,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
 | 
			
		||||
 | 
			
		||||
@ -92,7 +92,7 @@ func init() {
 | 
			
		||||
func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFunc, name string) {
 | 
			
		||||
 | 
			
		||||
	var (
 | 
			
		||||
		env            = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		env            = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		stack          = newstack()
 | 
			
		||||
		rstack         = newReturnStack()
 | 
			
		||||
		pc             = uint64(0)
 | 
			
		||||
@ -192,7 +192,7 @@ func TestSAR(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
func TestAddMod(t *testing.T) {
 | 
			
		||||
	var (
 | 
			
		||||
		env            = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		env            = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		stack          = newstack()
 | 
			
		||||
		evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
 | 
			
		||||
		pc             = uint64(0)
 | 
			
		||||
@ -231,7 +231,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, params.TestChainConfig, Config{})
 | 
			
		||||
		env           = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		stack, rstack = newstack(), newReturnStack()
 | 
			
		||||
		pc            = uint64(0)
 | 
			
		||||
		interpreter   = env.interpreter.(*EVMInterpreter)
 | 
			
		||||
@ -281,7 +281,7 @@ func TestJsonTestcases(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
 | 
			
		||||
	var (
 | 
			
		||||
		env            = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		env            = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		stack, rstack  = newstack(), newReturnStack()
 | 
			
		||||
		evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
 | 
			
		||||
	)
 | 
			
		||||
@ -515,7 +515,7 @@ func BenchmarkOpIsZero(b *testing.B) {
 | 
			
		||||
 | 
			
		||||
func TestOpMstore(t *testing.T) {
 | 
			
		||||
	var (
 | 
			
		||||
		env            = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		env            = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		stack, rstack  = newstack(), newReturnStack()
 | 
			
		||||
		mem            = NewMemory()
 | 
			
		||||
		evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
 | 
			
		||||
@ -539,7 +539,7 @@ func TestOpMstore(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
func BenchmarkOpMstore(bench *testing.B) {
 | 
			
		||||
	var (
 | 
			
		||||
		env            = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		env            = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		stack, rstack  = newstack(), newReturnStack()
 | 
			
		||||
		mem            = NewMemory()
 | 
			
		||||
		evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
 | 
			
		||||
@ -560,7 +560,7 @@ func BenchmarkOpMstore(bench *testing.B) {
 | 
			
		||||
 | 
			
		||||
func BenchmarkOpSHA3(bench *testing.B) {
 | 
			
		||||
	var (
 | 
			
		||||
		env            = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		env            = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{})
 | 
			
		||||
		stack, rstack  = newstack(), newReturnStack()
 | 
			
		||||
		mem            = NewMemory()
 | 
			
		||||
		evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
 | 
			
		||||
 | 
			
		||||
@ -51,7 +51,7 @@ func (*dummyStatedb) GetRefund() uint64 { return 1337 }
 | 
			
		||||
 | 
			
		||||
func TestStoreCapture(t *testing.T) {
 | 
			
		||||
	var (
 | 
			
		||||
		env      = NewEVM(Context{}, &dummyStatedb{}, params.TestChainConfig, Config{})
 | 
			
		||||
		env      = NewEVM(BlockContext{}, TxContext{}, &dummyStatedb{}, params.TestChainConfig, Config{})
 | 
			
		||||
		logger   = NewStructLogger(nil)
 | 
			
		||||
		mem      = NewMemory()
 | 
			
		||||
		stack    = newstack()
 | 
			
		||||
 | 
			
		||||
@ -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, cfg.ChainConfig, cfg.EVMConfig)
 | 
			
		||||
	return vm.NewEVM(blockContext, txContext, cfg.State, cfg.ChainConfig, cfg.EVMConfig)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -113,7 +113,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
 | 
			
		||||
		vmenv   = NewEnv(cfg)
 | 
			
		||||
		sender  = vm.AccountRef(cfg.Origin)
 | 
			
		||||
	)
 | 
			
		||||
	if cfg.ChainConfig.IsYoloV2(vmenv.BlockNumber) {
 | 
			
		||||
	if cfg.ChainConfig.IsYoloV2(vmenv.Context.BlockNumber) {
 | 
			
		||||
		cfg.State.AddAddressToAccessList(cfg.Origin)
 | 
			
		||||
		cfg.State.AddAddressToAccessList(address)
 | 
			
		||||
		for _, addr := range vmenv.ActivePrecompiles() {
 | 
			
		||||
@ -150,7 +150,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
 | 
			
		||||
		vmenv  = NewEnv(cfg)
 | 
			
		||||
		sender = vm.AccountRef(cfg.Origin)
 | 
			
		||||
	)
 | 
			
		||||
	if cfg.ChainConfig.IsYoloV2(vmenv.BlockNumber) {
 | 
			
		||||
	if cfg.ChainConfig.IsYoloV2(vmenv.Context.BlockNumber) {
 | 
			
		||||
		cfg.State.AddAddressToAccessList(cfg.Origin)
 | 
			
		||||
		for _, addr := range vmenv.ActivePrecompiles() {
 | 
			
		||||
			cfg.State.AddAddressToAccessList(addr)
 | 
			
		||||
@ -178,7 +178,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er
 | 
			
		||||
	vmenv := NewEnv(cfg)
 | 
			
		||||
 | 
			
		||||
	sender := cfg.State.GetOrNewStateObject(cfg.Origin)
 | 
			
		||||
	if cfg.ChainConfig.IsYoloV2(vmenv.BlockNumber) {
 | 
			
		||||
	if cfg.ChainConfig.IsYoloV2(vmenv.Context.BlockNumber) {
 | 
			
		||||
		cfg.State.AddAddressToAccessList(cfg.Origin)
 | 
			
		||||
		cfg.State.AddAddressToAccessList(address)
 | 
			
		||||
		for _, addr := range vmenv.ActivePrecompiles() {
 | 
			
		||||
 | 
			
		||||
@ -194,8 +194,9 @@ func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
 | 
			
		||||
func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) {
 | 
			
		||||
	vmError := func() error { return nil }
 | 
			
		||||
 | 
			
		||||
	context := core.NewEVMContext(msg, header, b.eth.BlockChain(), nil)
 | 
			
		||||
	return vm.NewEVM(context, state, b.eth.blockchain.Config(), *b.eth.blockchain.GetVMConfig()), vmError, nil
 | 
			
		||||
	txContext := core.NewEVMTxContext(msg)
 | 
			
		||||
	context := core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
 | 
			
		||||
	return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *b.eth.blockchain.GetVMConfig()), vmError, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
 | 
			
		||||
 | 
			
		||||
@ -203,13 +203,11 @@ 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.eth.blockchain.Config(), task.block.Number())
 | 
			
		||||
 | 
			
		||||
				blockCtx := core.NewEVMBlockContext(task.block.Header(), api.eth.blockchain, nil)
 | 
			
		||||
				// Trace all the transactions contained within
 | 
			
		||||
				for i, tx := range task.block.Transactions() {
 | 
			
		||||
					msg, _ := tx.AsMessage(signer)
 | 
			
		||||
					vmctx := core.NewEVMContext(msg, task.block.Header(), api.eth.blockchain, nil)
 | 
			
		||||
 | 
			
		||||
					res, err := api.traceTx(ctx, msg, vmctx, task.statedb, config)
 | 
			
		||||
					res, err := api.traceTx(ctx, msg, 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,17 +471,15 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
 | 
			
		||||
	if threads > len(txs) {
 | 
			
		||||
		threads = len(txs)
 | 
			
		||||
	}
 | 
			
		||||
	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 {
 | 
			
		||||
				msg, _ := txs[task.index].AsMessage(signer)
 | 
			
		||||
				vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
 | 
			
		||||
 | 
			
		||||
				res, err := api.traceTx(ctx, msg, vmctx, task.statedb, config)
 | 
			
		||||
				res, err := api.traceTx(ctx, msg, blockCtx, task.statedb, config)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					results[task.index] = &txTraceResult{Error: err.Error()}
 | 
			
		||||
					continue
 | 
			
		||||
@ -500,9 +496,9 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
 | 
			
		||||
 | 
			
		||||
		// Generate the next state snapshot fast without tracing
 | 
			
		||||
		msg, _ := tx.AsMessage(signer)
 | 
			
		||||
		vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
 | 
			
		||||
		txContext := core.NewEVMTxContext(msg)
 | 
			
		||||
 | 
			
		||||
		vmenv := vm.NewEVM(vmctx, statedb, api.eth.blockchain.Config(), vm.Config{})
 | 
			
		||||
		vmenv := vm.NewEVM(blockCtx, txContext, statedb, api.eth.blockchain.Config(), vm.Config{})
 | 
			
		||||
		if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil {
 | 
			
		||||
			failed = err
 | 
			
		||||
			break
 | 
			
		||||
@ -565,6 +561,7 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block
 | 
			
		||||
		signer      = types.MakeSigner(api.eth.blockchain.Config(), block.Number())
 | 
			
		||||
		dumps       []string
 | 
			
		||||
		chainConfig = api.eth.blockchain.Config()
 | 
			
		||||
		vmctx       = core.NewEVMBlockContext(block.Header(), api.eth.blockchain, nil)
 | 
			
		||||
		canon       = true
 | 
			
		||||
	)
 | 
			
		||||
	// Check if there are any overrides: the caller may wish to enable a future
 | 
			
		||||
@ -588,8 +585,7 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block
 | 
			
		||||
		// Prepare the trasaction for un-traced execution
 | 
			
		||||
		var (
 | 
			
		||||
			msg, _    = tx.AsMessage(signer)
 | 
			
		||||
			vmctx  = core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
 | 
			
		||||
 | 
			
		||||
			txContext = core.NewEVMTxContext(msg)
 | 
			
		||||
			vmConf    vm.Config
 | 
			
		||||
			dump      *os.File
 | 
			
		||||
			writer    *bufio.Writer
 | 
			
		||||
@ -617,7 +613,7 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		// Execute the transaction and flush any traces to disk
 | 
			
		||||
		vmenv := vm.NewEVM(vmctx, statedb, chainConfig, vmConf)
 | 
			
		||||
		vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf)
 | 
			
		||||
		_, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()))
 | 
			
		||||
		if writer != nil {
 | 
			
		||||
			writer.Flush()
 | 
			
		||||
@ -776,18 +772,19 @@ func (api *PrivateDebugAPI) TraceCall(ctx context.Context, args ethapi.CallArgs,
 | 
			
		||||
 | 
			
		||||
	// Execute the trace
 | 
			
		||||
	msg := args.ToMessage(api.eth.APIBackend.RPCGasCap())
 | 
			
		||||
	vmctx := core.NewEVMContext(msg, header, api.eth.blockchain, nil)
 | 
			
		||||
	vmctx := core.NewEVMBlockContext(header, api.eth.blockchain, nil)
 | 
			
		||||
	return api.traceTx(ctx, msg, vmctx, statedb, config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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, vmctx vm.Context, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
 | 
			
		||||
func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
 | 
			
		||||
	// Assemble the structured logger or the JavaScript tracer
 | 
			
		||||
	var (
 | 
			
		||||
		tracer    vm.Tracer
 | 
			
		||||
		err       error
 | 
			
		||||
		txContext = core.NewEVMTxContext(message)
 | 
			
		||||
	)
 | 
			
		||||
	switch {
 | 
			
		||||
	case config != nil && config.Tracer != nil:
 | 
			
		||||
@ -817,7 +814,7 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, v
 | 
			
		||||
		tracer = vm.NewStructLogger(config.LogConfig)
 | 
			
		||||
	}
 | 
			
		||||
	// Run the transaction with tracing enabled.
 | 
			
		||||
	vmenv := vm.NewEVM(vmctx, statedb, api.eth.blockchain.Config(), vm.Config{Debug: true, Tracer: tracer})
 | 
			
		||||
	vmenv := vm.NewEVM(vmctx, txContext, statedb, api.eth.blockchain.Config(), vm.Config{Debug: true, Tracer: tracer})
 | 
			
		||||
 | 
			
		||||
	result, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@ -847,19 +844,19 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// computeTxEnv returns the execution environment of a certain transaction.
 | 
			
		||||
func (api *PrivateDebugAPI) computeTxEnv(block *types.Block, txIndex int, reexec uint64) (core.Message, vm.Context, *state.StateDB, error) {
 | 
			
		||||
func (api *PrivateDebugAPI) computeTxEnv(block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error) {
 | 
			
		||||
	// Create the parent state database
 | 
			
		||||
	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, err := api.computeStateDB(parent, reexec)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, vm.Context{}, nil, err
 | 
			
		||||
		return nil, vm.BlockContext{}, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if txIndex == 0 && len(block.Transactions()) == 0 {
 | 
			
		||||
		return nil, vm.Context{}, statedb, nil
 | 
			
		||||
		return nil, vm.BlockContext{}, statedb, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Recompute transactions up to the target index.
 | 
			
		||||
@ -868,18 +865,19 @@ func (api *PrivateDebugAPI) computeTxEnv(block *types.Block, txIndex int, reexec
 | 
			
		||||
	for idx, tx := range block.Transactions() {
 | 
			
		||||
		// Assemble the transaction call message and return if the requested offset
 | 
			
		||||
		msg, _ := tx.AsMessage(signer)
 | 
			
		||||
		context := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
 | 
			
		||||
		txContext := core.NewEVMTxContext(msg)
 | 
			
		||||
		context := core.NewEVMBlockContext(block.Header(), api.eth.blockchain, nil)
 | 
			
		||||
		if idx == txIndex {
 | 
			
		||||
			return msg, context, statedb, nil
 | 
			
		||||
		}
 | 
			
		||||
		// Not yet the searched for transaction, execute on top of the current state
 | 
			
		||||
		vmenv := vm.NewEVM(context, statedb, api.eth.blockchain.Config(), vm.Config{})
 | 
			
		||||
		vmenv := vm.NewEVM(context, txContext, statedb, api.eth.blockchain.Config(), vm.Config{})
 | 
			
		||||
		if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
 | 
			
		||||
			return nil, vm.Context{}, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
 | 
			
		||||
			return nil, vm.BlockContext{}, 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()))
 | 
			
		||||
	}
 | 
			
		||||
	return nil, vm.Context{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
 | 
			
		||||
	return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -545,7 +545,7 @@ func (jst *Tracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost
 | 
			
		||||
	if jst.err == nil {
 | 
			
		||||
		// Initialize the context if it wasn't done yet
 | 
			
		||||
		if !jst.inited {
 | 
			
		||||
			jst.ctx["block"] = env.BlockNumber.Uint64()
 | 
			
		||||
			jst.ctx["block"] = env.Context.BlockNumber.Uint64()
 | 
			
		||||
			jst.inited = true
 | 
			
		||||
		}
 | 
			
		||||
		// If tracing was interrupted, set the error and stop
 | 
			
		||||
 | 
			
		||||
@ -51,7 +51,7 @@ type dummyStatedb struct {
 | 
			
		||||
func (*dummyStatedb) GetRefund() uint64 { return 1337 }
 | 
			
		||||
 | 
			
		||||
func runTrace(tracer *Tracer) (json.RawMessage, error) {
 | 
			
		||||
	env := vm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
 | 
			
		||||
	env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
 | 
			
		||||
 | 
			
		||||
	contract := vm.NewContract(account{}, account{}, big.NewInt(0), 10000)
 | 
			
		||||
	contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
 | 
			
		||||
@ -166,7 +166,7 @@ func TestHaltBetweenSteps(t *testing.T) {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	env := vm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
 | 
			
		||||
	env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
 | 
			
		||||
	contract := vm.NewContract(&account{}, &account{}, big.NewInt(0), 0)
 | 
			
		||||
 | 
			
		||||
	tracer.CaptureState(env, 0, 0, 0, 0, nil, nil, nil, nil, contract, 0, nil)
 | 
			
		||||
 | 
			
		||||
@ -143,16 +143,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{}
 | 
			
		||||
 | 
			
		||||
@ -175,7 +177,7 @@ func TestPrestateTracerCreate2(t *testing.T) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("failed to create call tracer: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	evm := vm.NewEVM(context, statedb, params.MainnetChainConfig, vm.Config{Debug: true, Tracer: tracer})
 | 
			
		||||
	evm := vm.NewEVM(context, txContext, statedb, params.MainnetChainConfig, vm.Config{Debug: true, Tracer: tracer})
 | 
			
		||||
 | 
			
		||||
	msg, err := tx.AsMessage(signer)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@ -230,17 +232,18 @@ func TestCallTracer(t *testing.T) {
 | 
			
		||||
			}
 | 
			
		||||
			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,
 | 
			
		||||
				Origin:      origin,
 | 
			
		||||
				Coinbase:    test.Context.Miner,
 | 
			
		||||
				BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
 | 
			
		||||
				Time:        new(big.Int).SetUint64(uint64(test.Context.Time)),
 | 
			
		||||
				Difficulty:  (*big.Int)(test.Context.Difficulty),
 | 
			
		||||
				GasLimit:    uint64(test.Context.GasLimit),
 | 
			
		||||
				GasPrice:    tx.GasPrice(),
 | 
			
		||||
			}
 | 
			
		||||
			_, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false)
 | 
			
		||||
 | 
			
		||||
@ -249,7 +252,7 @@ func TestCallTracer(t *testing.T) {
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("failed to create call tracer: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
			evm := vm.NewEVM(context, statedb, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer})
 | 
			
		||||
			evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer})
 | 
			
		||||
 | 
			
		||||
			msg, err := tx.AsMessage(signer)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
 | 
			
		||||
@ -171,8 +171,9 @@ func (b *LesApiBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *LesApiBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) {
 | 
			
		||||
	context := core.NewEVMContext(msg, header, b.eth.blockchain, nil)
 | 
			
		||||
	return vm.NewEVM(context, state, b.eth.chainConfig, vm.Config{}), state.Error, nil
 | 
			
		||||
	txContext := core.NewEVMTxContext(msg)
 | 
			
		||||
	context := core.NewEVMBlockContext(header, b.eth.blockchain, nil)
 | 
			
		||||
	return vm.NewEVM(context, txContext, state, b.eth.chainConfig, vm.Config{}), state.Error, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *LesApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
 | 
			
		||||
 | 
			
		||||
@ -130,8 +130,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, false)}
 | 
			
		||||
 | 
			
		||||
				context := core.NewEVMContext(msg, header, bc, nil)
 | 
			
		||||
				vmenv := vm.NewEVM(context, statedb, config, vm.Config{})
 | 
			
		||||
				context := core.NewEVMBlockContext(header, bc, nil)
 | 
			
		||||
				txContext := core.NewEVMTxContext(msg)
 | 
			
		||||
				vmenv := vm.NewEVM(context, txContext, statedb, config, vm.Config{})
 | 
			
		||||
 | 
			
		||||
				//vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{})
 | 
			
		||||
				gp := new(core.GasPool).AddGas(math.MaxUint64)
 | 
			
		||||
@ -143,8 +144,9 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
 | 
			
		||||
			state := light.NewState(ctx, header, lc.Odr())
 | 
			
		||||
			state.SetBalance(bankAddr, math.MaxBig256)
 | 
			
		||||
			msg := callmsg{types.NewMessage(bankAddr, &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false)}
 | 
			
		||||
			context := core.NewEVMContext(msg, header, lc, nil)
 | 
			
		||||
			vmenv := vm.NewEVM(context, state, config, vm.Config{})
 | 
			
		||||
			context := core.NewEVMBlockContext(header, lc, nil)
 | 
			
		||||
			txContext := core.NewEVMTxContext(msg)
 | 
			
		||||
			vmenv := vm.NewEVM(context, txContext, state, config, vm.Config{})
 | 
			
		||||
			gp := new(core.GasPool).AddGas(math.MaxUint64)
 | 
			
		||||
			result, _ := core.ApplyMessage(vmenv, msg, gp)
 | 
			
		||||
			if state.Error() == nil {
 | 
			
		||||
 | 
			
		||||
@ -195,8 +195,9 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
 | 
			
		||||
		// Perform read-only call.
 | 
			
		||||
		st.SetBalance(testBankAddress, math.MaxBig256)
 | 
			
		||||
		msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, new(big.Int), data, false)}
 | 
			
		||||
		context := core.NewEVMContext(msg, header, chain, nil)
 | 
			
		||||
		vmenv := vm.NewEVM(context, st, config, vm.Config{})
 | 
			
		||||
		txContext := core.NewEVMTxContext(msg)
 | 
			
		||||
		context := core.NewEVMBlockContext(header, chain, nil)
 | 
			
		||||
		vmenv := vm.NewEVM(context, txContext, st, config, vm.Config{})
 | 
			
		||||
		gp := new(core.GasPool).AddGas(math.MaxUint64)
 | 
			
		||||
		result, _ := core.ApplyMessage(vmenv, msg, gp)
 | 
			
		||||
		res = append(res, result.Return()...)
 | 
			
		||||
 | 
			
		||||
@ -182,9 +182,10 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, common.Hash{}, err
 | 
			
		||||
	}
 | 
			
		||||
	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, config, vmconfig)
 | 
			
		||||
	evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)
 | 
			
		||||
 | 
			
		||||
	if config.IsYoloV2(context.BlockNumber) {
 | 
			
		||||
		statedb.AddAddressToAccessList(msg.From())
 | 
			
		||||
 | 
			
		||||
@ -138,20 +138,22 @@ 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,
 | 
			
		||||
	}
 | 
			
		||||
	vmconfig.NoRecursion = true
 | 
			
		||||
	return vm.NewEVM(context, statedb, params.MainnetChainConfig, vmconfig)
 | 
			
		||||
	return vm.NewEVM(context, txContext, statedb, params.MainnetChainConfig, vmconfig)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func vmTestBlockHash(n uint64) common.Hash {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user