|
|
|
@ -128,7 +128,7 @@ type EVM struct { |
|
|
|
|
chainRules params.Rules |
|
|
|
|
// virtual machine configuration options used to initialise the
|
|
|
|
|
// evm.
|
|
|
|
|
vmConfig Config |
|
|
|
|
Config Config |
|
|
|
|
// global (to this context) ethereum virtual machine
|
|
|
|
|
// used throughout the execution of the tx.
|
|
|
|
|
interpreters []Interpreter |
|
|
|
@ -144,12 +144,12 @@ type EVM struct { |
|
|
|
|
|
|
|
|
|
// NewEVM returns a new EVM. The returned EVM is not thread safe and should
|
|
|
|
|
// only ever be used *once*.
|
|
|
|
|
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM { |
|
|
|
|
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM { |
|
|
|
|
evm := &EVM{ |
|
|
|
|
Context: blockCtx, |
|
|
|
|
TxContext: txCtx, |
|
|
|
|
StateDB: statedb, |
|
|
|
|
vmConfig: vmConfig, |
|
|
|
|
Config: config, |
|
|
|
|
chainConfig: chainConfig, |
|
|
|
|
chainRules: chainConfig.Rules(blockCtx.BlockNumber), |
|
|
|
|
interpreters: make([]Interpreter, 0, 1), |
|
|
|
@ -173,7 +173,7 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig |
|
|
|
|
|
|
|
|
|
// vmConfig.EVMInterpreter will be used by EVM-C, it won't be checked here
|
|
|
|
|
// as we always want to have the built-in EVM as the failover option.
|
|
|
|
|
evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, vmConfig)) |
|
|
|
|
evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, config)) |
|
|
|
|
evm.interpreter = evm.interpreters[0] |
|
|
|
|
|
|
|
|
|
return evm |
|
|
|
@ -207,7 +207,7 @@ func (evm *EVM) Interpreter() Interpreter { |
|
|
|
|
// the necessary steps to create accounts and reverses the state in case of an
|
|
|
|
|
// execution error or failed value transfer.
|
|
|
|
|
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { |
|
|
|
|
if evm.vmConfig.NoRecursion && evm.depth > 0 { |
|
|
|
|
if evm.Config.NoRecursion && evm.depth > 0 { |
|
|
|
|
return nil, gas, nil |
|
|
|
|
} |
|
|
|
|
// Fail if we're trying to execute above the call depth limit
|
|
|
|
@ -224,9 +224,9 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas |
|
|
|
|
if !evm.StateDB.Exist(addr) { |
|
|
|
|
if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 { |
|
|
|
|
// Calling a non existing account, don't do anything, but ping the tracer
|
|
|
|
|
if evm.vmConfig.Debug && evm.depth == 0 { |
|
|
|
|
evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) |
|
|
|
|
evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil) |
|
|
|
|
if evm.Config.Debug && evm.depth == 0 { |
|
|
|
|
evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) |
|
|
|
|
evm.Config.Tracer.CaptureEnd(ret, 0, 0, nil) |
|
|
|
|
} |
|
|
|
|
return nil, gas, nil |
|
|
|
|
} |
|
|
|
@ -235,10 +235,10 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas |
|
|
|
|
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 { |
|
|
|
|
evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) |
|
|
|
|
if evm.Config.Debug && evm.depth == 0 { |
|
|
|
|
evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) |
|
|
|
|
defer func(startGas uint64, startTime time.Time) { // Lazy evaluation of the parameters
|
|
|
|
|
evm.vmConfig.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err) |
|
|
|
|
evm.Config.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err) |
|
|
|
|
}(gas, time.Now()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -283,7 +283,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas |
|
|
|
|
// CallCode differs from Call in the sense that it executes the given address'
|
|
|
|
|
// code with the caller as context.
|
|
|
|
|
func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { |
|
|
|
|
if evm.vmConfig.NoRecursion && evm.depth > 0 { |
|
|
|
|
if evm.Config.NoRecursion && evm.depth > 0 { |
|
|
|
|
return nil, gas, nil |
|
|
|
|
} |
|
|
|
|
// Fail if we're trying to execute above the call depth limit
|
|
|
|
@ -326,7 +326,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, |
|
|
|
|
// DelegateCall differs from CallCode in the sense that it executes the given address'
|
|
|
|
|
// code with the caller as context and the caller is set to the caller of the caller.
|
|
|
|
|
func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { |
|
|
|
|
if evm.vmConfig.NoRecursion && evm.depth > 0 { |
|
|
|
|
if evm.Config.NoRecursion && evm.depth > 0 { |
|
|
|
|
return nil, gas, nil |
|
|
|
|
} |
|
|
|
|
// Fail if we're trying to execute above the call depth limit
|
|
|
|
@ -360,7 +360,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by |
|
|
|
|
// Opcodes that attempt to perform such modifications will result in exceptions
|
|
|
|
|
// instead of performing the modifications.
|
|
|
|
|
func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { |
|
|
|
|
if evm.vmConfig.NoRecursion && evm.depth > 0 { |
|
|
|
|
if evm.Config.NoRecursion && evm.depth > 0 { |
|
|
|
|
return nil, gas, nil |
|
|
|
|
} |
|
|
|
|
// Fail if we're trying to execute above the call depth limit
|
|
|
|
@ -453,12 +453,12 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, |
|
|
|
|
contract := NewContract(caller, AccountRef(address), value, gas) |
|
|
|
|
contract.SetCodeOptionalHash(&address, codeAndHash) |
|
|
|
|
|
|
|
|
|
if evm.vmConfig.NoRecursion && evm.depth > 0 { |
|
|
|
|
if evm.Config.NoRecursion && evm.depth > 0 { |
|
|
|
|
return nil, address, gas, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if evm.vmConfig.Debug && evm.depth == 0 { |
|
|
|
|
evm.vmConfig.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value) |
|
|
|
|
if evm.Config.Debug && evm.depth == 0 { |
|
|
|
|
evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value) |
|
|
|
|
} |
|
|
|
|
start := time.Now() |
|
|
|
|
|
|
|
|
@ -497,8 +497,8 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if evm.vmConfig.Debug && evm.depth == 0 { |
|
|
|
|
evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err) |
|
|
|
|
if evm.Config.Debug && evm.depth == 0 { |
|
|
|
|
evm.Config.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err) |
|
|
|
|
} |
|
|
|
|
return ret, address, contract.Gas, err |
|
|
|
|
} |
|
|
|
|