@@ -19,14 +19,41 @@ package logger
1919import (
2020 "encoding/json"
2121 "io"
22+ "math/big"
2223
2324 "github.com/XinFinOrg/XDPoSChain/common"
25+ "github.com/XinFinOrg/XDPoSChain/common/hexutil"
2426 "github.com/XinFinOrg/XDPoSChain/common/math"
2527 "github.com/XinFinOrg/XDPoSChain/core/tracing"
2628 "github.com/XinFinOrg/XDPoSChain/core/types"
2729 "github.com/XinFinOrg/XDPoSChain/core/vm"
2830)
2931
32+ //go:generate go run github.com/fjl/gencodec -type callFrame -field-override callFrameMarshaling -out gen_callframe.go
33+
34+ // overrides for gencodec
35+ type callFrameMarshaling struct {
36+ Input hexutil.Bytes
37+ Gas math.HexOrDecimal64
38+ Value * hexutil.Big
39+ Type string `json:"type"` // adds call to Type() in MarshalJSON
40+ }
41+
42+ // callFrame is emitted every call frame entered.
43+ type callFrame struct {
44+ op vm.OpCode
45+ From common.Address `json:"from"`
46+ To common.Address `json:"to"`
47+ Input []byte `json:"input,omitempty"`
48+ Gas uint64 `json:"gas"`
49+ Value * big.Int `json:"value"`
50+ }
51+
52+ // Type formats the call type in a human-readable format.
53+ func (c * callFrame ) Type () string {
54+ return c .op .String ()
55+ }
56+
3057type jsonLogger struct {
3158 encoder * json.Encoder
3259 cfg * Config
@@ -48,6 +75,22 @@ func NewJSONLogger(cfg *Config, writer io.Writer) *tracing.Hooks {
4875 }
4976}
5077
78+ // NewJSONLoggerWithCallFrames creates a new EVM tracer that prints execution steps as JSON objects
79+ // into the provided stream. It also includes call frames in the output.
80+ func NewJSONLoggerWithCallFrames (cfg * Config , writer io.Writer ) * tracing.Hooks {
81+ l := & jsonLogger {encoder : json .NewEncoder (writer ), cfg : cfg }
82+ if l .cfg == nil {
83+ l .cfg = & Config {}
84+ }
85+ return & tracing.Hooks {
86+ OnTxStart : l .OnTxStart ,
87+ OnEnter : l .OnEnter ,
88+ OnExit : l .OnExit ,
89+ OnOpcode : l .OnOpcode ,
90+ OnFault : l .OnFault ,
91+ }
92+ }
93+
5194func (l * jsonLogger ) OnFault (pc uint64 , op byte , gas uint64 , cost uint64 , scope tracing.OpContext , depth int , err error ) {
5295 // TODO: Add rData to this interface as well
5396 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
79122 l .encoder .Encode (log )
80123}
81124
82- func (l * jsonLogger ) OnExit (depth int , output []byte , gasUsed uint64 , err error , reverted bool ) {
125+ // OnEnter is not enabled by default.
126+ func (l * jsonLogger ) OnEnter (depth int , typ byte , from common.Address , to common.Address , input []byte , gas uint64 , value * big.Int ) {
127+ frame := callFrame {
128+ op : vm .OpCode (typ ),
129+ From : from ,
130+ To : to ,
131+ Gas : gas ,
132+ Value : value ,
133+ }
134+ if l .cfg .EnableMemory {
135+ frame .Input = input
136+ }
137+ l .encoder .Encode (frame )
138+ }
139+
140+ func (l * jsonLogger ) OnEnd (depth int , output []byte , gasUsed uint64 , err error , reverted bool ) {
83141 if depth > 0 {
84142 return
85143 }
144+ l .OnExit (depth , output , gasUsed , err , false )
145+ }
146+
147+ func (l * jsonLogger ) OnExit (depth int , output []byte , gasUsed uint64 , err error , reverted bool ) {
86148 type endLog struct {
87149 Output string `json:"output"`
88150 GasUsed math.HexOrDecimal64 `json:"gasUsed"`
0 commit comments