mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 03:30:37 +00:00
impr(evm): Move callstack depth to the interpreter (#6632)
This is a more logical / semantically correct place to keep track of the call stack depth.
This commit is contained in:
parent
f2111b4132
commit
b8fcb775e3
@ -77,8 +77,6 @@ type EVM struct {
|
||||
txContext evmtypes.TxContext
|
||||
// IntraBlockState gives access to the underlying state
|
||||
intraBlockState evmtypes.IntraBlockState
|
||||
// Depth is the current call stack
|
||||
depth int
|
||||
|
||||
// chainConfig contains information about the current chain
|
||||
chainConfig *chain.Config
|
||||
@ -150,21 +148,6 @@ func (evm *EVM) Cancelled() bool {
|
||||
return atomic.LoadInt32(&evm.abort) == 1
|
||||
}
|
||||
|
||||
// Depth returns the current call stack depth
|
||||
func (evm *EVM) Depth() int {
|
||||
return evm.depth
|
||||
}
|
||||
|
||||
// IncrementDepth increments the call stack depth
|
||||
func (evm *EVM) IncrementDepth() {
|
||||
evm.depth++
|
||||
}
|
||||
|
||||
// DecrementDepth decrements the call stack depth
|
||||
func (evm *EVM) DecrementDepth() {
|
||||
evm.depth--
|
||||
}
|
||||
|
||||
// CallGasTemp returns the callGasTemp for the EVM
|
||||
func (evm *EVM) CallGasTemp() uint64 {
|
||||
return evm.callGasTemp
|
||||
@ -181,11 +164,11 @@ func (evm *EVM) Interpreter() Interpreter {
|
||||
}
|
||||
|
||||
func (evm *EVM) call(typ OpCode, caller ContractRef, addr libcommon.Address, input []byte, gas uint64, value *uint256.Int, bailout bool) (ret []byte, leftOverGas uint64, err error) {
|
||||
if evm.config.NoRecursion && evm.depth > 0 {
|
||||
if evm.config.NoRecursion && evm.interpreter.Depth() > 0 {
|
||||
return nil, gas, nil
|
||||
}
|
||||
// Fail if we're trying to execute above the call depth limit
|
||||
if evm.depth > int(params.CallCreateDepth) {
|
||||
if evm.interpreter.Depth() > int(params.CallCreateDepth) {
|
||||
return nil, gas, ErrDepth
|
||||
}
|
||||
if typ == CALL || typ == CALLCODE {
|
||||
@ -213,7 +196,7 @@ func (evm *EVM) call(typ OpCode, caller ContractRef, addr libcommon.Address, inp
|
||||
v = nil
|
||||
}
|
||||
// Calling a non existing account, don't do anything, but ping the tracer
|
||||
if evm.depth == 0 {
|
||||
if evm.interpreter.Depth() == 0 {
|
||||
evm.config.Tracer.CaptureStart(evm, caller.Address(), addr, isPrecompile, false /* create */, input, gas, v, code)
|
||||
defer func(startGas uint64) { // Lazy evaluation of the parameters
|
||||
evm.config.Tracer.CaptureEnd(ret, 0, err)
|
||||
@ -242,7 +225,7 @@ func (evm *EVM) call(typ OpCode, caller ContractRef, addr libcommon.Address, inp
|
||||
if typ == STATICCALL {
|
||||
v = nil
|
||||
}
|
||||
if evm.depth == 0 {
|
||||
if evm.interpreter.Depth() == 0 {
|
||||
evm.config.Tracer.CaptureStart(evm, caller.Address(), addr, isPrecompile, false /* create */, input, gas, v, code)
|
||||
defer func(startGas uint64) { // Lazy evaluation of the parameters
|
||||
evm.config.Tracer.CaptureEnd(ret, startGas-gas, err)
|
||||
@ -355,7 +338,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
||||
var err error
|
||||
// Depth check execution. Fail if we're trying to execute above the
|
||||
// limit.
|
||||
if evm.depth > int(params.CallCreateDepth) {
|
||||
if evm.interpreter.Depth() > int(params.CallCreateDepth) {
|
||||
return nil, libcommon.Address{}, gas, ErrDepth
|
||||
}
|
||||
if !evm.context.CanTransfer(evm.intraBlockState, caller.Address(), value) {
|
||||
@ -393,14 +376,14 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
||||
contract.SetCodeOptionalHash(&address, codeAndHash)
|
||||
|
||||
if evm.config.Debug {
|
||||
if evm.depth == 0 {
|
||||
if evm.interpreter.Depth() == 0 {
|
||||
evm.config.Tracer.CaptureStart(evm, caller.Address(), address, false /* precompile */, true /* create */, codeAndHash.code, gas, value, nil)
|
||||
} else {
|
||||
evm.config.Tracer.CaptureEnter(typ, caller.Address(), address, false /* precompile */, true /* create */, codeAndHash.code, gas, value, nil)
|
||||
}
|
||||
}
|
||||
|
||||
if evm.config.NoRecursion && evm.depth > 0 {
|
||||
if evm.config.NoRecursion && evm.interpreter.Depth() > 0 {
|
||||
return nil, address, gas, nil
|
||||
}
|
||||
|
||||
@ -439,7 +422,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
||||
}
|
||||
|
||||
if evm.config.Debug {
|
||||
if evm.depth == 0 {
|
||||
if evm.interpreter.Depth() == 0 {
|
||||
evm.config.Tracer.CaptureEnd(ret, gas-contract.Gas, err)
|
||||
} else {
|
||||
evm.config.Tracer.CaptureExit(ret, gas-contract.Gas, err)
|
||||
|
@ -57,9 +57,6 @@ type VMInterface interface {
|
||||
type VMInterpreter interface {
|
||||
VMInterface
|
||||
Cancelled() bool
|
||||
IncrementDepth()
|
||||
DecrementDepth()
|
||||
Depth() int
|
||||
SetCallGasTemp(gas uint64)
|
||||
CallGasTemp() uint64
|
||||
StaticCall(caller ContractRef, addr libcommon.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error)
|
||||
|
@ -60,6 +60,9 @@ type Interpreter interface {
|
||||
// Run loops and evaluates the contract's code with the given input data and returns
|
||||
// the return byte-slice and an error if one occurred.
|
||||
Run(contract *Contract, input []byte, static bool) ([]byte, error)
|
||||
|
||||
// `Depth` returns the current call stack's depth.
|
||||
Depth() int
|
||||
}
|
||||
|
||||
// ScopeContext contains the things that are per-call, such as stack and memory,
|
||||
@ -81,7 +84,8 @@ type keccakState interface {
|
||||
// EVMInterpreter represents an EVM interpreter
|
||||
type EVMInterpreter struct {
|
||||
*VM
|
||||
jt *JumpTable // EVM instruction table
|
||||
jt *JumpTable // EVM instruction table
|
||||
depth int
|
||||
}
|
||||
|
||||
// structcheck doesn't see embedding
|
||||
@ -164,8 +168,8 @@ func NewEVMInterpreter(evm VMInterpreter, cfg Config) *EVMInterpreter {
|
||||
// ErrExecutionReverted which means revert-and-keep-gas-left.
|
||||
func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) {
|
||||
// Increment the call depth which is restricted to 1024
|
||||
in.evm.IncrementDepth()
|
||||
defer func() { in.evm.DecrementDepth() }()
|
||||
in.depth++
|
||||
defer func() { in.depth-- }()
|
||||
|
||||
// Make sure the readOnly is only set if we aren't in readOnly yet.
|
||||
// This makes also sure that the readOnly flag isn't removed for child calls.
|
||||
@ -212,9 +216,9 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if !logged {
|
||||
in.cfg.Tracer.CaptureState(pcCopy, op, gasCopy, cost, callContext, in.returnData, in.evm.Depth(), err) //nolint:errcheck
|
||||
in.cfg.Tracer.CaptureState(pcCopy, op, gasCopy, cost, callContext, in.returnData, in.depth, err) //nolint:errcheck
|
||||
} else {
|
||||
in.cfg.Tracer.CaptureFault(pcCopy, op, gasCopy, cost, callContext, in.evm.Depth(), err)
|
||||
in.cfg.Tracer.CaptureFault(pcCopy, op, gasCopy, cost, callContext, in.depth, err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
@ -278,7 +282,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
||||
}
|
||||
}
|
||||
if in.cfg.Debug {
|
||||
in.cfg.Tracer.CaptureState(_pc, op, gasCopy, cost, callContext, in.returnData, in.evm.Depth(), err) //nolint:errcheck
|
||||
in.cfg.Tracer.CaptureState(_pc, op, gasCopy, cost, callContext, in.returnData, in.depth, err) //nolint:errcheck
|
||||
logged = true
|
||||
}
|
||||
// execute the operation
|
||||
@ -297,6 +301,11 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
||||
return res, err
|
||||
}
|
||||
|
||||
// Depth returns the current call stack depth.
|
||||
func (in *EVMInterpreter) Depth() int {
|
||||
return in.depth
|
||||
}
|
||||
|
||||
func (vm *VM) setReadonly(outerReadonly bool) func() {
|
||||
if outerReadonly && !vm.readOnly {
|
||||
vm.readOnly = true
|
||||
|
@ -62,6 +62,10 @@ func (evm *testVM) Run(_ *Contract, _ []byte, readOnly bool) (ret []byte, err er
|
||||
return
|
||||
}
|
||||
|
||||
func (evm *testVM) Depth() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
type readOnlyState struct {
|
||||
outer bool
|
||||
before bool
|
||||
|
Loading…
Reference in New Issue
Block a user