mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 02:12:23 +00:00
core/vm: don't check code for non-existing accounts
This commit is contained in:
parent
4394e4dc38
commit
c3c07bc755
2 changed files with 36 additions and 7 deletions
|
|
@ -64,6 +64,18 @@ type Contract struct {
|
||||||
DelegateCall bool
|
DelegateCall bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewPrecompiledContract( caller ContractRef, object ContractRef,value *big.Int, gas uint64) *Contract{
|
||||||
|
|
||||||
|
c := &Contract{CallerAddress: caller.Address(), caller: caller, self: object, Args: nil}
|
||||||
|
// Gas should be a pointer so it can safely be reduced through the run
|
||||||
|
// This pointer will be off the state transition
|
||||||
|
c.Gas = gas
|
||||||
|
// ensures a value is set
|
||||||
|
c.value = value
|
||||||
|
return c
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// NewContract returns a new contract environment for the execution of EVM.
|
// NewContract returns a new contract environment for the execution of EVM.
|
||||||
func NewContract(caller ContractRef, object ContractRef, value *big.Int, gas uint64) *Contract {
|
func NewContract(caller ContractRef, object ContractRef, value *big.Int, gas uint64) *Contract {
|
||||||
c := &Contract{CallerAddress: caller.Address(), caller: caller, self: object, Args: nil}
|
c := &Contract{CallerAddress: caller.Address(), caller: caller, self: object, Args: nil}
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,8 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
||||||
to = AccountRef(addr)
|
to = AccountRef(addr)
|
||||||
snapshot = evm.StateDB.Snapshot()
|
snapshot = evm.StateDB.Snapshot()
|
||||||
)
|
)
|
||||||
if !evm.StateDB.Exist(addr) {
|
exists := evm.StateDB.Exist(addr)
|
||||||
|
if !exists{
|
||||||
if evm.BlockContext.Precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockContext.BlockNumber) && value.Sign() == 0 {
|
if evm.BlockContext.Precompiles[addr] == nil && 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 antything, but ping the tracer
|
||||||
if evm.vmConfig.Debug && evm.depth == 0 {
|
if evm.vmConfig.Debug && evm.depth == 0 {
|
||||||
|
|
@ -180,9 +181,17 @@ 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)
|
code := evm.StateDB.GetCode(addr)
|
||||||
codeHash := evm.StateDB.GetCodeHash(addr)
|
codeHash := evm.StateDB.GetCodeHash(addr)
|
||||||
_, isPrecompile := evm.BlockContext.Precompiles[addr]
|
|
||||||
|
|
||||||
if !isPrecompile && len(code) == 0 {
|
if !isPrecompile && len(code) == 0 {
|
||||||
// Shortcut execution if there is no code,
|
// Shortcut execution if there is no code,
|
||||||
|
|
@ -193,21 +202,29 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
||||||
|
|
||||||
// Initialise a new contract and set the code that is to be used by the EVM.
|
// 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.
|
// The contract is a scoped environment for this execution context only.
|
||||||
contract := NewContract(caller, to, value, gas)
|
var contract *Contract
|
||||||
contract.SetCallCode(&addr, codeHash, code)
|
|
||||||
|
|
||||||
start := time.Now()
|
|
||||||
|
|
||||||
|
if!isPrecompile {
|
||||||
|
contract = NewContract(caller, to, value, gas)
|
||||||
|
contract.SetCallCode(&addr, codeHash, code)
|
||||||
|
}else{
|
||||||
|
contract = NewPrecompiledContract(caller, to, value, gas)
|
||||||
|
}
|
||||||
// Capture the tracer start/end events in debug mode
|
// Capture the tracer start/end events in debug mode
|
||||||
if evm.vmConfig.Debug && evm.depth == 0 {
|
if evm.vmConfig.Debug && evm.depth == 0 {
|
||||||
|
start := time.Now()
|
||||||
evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
|
evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
|
||||||
|
|
||||||
defer func() { // Lazy evaluation of the parameters
|
defer func() { // Lazy evaluation of the parameters
|
||||||
evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
|
evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
ret, err = run(evm, contract, input)
|
|
||||||
|
|
||||||
|
if!isPrecompile{
|
||||||
|
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
|
||||||
// when we're in homestead this also counts for code storage gas errors.
|
// when we're in homestead this also counts for code storage gas errors.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue