core/evm: refactor CALL

This commit is contained in:
Martin Holst Swende 2018-05-23 12:41:33 +02:00
parent c3c07bc755
commit 56819e1de5
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0

View file

@ -168,9 +168,11 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
snapshot = evm.StateDB.Snapshot() snapshot = evm.StateDB.Snapshot()
) )
exists := evm.StateDB.Exist(addr) exists := evm.StateDB.Exist(addr)
precompile, isPrecompile := evm.BlockContext.Precompiles[addr]
if !exists{ if !exists{
if evm.BlockContext.Precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockContext.BlockNumber) && value.Sign() == 0 { if !isPrecompile && evm.ChainConfig().IsEIP158(evm.BlockContext.BlockNumber) && value.Sign() == 0 {
// Calling a non existing account, don't do antything, but ping the tracer // Calling a non existing account, don't do anything, but ping the tracer
if evm.vmConfig.Debug && evm.depth == 0 { if evm.vmConfig.Debug && evm.depth == 0 {
evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil) evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil)
@ -181,49 +183,48 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
} }
evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value) evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
precompile, isPrecompile := evm.BlockContext.Precompiles[addr]
if !exists && !isPrecompile{
// Shortcut execution -- account didn't exist,
// so no need to lookup the code
// but make sure to set returndata to nil
evm.interpreter.returnData = nil
return nil, gas, nil
}
code := evm.StateDB.GetCode(addr)
codeHash := evm.StateDB.GetCodeHash(addr)
if !isPrecompile && len(code) == 0 {
// Shortcut execution if there is no code,
// but make sure to set returndata to nil
evm.interpreter.returnData = nil
return nil, gas, nil
}
// 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.
var contract *Contract var contract *Contract
if isPrecompile{
if!isPrecompile { // A 'contract' is needed for gas accounting
contract = NewPrecompiledContract(caller, to, value, gas)
ret, err = RunPrecompiledContract(precompile, input, contract)
// Capture the tracer start/end events in debug mode
if evm.vmConfig.Debug && evm.depth == 0 {
start := time.Now()
evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
defer func() { // Lazy evaluation of the parameters
evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
}()
}
}else{
if !exists{
// Shortcut execution -- account didn't exist,
// so no need to lookup the code
// but make sure to set returndata to nil
evm.interpreter.returnData = nil
return nil, gas, nil
}
code := evm.StateDB.GetCode(addr)
if len(code) == 0 {
// Shortcut execution if there is no code,
// but make sure to set returndata to nil
evm.interpreter.returnData = nil
return nil, gas, nil
}
codeHash := evm.StateDB.GetCodeHash(addr)
contract = NewContract(caller, to, value, gas) contract = NewContract(caller, to, value, gas)
contract.SetCallCode(&addr, codeHash, code) contract.SetCallCode(&addr, codeHash, code)
}else{
contract = NewPrecompiledContract(caller, to, value, gas)
}
// Capture the tracer start/end events in debug mode
if evm.vmConfig.Debug && evm.depth == 0 {
start := time.Now()
evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
defer func() { // Lazy evaluation of the parameters // Capture the tracer start/end events in debug mode
evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err) if evm.vmConfig.Debug && evm.depth == 0 {
}() start := time.Now()
} evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
if!isPrecompile{ defer func() { // Lazy evaluation of the parameters
evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
}()
}
ret, err = evm.interpreter.Run(contract, input) ret, err = evm.interpreter.Run(contract, input)
}else{
ret, err = RunPrecompiledContract(precompile, input, contract)
} }
// When an error was returned by the EVM or when setting the creation code // 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 // above we revert to the snapshot and consume any gas remaining. Additionally