diff --git a/eth/tracers/logger/gen_callframelog.go b/eth/tracers/logger/gen_callframelog.go new file mode 100644 index 0000000000..2de928e340 --- /dev/null +++ b/eth/tracers/logger/gen_callframelog.go @@ -0,0 +1,72 @@ +// 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" + "github.com/ethereum/go-ethereum/core/vm" +) + +var _ = (*callFrameLogMarshaling)(nil) + +// MarshalJSON marshals as JSON. +func (c CallFrameLog) MarshalJSON() ([]byte, error) { + type CallFrameLog struct { + Op *vm.OpCode `json:"op,omitempty"` + 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"` + OpName *string `json:"opName,omitempty"` + } + var enc CallFrameLog + enc.Op = c.Op + 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.OpName = c.OpName() + return json.Marshal(&enc) +} + +// UnmarshalJSON unmarshals from JSON. +func (c *CallFrameLog) UnmarshalJSON(input []byte) error { + type CallFrameLog struct { + Op *vm.OpCode `json:"op,omitempty"` + 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 CallFrameLog + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.Op != nil { + c.Op = dec.Op + } + 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 +} diff --git a/eth/tracers/logger/logger.go b/eth/tracers/logger/logger.go index 2b36f9f492..3c20abca32 100644 --- a/eth/tracers/logger/logger.go +++ b/eth/tracers/logger/logger.go @@ -52,6 +52,7 @@ type Config struct { DisableStack bool // disable stack capture DisableStorage bool // disable storage capture EnableReturnData bool // enable return data capture + EnableCallFrame bool // enable call frame enter capture Debug bool // print output during capture end Limit int // maximum length of output, but zero means unlimited // Chain overrides, can be used to execute a trace using future fork rules @@ -101,6 +102,35 @@ func (s *StructLog) ErrorString() string { return "" } +//go:generate go run github.com/fjl/gencodec -type CallFrameLog -field-override callFrameLogMarshaling -out gen_callframelog.go + +// CallFrameLog is emitted every call frame entered. +type CallFrameLog struct { + Op *vm.OpCode `json:"op,omitempty"` + From common.Address `json:"from"` + To common.Address `json:"to"` + Input []byte `json:"input,omitempty"` + Gas uint64 `json:"gas"` + Value *big.Int `json:"value"` +} + +// overrides for gencodec +type callFrameLogMarshaling struct { + Input hexutil.Bytes + Gas math.HexOrDecimal64 + Value *hexutil.Big + OpName *string `json:"opName,omitempty"` // adds call to OpName() in MarshalJSON +} + +// OpName formats the operand name in a human-readable format. +func (c *CallFrameLog) OpName() *string { + if c.Op != nil { + op := c.Op.String() + return &op + } + return nil +} + // StructLogger is an EVM state logger and implements EVMLogger. // // StructLogger can capture state based on the given Log configuration and also keeps diff --git a/eth/tracers/logger/logger_json.go b/eth/tracers/logger/logger_json.go index a2cb4cd9fc..c8381ac902 100644 --- a/eth/tracers/logger/logger_json.go +++ b/eth/tracers/logger/logger_json.go @@ -44,6 +44,18 @@ func NewJSONLogger(cfg *Config, writer io.Writer) *JSONLogger { func (l *JSONLogger) CaptureStart(env *vm.EVM, from, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { l.env = env + if l.cfg.EnableCallFrame { + log := CallFrameLog{ + From: from, + To: to, + Gas: gas, + Value: value, + } + if l.cfg.EnableMemory { + log.Input = input + } + l.encoder.Encode(log) + } } func (l *JSONLogger) CaptureFault(pc uint64, op vm.OpCode, gas uint64, cost uint64, scope *vm.ScopeContext, depth int, err error) { @@ -93,6 +105,19 @@ func (l *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, err error) { } func (l *JSONLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + if l.cfg.EnableCallFrame { + log := CallFrameLog{ + Op: &typ, + From: from, + To: to, + Gas: gas, + Value: value, + } + if l.cfg.EnableMemory { + log.Input = input + } + l.encoder.Encode(log) + } } func (l *JSONLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}