mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 05:36:46 +00:00
core/vm: introduce a tracer wrapper
to clean up the callsites a little and allow compile time disabling of tracing.
This commit is contained in:
parent
c3ef6c77c2
commit
45609bb555
10 changed files with 289 additions and 150 deletions
|
|
@ -18,7 +18,6 @@ package vm
|
|||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
|
|
@ -125,29 +124,6 @@ func (c *Contract) Caller() common.Address {
|
|||
return c.caller
|
||||
}
|
||||
|
||||
// UseGas attempts the use gas and subtracts it and returns true on success
|
||||
func (c *Contract) UseGas(gas uint64, logger *tracing.Hooks, reason tracing.GasChangeReason) (ok bool) {
|
||||
if c.Gas < gas {
|
||||
return false
|
||||
}
|
||||
if logger != nil && logger.OnGasChange != nil && reason != tracing.GasChangeIgnored {
|
||||
logger.OnGasChange(c.Gas, c.Gas-gas, reason)
|
||||
}
|
||||
c.Gas -= gas
|
||||
return true
|
||||
}
|
||||
|
||||
// RefundGas refunds gas to the contract
|
||||
func (c *Contract) RefundGas(gas uint64, logger *tracing.Hooks, reason tracing.GasChangeReason) {
|
||||
if gas == 0 {
|
||||
return
|
||||
}
|
||||
if logger != nil && logger.OnGasChange != nil && reason != tracing.GasChangeIgnored {
|
||||
logger.OnGasChange(c.Gas, c.Gas+gas, reason)
|
||||
}
|
||||
c.Gas += gas
|
||||
}
|
||||
|
||||
// Address returns the contracts address
|
||||
func (c *Contract) Address() common.Address {
|
||||
return c.address
|
||||
|
|
|
|||
|
|
@ -257,14 +257,12 @@ func ActivePrecompiles(rules params.Rules) []common.Address {
|
|||
// - the returned bytes,
|
||||
// - the _remaining_ gas,
|
||||
// - any error that occurred
|
||||
func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uint64, logger *tracing.Hooks) (ret []byte, remainingGas uint64, err error) {
|
||||
func RunPrecompiledContract[TS TracingSwitch](p PrecompiledContract, input []byte, suppliedGas uint64, tracer tracer[TS]) (ret []byte, remainingGas uint64, err error) {
|
||||
gasCost := p.RequiredGas(input)
|
||||
if suppliedGas < gasCost {
|
||||
return nil, 0, ErrOutOfGas
|
||||
}
|
||||
if logger != nil && logger.OnGasChange != nil {
|
||||
logger.OnGasChange(suppliedGas, suppliedGas-gasCost, tracing.GasChangeCallPrecompiledContract)
|
||||
}
|
||||
tracer.OnGasChange(suppliedGas, suppliedGas-gasCost, tracing.GasChangeCallPrecompiledContract)
|
||||
suppliedGas -= gasCost
|
||||
output, err := p.Run(input)
|
||||
return output, suppliedGas, err
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ func FuzzPrecompiledContracts(f *testing.F) {
|
|||
return
|
||||
}
|
||||
inWant := string(input)
|
||||
RunPrecompiledContract(p, input, gas, nil)
|
||||
RunPrecompiledContract(p, input, gas, NewTracer[TracingDisabled](nil))
|
||||
if inHave := string(input); inWant != inHave {
|
||||
t.Errorf("Precompiled %v modified input data", a)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ func testPrecompiled(addr string, test precompiledTest, t *testing.T) {
|
|||
in := common.Hex2Bytes(test.Input)
|
||||
gas := p.RequiredGas(in)
|
||||
t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) {
|
||||
if res, _, err := RunPrecompiledContract(p, in, gas, nil); err != nil {
|
||||
if res, _, err := RunPrecompiledContract(p, in, gas, NewTracer[TracingDisabled](nil)); err != nil {
|
||||
t.Error(err)
|
||||
} else if common.Bytes2Hex(res) != test.Expected {
|
||||
t.Errorf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res))
|
||||
|
|
@ -121,7 +121,7 @@ func testPrecompiledOOG(addr string, test precompiledTest, t *testing.T) {
|
|||
gas := p.RequiredGas(in) - 1
|
||||
|
||||
t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) {
|
||||
_, _, err := RunPrecompiledContract(p, in, gas, nil)
|
||||
_, _, err := RunPrecompiledContract(p, in, gas, NewTracer[TracingDisabled](nil))
|
||||
if err.Error() != "out of gas" {
|
||||
t.Errorf("Expected error [out of gas], got [%v]", err)
|
||||
}
|
||||
|
|
@ -138,7 +138,7 @@ func testPrecompiledFailure(addr string, test precompiledFailureTest, t *testing
|
|||
in := common.Hex2Bytes(test.Input)
|
||||
gas := p.RequiredGas(in)
|
||||
t.Run(test.Name, func(t *testing.T) {
|
||||
_, _, err := RunPrecompiledContract(p, in, gas, nil)
|
||||
_, _, err := RunPrecompiledContract(p, in, gas, NewTracer[TracingDisabled](nil))
|
||||
if err.Error() != test.ExpectedError {
|
||||
t.Errorf("Expected error [%v], got [%v]", test.ExpectedError, err)
|
||||
}
|
||||
|
|
@ -170,7 +170,7 @@ func benchmarkPrecompiled(addr string, test precompiledTest, bench *testing.B) {
|
|||
bench.ResetTimer()
|
||||
for i := 0; i < bench.N; i++ {
|
||||
copy(data, in)
|
||||
res, _, err = RunPrecompiledContract(p, data, reqGas, nil)
|
||||
res, _, err = RunPrecompiledContract(p, data, reqGas, NewTracer[TracingDisabled](nil))
|
||||
}
|
||||
bench.StopTimer()
|
||||
elapsed := uint64(time.Since(start))
|
||||
|
|
|
|||
|
|
@ -358,7 +358,7 @@ func opExtCodeCopyEIP4762(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, er
|
|||
code := evm.StateDB.GetCode(addr)
|
||||
paddedCodeCopy, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(code, uint64CodeOffset, length.Uint64())
|
||||
consumed, wanted := evm.AccessEvents.CodeChunksRangeGas(addr, copyOffset, nonPaddedCopyLength, uint64(len(code)), false, scope.Contract.Gas)
|
||||
scope.Contract.UseGas(consumed, evm.Config.Tracer, tracing.GasChangeUnspecified)
|
||||
evm.UseGas(scope.Contract, consumed, tracing.GasChangeUnspecified)
|
||||
if consumed < wanted {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
|
@ -384,7 +384,7 @@ func opPush1EIP4762(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
// advanced past this boundary.
|
||||
contractAddr := scope.Contract.Address()
|
||||
consumed, wanted := evm.AccessEvents.CodeChunksRangeGas(contractAddr, *pc+1, uint64(1), uint64(len(scope.Contract.Code)), false, scope.Contract.Gas)
|
||||
scope.Contract.UseGas(wanted, evm.Config.Tracer, tracing.GasChangeUnspecified)
|
||||
evm.UseGas(scope.Contract, wanted, tracing.GasChangeUnspecified)
|
||||
if consumed < wanted {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
|
@ -412,7 +412,7 @@ func makePushEIP4762(size uint64, pushByteSize int) executionFunc {
|
|||
if !scope.Contract.IsDeployment && !scope.Contract.IsSystemCall {
|
||||
contractAddr := scope.Contract.Address()
|
||||
consumed, wanted := evm.AccessEvents.CodeChunksRangeGas(contractAddr, uint64(start), uint64(pushByteSize), uint64(len(scope.Contract.Code)), false, scope.Contract.Gas)
|
||||
scope.Contract.UseGas(consumed, evm.Config.Tracer, tracing.GasChangeUnspecified)
|
||||
evm.UseGas(scope.Contract, consumed, tracing.GasChangeUnspecified)
|
||||
if consumed < wanted {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
|
|
|||
116
core/vm/evm.go
116
core/vm/evm.go
|
|
@ -125,6 +125,9 @@ type EVM struct {
|
|||
// jumpDests stores results of JUMPDEST analysis.
|
||||
jumpDests JumpDestCache
|
||||
|
||||
// tracer provides a nil-safe access to a tracing.Hooks
|
||||
tracer tracer[TracingEnabled]
|
||||
|
||||
hasher crypto.KeccakState // Keccak256 hasher instance shared across opcodes
|
||||
hasherBuf common.Hash // Keccak256 hasher result array shared across opcodes
|
||||
|
||||
|
|
@ -145,6 +148,7 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon
|
|||
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time),
|
||||
jumpDests: newMapJumpDests(),
|
||||
hasher: crypto.NewKeccakState(),
|
||||
tracer: NewTracer[TracingEnabled](config.Tracer),
|
||||
}
|
||||
evm.precompiles = activePrecompiledContracts(evm.chainRules)
|
||||
|
||||
|
|
@ -240,12 +244,10 @@ func isSystemCall(caller common.Address) bool {
|
|||
// execution error or failed value transfer.
|
||||
func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) {
|
||||
// Capture the tracer start/end events in debug mode
|
||||
if evm.Config.Tracer != nil {
|
||||
evm.captureBegin(evm.depth, CALL, caller, addr, input, gas, value.ToBig())
|
||||
defer func(startGas uint64) {
|
||||
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
|
||||
}(gas)
|
||||
}
|
||||
evm.captureBegin(evm.depth, CALL, caller, addr, input, gas, value.ToBig())
|
||||
defer func(startGas uint64) {
|
||||
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
|
||||
}(gas)
|
||||
// Fail if we're trying to execute above the call depth limit
|
||||
if evm.depth > int(params.CallCreateDepth) {
|
||||
return nil, gas, ErrDepth
|
||||
|
|
@ -283,7 +285,7 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
|
|||
evm.Context.Transfer(evm.StateDB, caller, addr, value)
|
||||
|
||||
if isPrecompile {
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.tracer)
|
||||
} else {
|
||||
// Initialise a new contract and set the code that is to be used by the EVM.
|
||||
code := evm.resolveCode(addr)
|
||||
|
|
@ -304,9 +306,7 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
|
|||
if err != nil {
|
||||
evm.StateDB.RevertToSnapshot(snapshot)
|
||||
if err != ErrExecutionReverted {
|
||||
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
|
||||
evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution)
|
||||
}
|
||||
evm.tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution)
|
||||
|
||||
gas = 0
|
||||
}
|
||||
|
|
@ -326,12 +326,10 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
|
|||
// code with the caller as context.
|
||||
func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) {
|
||||
// Invoke tracer hooks that signal entering/exiting a call frame
|
||||
if evm.Config.Tracer != nil {
|
||||
evm.captureBegin(evm.depth, CALLCODE, caller, addr, input, gas, value.ToBig())
|
||||
defer func(startGas uint64) {
|
||||
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
|
||||
}(gas)
|
||||
}
|
||||
evm.captureBegin(evm.depth, CALLCODE, caller, addr, input, gas, value.ToBig())
|
||||
defer func(startGas uint64) {
|
||||
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
|
||||
}(gas)
|
||||
// Fail if we're trying to execute above the call depth limit
|
||||
if evm.depth > int(params.CallCreateDepth) {
|
||||
return nil, gas, ErrDepth
|
||||
|
|
@ -347,7 +345,7 @@ func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byt
|
|||
|
||||
// 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)
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.tracer)
|
||||
} else {
|
||||
// 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.
|
||||
|
|
@ -359,9 +357,7 @@ func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byt
|
|||
if err != nil {
|
||||
evm.StateDB.RevertToSnapshot(snapshot)
|
||||
if err != ErrExecutionReverted {
|
||||
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
|
||||
evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution)
|
||||
}
|
||||
evm.tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution)
|
||||
gas = 0
|
||||
}
|
||||
}
|
||||
|
|
@ -375,13 +371,11 @@ func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byt
|
|||
// code with the caller as context and the caller is set to the caller of the caller.
|
||||
func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) {
|
||||
// Invoke tracer hooks that signal entering/exiting a call frame
|
||||
if evm.Config.Tracer != nil {
|
||||
// DELEGATECALL inherits value from parent call
|
||||
evm.captureBegin(evm.depth, DELEGATECALL, caller, addr, input, gas, value.ToBig())
|
||||
defer func(startGas uint64) {
|
||||
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
|
||||
}(gas)
|
||||
}
|
||||
// DELEGATECALL inherits value from parent call
|
||||
evm.captureBegin(evm.depth, DELEGATECALL, caller, addr, input, gas, value.ToBig())
|
||||
defer func(startGas uint64) {
|
||||
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
|
||||
}(gas)
|
||||
// Fail if we're trying to execute above the call depth limit
|
||||
if evm.depth > int(params.CallCreateDepth) {
|
||||
return nil, gas, ErrDepth
|
||||
|
|
@ -390,7 +384,7 @@ func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address,
|
|||
|
||||
// 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)
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.tracer)
|
||||
} else {
|
||||
// Initialise a new contract and make initialise the delegate values
|
||||
//
|
||||
|
|
@ -403,9 +397,7 @@ func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address,
|
|||
if err != nil {
|
||||
evm.StateDB.RevertToSnapshot(snapshot)
|
||||
if err != ErrExecutionReverted {
|
||||
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
|
||||
evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution)
|
||||
}
|
||||
evm.tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution)
|
||||
gas = 0
|
||||
}
|
||||
}
|
||||
|
|
@ -418,12 +410,10 @@ func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address,
|
|||
// instead of performing the modifications.
|
||||
func (evm *EVM) StaticCall(caller common.Address, 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.Tracer != nil {
|
||||
evm.captureBegin(evm.depth, STATICCALL, caller, addr, input, gas, nil)
|
||||
defer func(startGas uint64) {
|
||||
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
|
||||
}(gas)
|
||||
}
|
||||
evm.captureBegin(evm.depth, STATICCALL, caller, addr, input, gas, nil)
|
||||
defer func(startGas uint64) {
|
||||
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
|
||||
}(gas)
|
||||
// Fail if we're trying to execute above the call depth limit
|
||||
if evm.depth > int(params.CallCreateDepth) {
|
||||
return nil, gas, ErrDepth
|
||||
|
|
@ -442,7 +432,7 @@ func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []b
|
|||
evm.StateDB.AddBalance(addr, new(uint256.Int), tracing.BalanceChangeTouchAccount)
|
||||
|
||||
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.tracer)
|
||||
} else {
|
||||
// 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.
|
||||
|
|
@ -458,9 +448,7 @@ func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []b
|
|||
if err != nil {
|
||||
evm.StateDB.RevertToSnapshot(snapshot)
|
||||
if err != ErrExecutionReverted {
|
||||
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
|
||||
evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution)
|
||||
}
|
||||
evm.tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution)
|
||||
|
||||
gas = 0
|
||||
}
|
||||
|
|
@ -470,12 +458,10 @@ func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []b
|
|||
|
||||
// create creates a new contract using code as deployment code.
|
||||
func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *uint256.Int, address common.Address, typ OpCode) (ret []byte, createAddress common.Address, leftOverGas uint64, err error) {
|
||||
if evm.Config.Tracer != nil {
|
||||
evm.captureBegin(evm.depth, typ, caller, address, code, gas, value.ToBig())
|
||||
defer func(startGas uint64) {
|
||||
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
|
||||
}(gas)
|
||||
}
|
||||
evm.captureBegin(evm.depth, typ, caller, address, code, gas, value.ToBig())
|
||||
defer func(startGas uint64) {
|
||||
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
|
||||
}(gas)
|
||||
// Depth check execution. Fail if we're trying to execute above the
|
||||
// limit.
|
||||
if evm.depth > int(params.CallCreateDepth) {
|
||||
|
|
@ -496,9 +482,7 @@ func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *ui
|
|||
if statelessGas > gas {
|
||||
return nil, common.Address{}, 0, ErrOutOfGas
|
||||
}
|
||||
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
|
||||
evm.Config.Tracer.OnGasChange(gas, gas-statelessGas, tracing.GasChangeWitnessContractCollisionCheck)
|
||||
}
|
||||
evm.tracer.OnGasChange(gas, gas-statelessGas, tracing.GasChangeWitnessContractCollisionCheck)
|
||||
gas = gas - statelessGas
|
||||
}
|
||||
|
||||
|
|
@ -517,9 +501,7 @@ func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *ui
|
|||
if evm.StateDB.GetNonce(address) != 0 ||
|
||||
(contractHash != (common.Hash{}) && contractHash != types.EmptyCodeHash) || // non-empty code
|
||||
(storageRoot != (common.Hash{}) && storageRoot != types.EmptyRootHash) { // non-empty storage
|
||||
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
|
||||
evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution)
|
||||
}
|
||||
evm.tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution)
|
||||
return nil, common.Address{}, 0, ErrContractAddressCollision
|
||||
}
|
||||
// Create a new account on the state only if the object was not present.
|
||||
|
|
@ -544,9 +526,7 @@ func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *ui
|
|||
if consumed < wanted {
|
||||
return nil, common.Address{}, 0, ErrOutOfGas
|
||||
}
|
||||
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
|
||||
evm.Config.Tracer.OnGasChange(gas, gas-consumed, tracing.GasChangeWitnessContractInit)
|
||||
}
|
||||
evm.tracer.OnGasChange(gas, gas-consumed, tracing.GasChangeWitnessContractInit)
|
||||
gas = gas - consumed
|
||||
}
|
||||
evm.Context.Transfer(evm.StateDB, caller, address, value)
|
||||
|
|
@ -564,7 +544,7 @@ func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *ui
|
|||
if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) {
|
||||
evm.StateDB.RevertToSnapshot(snapshot)
|
||||
if err != ErrExecutionReverted {
|
||||
contract.UseGas(contract.Gas, evm.Config.Tracer, tracing.GasChangeCallFailedExecution)
|
||||
evm.UseGas(contract, contract.Gas, tracing.GasChangeCallFailedExecution)
|
||||
}
|
||||
}
|
||||
return ret, address, contract.Gas, err
|
||||
|
|
@ -590,12 +570,12 @@ func (evm *EVM) initNewContract(contract *Contract, address common.Address) ([]b
|
|||
|
||||
if !evm.chainRules.IsEIP4762 {
|
||||
createDataGas := uint64(len(ret)) * params.CreateDataGas
|
||||
if !contract.UseGas(createDataGas, evm.Config.Tracer, tracing.GasChangeCallCodeStorage) {
|
||||
if !evm.UseGas(contract, createDataGas, tracing.GasChangeCallCodeStorage) {
|
||||
return ret, ErrCodeStoreOutOfGas
|
||||
}
|
||||
} else {
|
||||
consumed, wanted := evm.AccessEvents.CodeChunksRangeGas(address, 0, uint64(len(ret)), uint64(len(ret)), true, contract.Gas)
|
||||
contract.UseGas(consumed, evm.Config.Tracer, tracing.GasChangeWitnessCodeChunk)
|
||||
evm.UseGas(contract, consumed, tracing.GasChangeWitnessCodeChunk)
|
||||
if len(ret) > 0 && (consumed < wanted) {
|
||||
return ret, ErrCodeStoreOutOfGas
|
||||
}
|
||||
|
|
@ -654,19 +634,13 @@ func (evm *EVM) resolveCodeHash(addr common.Address) common.Hash {
|
|||
func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }
|
||||
|
||||
func (evm *EVM) captureBegin(depth int, typ OpCode, from common.Address, to common.Address, input []byte, startGas uint64, value *big.Int) {
|
||||
tracer := evm.Config.Tracer
|
||||
if tracer.OnEnter != nil {
|
||||
tracer.OnEnter(depth, byte(typ), from, to, input, startGas, value)
|
||||
}
|
||||
if tracer.OnGasChange != nil {
|
||||
tracer.OnGasChange(0, startGas, tracing.GasChangeCallInitialBalance)
|
||||
}
|
||||
evm.tracer.OnEnter(depth, byte(typ), from, to, input, startGas, value)
|
||||
evm.tracer.OnGasChange(0, startGas, tracing.GasChangeCallInitialBalance)
|
||||
}
|
||||
|
||||
func (evm *EVM) captureEnd(depth int, startGas uint64, leftOverGas uint64, ret []byte, err error) {
|
||||
tracer := evm.Config.Tracer
|
||||
if leftOverGas != 0 && tracer.OnGasChange != nil {
|
||||
tracer.OnGasChange(leftOverGas, 0, tracing.GasChangeCallLeftOverReturned)
|
||||
if leftOverGas != 0 {
|
||||
evm.tracer.OnGasChange(leftOverGas, 0, tracing.GasChangeCallLeftOverReturned)
|
||||
}
|
||||
var reverted bool
|
||||
if err != nil {
|
||||
|
|
@ -675,9 +649,7 @@ func (evm *EVM) captureEnd(depth int, startGas uint64, leftOverGas uint64, ret [
|
|||
if !evm.chainRules.IsHomestead && errors.Is(err, ErrCodeStoreOutOfGas) {
|
||||
reverted = false
|
||||
}
|
||||
if tracer.OnExit != nil {
|
||||
tracer.OnExit(depth, ret, startGas-leftOverGas, VMErrorFromErr(err), reverted)
|
||||
}
|
||||
evm.tracer.OnExit(depth, ret, startGas-leftOverGas, VMErrorFromErr(err), reverted)
|
||||
}
|
||||
|
||||
// GetVMContext provides context about the block being executed as well as state
|
||||
|
|
|
|||
|
|
@ -442,9 +442,7 @@ func opBlockhash(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
if witness := evm.StateDB.Witness(); witness != nil {
|
||||
witness.AddBlockHash(num64)
|
||||
}
|
||||
if tracer := evm.Config.Tracer; tracer != nil && tracer.OnBlockHashRead != nil {
|
||||
tracer.OnBlockHashRead(num64, res)
|
||||
}
|
||||
evm.tracer.OnBlockHashRead(num64, res)
|
||||
num.SetBytes(res[:])
|
||||
} else {
|
||||
num.Clear()
|
||||
|
|
@ -669,7 +667,7 @@ func opCreate(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
// reuse size int for stackvalue
|
||||
stackvalue := size
|
||||
|
||||
scope.Contract.UseGas(gas, evm.Config.Tracer, tracing.GasChangeCallContractCreation)
|
||||
evm.UseGas(scope.Contract, gas, tracing.GasChangeCallContractCreation)
|
||||
|
||||
res, addr, returnGas, suberr := evm.Create(scope.Contract.Address(), input, gas, &value)
|
||||
// Push item on the stack based on the returned error. If the ruleset is
|
||||
|
|
@ -685,7 +683,7 @@ func opCreate(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
}
|
||||
scope.Stack.push(&stackvalue)
|
||||
|
||||
scope.Contract.RefundGas(returnGas, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
evm.RefundGas(scope.Contract, returnGas, tracing.GasChangeCallLeftOverRefunded)
|
||||
|
||||
if suberr == ErrExecutionReverted {
|
||||
evm.returnData = res // set REVERT data to return data buffer
|
||||
|
|
@ -709,7 +707,7 @@ func opCreate2(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
|
||||
// Apply EIP150
|
||||
gas -= gas / 64
|
||||
scope.Contract.UseGas(gas, evm.Config.Tracer, tracing.GasChangeCallContractCreation2)
|
||||
evm.UseGas(scope.Contract, gas, tracing.GasChangeCallContractCreation2)
|
||||
// reuse size int for stackvalue
|
||||
stackvalue := size
|
||||
res, addr, returnGas, suberr := evm.Create2(scope.Contract.Address(), input, gas,
|
||||
|
|
@ -721,7 +719,7 @@ func opCreate2(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
stackvalue.SetBytes(addr.Bytes())
|
||||
}
|
||||
scope.Stack.push(&stackvalue)
|
||||
scope.Contract.RefundGas(returnGas, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
evm.RefundGas(scope.Contract, returnGas, tracing.GasChangeCallLeftOverRefunded)
|
||||
|
||||
if suberr == ErrExecutionReverted {
|
||||
evm.returnData = res // set REVERT data to return data buffer
|
||||
|
|
@ -761,7 +759,7 @@ func opCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
|
||||
scope.Contract.RefundGas(returnGas, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
evm.RefundGas(scope.Contract, returnGas, tracing.GasChangeCallLeftOverRefunded)
|
||||
|
||||
evm.returnData = ret
|
||||
return ret, nil
|
||||
|
|
@ -794,7 +792,7 @@ func opCallCode(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
|
||||
scope.Contract.RefundGas(returnGas, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
evm.RefundGas(scope.Contract, returnGas, tracing.GasChangeCallLeftOverRefunded)
|
||||
|
||||
evm.returnData = ret
|
||||
return ret, nil
|
||||
|
|
@ -823,7 +821,7 @@ func opDelegateCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
|
||||
scope.Contract.RefundGas(returnGas, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
evm.RefundGas(scope.Contract, returnGas, tracing.GasChangeCallLeftOverRefunded)
|
||||
|
||||
evm.returnData = ret
|
||||
return ret, nil
|
||||
|
|
@ -852,7 +850,7 @@ func opStaticCall(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||
}
|
||||
|
||||
scope.Contract.RefundGas(returnGas, evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
|
||||
evm.RefundGas(scope.Contract, returnGas, tracing.GasChangeCallLeftOverRefunded)
|
||||
|
||||
evm.returnData = ret
|
||||
return ret, nil
|
||||
|
|
@ -889,14 +887,8 @@ func opSelfdestruct(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
|
|||
balance := evm.StateDB.GetBalance(scope.Contract.Address())
|
||||
evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct)
|
||||
evm.StateDB.SelfDestruct(scope.Contract.Address())
|
||||
if tracer := evm.Config.Tracer; tracer != nil {
|
||||
if tracer.OnEnter != nil {
|
||||
tracer.OnEnter(evm.depth, byte(SELFDESTRUCT), scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig())
|
||||
}
|
||||
if tracer.OnExit != nil {
|
||||
tracer.OnExit(evm.depth, []byte{}, 0, nil, false)
|
||||
}
|
||||
}
|
||||
evm.tracer.OnEnter(evm.depth, byte(SELFDESTRUCT), scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig())
|
||||
evm.tracer.OnExit(evm.depth, []byte{}, 0, nil, false)
|
||||
return nil, errStopToken
|
||||
}
|
||||
|
||||
|
|
@ -909,14 +901,8 @@ func opSelfdestruct6780(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, erro
|
|||
evm.StateDB.SubBalance(scope.Contract.Address(), balance, tracing.BalanceDecreaseSelfdestruct)
|
||||
evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct)
|
||||
evm.StateDB.SelfDestruct6780(scope.Contract.Address())
|
||||
if tracer := evm.Config.Tracer; tracer != nil {
|
||||
if tracer.OnEnter != nil {
|
||||
tracer.OnEnter(evm.depth, byte(SELFDESTRUCT), scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig())
|
||||
}
|
||||
if tracer.OnExit != nil {
|
||||
tracer.OnExit(evm.depth, []byte{}, 0, nil, false)
|
||||
}
|
||||
}
|
||||
evm.tracer.OnEnter(evm.depth, byte(SELFDESTRUCT), scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig())
|
||||
evm.tracer.OnExit(evm.depth, []byte{}, 0, nil, false)
|
||||
return nil, errStopToken
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -151,11 +151,11 @@ func (evm *EVM) Run(contract *Contract, input []byte, readOnly bool) (ret []byte
|
|||
if err == nil {
|
||||
return
|
||||
}
|
||||
if !logged && evm.Config.Tracer.OnOpcode != nil {
|
||||
evm.Config.Tracer.OnOpcode(pcCopy, byte(op), gasCopy, cost, callContext, evm.returnData, evm.depth, VMErrorFromErr(err))
|
||||
if !logged {
|
||||
evm.tracer.OnOpcode(pcCopy, byte(op), gasCopy, cost, callContext, evm.returnData, evm.depth, VMErrorFromErr(err))
|
||||
}
|
||||
if logged && evm.Config.Tracer.OnFault != nil {
|
||||
evm.Config.Tracer.OnFault(pcCopy, byte(op), gasCopy, cost, callContext, evm.depth, VMErrorFromErr(err))
|
||||
if logged {
|
||||
evm.tracer.OnFault(pcCopy, byte(op), gasCopy, cost, callContext, evm.depth, VMErrorFromErr(err))
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
|
@ -175,7 +175,7 @@ func (evm *EVM) Run(contract *Contract, input []byte, readOnly bool) (ret []byte
|
|||
// associated costs.
|
||||
contractAddr := contract.Address()
|
||||
consumed, wanted := evm.TxContext.AccessEvents.CodeChunksRangeGas(contractAddr, pc, 1, uint64(len(contract.Code)), false, contract.Gas)
|
||||
contract.UseGas(consumed, evm.Config.Tracer, tracing.GasChangeWitnessCodeChunk)
|
||||
evm.UseGas(contract, consumed, tracing.GasChangeWitnessCodeChunk)
|
||||
if consumed < wanted {
|
||||
return nil, ErrOutOfGas
|
||||
}
|
||||
|
|
@ -235,13 +235,9 @@ func (evm *EVM) Run(contract *Contract, input []byte, readOnly bool) (ret []byte
|
|||
|
||||
// Do tracing before potential memory expansion
|
||||
if debug {
|
||||
if evm.Config.Tracer.OnGasChange != nil {
|
||||
evm.Config.Tracer.OnGasChange(gasCopy, gasCopy-cost, tracing.GasChangeCallOpCode)
|
||||
}
|
||||
if evm.Config.Tracer.OnOpcode != nil {
|
||||
evm.Config.Tracer.OnOpcode(pc, byte(op), gasCopy, cost, callContext, evm.returnData, evm.depth, VMErrorFromErr(err))
|
||||
logged = true
|
||||
}
|
||||
evm.tracer.OnGasChange(gasCopy, gasCopy-cost, tracing.GasChangeCallOpCode)
|
||||
evm.tracer.OnOpcode(pc, byte(op), gasCopy, cost, callContext, evm.returnData, evm.depth, VMErrorFromErr(err))
|
||||
logged = true
|
||||
}
|
||||
if memorySize > 0 {
|
||||
mem.Resize(memorySize)
|
||||
|
|
@ -261,3 +257,26 @@ func (evm *EVM) Run(contract *Contract, input []byte, readOnly bool) (ret []byte
|
|||
|
||||
return res, err
|
||||
}
|
||||
|
||||
// UseGas attempts the use gas and subtracts it and returns true on success
|
||||
func (evm *EVM) UseGas(c *Contract, gas uint64, reason tracing.GasChangeReason) (ok bool) {
|
||||
if c.Gas < gas {
|
||||
return false
|
||||
}
|
||||
if reason != tracing.GasChangeIgnored {
|
||||
evm.tracer.OnGasChange(c.Gas, c.Gas-gas, reason)
|
||||
}
|
||||
c.Gas -= gas
|
||||
return true
|
||||
}
|
||||
|
||||
// RefundGas refunds gas to the contract
|
||||
func (evm *EVM) RefundGas(c *Contract, gas uint64, reason tracing.GasChangeReason) {
|
||||
if gas == 0 {
|
||||
return
|
||||
}
|
||||
if reason != tracing.GasChangeIgnored {
|
||||
evm.tracer.OnGasChange(c.Gas, c.Gas+gas, reason)
|
||||
}
|
||||
c.Gas += gas
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ func makeCallVariantGasCallEIP2929(oldCalculator gasFunc, addressPosition int) g
|
|||
evm.StateDB.AddAddressToAccessList(addr)
|
||||
// Charge the remaining difference here already, to correctly calculate available
|
||||
// gas for call
|
||||
if !contract.UseGas(coldCost, evm.Config.Tracer, tracing.GasChangeCallStorageColdAccess) {
|
||||
if !evm.UseGas(contract, coldCost, tracing.GasChangeCallStorageColdAccess) {
|
||||
return 0, ErrOutOfGas
|
||||
}
|
||||
}
|
||||
|
|
@ -265,7 +265,7 @@ func makeCallVariantGasCallEIP7702(oldCalculator gasFunc) gasFunc {
|
|||
coldCost := params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929
|
||||
// Charge the remaining difference here already, to correctly calculate available
|
||||
// gas for call
|
||||
if !contract.UseGas(coldCost, evm.Config.Tracer, tracing.GasChangeCallStorageColdAccess) {
|
||||
if !evm.UseGas(contract, coldCost, tracing.GasChangeCallStorageColdAccess) {
|
||||
return 0, ErrOutOfGas
|
||||
}
|
||||
total += coldCost
|
||||
|
|
@ -280,7 +280,7 @@ func makeCallVariantGasCallEIP7702(oldCalculator gasFunc) gasFunc {
|
|||
evm.StateDB.AddAddressToAccessList(target)
|
||||
cost = params.ColdAccountAccessCostEIP2929
|
||||
}
|
||||
if !contract.UseGas(cost, evm.Config.Tracer, tracing.GasChangeCallStorageColdAccess) {
|
||||
if !evm.UseGas(contract, cost, tracing.GasChangeCallStorageColdAccess) {
|
||||
return 0, ErrOutOfGas
|
||||
}
|
||||
total += cost
|
||||
|
|
|
|||
188
core/vm/tracer.go
Normal file
188
core/vm/tracer.go
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
// Copyright 2025 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package vm
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
const tracingEnabledSize = 1
|
||||
|
||||
type TracingEnabled byte
|
||||
type TracingDisabled uint16
|
||||
|
||||
type TracingSwitch interface {
|
||||
TracingEnabled | TracingDisabled
|
||||
}
|
||||
|
||||
// tracer is a wrapper that gives nil-safe access to a tracing.Hooks
|
||||
// and also enables VM tracing to be disabled at compile time
|
||||
type tracer[TS TracingSwitch] struct {
|
||||
hooks tracing.Hooks
|
||||
}
|
||||
|
||||
func NewTracer[TS TracingSwitch](hooks *tracing.Hooks) tracer[TS] {
|
||||
var t tracer[TS]
|
||||
if hooks != nil {
|
||||
t.hooks = *hooks
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnTxStart(vm *tracing.VMContext, tx *types.Transaction, from common.Address) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnTxStart != nil {
|
||||
t.hooks.OnTxStart(vm, tx, from)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnTxEnd(receipt *types.Receipt, err error) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnTxEnd != nil {
|
||||
t.hooks.OnTxEnd(receipt, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnEnter != nil {
|
||||
t.hooks.OnEnter(depth, typ, from, to, input, gas, value)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnExit != nil {
|
||||
t.hooks.OnExit(depth, output, gasUsed, err, reverted)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnOpcode != nil {
|
||||
t.hooks.OnOpcode(pc, op, gas, cost, scope, rData, depth, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnFault(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, depth int, err error) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnFault != nil {
|
||||
t.hooks.OnFault(pc, op, gas, cost, scope, depth, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnGasChange(oldGas, newGas uint64, reason tracing.GasChangeReason) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnGasChange != nil {
|
||||
t.hooks.OnGasChange(oldGas, newGas, reason)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnBlockchainInit(chainConfig *params.ChainConfig) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnBlockchainInit != nil {
|
||||
t.hooks.OnBlockchainInit(chainConfig)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnClose() {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnClose != nil {
|
||||
t.hooks.OnClose()
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnBlockStart(event tracing.BlockEvent) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnBlockStart != nil {
|
||||
t.hooks.OnBlockStart(event)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnBlockEnd(err error) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnBlockEnd != nil {
|
||||
t.hooks.OnBlockEnd(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnSkippedBlock(event tracing.BlockEvent) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnSkippedBlock != nil {
|
||||
t.hooks.OnSkippedBlock(event)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnGenesisBlock(genesis *types.Block, alloc types.GenesisAlloc) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnGenesisBlock != nil {
|
||||
t.hooks.OnGenesisBlock(genesis, alloc)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnSystemCallStart() {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnSystemCallStart != nil {
|
||||
t.hooks.OnSystemCallStart()
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnSystemCallStartV2(vm *tracing.VMContext) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnSystemCallStartV2 != nil {
|
||||
t.hooks.OnSystemCallStartV2(vm)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnSystemCallEnd() {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnSystemCallEnd != nil {
|
||||
t.hooks.OnSystemCallEnd()
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnBalanceChange(addr common.Address, prevBalance, newBalance *big.Int, reason tracing.BalanceChangeReason) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnBalanceChange != nil {
|
||||
t.hooks.OnBalanceChange(addr, prevBalance, newBalance, reason)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnNonceChange(addr common.Address, prevNonce, newNonce uint64) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnNonceChange != nil {
|
||||
t.hooks.OnNonceChange(addr, prevNonce, newNonce)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnNonceChangeV2(addr common.Address, prevNonce, newNonce uint64, reason tracing.NonceChangeReason) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnNonceChangeV2 != nil {
|
||||
t.hooks.OnNonceChangeV2(addr, prevNonce, newNonce, reason)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnCodeChange(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnCodeChange != nil {
|
||||
t.hooks.OnCodeChange(addr, prevCodeHash, prevCode, codeHash, code)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnStorageChange(addr common.Address, slot common.Hash, prevValue, newValue common.Hash) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnStorageChange != nil {
|
||||
t.hooks.OnStorageChange(addr, slot, prevValue, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnLog(log *types.Log) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnLog != nil {
|
||||
t.hooks.OnLog(log)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tracer[TS]) OnBlockHashRead(blockNumber uint64, hash common.Hash) {
|
||||
if unsafe.Sizeof(*new(TS)) == tracingEnabledSize && t.hooks.OnBlockHashRead != nil {
|
||||
t.hooks.OnBlockHashRead(blockNumber, hash)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue