t8ntool: add optional call frames to json logger (#29353)
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: Mario Vega <marioevz@gmail.com>
This commit is contained in:
parent
fa5019de19
commit
767b00b0b5
@ -50,6 +50,10 @@ var (
|
||||
Name: "trace.returndata",
|
||||
Usage: "Enable return data output in traces",
|
||||
}
|
||||
TraceEnableCallFramesFlag = &cli.BoolFlag{
|
||||
Name: "trace.callframes",
|
||||
Usage: "Enable call frames output in traces",
|
||||
}
|
||||
OutputBasedir = &cli.StringFlag{
|
||||
Name: "output.basedir",
|
||||
Usage: "Specifies where output files are placed. Will be created if it does not exist.",
|
||||
|
@ -29,6 +29,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||
@ -101,9 +102,14 @@ func Transition(ctx *cli.Context) error {
|
||||
if err != nil {
|
||||
return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
|
||||
}
|
||||
logger := logger.NewJSONLogger(logConfig, traceFile)
|
||||
var l *tracing.Hooks
|
||||
if ctx.Bool(TraceEnableCallFramesFlag.Name) {
|
||||
l = logger.NewJSONLoggerWithCallFrames(logConfig, traceFile)
|
||||
} else {
|
||||
l = logger.NewJSONLogger(logConfig, traceFile)
|
||||
}
|
||||
tracer := &tracers.Tracer{
|
||||
Hooks: logger,
|
||||
Hooks: l,
|
||||
// jsonLogger streams out result to file.
|
||||
GetResult: func() (json.RawMessage, error) { return nil, nil },
|
||||
Stop: func(err error) {},
|
||||
|
@ -152,6 +152,7 @@ var stateTransitionCommand = &cli.Command{
|
||||
t8ntool.TraceEnableMemoryFlag,
|
||||
t8ntool.TraceDisableStackFlag,
|
||||
t8ntool.TraceEnableReturnDataFlag,
|
||||
t8ntool.TraceEnableCallFramesFlag,
|
||||
t8ntool.OutputBasedir,
|
||||
t8ntool.OutputAllocFlag,
|
||||
t8ntool.OutputResultFlag,
|
||||
|
@ -375,6 +375,14 @@ func TestT8nTracing(t *testing.T) {
|
||||
}`},
|
||||
expectedTraces: []string{"trace-0-0x88f5fbd1524731a81e49f637aa847543268a5aaf2a6b32a69d2c6d978c45dcfb.json"},
|
||||
},
|
||||
{
|
||||
base: "./testdata/32",
|
||||
input: t8nInput{
|
||||
"alloc.json", "txs.json", "env.json", "Merge", "",
|
||||
},
|
||||
extraArgs: []string{"--trace", "--trace.callframes"},
|
||||
expectedTraces: []string{"trace-0-0x47806361c0fa084be3caa18afe8c48156747c01dbdfc1ee11b5aecdbe4fcf23e.jsonl"},
|
||||
},
|
||||
} {
|
||||
args := []string{"t8n"}
|
||||
args = append(args, tc.input.get(tc.base)...)
|
||||
|
1
cmd/evm/testdata/32/README.md
vendored
Normal file
1
cmd/evm/testdata/32/README.md
vendored
Normal file
@ -0,0 +1 @@
|
||||
This test does some EVM execution, and can be used to test callframes emitted by the tracer when they are enabled.
|
30
cmd/evm/testdata/32/alloc.json
vendored
Normal file
30
cmd/evm/testdata/32/alloc.json
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"0x8a0a19589531694250d570040a0c4b74576919b8": {
|
||||
"nonce": "0x00",
|
||||
"balance": "0x0de0b6b3a7640000",
|
||||
"code": "0x600060006000600060007310000000000000000000000000000000000000015af1600155600060006000600060007310000000000000000000000000000000000000025af16002553d600060003e600051600355",
|
||||
"storage": {
|
||||
"0x01": "0x0100",
|
||||
"0x02": "0x0100",
|
||||
"0x03": "0x0100"
|
||||
}
|
||||
},
|
||||
"0x1000000000000000000000000000000000000001": {
|
||||
"nonce": "0x00",
|
||||
"balance": "0x29a2241af62c0000",
|
||||
"code": "0x6103e8ff",
|
||||
"storage": {}
|
||||
},
|
||||
"0x1000000000000000000000000000000000000002": {
|
||||
"nonce": "0x00",
|
||||
"balance": "0x4563918244f40000",
|
||||
"code": "0x600060006000600060647310000000000000000000000000000000000000015af1600f0160005260206000fd",
|
||||
"storage": {}
|
||||
},
|
||||
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
|
||||
"nonce": "0x00",
|
||||
"balance": "0x6124fee993bc0000",
|
||||
"code": "0x",
|
||||
"storage": {}
|
||||
}
|
||||
}
|
12
cmd/evm/testdata/32/env.json
vendored
Normal file
12
cmd/evm/testdata/32/env.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"currentCoinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||
"currentGasLimit": "71794957647893862",
|
||||
"currentNumber": "1",
|
||||
"currentTimestamp": "1000",
|
||||
"currentRandom": "0",
|
||||
"currentDifficulty": "0",
|
||||
"blockHashes": {},
|
||||
"ommers": [],
|
||||
"currentBaseFee": "7",
|
||||
"parentUncleHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
61
cmd/evm/testdata/32/trace-0-0x47806361c0fa084be3caa18afe8c48156747c01dbdfc1ee11b5aecdbe4fcf23e.jsonl
vendored
Normal file
61
cmd/evm/testdata/32/trace-0-0x47806361c0fa084be3caa18afe8c48156747c01dbdfc1ee11b5aecdbe4fcf23e.jsonl
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
{"from":"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b","to":"0x8a0a19589531694250d570040a0c4b74576919b8","gas":"0x74f18","value":"0x0","type":"CALL"}
|
||||
{"pc":0,"op":96,"gas":"0x74f18","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":2,"op":96,"gas":"0x74f15","gasCost":"0x3","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":4,"op":96,"gas":"0x74f12","gasCost":"0x3","memSize":0,"stack":["0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":6,"op":96,"gas":"0x74f0f","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":8,"op":96,"gas":"0x74f0c","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":10,"op":115,"gas":"0x74f09","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH20"}
|
||||
{"pc":31,"op":90,"gas":"0x74f06","gasCost":"0x2","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0x1000000000000000000000000000000000000001"],"depth":1,"refund":0,"opName":"GAS"}
|
||||
{"pc":32,"op":241,"gas":"0x74f04","gasCost":"0x731f1","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0x1000000000000000000000000000000000000001","0x74f04"],"depth":1,"refund":0,"opName":"CALL"}
|
||||
{"from":"0x8a0a19589531694250d570040a0c4b74576919b8","to":"0x1000000000000000000000000000000000000001","gas":"0x727c9","value":"0x0","type":"CALL"}
|
||||
{"pc":0,"op":97,"gas":"0x727c9","gasCost":"0x3","memSize":0,"stack":[],"depth":2,"refund":0,"opName":"PUSH2"}
|
||||
{"pc":3,"op":255,"gas":"0x727c6","gasCost":"0x7f58","memSize":0,"stack":["0x3e8"],"depth":2,"refund":0,"opName":"SELFDESTRUCT"}
|
||||
{"from":"0x1000000000000000000000000000000000000001","to":"0x00000000000000000000000000000000000003e8","gas":"0x0","value":"0x29a2241af62c0000","type":"SELFDESTRUCT"}
|
||||
{"output":"","gasUsed":"0x0"}
|
||||
{"output":"","gasUsed":"0x7f5b"}
|
||||
{"pc":33,"op":96,"gas":"0x6c581","gasCost":"0x3","memSize":0,"stack":["0x1"],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":35,"op":85,"gas":"0x6c57e","gasCost":"0x1388","memSize":0,"stack":["0x1","0x1"],"depth":1,"refund":0,"opName":"SSTORE"}
|
||||
{"pc":36,"op":96,"gas":"0x6b1f6","gasCost":"0x3","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":38,"op":96,"gas":"0x6b1f3","gasCost":"0x3","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":40,"op":96,"gas":"0x6b1f0","gasCost":"0x3","memSize":0,"stack":["0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":42,"op":96,"gas":"0x6b1ed","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":44,"op":96,"gas":"0x6b1ea","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":46,"op":115,"gas":"0x6b1e7","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0"],"depth":1,"refund":0,"opName":"PUSH20"}
|
||||
{"pc":67,"op":90,"gas":"0x6b1e4","gasCost":"0x2","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0x1000000000000000000000000000000000000002"],"depth":1,"refund":0,"opName":"GAS"}
|
||||
{"pc":68,"op":241,"gas":"0x6b1e2","gasCost":"0x69744","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0x1000000000000000000000000000000000000002","0x6b1e2"],"depth":1,"refund":0,"opName":"CALL"}
|
||||
{"from":"0x8a0a19589531694250d570040a0c4b74576919b8","to":"0x1000000000000000000000000000000000000002","gas":"0x68d1c","value":"0x0","type":"CALL"}
|
||||
{"pc":0,"op":96,"gas":"0x68d1c","gasCost":"0x3","memSize":0,"stack":[],"depth":2,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":2,"op":96,"gas":"0x68d19","gasCost":"0x3","memSize":0,"stack":["0x0"],"depth":2,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":4,"op":96,"gas":"0x68d16","gasCost":"0x3","memSize":0,"stack":["0x0","0x0"],"depth":2,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":6,"op":96,"gas":"0x68d13","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0"],"depth":2,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":8,"op":96,"gas":"0x68d10","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0","0x0"],"depth":2,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":10,"op":115,"gas":"0x68d0d","gasCost":"0x3","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x64"],"depth":2,"refund":0,"opName":"PUSH20"}
|
||||
{"pc":31,"op":90,"gas":"0x68d0a","gasCost":"0x2","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x64","0x1000000000000000000000000000000000000001"],"depth":2,"refund":0,"opName":"GAS"}
|
||||
{"pc":32,"op":241,"gas":"0x68d08","gasCost":"0x67363","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x64","0x1000000000000000000000000000000000000001","0x68d08"],"depth":2,"refund":0,"opName":"CALL"}
|
||||
{"from":"0x1000000000000000000000000000000000000002","to":"0x1000000000000000000000000000000000000001","gas":"0x658d3","value":"0x64","type":"CALL"}
|
||||
{"pc":0,"op":97,"gas":"0x658d3","gasCost":"0x3","memSize":0,"stack":[],"depth":3,"refund":0,"opName":"PUSH2"}
|
||||
{"pc":3,"op":255,"gas":"0x658d0","gasCost":"0x1388","memSize":0,"stack":["0x3e8"],"depth":3,"refund":0,"opName":"SELFDESTRUCT"}
|
||||
{"from":"0x1000000000000000000000000000000000000001","to":"0x00000000000000000000000000000000000003e8","gas":"0x0","value":"0x64","type":"SELFDESTRUCT"}
|
||||
{"output":"","gasUsed":"0x0"}
|
||||
{"output":"","gasUsed":"0x138b"}
|
||||
{"pc":33,"op":96,"gas":"0x65eed","gasCost":"0x3","memSize":0,"stack":["0x1"],"depth":2,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":35,"op":1,"gas":"0x65eea","gasCost":"0x3","memSize":0,"stack":["0x1","0xf"],"depth":2,"refund":0,"opName":"ADD"}
|
||||
{"pc":36,"op":96,"gas":"0x65ee7","gasCost":"0x3","memSize":0,"stack":["0x10"],"depth":2,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":38,"op":82,"gas":"0x65ee4","gasCost":"0x6","memSize":0,"stack":["0x10","0x0"],"depth":2,"refund":0,"opName":"MSTORE"}
|
||||
{"pc":39,"op":96,"gas":"0x65ede","gasCost":"0x3","memSize":32,"stack":[],"depth":2,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":41,"op":96,"gas":"0x65edb","gasCost":"0x3","memSize":32,"stack":["0x20"],"depth":2,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":43,"op":253,"gas":"0x65ed8","gasCost":"0x0","memSize":32,"stack":["0x20","0x0"],"depth":2,"refund":0,"opName":"REVERT"}
|
||||
{"pc":43,"op":253,"gas":"0x65ed8","gasCost":"0x0","memSize":32,"stack":[],"depth":2,"refund":0,"opName":"REVERT","error":"execution reverted"}
|
||||
{"output":"0000000000000000000000000000000000000000000000000000000000000010","gasUsed":"0x2e44","error":"execution reverted"}
|
||||
{"pc":69,"op":96,"gas":"0x67976","gasCost":"0x3","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"PUSH1"}
|
||||
{"pc":71,"op":85,"gas":"0x67973","gasCost":"0x1388","memSize":0,"stack":["0x0","0x2"],"depth":1,"refund":4800,"opName":"SSTORE"}
|
||||
{"pc":72,"op":61,"gas":"0x665eb","gasCost":"0x2","memSize":0,"stack":[],"depth":1,"refund":4800,"opName":"RETURNDATASIZE"}
|
||||
{"pc":73,"op":96,"gas":"0x665e9","gasCost":"0x3","memSize":0,"stack":["0x20"],"depth":1,"refund":4800,"opName":"PUSH1"}
|
||||
{"pc":75,"op":96,"gas":"0x665e6","gasCost":"0x3","memSize":0,"stack":["0x20","0x0"],"depth":1,"refund":4800,"opName":"PUSH1"}
|
||||
{"pc":77,"op":62,"gas":"0x665e3","gasCost":"0x9","memSize":0,"stack":["0x20","0x0","0x0"],"depth":1,"refund":4800,"opName":"RETURNDATACOPY"}
|
||||
{"pc":78,"op":96,"gas":"0x665da","gasCost":"0x3","memSize":32,"stack":[],"depth":1,"refund":4800,"opName":"PUSH1"}
|
||||
{"pc":80,"op":81,"gas":"0x665d7","gasCost":"0x3","memSize":32,"stack":["0x0"],"depth":1,"refund":4800,"opName":"MLOAD"}
|
||||
{"pc":81,"op":96,"gas":"0x665d4","gasCost":"0x3","memSize":32,"stack":["0x10"],"depth":1,"refund":4800,"opName":"PUSH1"}
|
||||
{"pc":83,"op":85,"gas":"0x665d1","gasCost":"0x1388","memSize":32,"stack":["0x10","0x3"],"depth":1,"refund":4800,"opName":"SSTORE"}
|
||||
{"pc":84,"op":0,"gas":"0x65249","gasCost":"0x0","memSize":32,"stack":[],"depth":1,"refund":4800,"opName":"STOP"}
|
||||
{"output":"","gasUsed":"0xfccf"}
|
17
cmd/evm/testdata/32/txs.json
vendored
Normal file
17
cmd/evm/testdata/32/txs.json
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
[
|
||||
{
|
||||
"type": "0x0",
|
||||
"chainId": "0x0",
|
||||
"nonce": "0x0",
|
||||
"gasPrice": "0xa",
|
||||
"gas": "0x7a120",
|
||||
"to": "0x8a0a19589531694250d570040a0c4b74576919b8",
|
||||
"value": "0x0",
|
||||
"input": "0x",
|
||||
"v": "0x1c",
|
||||
"r": "0x9a207ad45b7fc2aa5f8e72a30487f2b0bc489778e6d022f19036efdf2a922a17",
|
||||
"s": "0x640d4da05078b5a4aa561f1b4d58176ea828bfa0f88d27d14459c1d789e1a1eb",
|
||||
"sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8"
|
||||
}
|
||||
]
|
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/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/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/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/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 New Issue
Block a user