diff --git a/core/vm/evm.go b/core/vm/evm.go index 60f60629c9..3d30c3bb50 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -176,11 +176,19 @@ func (evm *EVM) SetBlockContext(blockCtx BlockContext) { // 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 v, ok := evm.Config.Tracer.(EVMLoggerExtended); evm.Config.Tracer != nil && ok { - v.CaptureCallStart(CALL, caller.Address(), addr, input, gas, value) - defer func(startGas uint64) { - v.CaptureCallEnd(ret, startGas-gas, err) - }(gas) + if tracer := evm.Config.Tracer; tracer != nil { + if evm.depth == 0 { + tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) + defer func(startGas uint64) { // Lazy evaluation of the parameters + tracer.CaptureEnd(ret, startGas-gas, err) + }(gas) + } else { + // Handle tracer events for entering and exiting a call frame + tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value) + defer func(startGas uint64) { + tracer.CaptureExit(ret, startGas-gas, err) + }(gas) + } } // Fail if we're trying to execute above the call depth limit @@ -193,42 +201,15 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas } snapshot := evm.StateDB.Snapshot() p, isPrecompile := evm.precompile(addr) - debug := evm.Config.Tracer != nil 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 debug { - if evm.depth == 0 { - evm.Config.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) - evm.Config.Tracer.CaptureEnd(ret, 0, nil) - } else { - evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value) - evm.Config.Tracer.CaptureExit(ret, 0, nil) - } - } return nil, gas, nil } evm.StateDB.CreateAccount(addr) } evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value) - // Capture the tracer start/end events in debug mode - if debug { - if evm.depth == 0 { - evm.Config.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) - defer func(startGas uint64) { // Lazy evaluation of the parameters - evm.Config.Tracer.CaptureEnd(ret, startGas-gas, err) - }(gas) - } else { - // Handle tracer events for entering and exiting a call frame - evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value) - defer func(startGas uint64) { - evm.Config.Tracer.CaptureExit(ret, startGas-gas, err) - }(gas) - } - } - if isPrecompile { ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) } else { @@ -270,10 +251,11 @@ 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 v, ok := evm.Config.Tracer.(EVMLoggerExtended); evm.Config.Tracer != nil && ok { - v.CaptureCallStart(CALLCODE, caller.Address(), addr, input, gas, value) + // Invoke tracer hooks that signal entering/exiting a call frame + if tracer := evm.Config.Tracer; tracer != nil { + tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value) defer func(startGas uint64) { - v.CaptureCallEnd(ret, startGas-gas, err) + tracer.CaptureExit(ret, startGas-gas, err) }(gas) } @@ -290,14 +272,6 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, } var snapshot = evm.StateDB.Snapshot() - // Invoke tracer hooks that signal entering/exiting a call frame - if evm.Config.Tracer != nil { - evm.Config.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value) - defer func(startGas uint64) { - evm.Config.Tracer.CaptureExit(ret, startGas-gas, err) - }(gas) - } - // It is allowed to call precompiles, even via delegatecall if p, isPrecompile := evm.precompile(addr); isPrecompile { ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) @@ -325,12 +299,15 @@ 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 v, ok := evm.Config.Tracer.(EVMLoggerExtended); evm.Config.Tracer != nil && ok { + // Invoke tracer hooks that signal entering/exiting a call frame + if tracer := evm.Config.Tracer; tracer != nil { + // NOTE: caller must, at all times be a contract. It should never happen + // that caller is something other than a Contract. parent := caller.(*Contract) - - v.CaptureCallStart(DELEGATECALL, caller.Address(), addr, input, gas, parent.value) + // DELEGATECALL inherits value from parent call + tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, parent.value) defer func(startGas uint64) { - v.CaptureCallEnd(ret, startGas-gas, err) + tracer.CaptureExit(ret, startGas-gas, err) }(gas) } @@ -340,18 +317,6 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by } var snapshot = evm.StateDB.Snapshot() - // Invoke tracer hooks that signal entering/exiting a call frame - if evm.Config.Tracer != nil { - // NOTE: caller must, at all times be a contract. It should never happen - // that caller is something other than a Contract. - parent := caller.(*Contract) - // DELEGATECALL inherits value from parent call - evm.Config.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, parent.value) - defer func(startGas uint64) { - evm.Config.Tracer.CaptureExit(ret, startGas-gas, err) - }(gas) - } - // It is allowed to call precompiles, even via delegatecall if p, isPrecompile := evm.precompile(addr); isPrecompile { ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) @@ -377,10 +342,11 @@ 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 v, ok := evm.Config.Tracer.(EVMLoggerExtended); evm.Config.Tracer != nil && ok { - v.CaptureCallStart(STATICCALL, caller.Address(), addr, input, gas, nil) + // Invoke tracer hooks that signal entering/exiting a call frame + if tracer := evm.Config.Tracer; tracer != nil { + tracer.CaptureEnter(STATICCALL, caller.Address(), addr, input, gas, nil) defer func(startGas uint64) { - v.CaptureCallEnd(ret, startGas-gas, err) + tracer.CaptureExit(ret, startGas-gas, err) }(gas) } @@ -401,14 +367,6 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte // future scenarios evm.StateDB.AddBalance(addr, big0, state.BalanceChangeTouchAccount) - // Invoke tracer hooks that signal entering/exiting a call frame - if evm.Config.Tracer != nil { - evm.Config.Tracer.CaptureEnter(STATICCALL, caller.Address(), addr, input, gas, nil) - defer func(startGas uint64) { - evm.Config.Tracer.CaptureExit(ret, startGas-gas, err) - }(gas) - } - if p, isPrecompile := evm.precompile(addr); isPrecompile { ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) } else { @@ -449,11 +407,14 @@ func (c *codeAndHash) Hash() common.Hash { // create creates a new contract using code as deployment code. func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address, typ OpCode) (ret []byte, created common.Address, leftOverGas uint64, err error) { - if v, ok := evm.Config.Tracer.(EVMLoggerExtended); evm.Config.Tracer != nil && ok { - v.CaptureCallStart(typ, caller.Address(), address, codeAndHash.code, gas, nil) - defer func(startGas uint64) { - v.CaptureCallEnd(ret, startGas-leftOverGas, err) - }(gas) + if tracer := evm.Config.Tracer; tracer != nil { + if evm.depth == 0 { + tracer.CaptureStart(caller.Address(), address, true, codeAndHash.code, gas, value) + defer tracer.CaptureEnd(ret, gas-leftOverGas, err) + } else { + tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value) + defer tracer.CaptureExit(ret, gas-leftOverGas, err) + } } // Depth check execution. Fail if we're trying to execute above the @@ -492,14 +453,6 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, contract := NewContract(caller, AccountRef(address), value, gas) contract.SetCodeOptionalHash(&address, codeAndHash) - if evm.Config.Tracer != nil { - if evm.depth == 0 { - evm.Config.Tracer.CaptureStart(caller.Address(), address, true, codeAndHash.code, gas, value) - } else { - evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value) - } - } - ret, err = evm.interpreter.Run(contract, nil, false) // Check whether the max code size has been exceeded, assign err if the case. @@ -535,14 +488,6 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, } } - if evm.Config.Tracer != nil { - if evm.depth == 0 { - evm.Config.Tracer.CaptureEnd(ret, gas-contract.Gas, err) - } else { - evm.Config.Tracer.CaptureExit(ret, gas-contract.Gas, err) - } - } - leftOverGas = contract.Gas return ret, address, contract.Gas, err } diff --git a/core/vm/logger.go b/core/vm/logger.go index e35ca95c6b..b7b0fc4d8e 100644 --- a/core/vm/logger.go +++ b/core/vm/logger.go @@ -45,8 +45,3 @@ type EVMLogger interface { // Misc OnGasConsumed(gas, amount uint64) } - -type EVMLoggerExtended interface { - CaptureCallStart(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) - CaptureCallEnd(output []byte, gasUsed uint64, err error) -}