Skip to content

Commit 09332a9

Browse files
s1naHanWang233
authored andcommitted
eth/tracers: add onlyTopCall option to callTracer (ethereum#25430)
This PR allows users to pass in a config object directly to the tracers. Previously only the struct logger was configurable. It also adds an option to the call tracer which if enabled makes it ignore any subcall and collect only information about the top-level call. See ethereum#25419 for discussion. The tracers will silently ignore if they are passed a config they don't care about.
1 parent 8548126 commit 09332a9

File tree

13 files changed

+174
-41
lines changed

13 files changed

+174
-41
lines changed

core/vm/runtime/runtime_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode
333333
cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
334334
cfg.GasLimit = gas
335335
if len(tracerCode) > 0 {
336-
tracer, err := tracers.New(tracerCode, new(tracers.Context))
336+
tracer, err := tracers.New(tracerCode, new(tracers.Context), nil)
337337
if err != nil {
338338
b.Fatal(err)
339339
}
@@ -832,7 +832,7 @@ func TestRuntimeJSTracer(t *testing.T) {
832832
statedb.SetCode(common.HexToAddress("0xee"), calleeCode)
833833
statedb.SetCode(common.HexToAddress("0xff"), depressedCode)
834834

835-
tracer, err := tracers.New(jsTracer, new(tracers.Context))
835+
tracer, err := tracers.New(jsTracer, new(tracers.Context), nil)
836836
if err != nil {
837837
t.Fatal(err)
838838
}
@@ -868,7 +868,7 @@ func TestJSTracerCreateTx(t *testing.T) {
868868
code := []byte{byte(vm.PUSH1), 0, byte(vm.PUSH1), 0, byte(vm.RETURN)}
869869

870870
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
871-
tracer, err := tracers.New(jsTracer, new(tracers.Context))
871+
tracer, err := tracers.New(jsTracer, new(tracers.Context), nil)
872872
if err != nil {
873873
t.Fatal(err)
874874
}

eth/tracers/api.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"bufio"
2121
"bytes"
2222
"context"
23+
"encoding/json"
2324
"errors"
2425
"fmt"
2526
"os"
@@ -169,15 +170,15 @@ type TraceConfig struct {
169170
Tracer *string
170171
Timeout *string
171172
Reexec *uint64
173+
// Config specific to given tracer. Note struct logger
174+
// config are historically embedded in main object.
175+
TracerConfig json.RawMessage
172176
}
173177

174178
// TraceCallConfig is the config for traceCall API. It holds one more
175179
// field to override the state for tracing.
176180
type TraceCallConfig struct {
177-
*logger.Config
178-
Tracer *string
179-
Timeout *string
180-
Reexec *uint64
181+
TraceConfig
181182
StateOverrides *ethapi.StateOverride
182183
BlockOverrides *ethapi.BlockOverrides
183184
}
@@ -882,7 +883,7 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Contex
882883
// Default tracer is the struct logger
883884
tracer = logger.NewStructLogger(config.Config)
884885
if config.Tracer != nil {
885-
tracer, err = New(*config.Tracer, txctx)
886+
tracer, err = New(*config.Tracer, txctx, config.TracerConfig)
886887
if err != nil {
887888
return nil, err
888889
}

eth/tracers/internal/tracetest/calltrace_test.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,11 @@ type callTrace struct {
118118

119119
// callTracerTest defines a single test to check the call tracer against.
120120
type callTracerTest struct {
121-
Genesis *core.Genesis `json:"genesis"`
122-
Context *callContext `json:"context"`
123-
Input string `json:"input"`
124-
Result *callTrace `json:"result"`
121+
Genesis *core.Genesis `json:"genesis"`
122+
Context *callContext `json:"context"`
123+
Input string `json:"input"`
124+
TracerConfig json.RawMessage `json:"tracerConfig"`
125+
Result *callTrace `json:"result"`
125126
}
126127

127128
// Iterates over all the input-output datasets in the tracer test harness and
@@ -179,7 +180,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
179180
}
180181
_, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false)
181182
)
182-
tracer, err := tracers.New(tracerName, new(tracers.Context))
183+
tracer, err := tracers.New(tracerName, new(tracers.Context), test.TracerConfig)
183184
if err != nil {
184185
t.Fatalf("failed to create call tracer: %v", err)
185186
}
@@ -293,7 +294,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
293294
b.ReportAllocs()
294295
b.ResetTimer()
295296
for i := 0; i < b.N; i++ {
296-
tracer, err := tracers.New(tracerName, new(tracers.Context))
297+
tracer, err := tracers.New(tracerName, new(tracers.Context), nil)
297298
if err != nil {
298299
b.Fatalf("failed to create call tracer: %v", err)
299300
}
@@ -359,7 +360,7 @@ func TestZeroValueToNotExitCall(t *testing.T) {
359360
}
360361
_, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc, false)
361362
// Create the tracer, the EVM environment and run it
362-
tracer, err := tracers.New("callTracer", nil)
363+
tracer, err := tracers.New("callTracer", nil, nil)
363364
if err != nil {
364365
t.Fatalf("failed to create call tracer: %v", err)
365366
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
{
2+
"context": {
3+
"difficulty": "3502894804",
4+
"gasLimit": "4722976",
5+
"miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724",
6+
"number": "2289806",
7+
"timestamp": "1513601314"
8+
},
9+
"genesis": {
10+
"alloc": {
11+
"0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": {
12+
"balance": "0x0",
13+
"code": "0x",
14+
"nonce": "22",
15+
"storage": {}
16+
},
17+
"0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe": {
18+
"balance": "0x4d87094125a369d9bd5",
19+
"code": "0x606060405236156100935763ffffffff60e060020a60003504166311ee8382811461009c57806313af4035146100be5780631f5e8f4c146100ee57806324daddc5146101125780634921a91a1461013b57806363e4bff414610157578063764978f91461017f578063893d20e8146101a1578063ba40aaa1146101cd578063cebc9a82146101f4578063e177246e14610216575b61009a5b5b565b005b34156100a457fe5b6100ac61023d565b60408051918252519081900360200190f35b34156100c657fe5b6100da600160a060020a0360043516610244565b604080519115158252519081900360200190f35b34156100f657fe5b6100da610307565b604080519115158252519081900360200190f35b341561011a57fe5b6100da6004351515610318565b604080519115158252519081900360200190f35b6100da6103d6565b604080519115158252519081900360200190f35b6100da600160a060020a0360043516610420565b604080519115158252519081900360200190f35b341561018757fe5b6100ac61046c565b60408051918252519081900360200190f35b34156101a957fe5b6101b1610473565b60408051600160a060020a039092168252519081900360200190f35b34156101d557fe5b6100da600435610483565b604080519115158252519081900360200190f35b34156101fc57fe5b6100ac61050d565b60408051918252519081900360200190f35b341561021e57fe5b6100da600435610514565b604080519115158252519081900360200190f35b6003545b90565b60006000610250610473565b600160a060020a031633600160a060020a03161415156102705760006000fd5b600160a060020a03831615156102865760006000fd5b50600054600160a060020a0390811690831681146102fb57604051600160a060020a0380851691908316907ffcf23a92150d56e85e3a3d33b357493246e55783095eb6a733eb8439ffc752c890600090a360008054600160a060020a031916600160a060020a03851617905560019150610300565b600091505b5b50919050565b60005460a060020a900460ff165b90565b60006000610324610473565b600160a060020a031633600160a060020a03161415156103445760006000fd5b5060005460a060020a900460ff16801515831515146102fb576000546040805160a060020a90920460ff1615158252841515602083015280517fe6cd46a119083b86efc6884b970bfa30c1708f53ba57b86716f15b2f4551a9539281900390910190a16000805460a060020a60ff02191660a060020a8515150217905560019150610300565b600091505b5b50919050565b60006103e0610307565b801561040557506103ef610473565b600160a060020a031633600160a060020a031614155b156104105760006000fd5b610419336105a0565b90505b5b90565b600061042a610307565b801561044f5750610439610473565b600160a060020a031633600160a060020a031614155b1561045a5760006000fd5b610463826105a0565b90505b5b919050565b6001545b90565b600054600160a060020a03165b90565b6000600061048f610473565b600160a060020a031633600160a060020a03161415156104af5760006000fd5b506001548281146102fb57604080518281526020810185905281517f79a3746dde45672c9e8ab3644b8bb9c399a103da2dc94b56ba09777330a83509929181900390910190a160018381559150610300565b600091505b5b50919050565b6002545b90565b60006000610520610473565b600160a060020a031633600160a060020a03161415156105405760006000fd5b506002548281146102fb57604080518281526020810185905281517ff6991a728965fedd6e927fdf16bdad42d8995970b4b31b8a2bf88767516e2494929181900390910190a1600283905560019150610300565b600091505b5b50919050565b60006000426105ad61023d565b116102fb576105c46105bd61050d565b4201610652565b6105cc61046c565b604051909150600160a060020a038416908290600081818185876187965a03f1925050501561063d57604080518281529051600160a060020a038516917f9bca65ce52fdef8a470977b51f247a2295123a4807dfa9e502edf0d30722da3b919081900360200190a260019150610300565b6102fb42610652565b5b600091505b50919050565b60038190555b505600a165627a7a72305820f3c973c8b7ed1f62000b6701bd5b708469e19d0f1d73fde378a56c07fd0b19090029",
20+
"nonce": "1",
21+
"storage": {
22+
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000001b436ba50d378d4bbc8660d312a13df6af6e89dfb",
23+
"0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000000000000000000000000000006f05b59d3b20000",
24+
"0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c",
25+
"0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834"
26+
}
27+
},
28+
"0xb436ba50d378d4bbc8660d312a13df6af6e89dfb": {
29+
"balance": "0x1780d77678137ac1b775",
30+
"code": "0x",
31+
"nonce": "29072",
32+
"storage": {}
33+
}
34+
},
35+
"config": {
36+
"byzantiumBlock": 1700000,
37+
"chainId": 3,
38+
"daoForkSupport": true,
39+
"eip150Block": 0,
40+
"eip150Hash": "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d",
41+
"eip155Block": 10,
42+
"eip158Block": 10,
43+
"ethash": {},
44+
"homesteadBlock": 0
45+
},
46+
"difficulty": "3509749784",
47+
"extraData": "0x4554482e45544846414e532e4f52472d4641313738394444",
48+
"gasLimit": "4727564",
49+
"hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440",
50+
"miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3",
51+
"mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada",
52+
"nonce": "0x4eb12e19c16d43da",
53+
"number": "2289805",
54+
"stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f",
55+
"timestamp": "1513601261",
56+
"totalDifficulty": "7143276353481064"
57+
},
58+
"input": "0xf88b8271908506fc23ac0083015f90943b873a919aa0512d5a0f09e6dcceaa4a6727fafe80a463e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c52aa0bdce0b59e8761854e857fe64015f06dd08a4fbb7624f6094893a79a72e6ad6bea01d9dde033cff7bb235a3163f348a6d7ab8d6b52bc0963a95b91612e40ca766a4",
59+
"tracerConfig": {
60+
"onlyTopCall": true
61+
},
62+
"result": {
63+
"from": "0xb436ba50d378d4bbc8660d312a13df6af6e89dfb",
64+
"gas": "0x10738",
65+
"gasUsed": "0x3ef9",
66+
"input": "0x63e4bff40000000000000000000000000024f658a46fbb89d8ac105e98d7ac7cbbaf27c5",
67+
"output": "0x0000000000000000000000000000000000000000000000000000000000000001",
68+
"to": "0x3b873a919aa0512d5a0f09e6dcceaa4a6727fafe",
69+
"type": "CALL",
70+
"value": "0x0"
71+
}
72+
}

eth/tracers/js/goja.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ type jsTracer struct {
125125
// The methods `result` and `fault` are required to be present.
126126
// The methods `step`, `enter`, and `exit` are optional, but note that
127127
// `enter` and `exit` always go together.
128-
func newJsTracer(code string, ctx *tracers.Context) (tracers.Tracer, error) {
128+
func newJsTracer(code string, ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) {
129129
if c, ok := assetTracers[code]; ok {
130130
code = c
131131
}
@@ -177,6 +177,17 @@ func newJsTracer(code string, ctx *tracers.Context) (tracers.Tracer, error) {
177177
t.exit = exit
178178
t.result = result
179179
t.fault = fault
180+
181+
// Pass in config
182+
if setup, ok := goja.AssertFunction(obj.Get("setup")); ok {
183+
cfgStr := "{}"
184+
if cfg != nil {
185+
cfgStr = string(cfg)
186+
}
187+
if _, err := setup(obj, vm.ToValue(cfgStr)); err != nil {
188+
return nil, err
189+
}
190+
}
180191
// Setup objects carrying data to JS. These are created once and re-used.
181192
t.log = &steplog{
182193
vm: vm,

eth/tracers/js/tracer_test.go

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCon
8585
func TestTracer(t *testing.T) {
8686
execTracer := func(code string) ([]byte, string) {
8787
t.Helper()
88-
tracer, err := newJsTracer(code, nil)
88+
tracer, err := newJsTracer(code, nil, nil)
8989
if err != nil {
9090
t.Fatal(err)
9191
}
@@ -149,7 +149,7 @@ func TestTracer(t *testing.T) {
149149

150150
func TestHalt(t *testing.T) {
151151
timeout := errors.New("stahp")
152-
tracer, err := newJsTracer("{step: function() { while(1); }, result: function() { return null; }, fault: function(){}}", nil)
152+
tracer, err := newJsTracer("{step: function() { while(1); }, result: function() { return null; }, fault: function(){}}", nil, nil)
153153
if err != nil {
154154
t.Fatal(err)
155155
}
@@ -163,7 +163,7 @@ func TestHalt(t *testing.T) {
163163
}
164164

165165
func TestHaltBetweenSteps(t *testing.T) {
166-
tracer, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }}", nil)
166+
tracer, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }}", nil, nil)
167167
if err != nil {
168168
t.Fatal(err)
169169
}
@@ -187,7 +187,7 @@ func TestHaltBetweenSteps(t *testing.T) {
187187
func TestNoStepExec(t *testing.T) {
188188
execTracer := func(code string) []byte {
189189
t.Helper()
190-
tracer, err := newJsTracer(code, nil)
190+
tracer, err := newJsTracer(code, nil, nil)
191191
if err != nil {
192192
t.Fatal(err)
193193
}
@@ -221,7 +221,7 @@ func TestIsPrecompile(t *testing.T) {
221221
chaincfg.IstanbulBlock = big.NewInt(200)
222222
chaincfg.BerlinBlock = big.NewInt(300)
223223
txCtx := vm.TxContext{GasPrice: big.NewInt(100000)}
224-
tracer, err := newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil)
224+
tracer, err := newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil, nil)
225225
if err != nil {
226226
t.Fatal(err)
227227
}
@@ -235,7 +235,7 @@ func TestIsPrecompile(t *testing.T) {
235235
t.Errorf("tracer should not consider blake2f as precompile in byzantium")
236236
}
237237

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

249249
func TestEnterExit(t *testing.T) {
250250
// test that either both or none of enter() and exit() are defined
251-
if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}}", new(tracers.Context)); err == nil {
251+
if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}}", new(tracers.Context), nil); err == nil {
252252
t.Fatal("tracer creation should've failed without exit() definition")
253253
}
254-
if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}, exit: function() {}}", new(tracers.Context)); err != nil {
254+
if _, err := newJsTracer("{step: function() {}, fault: function() {}, result: function() { return null; }, enter: function() {}, exit: function() {}}", new(tracers.Context), nil); err != nil {
255255
t.Fatal(err)
256256
}
257257
// test that the enter and exit method are correctly invoked and the values passed
258-
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))
258+
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)
259259
if err != nil {
260260
t.Fatal(err)
261261
}
@@ -274,3 +274,33 @@ func TestEnterExit(t *testing.T) {
274274
t.Errorf("Number of invocations of enter() and exit() is wrong. Have %s, want %s\n", have, want)
275275
}
276276
}
277+
278+
func TestSetup(t *testing.T) {
279+
// Test empty config
280+
_, err := newJsTracer(`{setup: function(cfg) { if (cfg !== "{}") { throw("invalid empty config") } }, fault: function() {}, result: function() {}}`, new(tracers.Context), nil)
281+
if err != nil {
282+
t.Error(err)
283+
}
284+
285+
cfg, err := json.Marshal(map[string]string{"foo": "bar"})
286+
if err != nil {
287+
t.Fatal(err)
288+
}
289+
// Test no setup func
290+
_, err = newJsTracer(`{fault: function() {}, result: function() {}}`, new(tracers.Context), cfg)
291+
if err != nil {
292+
t.Fatal(err)
293+
}
294+
// Test config value
295+
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)
296+
if err != nil {
297+
t.Fatal(err)
298+
}
299+
have, err := tracer.GetResult()
300+
if err != nil {
301+
t.Fatal(err)
302+
}
303+
if string(have) != `"bar"` {
304+
t.Errorf("tracer returned wrong result. have: %s, want: \"bar\"\n", string(have))
305+
}
306+
}

eth/tracers/native/4byte.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@ type fourByteTracer struct {
5555

5656
// newFourByteTracer returns a native go tracer which collects
5757
// 4 byte-identifiers of a tx, and implements vm.EVMLogger.
58-
func newFourByteTracer(ctx *tracers.Context) tracers.Tracer {
58+
func newFourByteTracer(ctx *tracers.Context, _ json.RawMessage) (tracers.Tracer, error) {
5959
t := &fourByteTracer{
6060
ids: make(map[string]int),
6161
}
62-
return t
62+
return t, nil
6363
}
6464

6565
// isPrecompiled returns whether the addr is a precompile. Logic borrowed from newJsTracer in eth/tracers/js/tracer.go

eth/tracers/native/call.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,27 @@ type callFrame struct {
5050
type callTracer struct {
5151
env *vm.EVM
5252
callstack []callFrame
53+
config callTracerConfig
5354
interrupt uint32 // Atomic flag to signal execution interruption
5455
reason error // Textual reason for the interruption
5556
}
5657

58+
type callTracerConfig struct {
59+
OnlyTopCall bool `json:"onlyTopCall"` // If true, call tracer won't collect any subcalls
60+
}
61+
5762
// newCallTracer returns a native go tracer which tracks
5863
// call frames of a tx, and implements vm.EVMLogger.
59-
func newCallTracer(ctx *tracers.Context) tracers.Tracer {
64+
func newCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) {
65+
var config callTracerConfig
66+
if cfg != nil {
67+
if err := json.Unmarshal(cfg, &config); err != nil {
68+
return nil, err
69+
}
70+
}
6071
// First callframe contains tx context info
6172
// and is populated on start and end.
62-
return &callTracer{callstack: make([]callFrame, 1)}
73+
return &callTracer{callstack: make([]callFrame, 1), config: config}, nil
6374
}
6475

6576
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
@@ -101,6 +112,9 @@ func (t *callTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, _ *
101112

102113
// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
103114
func (t *callTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
115+
if t.config.OnlyTopCall {
116+
return
117+
}
104118
// Skip if tracing was interrupted
105119
if atomic.LoadUint32(&t.interrupt) > 0 {
106120
t.env.Cancel()
@@ -121,6 +135,9 @@ func (t *callTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.
121135
// CaptureExit is called when EVM exits a scope, even if the scope didn't
122136
// execute any code.
123137
func (t *callTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
138+
if t.config.OnlyTopCall {
139+
return
140+
}
124141
size := len(t.callstack)
125142
if size <= 1 {
126143
return

eth/tracers/native/noop.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ func init() {
3535
type noopTracer struct{}
3636

3737
// newNoopTracer returns a new noop tracer.
38-
func newNoopTracer(ctx *tracers.Context) tracers.Tracer {
39-
return &noopTracer{}
38+
func newNoopTracer(ctx *tracers.Context, _ json.RawMessage) (tracers.Tracer, error) {
39+
return &noopTracer{}, nil
4040
}
4141

4242
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.

0 commit comments

Comments
 (0)