Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eth/tracers: trace without passing ctx #30337

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/evm/internal/t8ntool/transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func Transition(ctx *cli.Context) error {
if err != nil {
return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
}
tracer, err := tracers.DefaultDirectory.New(ctx.String(TraceTracerFlag.Name), nil, config)
tracer, err := tracers.DefaultDirectory.New(ctx.String(TraceTracerFlag.Name), config)
if err != nil {
return nil, nil, NewError(ErrorConfig, fmt.Errorf("failed instantiating tracer: %w", err))
}
Expand Down
6 changes: 3 additions & 3 deletions core/vm/runtime/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode
cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
cfg.GasLimit = gas
if len(tracerCode) > 0 {
tracer, err := tracers.DefaultDirectory.New(tracerCode, new(tracers.Context), nil)
tracer, err := tracers.DefaultDirectory.New(tracerCode, nil)
if err != nil {
b.Fatal(err)
}
Expand Down Expand Up @@ -887,7 +887,7 @@ func TestRuntimeJSTracer(t *testing.T) {
statedb.SetCode(common.HexToAddress("0xee"), calleeCode)
statedb.SetCode(common.HexToAddress("0xff"), suicideCode)

tracer, err := tracers.DefaultDirectory.New(jsTracer, new(tracers.Context), nil)
tracer, err := tracers.DefaultDirectory.New(jsTracer, nil)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -922,7 +922,7 @@ func TestJSTracerCreateTx(t *testing.T) {
code := []byte{byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.RETURN)}

statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
tracer, err := tracers.DefaultDirectory.New(jsTracer, new(tracers.Context), nil)
tracer, err := tracers.DefaultDirectory.New(jsTracer, nil)
if err != nil {
t.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion eth/tracers/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1009,7 +1009,7 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
Stop: logger.Stop,
}
} else {
tracer, err = DefaultDirectory.New(*config.Tracer, txctx, config.TracerConfig)
tracer, err = DefaultDirectory.New(*config.Tracer, config.TracerConfig)
if err != nil {
return nil, err
}
Expand Down
10 changes: 5 additions & 5 deletions eth/tracers/dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ type Tracer struct {
Stop func(err error)
}

type ctorFn func(*Context, json.RawMessage) (*Tracer, error)
type jsCtorFn func(string, *Context, json.RawMessage) (*Tracer, error)
type ctorFn func(json.RawMessage) (*Tracer, error)
type jsCtorFn func(string, json.RawMessage) (*Tracer, error)

type elem struct {
ctor ctorFn
Expand Down Expand Up @@ -78,12 +78,12 @@ func (d *directory) RegisterJSEval(f jsCtorFn) {
// New returns a new instance of a tracer, by iterating through the
// registered lookups. Name is either name of an existing tracer
// or an arbitrary JS code.
func (d *directory) New(name string, ctx *Context, cfg json.RawMessage) (*Tracer, error) {
func (d *directory) New(name string, cfg json.RawMessage) (*Tracer, error) {
if elem, ok := d.elems[name]; ok {
return elem.ctor(ctx, cfg)
return elem.ctor(cfg)
}
// Assume JS code
return d.jsEval(name, ctx, cfg)
return d.jsEval(name, cfg)
}

// IsJS will return true if the given tracer will evaluate
Expand Down
6 changes: 3 additions & 3 deletions eth/tracers/internal/tracetest/calltrace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
)
state.Close()

tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig)
tracer, err := tracers.DefaultDirectory.New(tracerName, test.TracerConfig)
if err != nil {
t.Fatalf("failed to create call tracer: %v", err)
}
Expand Down Expand Up @@ -229,7 +229,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), nil)
tracer, err := tracers.DefaultDirectory.New(tracerName, nil)
if err != nil {
b.Fatalf("failed to create call tracer: %v", err)
}
Expand Down Expand Up @@ -266,7 +266,7 @@ func TestInternals(t *testing.T) {
}
)
mkTracer := func(name string, cfg json.RawMessage) *tracers.Tracer {
tr, err := tracers.DefaultDirectory.New(name, nil, cfg)
tr, err := tracers.DefaultDirectory.New(name, cfg)
if err != nil {
t.Fatalf("failed to create call tracer: %v", err)
}
Expand Down
2 changes: 1 addition & 1 deletion eth/tracers/internal/tracetest/flat_calltrace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
defer state.Close()

// Create the tracer, the EVM environment and run it
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig)
tracer, err := tracers.DefaultDirectory.New(tracerName, test.TracerConfig)
if err != nil {
return fmt.Errorf("failed to create call tracer: %v", err)
}
Expand Down
2 changes: 1 addition & 1 deletion eth/tracers/internal/tracetest/prestate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
)
defer state.Close()

tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig)
tracer, err := tracers.DefaultDirectory.New(tracerName, test.TracerConfig)
if err != nil {
t.Fatalf("failed to create call tracer: %v", err)
}
Expand Down
62 changes: 32 additions & 30 deletions eth/tracers/js/goja.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ func init() {
if err != nil {
panic(err)
}
type ctorFn = func(*tracers.Context, json.RawMessage) (*tracers.Tracer, error)
type ctorFn = func(json.RawMessage) (*tracers.Tracer, error)
lookup := func(code string) ctorFn {
return func(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, error) {
return newJsTracer(code, ctx, cfg)
return func(cfg json.RawMessage) (*tracers.Tracer, error) {
return newJsTracer(code, cfg)
}
}
for name, code := range assetTracers {
Expand Down Expand Up @@ -138,7 +138,7 @@ type jsTracer struct {
// The methods `result` and `fault` are required to be present.
// The methods `step`, `enter`, and `exit` are optional, but note that
// `enter` and `exit` always go together.
func newJsTracer(code string, ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, error) {
func newJsTracer(code string, cfg json.RawMessage) (*tracers.Tracer, error) {
vm := goja.New()
// By default field names are exported to JS as is, i.e. capitalized.
vm.SetFieldNameMapper(goja.UncapFieldNameMapper())
Expand All @@ -150,25 +150,6 @@ func newJsTracer(code string, ctx *tracers.Context, cfg json.RawMessage) (*trace
t.setTypeConverters()
t.setBuiltinFunctions()

if ctx == nil {
ctx = new(tracers.Context)
}
if ctx.BlockHash != (common.Hash{}) {
blockHash, err := t.toBuf(vm, ctx.BlockHash.Bytes())
if err != nil {
return nil, err
}
t.ctx["blockHash"] = blockHash
if ctx.TxHash != (common.Hash{}) {
t.ctx["txIndex"] = vm.ToValue(ctx.TxIndex)
txHash, err := t.toBuf(vm, ctx.TxHash.Bytes())
if err != nil {
return nil, err
}
t.ctx["txHash"] = txHash
}
}

ret, err := vm.RunString("(" + code + ")")
if err != nil {
return nil, err
Expand Down Expand Up @@ -224,18 +205,33 @@ func newJsTracer(code string, ctx *tracers.Context, cfg json.RawMessage) (*trace

return &tracers.Tracer{
Hooks: &tracing.Hooks{
OnTxStart: t.OnTxStart,
OnTxEnd: t.OnTxEnd,
OnEnter: t.OnEnter,
OnExit: t.OnExit,
OnOpcode: t.OnOpcode,
OnFault: t.OnFault,
OnBlockStart: t.OnBlockStart,
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
}

// OnBlockStart implements the Tracer interface and is invoked at the
// beginning of block processing.
func (t *jsTracer) OnBlockStart(evt tracing.BlockEvent) {
block := evt.Block
t.ctx["block"] = t.vm.ToValue(block.NumberU64())

blockHash, err := t.toBuf(t.vm, block.Hash().Bytes())
if err != nil {
t.err = err
return
}
t.ctx["blockHash"] = t.vm.ToValue(blockHash)
}

// OnTxStart implements the Tracer interface and is invoked at the beginning of
// transaction processing.
func (t *jsTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
Expand All @@ -246,7 +242,6 @@ func (t *jsTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, 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)
t.ctx["block"] = t.vm.ToValue(t.env.BlockNumber.Uint64())
t.ctx["gas"] = t.vm.ToValue(tx.Gas())
gasPriceBig, err := t.toBig(t.vm, env.GasPrice.String())
if err != nil {
Expand All @@ -260,6 +255,12 @@ func (t *jsTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from
return
}
t.ctx["coinbase"] = t.vm.ToValue(coinbase)
txHash, err := t.toBuf(t.vm, tx.Hash().Bytes())
if err != nil {
t.err = err
return
}
t.ctx["txHash"] = txHash
}

// OnTxEnd implements the Tracer interface and is invoked at the end of
Expand All @@ -277,6 +278,7 @@ func (t *jsTracer) OnTxEnd(receipt *types.Receipt, err error) {
}
if receipt != nil {
t.ctx["gasUsed"] = t.vm.ToValue(receipt.GasUsed)
t.ctx["txIndex"] = t.vm.ToValue(receipt.TransactionIndex)
}
}

Expand Down
24 changes: 12 additions & 12 deletions eth/tracers/js/tracer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func runTrace(tracer *tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCo
func TestTracer(t *testing.T) {
execTracer := func(code string, contract []byte) ([]byte, string) {
t.Helper()
tracer, err := newJsTracer(code, nil, nil)
tracer, err := newJsTracer(code, nil)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -167,7 +167,7 @@ func TestTracer(t *testing.T) {

func TestHalt(t *testing.T) {
timeout := errors.New("stahp")
tracer, err := newJsTracer("{step: function() { while(1); }, result: function() { return null; }, fault: function(){}}", nil, nil)
tracer, err := newJsTracer("{step: function() { while(1); }, result: function() { return null; }, fault: function(){}}", nil)
if err != nil {
t.Fatal(err)
}
Expand All @@ -181,7 +181,7 @@ func TestHalt(t *testing.T) {
}

func TestHaltBetweenSteps(t *testing.T) {
tracer, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }}", nil, nil)
tracer, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }}", nil)
if err != nil {
t.Fatal(err)
}
Expand All @@ -206,7 +206,7 @@ func TestHaltBetweenSteps(t *testing.T) {
func TestNoStepExec(t *testing.T) {
execTracer := func(code string) []byte {
t.Helper()
tracer, err := newJsTracer(code, nil, nil)
tracer, err := newJsTracer(code, nil)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -241,7 +241,7 @@ func TestIsPrecompile(t *testing.T) {
chaincfg.IstanbulBlock = big.NewInt(200)
chaincfg.BerlinBlock = big.NewInt(300)
txCtx := vm.TxContext{GasPrice: big.NewInt(100000)}
tracer, err := newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil, nil)
tracer, err := newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil)
if err != nil {
t.Fatal(err)
}
Expand All @@ -255,7 +255,7 @@ func TestIsPrecompile(t *testing.T) {
t.Errorf("tracer should not consider blake2f as precompile in byzantium")
}

tracer, _ = newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil, nil)
tracer, _ = newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil)
blockCtx = vm.BlockContext{BlockNumber: big.NewInt(250)}
res, err = runTrace(tracer, &vmContext{blockCtx, txCtx}, chaincfg, nil)
if err != nil {
Expand All @@ -268,14 +268,14 @@ func TestIsPrecompile(t *testing.T) {

func TestEnterExit(t *testing.T) {
// test that either both or none of enter() and exit() are defined
if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}}", new(tracers.Context), nil); err == nil {
if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}}", nil); err == nil {
t.Fatal("tracer creation should've failed without exit() definition")
}
if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}, exit: function() {}}", new(tracers.Context), nil); err != nil {
if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}, exit: function() {}}", nil); err != nil {
t.Fatal(err)
}
// test that the enter and exit method are correctly invoked and the values passed
tracer, err := newJsTracer("{enters: 0, exits: 0, enterGas: 0, gasUsed: 0, step: function() {}, fault: function() {}, result: function() { return {enters: this.enters, exits: this.exits, enterGas: this.enterGas, gasUsed: this.gasUsed} }, enter: function(frame) { this.enters++; this.enterGas = frame.getGas(); }, exit: function(res) { this.exits++; this.gasUsed = res.getGasUsed(); }}", new(tracers.Context), nil)
tracer, err := newJsTracer("{enters: 0, exits: 0, enterGas: 0, gasUsed: 0, step: function() {}, fault: function() {}, result: function() { return {enters: this.enters, exits: this.exits, enterGas: this.enterGas, gasUsed: this.gasUsed} }, enter: function(frame) { this.enters++; this.enterGas = frame.getGas(); }, exit: function(res) { this.exits++; this.gasUsed = res.getGasUsed(); }}", nil)
if err != nil {
t.Fatal(err)
}
Expand All @@ -297,7 +297,7 @@ func TestEnterExit(t *testing.T) {

func TestSetup(t *testing.T) {
// Test empty config
_, err := newJsTracer(`{setup: function(cfg) { if (cfg !== "{}") { throw("invalid empty config") } }, fault: function() {}, result: function() {}}`, new(tracers.Context), nil)
_, err := newJsTracer(`{setup: function(cfg) { if (cfg !== "{}") { throw("invalid empty config") } }, fault: function() {}, result: function() {}}`, nil)
if err != nil {
t.Error(err)
}
Expand All @@ -307,12 +307,12 @@ func TestSetup(t *testing.T) {
t.Fatal(err)
}
// Test no setup func
_, err = newJsTracer(`{fault: function() {}, result: function() {}}`, new(tracers.Context), cfg)
_, err = newJsTracer(`{fault: function() {}, result: function() {}}`, cfg)
if err != nil {
t.Fatal(err)
}
// Test config value
tracer, err := newJsTracer("{config: null, setup: function(cfg) { this.config = JSON.parse(cfg) }, step: function() {}, fault: function() {}, result: function() { return this.config.foo }}", new(tracers.Context), cfg)
tracer, err := newJsTracer("{config: null, setup: function(cfg) { this.config = JSON.parse(cfg) }, step: function() {}, fault: function() {}, result: function() { return this.config.foo }}", cfg)
if err != nil {
t.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion eth/tracers/native/4byte.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ type fourByteTracer struct {

// newFourByteTracer returns a native go tracer which collects
// 4 byte-identifiers of a tx, and implements vm.EVMLogger.
func newFourByteTracer(ctx *tracers.Context, _ json.RawMessage) (*tracers.Tracer, error) {
func newFourByteTracer(_ json.RawMessage) (*tracers.Tracer, error) {
t := &fourByteTracer{
ids: make(map[string]int),
}
Expand Down
6 changes: 3 additions & 3 deletions eth/tracers/native/call.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ type callTracerConfig struct {

// newCallTracer returns a native go tracer which tracks
// call frames of a tx, and implements vm.EVMLogger.
func newCallTracer(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, error) {
t, err := newCallTracerObject(ctx, cfg)
func newCallTracer(cfg json.RawMessage) (*tracers.Tracer, error) {
t, err := newCallTracerObject(cfg)
if err != nil {
return nil, err
}
Expand All @@ -143,7 +143,7 @@ func newCallTracer(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer,
}, nil
}

func newCallTracerObject(ctx *tracers.Context, cfg json.RawMessage) (*callTracer, error) {
func newCallTracerObject(cfg json.RawMessage) (*callTracer, error) {
var config callTracerConfig
if cfg != nil {
if err := json.Unmarshal(cfg, &config); err != nil {
Expand Down
15 changes: 12 additions & 3 deletions eth/tracers/native/call_flat.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ type flatCallTracerConfig struct {
}

// newFlatCallTracer returns a new flatCallTracer.
func newFlatCallTracer(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, error) {
func newFlatCallTracer(cfg json.RawMessage) (*tracers.Tracer, error) {
var config flatCallTracerConfig
if cfg != nil {
if err := json.Unmarshal(cfg, &config); err != nil {
Expand All @@ -135,12 +135,12 @@ func newFlatCallTracer(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Trac

// Create inner call tracer with default configuration, don't forward
// the OnlyTopCall or WithLog to inner for now
t, err := newCallTracerObject(ctx, nil)
t, err := newCallTracerObject(nil)
if err != nil {
return nil, err
}

ft := &flatCallTracer{tracer: t, ctx: ctx, config: config}
ft := &flatCallTracer{tracer: t, config: config}
return &tracers.Tracer{
Hooks: &tracing.Hooks{
OnTxStart: ft.OnTxStart,
Expand Down Expand Up @@ -214,6 +214,15 @@ func (t *flatCallTracer) OnTxEnd(receipt *types.Receipt, err error) {
if t.interrupt.Load() {
return
}
// Set the context for the tracer only if receipt is available and no error occured
if err == nil && receipt != nil {
t.ctx = &tracers.Context{
BlockHash: receipt.BlockHash,
BlockNumber: receipt.BlockNumber,
TxIndex: int(receipt.TransactionIndex),
TxHash: receipt.TxHash,
}
}
t.tracer.OnTxEnd(receipt, err)
}

Expand Down
Loading