Skip to content

Commit 90b6d88

Browse files
DeVikingMarks1na
authored andcommitted
feat(ethclient): add tracing API methods ethereum#31510
Added methods `TraceCallWithCallTracer` and `TraceTransactionWithCallTracer`. Fixes ethereum#28182 --------- Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
1 parent 50210d9 commit 90b6d88

File tree

3 files changed

+285
-0
lines changed

3 files changed

+285
-0
lines changed

ethclient/gethclient/gen_callframe_json.go

Lines changed: 104 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ethclient/gethclient/gen_calllog_json.go

Lines changed: 61 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ethclient/gethclient/gethclient.go

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ package gethclient
1919

2020
import (
2121
"context"
22+
"encoding/json"
2223
"fmt"
2324
"math/big"
2425
"runtime"
2526
"runtime/debug"
27+
"time"
2628

2729
ethereum "github.com/XinFinOrg/XDPoSChain"
2830
"github.com/XinFinOrg/XDPoSChain/common"
@@ -168,6 +170,124 @@ func (ec *Client) TraceBlock(ctx context.Context, hash common.Hash, config *trac
168170
return result, nil
169171
}
170172

173+
// CallTracerConfig configures the call tracer for
174+
// TraceTransactionWithCallTracer and TraceCallWithCallTracer.
175+
type CallTracerConfig struct {
176+
// OnlyTopCall, when true, limits tracing to the main (top-level) call only.
177+
OnlyTopCall bool
178+
// WithLog, when true, includes log emissions in the trace output.
179+
WithLog bool
180+
// Timeout is the maximum duration the tracer may run.
181+
// Zero means the server default (5s).
182+
Timeout time.Duration
183+
}
184+
185+
//go:generate go run github.com/fjl/gencodec -type CallLog -field-override callLogMarshaling -out gen_calllog_json.go
186+
187+
// CallLog represents a log emitted during a traced call.
188+
type CallLog struct {
189+
Address common.Address `json:"address"`
190+
Topics []common.Hash `json:"topics"`
191+
Data []byte `json:"data"`
192+
Index uint `json:"index"`
193+
Position uint `json:"position"`
194+
}
195+
196+
type callLogMarshaling struct {
197+
Data hexutil.Bytes
198+
Index hexutil.Uint
199+
Position hexutil.Uint
200+
}
201+
202+
//go:generate go run github.com/fjl/gencodec -type CallFrame -field-override callFrameMarshaling -out gen_callframe_json.go
203+
204+
// CallFrame contains the result of a call tracer run.
205+
type CallFrame struct {
206+
Type string `json:"type"`
207+
From common.Address `json:"from"`
208+
Gas uint64 `json:"gas"`
209+
GasUsed uint64 `json:"gasUsed"`
210+
To *common.Address `json:"to,omitempty"`
211+
Input []byte `json:"input"`
212+
Output []byte `json:"output,omitempty"`
213+
Error string `json:"error,omitempty"`
214+
RevertReason string `json:"revertReason,omitempty"`
215+
Calls []CallFrame `json:"calls,omitempty"`
216+
Logs []CallLog `json:"logs,omitempty"`
217+
Value *big.Int `json:"value,omitempty"`
218+
}
219+
220+
type callFrameMarshaling struct {
221+
Gas hexutil.Uint64
222+
GasUsed hexutil.Uint64
223+
Input hexutil.Bytes
224+
Output hexutil.Bytes
225+
Value *hexutil.Big
226+
}
227+
228+
// TraceTransactionWithCallTracer traces a transaction with the call tracer
229+
// and returns a typed CallFrame. If config is nil, defaults are used.
230+
func (ec *Client) TraceTransactionWithCallTracer(ctx context.Context, txHash common.Hash, config *CallTracerConfig) (*CallFrame, error) {
231+
var result CallFrame
232+
err := ec.c.CallContext(ctx, &result, "debug_traceTransaction", txHash, callTracerConfig(config))
233+
if err != nil {
234+
return nil, err
235+
}
236+
return &result, nil
237+
}
238+
239+
// TraceCallWithCallTracer executes a call with the call tracer and returns
240+
// a typed CallFrame. blockNrOrHash selects the block context for the call.
241+
// overrides specifies state overrides (nil for none), blockOverrides specifies
242+
// block header overrides (nil for none), and config configures the tracer
243+
// (nil for defaults).
244+
func (ec *Client) TraceCallWithCallTracer(ctx context.Context, msg ethereum.CallMsg, blockNrOrHash rpc.BlockNumberOrHash, overrides map[common.Address]OverrideAccount, blockOverrides *BlockOverrides, config *CallTracerConfig) (*CallFrame, error) {
245+
var result CallFrame
246+
err := ec.c.CallContext(ctx, &result, "debug_traceCall", toCallArg(msg), blockNrOrHash, callTraceCallConfig(config, overrides, blockOverrides))
247+
if err != nil {
248+
return nil, err
249+
}
250+
return &result, nil
251+
}
252+
253+
// callTracerConfig converts a CallTracerConfig to the wire-format TraceConfig.
254+
func callTracerConfig(config *CallTracerConfig) *tracers.TraceConfig {
255+
tracer := "callTracer"
256+
tc := &tracers.TraceConfig{Tracer: &tracer}
257+
if config != nil {
258+
if config.OnlyTopCall || config.WithLog {
259+
cfg, _ := json.Marshal(struct {
260+
OnlyTopCall bool `json:"onlyTopCall"`
261+
WithLog bool `json:"withLog"`
262+
}{config.OnlyTopCall, config.WithLog})
263+
tc.TracerConfig = cfg
264+
}
265+
if config.Timeout != 0 {
266+
s := config.Timeout.String()
267+
tc.Timeout = &s
268+
}
269+
}
270+
return tc
271+
}
272+
273+
// callTraceCallConfig builds the wire-format TraceCallConfig for debug_traceCall,
274+
// bundling tracer settings with optional state and block overrides.
275+
func callTraceCallConfig(config *CallTracerConfig, overrides map[common.Address]OverrideAccount, blockOverrides *BlockOverrides) interface{} {
276+
tc := callTracerConfig(config)
277+
// debug_traceCall expects a single config object that includes both
278+
// tracer settings and any state/block overrides.
279+
type traceCallConfig struct {
280+
*tracers.TraceConfig
281+
StateOverrides map[common.Address]OverrideAccount `json:"stateOverrides,omitempty"`
282+
BlockOverrides *BlockOverrides `json:"blockOverrides,omitempty"`
283+
}
284+
return &traceCallConfig{
285+
TraceConfig: tc,
286+
StateOverrides: overrides,
287+
BlockOverrides: blockOverrides,
288+
}
289+
}
290+
171291
func toBlockNumArg(number *big.Int) string {
172292
if number == nil {
173293
return "latest"

0 commit comments

Comments
 (0)