Skip to content

Commit

Permalink
vm: Relocate Tracer invocation
Browse files Browse the repository at this point in the history
  • Loading branch information
blukat29 committed Jun 20, 2024
1 parent 4d6de84 commit ad73a12
Showing 1 changed file with 58 additions and 78 deletions.
136 changes: 58 additions & 78 deletions blockchain/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,21 @@ func (evm *EVM) Cancelled() bool {
// 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 types.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Debug {
if evm.depth == 0 { // top frame
evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
defer func(startGas uint64) {
evm.Config.Tracer.CaptureEnd(ret, startGas-leftOverGas, err)
}(gas)
} else { // rest of the frames
evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
defer func(startGas uint64) {
evm.Config.Tracer.CaptureExit(ret, startGas-leftOverGas, err)
}(gas)
}
}

if evm.Config.NoRecursion && evm.depth > 0 {
return nil, gas, nil
}
Expand All @@ -238,23 +253,13 @@ func (evm *EVM) Call(caller types.ContractRef, addr common.Address, input []byte
var (
to = AccountRef(addr)
snapshot = evm.StateDB.Snapshot()
debug = evm.Config.Debug
)

// Filter out invalid precompiled address calls, and create a precompiled contract object if it is not exist.
if common.IsPrecompiledContractAddress(addr) {
precompiles := evm.GetPrecompiledContractMap(caller.Address())
if precompiles[addr] == nil || value.Sign() != 0 {
// Return an error if an enabled precompiled address is called or a value is transferred to a precompiled address.
if debug {
if evm.depth == 0 {
evm.Config.Tracer.CaptureStart(evm, 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, kerrors.ErrPrecompiledContractAddress
}
// create an account object of the enabled precompiled address if not exist.
Expand All @@ -268,37 +273,13 @@ func (evm *EVM) Call(caller types.ContractRef, addr common.Address, input []byte
if !evm.StateDB.Exist(addr) {
if value.Sign() == 0 {
// Calling a non-existing account (probably contract), don't do anything, but ping the tracer
if debug {
if evm.depth == 0 {
evm.Config.Tracer.CaptureStart(evm, 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
}
// If non-existing address is called with a value, an object of the address is created.
evm.StateDB.CreateEOA(addr, false, accountkey.NewAccountKeyLegacy())
}
evm.Context.Transfer(evm.StateDB, caller.Address(), to.Address(), value)

if debug {
if evm.depth == 0 {
evm.Config.Tracer.CaptureStart(evm, 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 isProgramAccount(evm, caller.Address(), addr, evm.StateDB) {
// 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.
Expand Down Expand Up @@ -329,6 +310,14 @@ func (evm *EVM) Call(caller types.ContractRef, addr common.Address, input []byte
// CallCode differs from Call in the sense that it executes the given address'
// code with the caller as context.
func (evm *EVM) CallCode(caller types.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Debug { // Note that CALLCODE cannot be the top frame
evm.Config.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value)
defer func(startGas uint64) {
evm.Config.Tracer.CaptureExit(ret, startGas-leftOverGas, err)
}(gas)
}

if evm.Config.NoRecursion && evm.depth > 0 {
return nil, gas, nil
}
Expand All @@ -354,14 +343,6 @@ func (evm *EVM) CallCode(caller types.ContractRef, addr common.Address, input []
to = AccountRef(caller.Address())
)

// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Debug {
evm.Config.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value)
defer func(startGas uint64) {
evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
}(gas)
}

// 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.
contract := NewContract(caller, to, value, gas)
Expand All @@ -383,6 +364,18 @@ func (evm *EVM) CallCode(caller types.ContractRef, addr common.Address, input []
// 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 types.ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Debug { // Note that DELEGATECALL cannot be the top frame
// 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-leftOverGas, err)
}(gas)
}

if evm.Config.NoRecursion && evm.depth > 0 {
return nil, gas, nil
}
Expand All @@ -401,18 +394,6 @@ func (evm *EVM) DelegateCall(caller types.ContractRef, addr common.Address, inpu
to = AccountRef(caller.Address())
)

// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Debug {
// 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)
}

// Initialise a new contract and make initialise the delegate values
contract := NewContract(caller, to, nil, gas).AsDelegate()
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
Expand All @@ -432,6 +413,14 @@ func (evm *EVM) DelegateCall(caller types.ContractRef, addr common.Address, inpu
// Opcodes that attempt to perform such modifications will result in exceptions
// instead of performing the modifications.
func (evm *EVM) StaticCall(caller types.ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Debug { // Note that STATICCALL cannot be the top frame
evm.Config.Tracer.CaptureEnter(STATICCALL, caller.Address(), addr, input, gas, nil)
defer func(startGas uint64) {
evm.Config.Tracer.CaptureExit(ret, startGas-leftOverGas, err)
}(gas)
}

if evm.Config.NoRecursion && evm.depth > 0 {
return nil, gas, nil
}
Expand All @@ -457,14 +446,6 @@ func (evm *EVM) StaticCall(caller types.ContractRef, addr common.Address, input
snapshot = evm.StateDB.Snapshot()
)

// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Debug {
evm.Config.Tracer.CaptureEnter(STATICCALL, caller.Address(), addr, input, gas, nil)
defer func(startGas uint64) {
evm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
}(gas)
}

// 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.
contract := NewContract(caller, to, new(big.Int), gas)
Expand Down Expand Up @@ -497,6 +478,21 @@ func (c *codeAndHash) Hash() common.Hash {

// Create creates a new contract using code as deployment code.
func (evm *EVM) create(caller types.ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address, typ OpCode, humanReadable bool, codeFormat params.CodeFormat) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
// Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Debug {
if evm.depth == 0 {
evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value)
defer func(startGas uint64) {
evm.Config.Tracer.CaptureEnd(ret, startGas-leftOverGas, err)
}(gas)
} else {
evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value)
defer func(startGas uint64) {
evm.Config.Tracer.CaptureExit(ret, startGas-leftOverGas, err)
}(gas)
}
}

// Depth check execution. Fail if we're trying to execute above the
// limit.
if evm.depth > int(params.CallCreateDepth) {
Expand Down Expand Up @@ -554,14 +550,6 @@ func (evm *EVM) create(caller types.ContractRef, codeAndHash *codeAndHash, gas u
return nil, address, gas, nil
}

if evm.Config.Debug {
if evm.depth == 0 {
evm.Config.Tracer.CaptureStart(evm, 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)

// check whether the max code size has been exceeded
Expand Down Expand Up @@ -605,14 +593,6 @@ func (evm *EVM) create(caller types.ContractRef, codeAndHash *codeAndHash, gas u
err = ErrInvalidCode
}

if evm.Config.Debug {
if evm.depth == 0 {
evm.Config.Tracer.CaptureEnd(ret, gas-contract.Gas, err)
} else {
evm.Config.Tracer.CaptureExit(ret, gas-contract.Gas, err)
}
}

return ret, address, contract.Gas, err
}

Expand Down

0 comments on commit ad73a12

Please sign in to comment.