Move up CaptureStart/CaptureEnd as well as CaptureEnter/CaptureExit higher directly when function starts

This commit is contained in:
Matthieu Vachon 2023-07-25 14:35:47 -04:00
parent 751b984c9b
commit dd86f19df4
2 changed files with 36 additions and 96 deletions

View file

@ -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
}

View file

@ -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)
}