mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-12 06:53:46 +00:00
Move up CaptureStart/CaptureEnd as well as CaptureEnter/CaptureExit higher directly when function starts
This commit is contained in:
parent
751b984c9b
commit
dd86f19df4
2 changed files with 36 additions and 96 deletions
127
core/vm/evm.go
127
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
|
// the necessary steps to create accounts and reverses the state in case of an
|
||||||
// execution error or failed value transfer.
|
// 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) {
|
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 {
|
if tracer := evm.Config.Tracer; tracer != nil {
|
||||||
v.CaptureCallStart(CALL, caller.Address(), addr, input, gas, value)
|
if evm.depth == 0 {
|
||||||
defer func(startGas uint64) {
|
tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
|
||||||
v.CaptureCallEnd(ret, startGas-gas, err)
|
defer func(startGas uint64) { // Lazy evaluation of the parameters
|
||||||
}(gas)
|
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
|
// 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()
|
snapshot := evm.StateDB.Snapshot()
|
||||||
p, isPrecompile := evm.precompile(addr)
|
p, isPrecompile := evm.precompile(addr)
|
||||||
debug := evm.Config.Tracer != nil
|
|
||||||
|
|
||||||
if !evm.StateDB.Exist(addr) {
|
if !evm.StateDB.Exist(addr) {
|
||||||
if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 {
|
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
|
return nil, gas, nil
|
||||||
}
|
}
|
||||||
evm.StateDB.CreateAccount(addr)
|
evm.StateDB.CreateAccount(addr)
|
||||||
}
|
}
|
||||||
evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value)
|
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 {
|
if isPrecompile {
|
||||||
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
|
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
|
||||||
} else {
|
} 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'
|
// CallCode differs from Call in the sense that it executes the given address'
|
||||||
// code with the caller as context.
|
// 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) {
|
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 {
|
// Invoke tracer hooks that signal entering/exiting a call frame
|
||||||
v.CaptureCallStart(CALLCODE, caller.Address(), addr, input, gas, value)
|
if tracer := evm.Config.Tracer; tracer != nil {
|
||||||
|
tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value)
|
||||||
defer func(startGas uint64) {
|
defer func(startGas uint64) {
|
||||||
v.CaptureCallEnd(ret, startGas-gas, err)
|
tracer.CaptureExit(ret, startGas-gas, err)
|
||||||
}(gas)
|
}(gas)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -290,14 +272,6 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
|
||||||
}
|
}
|
||||||
var snapshot = evm.StateDB.Snapshot()
|
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
|
// It is allowed to call precompiles, even via delegatecall
|
||||||
if p, isPrecompile := evm.precompile(addr); isPrecompile {
|
if p, isPrecompile := evm.precompile(addr); isPrecompile {
|
||||||
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
|
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'
|
// 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.
|
// 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) {
|
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)
|
parent := caller.(*Contract)
|
||||||
|
// DELEGATECALL inherits value from parent call
|
||||||
v.CaptureCallStart(DELEGATECALL, caller.Address(), addr, input, gas, parent.value)
|
tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, parent.value)
|
||||||
defer func(startGas uint64) {
|
defer func(startGas uint64) {
|
||||||
v.CaptureCallEnd(ret, startGas-gas, err)
|
tracer.CaptureExit(ret, startGas-gas, err)
|
||||||
}(gas)
|
}(gas)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -340,18 +317,6 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
|
||||||
}
|
}
|
||||||
var snapshot = evm.StateDB.Snapshot()
|
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
|
// It is allowed to call precompiles, even via delegatecall
|
||||||
if p, isPrecompile := evm.precompile(addr); isPrecompile {
|
if p, isPrecompile := evm.precompile(addr); isPrecompile {
|
||||||
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
|
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
|
// Opcodes that attempt to perform such modifications will result in exceptions
|
||||||
// instead of performing the modifications.
|
// instead of performing the modifications.
|
||||||
func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
|
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 {
|
// Invoke tracer hooks that signal entering/exiting a call frame
|
||||||
v.CaptureCallStart(STATICCALL, caller.Address(), addr, input, gas, nil)
|
if tracer := evm.Config.Tracer; tracer != nil {
|
||||||
|
tracer.CaptureEnter(STATICCALL, caller.Address(), addr, input, gas, nil)
|
||||||
defer func(startGas uint64) {
|
defer func(startGas uint64) {
|
||||||
v.CaptureCallEnd(ret, startGas-gas, err)
|
tracer.CaptureExit(ret, startGas-gas, err)
|
||||||
}(gas)
|
}(gas)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -401,14 +367,6 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
|
||||||
// future scenarios
|
// future scenarios
|
||||||
evm.StateDB.AddBalance(addr, big0, state.BalanceChangeTouchAccount)
|
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 {
|
if p, isPrecompile := evm.precompile(addr); isPrecompile {
|
||||||
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
|
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -449,11 +407,14 @@ func (c *codeAndHash) Hash() common.Hash {
|
||||||
|
|
||||||
// create creates a new contract using code as deployment code.
|
// 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) {
|
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 {
|
if tracer := evm.Config.Tracer; tracer != nil {
|
||||||
v.CaptureCallStart(typ, caller.Address(), address, codeAndHash.code, gas, nil)
|
if evm.depth == 0 {
|
||||||
defer func(startGas uint64) {
|
tracer.CaptureStart(caller.Address(), address, true, codeAndHash.code, gas, value)
|
||||||
v.CaptureCallEnd(ret, startGas-leftOverGas, err)
|
defer tracer.CaptureEnd(ret, gas-leftOverGas, err)
|
||||||
}(gas)
|
} 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
|
// 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 := NewContract(caller, AccountRef(address), value, gas)
|
||||||
contract.SetCodeOptionalHash(&address, codeAndHash)
|
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)
|
ret, err = evm.interpreter.Run(contract, nil, false)
|
||||||
|
|
||||||
// Check whether the max code size has been exceeded, assign err if the case.
|
// 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
|
leftOverGas = contract.Gas
|
||||||
return ret, address, contract.Gas, err
|
return ret, address, contract.Gas, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,3 @@ type EVMLogger interface {
|
||||||
// Misc
|
// Misc
|
||||||
OnGasConsumed(gas, amount uint64)
|
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)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue