diff --git a/cmd/evm/blockrunner.go b/cmd/evm/blockrunner.go index 1f7d07f31a..07af0bc9a2 100644 --- a/cmd/evm/blockrunner.go +++ b/cmd/evm/blockrunner.go @@ -50,7 +50,7 @@ func blockTestCmd(ctx *cli.Context) error { return errors.New("path-to-test argument required") } - var tracer *tracing.LiveLogger + var tracer *tracing.Hooks // Configure the EVM logger if ctx.Bool(MachineFlag.Name) { tracer = logger.NewJSONLogger(&logger.Config{ diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 4e72d11b5b..52e5bbe9de 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -229,7 +229,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, return nil, nil, nil, err } if vmConfig.Tracer != nil { - vmConfig.Tracer = tracer.LiveLogger + vmConfig.Tracer = tracer.Hooks } statedb.SetTxContext(tx.Hash(), txIndex) diff --git a/cmd/evm/internal/t8ntool/transition.go b/cmd/evm/internal/t8ntool/transition.go index 97a1101544..bb28620b01 100644 --- a/cmd/evm/internal/t8ntool/transition.go +++ b/cmd/evm/internal/t8ntool/transition.go @@ -126,7 +126,7 @@ func Transition(ctx *cli.Context) error { } logger := logger.NewJSONLogger(logConfig, traceFile).Hooks() tracer := &directory.Tracer{ - LiveLogger: logger, + Hooks: logger, // JSONLogger streams out result to file. GetResult: func() (json.RawMessage, error) { return nil, nil }, Stop: func(err error) {}, diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index 47ae707063..3d481d5fe7 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -117,7 +117,7 @@ func runCmd(ctx *cli.Context) error { } var ( - tracer *tracing.LiveLogger + tracer *tracing.Hooks debugLogger *logger.StructLogger statedb *state.StateDB chainConfig *params.ChainConfig diff --git a/core/blockchain.go b/core/blockchain.go index b3f72bd213..cc88434e8f 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -266,7 +266,7 @@ type BlockChain struct { processor Processor // Block transaction processor interface forker *ForkChoice vmConfig vm.Config - logger *tracing.LiveLogger + logger *tracing.Hooks } // NewBlockChain returns a fully initialised block chain using information diff --git a/core/state/statedb.go b/core/state/statedb.go index 0047a9c8e1..054f022708 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -64,7 +64,7 @@ type StateDB struct { prefetcher *triePrefetcher trie Trie hasher crypto.KeccakState - logger *tracing.LiveLogger + logger *tracing.Hooks snaps *snapshot.Tree // Nil if snapshot is not available snap snapshot.Snapshot // Nil if snapshot is not available @@ -175,7 +175,7 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) } // SetLogger sets the logger for account update hooks. -func (s *StateDB) SetLogger(l *tracing.LiveLogger) { +func (s *StateDB) SetLogger(l *tracing.Hooks) { s.logger = l } diff --git a/core/tracing/hooks.go b/core/tracing/hooks.go index f912a6c87d..872d4af2dd 100644 --- a/core/tracing/hooks.go +++ b/core/tracing/hooks.go @@ -20,6 +20,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" @@ -141,7 +142,7 @@ type ( SkippedBlockHook = func(event BlockEvent) // GenesisBlockHook is called when the genesis block is being processed. - GenesisBlockHook = func(genesis *types.Block, alloc types.GenesisAlloc) + GenesisBlockHook = func(genesis *types.Block, alloc core.GenesisAlloc) /* - State events - diff --git a/core/vm/contract.go b/core/vm/contract.go index 291a426b3b..860d0f2467 100644 --- a/core/vm/contract.go +++ b/core/vm/contract.go @@ -160,7 +160,7 @@ func (c *Contract) Caller() common.Address { } // UseGas attempts the use gas and subtracts it and returns true on success -func (c *Contract) UseGas(gas uint64, logger *tracing.LiveLogger, reason tracing.GasChangeReason) (ok bool) { +func (c *Contract) UseGas(gas uint64, logger *tracing.Hooks, reason tracing.GasChangeReason) (ok bool) { if c.Gas < gas { return false } diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 6b2512570a..821f33327a 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -169,7 +169,7 @@ 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.LiveLogger) (ret []byte, remainingGas uint64, err error) { +func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uint64, logger *tracing.Hooks) (ret []byte, remainingGas uint64, err error) { gasCost := p.RequiredGas(input) if suppliedGas < gasCost { return nil, 0, ErrOutOfGas diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 4d867fbc05..bee43ac1cd 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -27,7 +27,7 @@ import ( // Config are the configuration options for the Interpreter type Config struct { - Tracer *tracing.LiveLogger + Tracer *tracing.Hooks NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls) EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages ExtraEips []int // Additional EIPS that are to be enabled @@ -178,8 +178,8 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( res []byte // result of the opcode execution function debug = in.evm.Config.Tracer != nil ) - // Don't move this deferred function, it's placed before the capturestate-deferred method, - // so that it get's executed _after_: the capturestate needs the stacks before + // Don't move this deferred function, it's placed before the OnOpcode-deferred method, + // so that it gets executed _after_: the OnOpcode needs the stacks before // they are returned to the pools defer func() { returnStack(stack) diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 7abac3bec5..33ee536f88 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -153,7 +153,7 @@ type Config struct { EnablePreimageRecording bool // Enables VM tracing - VMTracer *tracing.LiveLogger + VMTracer *tracing.Hooks // Miscellaneous options DocRoot string `toml:"-"` diff --git a/eth/tracers/api.go b/eth/tracers/api.go index d0eefa84b1..447ba3119c 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -937,8 +937,8 @@ func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *direc return nil, err } } - vmenv := vm.NewEVM(vmctx, vm.TxContext{GasPrice: big.NewInt(0)}, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.LiveLogger, NoBaseFee: true}) - statedb.SetLogger(tracer.LiveLogger) + vmenv := vm.NewEVM(vmctx, vm.TxContext{GasPrice: big.NewInt(0)}, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true}) + statedb.SetLogger(tracer.Hooks) // Define a meaningful timeout of a single transaction trace if config.Timeout != nil { diff --git a/eth/tracers/directory/live/dir.go b/eth/tracers/directory/live/dir.go index a097754310..cedf81c35e 100644 --- a/eth/tracers/directory/live/dir.go +++ b/eth/tracers/directory/live/dir.go @@ -7,7 +7,7 @@ import ( "github.com/ethereum/go-ethereum/core/tracing" ) -type ctorFunc func(config json.RawMessage) (*tracing.LiveLogger, error) +type ctorFunc func(config json.RawMessage) (*tracing.Hooks, error) // Directory is the collection of tracers which can be used // during normal block import operations. @@ -23,7 +23,7 @@ func (d *directory) Register(name string, f ctorFunc) { } // New instantiates a tracer by name. -func (d *directory) New(name string, config json.RawMessage) (*tracing.LiveLogger, error) { +func (d *directory) New(name string, config json.RawMessage) (*tracing.Hooks, error) { if f, ok := d.elems[name]; ok { return f(config) } diff --git a/eth/tracers/directory/noop.go b/eth/tracers/directory/noop.go index 637f0da326..551c6635e1 100644 --- a/eth/tracers/directory/noop.go +++ b/eth/tracers/directory/noop.go @@ -38,15 +38,13 @@ func newNoopTracer(ctx *Context, _ json.RawMessage) (*Tracer, error) { t := &NoopTracer{} return &Tracer{ Hooks: &tracing.Hooks{ - OnTxStart: t.CaptureTxStart, - OnTxEnd: t.CaptureTxEnd, - OnStart: t.CaptureStart, - OnEnd: t.CaptureEnd, - OnEnter: t.CaptureEnter, - OnExit: t.CaptureExit, - OnOpcode: t.CaptureState, - OnFault: t.CaptureFault, - OnKeccakPreimage: t.CaptureKeccakPreimage, + OnTxStart: t.OnTxStart, + OnTxEnd: t.OnTxEnd, + OnEnter: t.OnEnter, + OnExit: t.OnExit, + OnOpcode: t.OnOpcode, + OnFault: t.OnFault, + OnKeccakPreimage: t.OnKeccakPreimage, OnGasChange: t.OnGasChange, OnBalanceChange: t.OnBalanceChange, OnNonceChange: t.OnNonceChange, @@ -59,41 +57,26 @@ func newNoopTracer(ctx *Context, _ json.RawMessage) (*Tracer, error) { }, nil } -// CaptureStart implements the EVMLogger interface to initialize the tracing operation. -func (t *NoopTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { +func (t *NoopTracer) OnOpcode(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { } -// CaptureEnd is called after the call finishes to finalize the tracing. -func (t *NoopTracer) CaptureEnd(output []byte, gasUsed uint64, err error, reverted bool) { +func (t *NoopTracer) OnFault(pc uint64, op tracing.OpCode, gas, cost uint64, _ tracing.OpContext, depth int, err error) { } -// CaptureState implements the EVMLogger interface to trace a single step of VM execution. -func (t *NoopTracer) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { -} +func (t *NoopTracer) OnKeccakPreimage(hash common.Hash, data []byte) {} -// CaptureFault implements the EVMLogger interface to trace an execution fault. -func (t *NoopTracer) CaptureFault(pc uint64, op tracing.OpCode, gas, cost uint64, _ tracing.OpContext, depth int, err error) { -} - -// CaptureKeccakPreimage is called during the KECCAK256 opcode. -func (t *NoopTracer) CaptureKeccakPreimage(hash common.Hash, data []byte) {} - -// OnGasChange is called when gas is either consumed or refunded. func (t *NoopTracer) OnGasChange(old, new uint64, reason tracing.GasChangeReason) {} -// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). -func (t *NoopTracer) CaptureEnter(typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { +func (t *NoopTracer) OnEnter(depth int, typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { } -// CaptureExit is called when EVM exits a scope, even if the scope didn't -// execute any code. -func (t *NoopTracer) CaptureExit(output []byte, gasUsed uint64, err error, reverted bool) { +func (t *NoopTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) { } -func (*NoopTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { +func (*NoopTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { } -func (*NoopTracer) CaptureTxEnd(receipt *types.Receipt, err error) {} +func (*NoopTracer) OnTxEnd(receipt *types.Receipt, err error) {} func (*NoopTracer) OnBalanceChange(a common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) { } diff --git a/eth/tracers/directory/tracers.go b/eth/tracers/directory/tracers.go index 78dc9ae6e7..766278974c 100644 --- a/eth/tracers/directory/tracers.go +++ b/eth/tracers/directory/tracers.go @@ -41,7 +41,7 @@ type Context struct { // This involves a method to retrieve results and one to // stop tracing. type Tracer struct { - *tracing.LiveLogger + *tracing.Hooks GetResult func() (json.RawMessage, error) // Stop terminates execution of the tracer at the first opportune moment. Stop func(err error) diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go index 01c5ae1fdb..8ca877aea5 100644 --- a/eth/tracers/internal/tracetest/calltrace_test.go +++ b/eth/tracers/internal/tracetest/calltrace_test.go @@ -144,7 +144,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) { t.Fatalf("failed to create call tracer: %v", err) } - statedb.SetLogger(tracer.LiveLogger) + statedb.SetLogger(tracer.Hooks) msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) @@ -251,7 +251,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) { if err != nil { b.Fatalf("failed to create call tracer: %v", err) } - evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer.LiveLogger}) + evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks}) snap := statedb.Snapshot() st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas())) if _, err = st.TransitionDb(); err != nil { @@ -379,7 +379,7 @@ func TestInternals(t *testing.T) { }, }, false, rawdb.HashScheme) defer triedb.Close() - statedb.SetLogger(tc.tracer.LiveLogger) + statedb.SetLogger(tc.tracer.Hooks) tx, err := types.SignNewTx(key, signer, &types.LegacyTx{ To: &to, Value: big.NewInt(0), @@ -393,7 +393,7 @@ func TestInternals(t *testing.T) { Origin: origin, GasPrice: tx.GasPrice(), } - evm := vm.NewEVM(context, txContext, statedb, config, vm.Config{Tracer: tc.tracer.LiveLogger}) + evm := vm.NewEVM(context, txContext, statedb, config, vm.Config{Tracer: tc.tracer.Hooks}) msg, err := core.TransactionToMessage(tx, signer, big.NewInt(0)) if err != nil { t.Fatalf("test %v: failed to create message: %v", tc.name, err) diff --git a/eth/tracers/internal/tracetest/flat_calltrace_test.go b/eth/tracers/internal/tracetest/flat_calltrace_test.go index 8cf9eae541..afffb80bf8 100644 --- a/eth/tracers/internal/tracetest/flat_calltrace_test.go +++ b/eth/tracers/internal/tracetest/flat_calltrace_test.go @@ -102,7 +102,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string return fmt.Errorf("failed to create call tracer: %v", err) } - statedb.SetLogger(tracer.LiveLogger) + statedb.SetLogger(tracer.Hooks) msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) if err != nil { return fmt.Errorf("failed to prepare transaction for tracing: %v", err) diff --git a/eth/tracers/internal/tracetest/prestate_test.go b/eth/tracers/internal/tracetest/prestate_test.go index a055ba334d..48a95f43c1 100644 --- a/eth/tracers/internal/tracetest/prestate_test.go +++ b/eth/tracers/internal/tracetest/prestate_test.go @@ -112,7 +112,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) { t.Fatalf("failed to create call tracer: %v", err) } - statedb.SetLogger(tracer.LiveLogger) + statedb.SetLogger(tracer.Hooks) msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) diff --git a/eth/tracers/js/goja.go b/eth/tracers/js/goja.go index 3d96253b71..4bac8edfeb 100644 --- a/eth/tracers/js/goja.go +++ b/eth/tracers/js/goja.go @@ -214,23 +214,21 @@ func newJsTracer(code string, ctx *directory.Context, cfg json.RawMessage) (*dir return &directory.Tracer{ Hooks: &tracing.Hooks{ - OnTxStart: t.CaptureTxStart, - OnTxEnd: t.CaptureTxEnd, - OnStart: t.CaptureStart, - OnEnd: t.CaptureEnd, - OnEnter: t.CaptureEnter, - OnExit: t.CaptureExit, - OnOpcode: t.CaptureState, - OnFault: t.CaptureFault, + OnTxStart: t.OnTxStart, + OnTxEnd: t.OnTxEnd, + OnEnter: t.OnEnter, + OnExit: t.OnExit, + OnOpcode: t.OnOpcode, + OnFault: t.OnFault, }, GetResult: t.GetResult, Stop: t.Stop, }, nil } -// CaptureTxStart implements the Tracer interface and is invoked at the beginning of +// OnTxStart implements the Tracer interface and is invoked at the beginning of // transaction processing. -func (t *jsTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { +func (t *jsTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { t.env = env // Need statedb access for db object db := &dbObj{db: env.StateDB, vm: t.vm, toBig: t.toBig, toBuf: t.toBuf, fromBuf: t.fromBuf} @@ -249,9 +247,9 @@ func (t *jsTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, t.ctx["gasPrice"] = gasPriceBig } -// CaptureTxEnd implements the Tracer interface and is invoked at the end of +// OnTxEnd implements the Tracer interface and is invoked at the end of // transaction processing. -func (t *jsTracer) CaptureTxEnd(receipt *types.Receipt, err error) { +func (t *jsTracer) OnTxEnd(receipt *types.Receipt, err error) { if err != nil { // Don't override vm error if _, ok := t.ctx["error"]; !ok { @@ -262,8 +260,8 @@ func (t *jsTracer) CaptureTxEnd(receipt *types.Receipt, err error) { t.ctx["gasUsed"] = t.vm.ToValue(receipt.GasUsed) } -// CaptureStart implements the Tracer interface to initialize the tracing operation. -func (t *jsTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { +// onStart implements the Tracer interface to initialize the tracing operation. +func (t *jsTracer) onStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { cancel := func(err error) { t.err = err t.env.VM.Cancel() @@ -299,8 +297,8 @@ func (t *jsTracer) CaptureStart(from common.Address, to common.Address, create b t.ctx["value"] = valueBig } -// CaptureState implements the Tracer interface to trace a single step of VM execution. -func (t *jsTracer) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { +// OnOpcode implements the Tracer interface to trace a single step of VM execution. +func (t *jsTracer) OnOpcode(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { if !t.traceStep { return } @@ -324,8 +322,8 @@ func (t *jsTracer) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, } } -// CaptureFault implements the Tracer interface to trace an execution fault -func (t *jsTracer) CaptureFault(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, depth int, err error) { +// OnFault implements the Tracer interface to trace an execution fault +func (t *jsTracer) OnFault(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, depth int, err error) { if t.err != nil { return } @@ -336,15 +334,19 @@ func (t *jsTracer) CaptureFault(pc uint64, op tracing.OpCode, gas, cost uint64, } } -// CaptureEnd is called after the call finishes to finalize the tracing. -func (t *jsTracer) CaptureEnd(output []byte, gasUsed uint64, err error, reverted bool) { +// onEnd is called after the call finishes to finalize the tracing. +func (t *jsTracer) onEnd(output []byte, gasUsed uint64, err error, reverted bool) { if err != nil { t.ctx["error"] = t.vm.ToValue(err.Error()) } } -// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). -func (t *jsTracer) CaptureEnter(typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { +// OnEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *jsTracer) OnEnter(depth int, typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + if depth == 0 { + t.onStart(from, to, vm.OpCode(typ) == vm.CREATE, input, gas, value) + return + } if !t.traceFrame { return } @@ -367,9 +369,13 @@ func (t *jsTracer) CaptureEnter(typ tracing.OpCode, from common.Address, to comm } } -// CaptureExit is called when EVM exits a scope, even if the scope didn't +// OnExit is called when EVM exits a scope, even if the scope didn't // execute any code. -func (t *jsTracer) CaptureExit(output []byte, gasUsed uint64, err error, reverted bool) { +func (t *jsTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) { + if depth == 0 { + t.onEnd(output, gasUsed, err, reverted) + return + } if !t.traceFrame { return } diff --git a/eth/tracers/js/tracer_test.go b/eth/tracers/js/tracer_test.go index c1546ca055..5893c6844f 100644 --- a/eth/tracers/js/tracer_test.go +++ b/eth/tracers/js/tracer_test.go @@ -64,7 +64,7 @@ func testCtx() *vmContext { func runTrace(tracer *directory.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig, contractCode []byte) (json.RawMessage, error) { var ( - env = vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Tracer: tracer.LiveLogger}) + env = vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Tracer: tracer.Hooks}) gasLimit uint64 = 31000 startGas uint64 = 10000 value = big.NewInt(0) diff --git a/eth/tracers/live/noop.go b/eth/tracers/live/noop.go index 05560cfb24..afb52a9448 100644 --- a/eth/tracers/live/noop.go +++ b/eth/tracers/live/noop.go @@ -21,18 +21,16 @@ func init() { // as soon as we have a real live tracer. type noop struct{} -func newNoopTracer(_ json.RawMessage) (*tracing.LiveLogger, error) { +func newNoopTracer(_ json.RawMessage) (*tracing.Hooks, error) { t := &noop{} return &tracing.Hooks{ - OnTxStart: t.CaptureTxStart, - OnTxEnd: t.CaptureTxEnd, - OnStart: t.CaptureStart, - OnEnd: t.CaptureEnd, - OnEnter: t.CaptureEnter, - OnExit: t.CaptureExit, - OnOpcode: t.CaptureState, - OnFault: t.CaptureFault, - OnKeccakPreimage: t.CaptureKeccakPreimage, + OnTxStart: t.OnTxStart, + OnTxEnd: t.OnTxEnd, + OnEnter: t.OnEnter, + OnExit: t.OnExit, + OnOpcode: t.OnOpcode, + OnFault: t.OnFault, + OnKeccakPreimage: t.OnKeccakPreimage, OnGasChange: t.OnGasChange, OnBlockchainInit: t.OnBlockchainInit, OnBlockStart: t.OnBlockStart, @@ -47,38 +45,24 @@ func newNoopTracer(_ json.RawMessage) (*tracing.LiveLogger, error) { }, nil } -// CaptureStart implements the EVMLogger interface to initialize the tracing operation. -func (t *noop) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { +func (t *noop) OnOpcode(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { } -// CaptureEnd is called after the call finishes to finalize the tracing. -func (t *noop) CaptureEnd(output []byte, gasUsed uint64, err error, reverted bool) { +func (t *noop) OnFault(pc uint64, op tracing.OpCode, gas, cost uint64, _ tracing.OpContext, depth int, err error) { } -// CaptureState implements the EVMLogger interface to trace a single step of VM execution. -func (t *noop) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { +func (t *noop) OnKeccakPreimage(hash common.Hash, data []byte) {} + +func (t *noop) OnEnter(depth int, typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { } -// CaptureFault implements the EVMLogger interface to trace an execution fault. -func (t *noop) CaptureFault(pc uint64, op tracing.OpCode, gas, cost uint64, _ tracing.OpContext, depth int, err error) { +func (t *noop) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) { } -// CaptureKeccakPreimage is called during the KECCAK256 opcode. -func (t *noop) CaptureKeccakPreimage(hash common.Hash, data []byte) {} - -// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). -func (t *noop) CaptureEnter(typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { +func (t *noop) OnTxStart(vm *tracing.VMContext, tx *types.Transaction, from common.Address) { } -// CaptureExit is called when EVM exits a scope, even if the scope didn't -// execute any code. -func (t *noop) CaptureExit(output []byte, gasUsed uint64, err error, reverted bool) { -} - -func (t *noop) CaptureTxStart(vm *tracing.VMContext, tx *types.Transaction, from common.Address) { -} - -func (t *noop) CaptureTxEnd(receipt *types.Receipt, err error) { +func (t *noop) OnTxEnd(receipt *types.Receipt, err error) { } func (t *noop) OnBlockStart(ev tracing.BlockEvent) { diff --git a/eth/tracers/logger/access_list_tracer.go b/eth/tracers/logger/access_list_tracer.go index 92df195fe0..4ac49fd91f 100644 --- a/eth/tracers/logger/access_list_tracer.go +++ b/eth/tracers/logger/access_list_tracer.go @@ -135,12 +135,12 @@ func NewAccessListTracer(acl types.AccessList, from, to common.Address, precompi func (a *AccessListTracer) Hooks() *tracing.Hooks { return &tracing.Hooks{ - OnOpcode: a.CaptureState, + OnOpcode: a.OnOpcode, } } -// CaptureState captures all opcodes that touch storage or addresses and adds them to the accesslist. -func (a *AccessListTracer) CaptureState(pc uint64, opcode tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { +// OnOpcode captures all opcodes that touch storage or addresses and adds them to the accesslist. +func (a *AccessListTracer) OnOpcode(pc uint64, opcode tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { stackData := scope.StackData() stackLen := len(stackData) op := vm.OpCode(opcode) diff --git a/eth/tracers/logger/logger.go b/eth/tracers/logger/logger.go index 6e694368b1..c0b66d8c27 100644 --- a/eth/tracers/logger/logger.go +++ b/eth/tracers/logger/logger.go @@ -135,10 +135,10 @@ func NewStructLogger(cfg *Config) *StructLogger { func (l *StructLogger) Hooks() *tracing.Hooks { return &tracing.Hooks{ - OnTxStart: l.CaptureTxStart, - OnTxEnd: l.CaptureTxEnd, - OnEnd: l.CaptureEnd, - OnOpcode: l.CaptureState, + OnTxStart: l.OnTxStart, + OnTxEnd: l.OnTxEnd, + OnExit: l.OnExit, + OnOpcode: l.OnOpcode, } } @@ -158,10 +158,10 @@ func (l *StructLogger) Reset() { l.err = nil } -// CaptureState logs a new structured log message and pushes it out to the environment +// OnOpcode logs a new structured log message and pushes it out to the environment // -// CaptureState also tracks SLOAD/SSTORE ops to track storage change. -func (l *StructLogger) CaptureState(pc uint64, opcode tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { +// OnOpcode also tracks SLOAD/SSTORE ops to track storage change. +func (l *StructLogger) OnOpcode(pc uint64, opcode tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { // If tracing was interrupted, set the error and stop if l.interrupt.Load() { return @@ -226,8 +226,11 @@ func (l *StructLogger) CaptureState(pc uint64, opcode tracing.OpCode, gas, cost l.logs = append(l.logs, log) } -// CaptureEnd is called after the call finishes to finalize the tracing. -func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, err error, reverted bool) { +// OnExit is called a call frame finishes processing. +func (l *StructLogger) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) { + if depth != 0 { + return + } l.output = output l.err = err if l.cfg.Debug { @@ -264,11 +267,11 @@ func (l *StructLogger) Stop(err error) { l.interrupt.Store(true) } -func (l *StructLogger) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { +func (l *StructLogger) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { l.env = env } -func (l *StructLogger) CaptureTxEnd(receipt *types.Receipt, err error) { +func (l *StructLogger) OnTxEnd(receipt *types.Receipt, err error) { if err != nil { // Don't override vm error if l.err == nil { @@ -354,19 +357,23 @@ func NewMarkdownLogger(cfg *Config, writer io.Writer) *mdLogger { func (t *mdLogger) Hooks() *tracing.Hooks { return &tracing.Hooks{ - OnTxStart: t.CaptureTxStart, - OnStart: t.CaptureStart, - OnOpcode: t.CaptureState, - OnFault: t.CaptureFault, - OnEnd: t.CaptureEnd, + OnTxStart: t.OnTxStart, + OnEnter: t.OnEnter, + OnExit: t.OnExit, + OnOpcode: t.OnOpcode, + OnFault: t.OnFault, } } -func (t *mdLogger) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { +func (t *mdLogger) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { t.env = env } -func (t *mdLogger) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { +func (t *mdLogger) OnEnter(depth int, typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + if depth != 0 { + return + } + create := vm.OpCode(typ) == vm.CREATE if !create { fmt.Fprintf(t.out, "From: `%v`\nTo: `%v`\nData: `%#x`\nGas: `%d`\nValue `%v` wei\n", from.String(), to.String(), @@ -383,8 +390,15 @@ func (t *mdLogger) CaptureStart(from common.Address, to common.Address, create b `) } -// CaptureState also tracks SLOAD/SSTORE ops to track storage change. -func (t *mdLogger) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { +func (t *mdLogger) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) { + if depth == 0 { + fmt.Fprintf(t.out, "\nOutput: `%#x`\nConsumed gas: `%d`\nError: `%v`\n", + output, gasUsed, err) + } +} + +// OnOpcode also tracks SLOAD/SSTORE ops to track storage change. +func (t *mdLogger) OnOpcode(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { stack := scope.StackData() fmt.Fprintf(t.out, "| %4d | %10v | %3d |", pc, op, cost) @@ -404,7 +418,7 @@ func (t *mdLogger) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, } } -func (t *mdLogger) CaptureFault(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, depth int, err error) { +func (t *mdLogger) OnFault(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, depth int, err error) { fmt.Fprintf(t.out, "\nError: at pc=%d, op=%v: %v\n", pc, op, err) } diff --git a/eth/tracers/logger/logger_json.go b/eth/tracers/logger/logger_json.go index 5067fb8a58..6744ac729c 100644 --- a/eth/tracers/logger/logger_json.go +++ b/eth/tracers/logger/logger_json.go @@ -47,20 +47,19 @@ func NewJSONLogger(cfg *Config, writer io.Writer) *JSONLogger { func (l *JSONLogger) Hooks() *tracing.Hooks { return &tracing.Hooks{ - OnTxStart: l.CaptureTxStart, - OnEnd: l.CaptureEnd, - OnOpcode: l.CaptureState, - OnFault: l.CaptureFault, + OnTxStart: l.OnTxStart, + OnExit: l.OnExit, + OnOpcode: l.OnOpcode, + OnFault: l.OnFault, } } -func (l *JSONLogger) CaptureFault(pc uint64, op tracing.OpCode, gas uint64, cost uint64, scope tracing.OpContext, depth int, err error) { +func (l *JSONLogger) OnFault(pc uint64, op tracing.OpCode, gas uint64, cost uint64, scope tracing.OpContext, depth int, err error) { // TODO: Add rData to this interface as well - l.CaptureState(pc, op, gas, cost, scope, nil, depth, err) + l.OnOpcode(pc, op, gas, cost, scope, nil, depth, err) } -// CaptureState outputs state information on the logger. -func (l *JSONLogger) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { +func (l *JSONLogger) OnOpcode(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { memory := scope.MemoryData() stack := scope.StackData() @@ -86,8 +85,10 @@ func (l *JSONLogger) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64 l.encoder.Encode(log) } -// CaptureEnd is triggered at end of execution. -func (l *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, err error, reverted bool) { +func (l *JSONLogger) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) { + if depth > 0 { + return + } type endLog struct { Output string `json:"output"` GasUsed math.HexOrDecimal64 `json:"gasUsed"` @@ -100,6 +101,6 @@ func (l *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, err error, revert l.encoder.Encode(endLog{common.Bytes2Hex(output), math.HexOrDecimal64(gasUsed), errMsg}) } -func (l *JSONLogger) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { +func (l *JSONLogger) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { l.env = env } diff --git a/eth/tracers/logger/logger_test.go b/eth/tracers/logger/logger_test.go index c2982ab036..d3bfc13a03 100644 --- a/eth/tracers/logger/logger_test.go +++ b/eth/tracers/logger/logger_test.go @@ -60,8 +60,7 @@ func TestStoreCapture(t *testing.T) { ) contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)} var index common.Hash - logger.CaptureTxStart(env.GetVMContext(), nil, common.Address{}) - logger.CaptureStart(common.Address{}, contract.Address(), false, nil, 0, nil) + logger.OnTxStart(env.GetVMContext(), nil, common.Address{}) _, err := env.Interpreter().Run(contract, []byte{}, false) if err != nil { t.Fatal(err) diff --git a/eth/tracers/native/4byte.go b/eth/tracers/native/4byte.go index a0a4a6ff4f..7add963e16 100644 --- a/eth/tracers/native/4byte.go +++ b/eth/tracers/native/4byte.go @@ -52,7 +52,7 @@ type fourByteTracer struct { ids map[string]int // ids aggregates the 4byte ids found interrupt atomic.Bool // Atomic flag to signal execution interruption reason error // Textual reason for the interruption - activePrecompiles []common.Address // Updated on CaptureStart based on given rules + activePrecompiles []common.Address // Updated on tx start based on given rules } // newFourByteTracer returns a native go tracer which collects @@ -63,9 +63,8 @@ func newFourByteTracer(ctx *directory.Context, _ json.RawMessage) (*directory.Tr } return &directory.Tracer{ Hooks: &tracing.Hooks{ - OnTxStart: t.CaptureTxStart, - OnStart: t.CaptureStart, - OnEnter: t.CaptureEnter, + OnTxStart: t.OnTxStart, + OnEnter: t.OnEnter, }, GetResult: t.GetResult, Stop: t.Stop, @@ -88,22 +87,14 @@ func (t *fourByteTracer) store(id []byte, size int) { t.ids[key] += 1 } -func (t *fourByteTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { +func (t *fourByteTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { // Update list of precompiles based on current block rules := env.ChainConfig.Rules(env.BlockNumber, env.Random != nil, env.Time) t.activePrecompiles = vm.ActivePrecompiles(rules) } -// CaptureStart implements the EVMLogger interface to initialize the tracing operation. -func (t *fourByteTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { - // Save the outer calldata - if len(input) >= 4 { - t.store(input[0:4], len(input)-4) - } -} - -// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). -func (t *fourByteTracer) CaptureEnter(opcode tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { +// OnEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *fourByteTracer) OnEnter(depth int, opcode tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { // Skip if tracing was interrupted if t.interrupt.Load() { return diff --git a/eth/tracers/native/call.go b/eth/tracers/native/call.go index d42f36666b..07e86ab1f0 100644 --- a/eth/tracers/native/call.go +++ b/eth/tracers/native/call.go @@ -127,27 +127,12 @@ func newCallTracer(ctx *directory.Context, cfg json.RawMessage) (*directory.Trac return nil, err } return &directory.Tracer{ -<<<<<<< HEAD - LiveLogger: &tracing.LiveLogger{ - CaptureTxStart: t.CaptureTxStart, - CaptureTxEnd: t.CaptureTxEnd, - CaptureStart: t.CaptureStart, - CaptureEnd: t.CaptureEnd, - CaptureEnter: t.CaptureEnter, - CaptureExit: t.CaptureExit, - CaptureState: t.CaptureState, - OnLog: t.OnLog, -======= Hooks: &tracing.Hooks{ - OnTxStart: t.CaptureTxStart, - OnTxEnd: t.CaptureTxEnd, - OnStart: t.CaptureStart, - OnEnd: t.CaptureEnd, - OnEnter: t.CaptureEnter, - OnExit: t.CaptureExit, - OnOpcode: t.CaptureState, + OnTxStart: t.OnTxStart, + OnTxEnd: t.OnTxEnd, + OnEnter: t.OnEnter, + OnExit: t.OnExit, OnLog: t.OnLog, ->>>>>>> 923c180058 (rename Capture hooks to On) }, GetResult: t.GetResult, Stop: t.Stop, @@ -191,10 +176,10 @@ func (t *callTracer) CaptureEnd(output []byte, gasUsed uint64, err error, revert func (t *callTracer) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { } -// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). -func (t *callTracer) CaptureEnter(typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { - t.depth++ - if t.config.OnlyTopCall { +// OnEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *callTracer) OnEnter(depth int, typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + t.depth = depth + if t.config.OnlyTopCall && depth > 0 { return } // Skip if tracing was interrupted @@ -214,10 +199,15 @@ func (t *callTracer) CaptureEnter(typ tracing.OpCode, from common.Address, to co t.callstack = append(t.callstack, call) } -// CaptureExit is called when EVM exits a scope, even if the scope didn't +// OnExit is called when EVM exits a scope, even if the scope didn't // execute any code. -func (t *callTracer) CaptureExit(output []byte, gasUsed uint64, err error, reverted bool) { - t.depth-- +func (t *callTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) { + if depth == 0 { + t.captureEnd(output, gasUsed, err, reverted) + return + } + + t.depth = depth - 1 if t.config.OnlyTopCall { return } @@ -235,11 +225,18 @@ func (t *callTracer) CaptureExit(output []byte, gasUsed uint64, err error, rever t.callstack[size-1].Calls = append(t.callstack[size-1].Calls, call) } -func (t *callTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { +func (t *callTracer) captureEnd(output []byte, gasUsed uint64, err error, reverted bool) { + if len(t.callstack) != 1 { + return + } + t.callstack[0].processOutput(output, err, reverted) +} + +func (t *callTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { t.gasLimit = tx.Gas() } -func (t *callTracer) CaptureTxEnd(receipt *types.Receipt, err error) { +func (t *callTracer) OnTxEnd(receipt *types.Receipt, err error) { // Error happened during tx validation. if err != nil { return diff --git a/eth/tracers/native/call_flat.go b/eth/tracers/native/call_flat.go index c0ec5c312e..d321278732 100644 --- a/eth/tracers/native/call_flat.go +++ b/eth/tracers/native/call_flat.go @@ -115,7 +115,7 @@ type flatCallTracer struct { config flatCallTracerConfig ctx *directory.Context // Holds tracer context data reason error // Textual reason for the interruption - activePrecompiles []common.Address // Updated on CaptureStart based on given rules + activePrecompiles []common.Address // Updated on tx start based on given rules } type flatCallTracerConfig struct { @@ -142,43 +142,19 @@ func newFlatCallTracer(ctx *directory.Context, cfg json.RawMessage) (*directory. ft := &flatCallTracer{tracer: t, ctx: ctx, config: config} return &directory.Tracer{ Hooks: &tracing.Hooks{ - OnTxStart: ft.CaptureTxStart, - OnTxEnd: ft.CaptureTxEnd, - OnStart: ft.CaptureStart, - OnEnd: ft.CaptureEnd, - OnEnter: ft.CaptureEnter, - OnExit: ft.CaptureExit, - OnOpcode: ft.CaptureState, - OnFault: ft.CaptureFault, + OnTxStart: ft.OnTxStart, + OnTxEnd: ft.OnTxEnd, + OnEnter: ft.OnEnter, + OnExit: ft.OnExit, }, Stop: ft.Stop, GetResult: ft.GetResult, }, nil } -// CaptureStart implements the EVMLogger interface to initialize the tracing operation. -func (t *flatCallTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { - t.tracer.CaptureStart(from, to, create, input, gas, value) -} - -// CaptureEnd is called after the call finishes to finalize the tracing. -func (t *flatCallTracer) CaptureEnd(output []byte, gasUsed uint64, err error, reverted bool) { - t.tracer.CaptureEnd(output, gasUsed, err, reverted) -} - -// CaptureState implements the EVMLogger interface to trace a single step of VM execution. -func (t *flatCallTracer) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { - t.tracer.CaptureState(pc, op, gas, cost, scope, rData, depth, err) -} - -// CaptureFault implements the EVMLogger interface to trace an execution fault. -func (t *flatCallTracer) CaptureFault(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, depth int, err error) { - t.tracer.CaptureFault(pc, op, gas, cost, scope, depth, err) -} - -// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). -func (t *flatCallTracer) CaptureEnter(typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { - t.tracer.CaptureEnter(typ, from, to, input, gas, value) +// OnEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *flatCallTracer) OnEnter(depth int, typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + t.tracer.OnEnter(depth, typ, from, to, input, gas, value) // Child calls must have a value, even if it's zero. // Practically speaking, only STATICCALL has nil value. Set it to zero. @@ -187,10 +163,10 @@ func (t *flatCallTracer) CaptureEnter(typ tracing.OpCode, from common.Address, t } } -// CaptureExit is called when EVM exits a scope, even if the scope didn't +// OnExit is called when EVM exits a scope, even if the scope didn't // execute any code. -func (t *flatCallTracer) CaptureExit(output []byte, gasUsed uint64, err error, reverted bool) { - t.tracer.CaptureExit(output, gasUsed, err, reverted) +func (t *flatCallTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) { + t.tracer.OnExit(depth, output, gasUsed, err, reverted) // Parity traces don't include CALL/STATICCALLs to precompiles. // By default we remove them from the callstack. @@ -211,15 +187,15 @@ func (t *flatCallTracer) CaptureExit(output []byte, gasUsed uint64, err error, r } } -func (t *flatCallTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { - t.tracer.CaptureTxStart(env, tx, from) +func (t *flatCallTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { + t.tracer.OnTxStart(env, tx, from) // Update list of precompiles based on current block rules := env.ChainConfig.Rules(env.BlockNumber, env.Random != nil, env.Time) t.activePrecompiles = vm.ActivePrecompiles(rules) } -func (t *flatCallTracer) CaptureTxEnd(receipt *types.Receipt, err error) { - t.tracer.CaptureTxEnd(receipt, err) +func (t *flatCallTracer) OnTxEnd(receipt *types.Receipt, err error) { + t.tracer.OnTxEnd(receipt, err) } // GetResult returns an empty json object. diff --git a/eth/tracers/native/mux.go b/eth/tracers/native/mux.go index 4516ab1dff..a54b5611af 100644 --- a/eth/tracers/native/mux.go +++ b/eth/tracers/native/mux.go @@ -59,15 +59,13 @@ func newMuxTracer(ctx *directory.Context, cfg json.RawMessage) (*directory.Trace t := &muxTracer{names: names, tracers: objects} return &directory.Tracer{ Hooks: &tracing.Hooks{ - OnTxStart: t.CaptureTxStart, - OnTxEnd: t.CaptureTxEnd, - OnStart: t.CaptureStart, - OnEnd: t.CaptureEnd, - OnEnter: t.CaptureEnter, - OnExit: t.CaptureExit, - OnOpcode: t.CaptureState, - OnFault: t.CaptureFault, - OnKeccakPreimage: t.CaptureKeccakPreimage, + OnTxStart: t.OnTxStart, + OnTxEnd: t.OnTxEnd, + OnEnter: t.OnEnter, + OnExit: t.OnExit, + OnOpcode: t.OnOpcode, + OnFault: t.OnFault, + OnKeccakPreimage: t.OnKeccakPreimage, OnGasChange: t.OnGasChange, OnBalanceChange: t.OnBalanceChange, OnNonceChange: t.OnNonceChange, @@ -80,26 +78,7 @@ func newMuxTracer(ctx *directory.Context, cfg json.RawMessage) (*directory.Trace }, nil } -// CaptureStart implements the EVMLogger interface to initialize the tracing operation. -func (t *muxTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { - for _, t := range t.tracers { - if t.OnStart != nil { - t.OnStart(from, to, create, input, gas, value) - } - } -} - -// CaptureEnd is called after the call finishes to finalize the tracing. -func (t *muxTracer) CaptureEnd(output []byte, gasUsed uint64, err error, reverted bool) { - for _, t := range t.tracers { - if t.OnEnd != nil { - t.OnEnd(output, gasUsed, err, reverted) - } - } -} - -// CaptureState implements the EVMLogger interface to trace a single step of VM execution. -func (t *muxTracer) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { +func (t *muxTracer) OnOpcode(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { for _, t := range t.tracers { if t.OnOpcode != nil { t.OnOpcode(pc, op, gas, cost, scope, rData, depth, err) @@ -107,8 +86,7 @@ func (t *muxTracer) CaptureState(pc uint64, op tracing.OpCode, gas, cost uint64, } } -// CaptureFault implements the EVMLogger interface to trace an execution fault. -func (t *muxTracer) CaptureFault(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, depth int, err error) { +func (t *muxTracer) OnFault(pc uint64, op tracing.OpCode, gas, cost uint64, scope tracing.OpContext, depth int, err error) { for _, t := range t.tracers { if t.OnFault != nil { t.OnFault(pc, op, gas, cost, scope, depth, err) @@ -116,8 +94,7 @@ func (t *muxTracer) CaptureFault(pc uint64, op tracing.OpCode, gas, cost uint64, } } -// CaptureKeccakPreimage is called during the KECCAK256 opcode. -func (t *muxTracer) CaptureKeccakPreimage(hash common.Hash, data []byte) { +func (t *muxTracer) OnKeccakPreimage(hash common.Hash, data []byte) { for _, t := range t.tracers { if t.OnKeccakPreimage != nil { t.OnKeccakPreimage(hash, data) @@ -125,7 +102,6 @@ func (t *muxTracer) CaptureKeccakPreimage(hash common.Hash, data []byte) { } } -// CaptureGasConsumed is called when gas is consumed. func (t *muxTracer) OnGasChange(old, new uint64, reason tracing.GasChangeReason) { for _, t := range t.tracers { if t.OnGasChange != nil { @@ -134,8 +110,7 @@ func (t *muxTracer) OnGasChange(old, new uint64, reason tracing.GasChangeReason) } } -// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). -func (t *muxTracer) CaptureEnter(typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { +func (t *muxTracer) OnEnter(depth int, typ tracing.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { for _, t := range t.tracers { if t.OnEnter != nil { t.OnEnter(typ, from, to, input, gas, value) @@ -143,9 +118,7 @@ func (t *muxTracer) CaptureEnter(typ tracing.OpCode, from common.Address, to com } } -// CaptureExit is called when EVM exits a scope, even if the scope didn't -// execute any code. -func (t *muxTracer) CaptureExit(output []byte, gasUsed uint64, err error, reverted bool) { +func (t *muxTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) { for _, t := range t.tracers { if t.OnExit != nil { t.OnExit(output, gasUsed, err, reverted) @@ -153,7 +126,7 @@ func (t *muxTracer) CaptureExit(output []byte, gasUsed uint64, err error, revert } } -func (t *muxTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { +func (t *muxTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { for _, t := range t.tracers { if t.OnTxStart != nil { t.OnTxStart(env, tx, from) @@ -161,7 +134,7 @@ func (t *muxTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction } } -func (t *muxTracer) CaptureTxEnd(receipt *types.Receipt, err error) { +func (t *muxTracer) OnTxEnd(receipt *types.Receipt, err error) { for _, t := range t.tracers { if t.OnTxEnd != nil { t.OnTxEnd(receipt, err) diff --git a/eth/tracers/native/prestate.go b/eth/tracers/native/prestate.go index 5e053236a9..d51780da21 100644 --- a/eth/tracers/native/prestate.go +++ b/eth/tracers/native/prestate.go @@ -90,17 +90,17 @@ func newPrestateTracer(ctx *directory.Context, cfg json.RawMessage) (*directory. } return &directory.Tracer{ Hooks: &tracing.Hooks{ - OnTxStart: t.CaptureTxStart, - OnTxEnd: t.CaptureTxEnd, - OnOpcode: t.CaptureState, + OnTxStart: t.OnTxStart, + OnTxEnd: t.OnTxEnd, + OnOpcode: t.OnOpcode, }, GetResult: t.GetResult, Stop: t.Stop, }, nil } -// CaptureState implements the EVMLogger interface to trace a single step of VM execution. -func (t *prestateTracer) CaptureState(pc uint64, opcode tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { +// OnOpcode implements the EVMLogger interface to trace a single step of VM execution. +func (t *prestateTracer) OnOpcode(pc uint64, opcode tracing.OpCode, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { if err != nil { return } @@ -146,7 +146,7 @@ func (t *prestateTracer) CaptureState(pc uint64, opcode tracing.OpCode, gas, cos } } -func (t *prestateTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { +func (t *prestateTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) { t.env = env if tx.To() == nil { t.to = crypto.CreateAddress(from, env.StateDB.GetNonce(from)) @@ -160,7 +160,7 @@ func (t *prestateTracer) CaptureTxStart(env *tracing.VMContext, tx *types.Transa t.lookupAccount(env.Coinbase) } -func (t *prestateTracer) CaptureTxEnd(receipt *types.Receipt, err error) { +func (t *prestateTracer) OnTxEnd(receipt *types.Receipt, err error) { if err != nil { return } diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 37b89afc51..e39cbf5aae 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -109,7 +109,7 @@ type btHeaderMarshaling struct { ExcessBlobGas *math.HexOrDecimal64 } -func (t *BlockTest) Run(snapshotter bool, scheme string, tracer *tracing.LiveLogger) error { +func (t *BlockTest) Run(snapshotter bool, scheme string, tracer *tracing.Hooks) error { config, ok := Forks[t.json.Network] if !ok { return UnsupportedForkError{t.json.Network}