mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
Adds a flag `--trace.callframes` to t8n which will log info when entering or exiting a call frame in addition to the execution steps. --------- Co-authored-by: Sina M <1591639+s1na@users.noreply.github.com> Co-authored-by: Mario Vega <marioevz@gmail.com>
This commit is contained in:
parent
6bd8df6b8f
commit
604ba0ea14
2 changed files with 128 additions and 1 deletions
65
eth/tracers/logger/gen_callframe.go
Normal file
65
eth/tracers/logger/gen_callframe.go
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||
|
||||
package logger
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/math"
|
||||
)
|
||||
|
||||
var _ = (*callFrameMarshaling)(nil)
|
||||
|
||||
// MarshalJSON marshals as JSON.
|
||||
func (c callFrame) MarshalJSON() ([]byte, error) {
|
||||
type callFrame struct {
|
||||
From common.Address `json:"from"`
|
||||
To common.Address `json:"to"`
|
||||
Input hexutil.Bytes `json:"input,omitempty"`
|
||||
Gas math.HexOrDecimal64 `json:"gas"`
|
||||
Value *hexutil.Big `json:"value"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
var enc callFrame
|
||||
enc.From = c.From
|
||||
enc.To = c.To
|
||||
enc.Input = c.Input
|
||||
enc.Gas = math.HexOrDecimal64(c.Gas)
|
||||
enc.Value = (*hexutil.Big)(c.Value)
|
||||
enc.Type = c.Type()
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from JSON.
|
||||
func (c *callFrame) UnmarshalJSON(input []byte) error {
|
||||
type callFrame struct {
|
||||
From *common.Address `json:"from"`
|
||||
To *common.Address `json:"to"`
|
||||
Input *hexutil.Bytes `json:"input,omitempty"`
|
||||
Gas *math.HexOrDecimal64 `json:"gas"`
|
||||
Value *hexutil.Big `json:"value"`
|
||||
}
|
||||
var dec callFrame
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
if dec.From != nil {
|
||||
c.From = *dec.From
|
||||
}
|
||||
if dec.To != nil {
|
||||
c.To = *dec.To
|
||||
}
|
||||
if dec.Input != nil {
|
||||
c.Input = *dec.Input
|
||||
}
|
||||
if dec.Gas != nil {
|
||||
c.Gas = uint64(*dec.Gas)
|
||||
}
|
||||
if dec.Value != nil {
|
||||
c.Value = (*big.Int)(dec.Value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -19,14 +19,41 @@ package logger
|
|||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/math"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/fjl/gencodec -type callFrame -field-override callFrameMarshaling -out gen_callframe.go
|
||||
|
||||
// overrides for gencodec
|
||||
type callFrameMarshaling struct {
|
||||
Input hexutil.Bytes
|
||||
Gas math.HexOrDecimal64
|
||||
Value *hexutil.Big
|
||||
Type string `json:"type"` // adds call to Type() in MarshalJSON
|
||||
}
|
||||
|
||||
// callFrame is emitted every call frame entered.
|
||||
type callFrame struct {
|
||||
op vm.OpCode
|
||||
From common.Address `json:"from"`
|
||||
To common.Address `json:"to"`
|
||||
Input []byte `json:"input,omitempty"`
|
||||
Gas uint64 `json:"gas"`
|
||||
Value *big.Int `json:"value"`
|
||||
}
|
||||
|
||||
// Type formats the call type in a human-readable format.
|
||||
func (c *callFrame) Type() string {
|
||||
return c.op.String()
|
||||
}
|
||||
|
||||
type jsonLogger struct {
|
||||
encoder *json.Encoder
|
||||
cfg *Config
|
||||
|
|
@ -48,6 +75,22 @@ func NewJSONLogger(cfg *Config, writer io.Writer) *tracing.Hooks {
|
|||
}
|
||||
}
|
||||
|
||||
// NewJSONLoggerWithCallFrames creates a new EVM tracer that prints execution steps as JSON objects
|
||||
// into the provided stream. It also includes call frames in the output.
|
||||
func NewJSONLoggerWithCallFrames(cfg *Config, writer io.Writer) *tracing.Hooks {
|
||||
l := &jsonLogger{encoder: json.NewEncoder(writer), cfg: cfg}
|
||||
if l.cfg == nil {
|
||||
l.cfg = &Config{}
|
||||
}
|
||||
return &tracing.Hooks{
|
||||
OnTxStart: l.OnTxStart,
|
||||
OnEnter: l.OnEnter,
|
||||
OnExit: l.OnExit,
|
||||
OnOpcode: l.OnOpcode,
|
||||
OnFault: l.OnFault,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *jsonLogger) OnFault(pc uint64, op byte, gas uint64, cost uint64, scope tracing.OpContext, depth int, err error) {
|
||||
// TODO: Add rData to this interface as well
|
||||
l.OnOpcode(pc, op, gas, cost, scope, nil, depth, err)
|
||||
|
|
@ -79,10 +122,29 @@ func (l *jsonLogger) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracin
|
|||
l.encoder.Encode(log)
|
||||
}
|
||||
|
||||
func (l *jsonLogger) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
|
||||
// OnEnter is not enabled by default.
|
||||
func (l *jsonLogger) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
||||
frame := callFrame{
|
||||
op: vm.OpCode(typ),
|
||||
From: from,
|
||||
To: to,
|
||||
Gas: gas,
|
||||
Value: value,
|
||||
}
|
||||
if l.cfg.EnableMemory {
|
||||
frame.Input = input
|
||||
}
|
||||
l.encoder.Encode(frame)
|
||||
}
|
||||
|
||||
func (l *jsonLogger) OnEnd(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
|
||||
if depth > 0 {
|
||||
return
|
||||
}
|
||||
l.OnExit(depth, output, gasUsed, err, false)
|
||||
}
|
||||
|
||||
func (l *jsonLogger) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
|
||||
type endLog struct {
|
||||
Output string `json:"output"`
|
||||
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
|
||||
|
|
|
|||
Loading…
Reference in a new issue