mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-17 10:20:44 +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 (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
|
||||||
"github.com/XinFinOrg/XDPoSChain/common/math"
|
"github.com/XinFinOrg/XDPoSChain/common/math"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
"github.com/XinFinOrg/XDPoSChain/core/tracing"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
"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 {
|
type jsonLogger struct {
|
||||||
encoder *json.Encoder
|
encoder *json.Encoder
|
||||||
cfg *Config
|
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) {
|
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
|
// TODO: Add rData to this interface as well
|
||||||
l.OnOpcode(pc, op, gas, cost, scope, nil, depth, err)
|
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)
|
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 {
|
if depth > 0 {
|
||||||
return
|
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 {
|
type endLog struct {
|
||||||
Output string `json:"output"`
|
Output string `json:"output"`
|
||||||
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
|
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue