mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 23:26:44 +00:00
cmd/evm: better json output, add result to json
This commit is contained in:
parent
c437b70c97
commit
567f69539e
3 changed files with 79 additions and 7 deletions
|
|
@ -86,8 +86,9 @@ func runCmd(ctx *cli.Context) error {
|
|||
} else if ctx.GlobalBool(DebugFlag.Name) {
|
||||
debugLogger = vm.NewStructLogger(nil)
|
||||
tracer = debugLogger
|
||||
} else {
|
||||
debugLogger = vm.NewStructLogger(nil)
|
||||
}
|
||||
|
||||
if ctx.GlobalString(GenesisFlag.Name) != "" {
|
||||
gen := readGenesis(ctx.GlobalString(GenesisFlag.Name))
|
||||
_, statedb = gen.ToBlock()
|
||||
|
|
@ -216,11 +217,14 @@ GC calls: %d
|
|||
|
||||
`, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC)
|
||||
}
|
||||
|
||||
fmt.Printf("0x%x", ret)
|
||||
if err != nil {
|
||||
fmt.Printf(" error: %v", err)
|
||||
if tracer != nil {
|
||||
tracer.CaptureEnd(ret, 0, execTime)
|
||||
} else {
|
||||
fmt.Printf("0x%x\n", ret)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf(" error: %v\n", err)
|
||||
}
|
||||
fmt.Println()
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
|
|
@ -61,6 +62,50 @@ type StructLog struct {
|
|||
Depth int
|
||||
Err error
|
||||
}
|
||||
type StructLogJsonOut struct {
|
||||
Pc uint64 `json:"pc"`
|
||||
Op OpCode `json:"op"`
|
||||
OpName string `json:"opName"`
|
||||
Gas math.HexOrDecimal64 `json:"gas"`
|
||||
GasCost math.HexOrDecimal64 `json:"gasCost"`
|
||||
Memory string `json:"memory"`
|
||||
Stack hexArray `json:"stack"`
|
||||
//Storage map[common.Hash]common.Hash `json:"storage"`
|
||||
Depth int `json:"depth"`
|
||||
//Err error
|
||||
}
|
||||
type hexArray []*big.Int
|
||||
|
||||
// MarshalJSON encodes the memory as 32-byte hex strings instead of bigints
|
||||
func (a hexArray) MarshalJSON() ([]byte, error) {
|
||||
|
||||
if items := ([]*big.Int)(a); len(items) > 0 {
|
||||
hexitems := make([]*math.HexOrDecimal256, len(items))
|
||||
for i, item := range items {
|
||||
x := math.HexOrDecimal256(*item)
|
||||
hexitems[i] = &x
|
||||
}
|
||||
return json.Marshal(hexitems)
|
||||
}
|
||||
return []byte("[]"), nil
|
||||
}
|
||||
|
||||
// MarshalJSON encodes StructLog for json output
|
||||
func (s StructLog) MarshalJSON() ([]byte, error) {
|
||||
var enc StructLogJsonOut
|
||||
enc.Pc = s.Pc
|
||||
enc.Op = s.Op
|
||||
enc.OpName = s.Op.String()
|
||||
enc.Gas = math.HexOrDecimal64(s.Gas)
|
||||
enc.GasCost = math.HexOrDecimal64(s.GasCost)
|
||||
//enc.Memory = fmt.Sprintf("0x%v", len(common.Bytes2Hex(s.Memory))/2)
|
||||
enc.Memory = fmt.Sprintf("%v bytes", len(s.Memory))
|
||||
|
||||
enc.Stack = s.Stack
|
||||
//enc.Storage = s.Storage
|
||||
enc.Depth = s.Depth
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
// Tracer is used to collect execution traces from an EVM transaction
|
||||
// execution. CaptureState is called for each step of the VM with the
|
||||
|
|
@ -69,6 +114,7 @@ type StructLog struct {
|
|||
// if you need to retain them beyond the current call.
|
||||
type Tracer interface {
|
||||
CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error
|
||||
CaptureEnd(output []byte, gasUsed uint64, t time.Duration) error
|
||||
}
|
||||
|
||||
// StructLogger is an EVM state logger and implements Tracer.
|
||||
|
|
@ -110,9 +156,20 @@ func NewJSONLogger(writer io.Writer) *JSONLogger {
|
|||
|
||||
// CaptureState outputs state information on the logger
|
||||
func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error {
|
||||
log := StructLog{pc, op, gas, cost, memory.Data(), stack.Data(), nil, env.depth, err}
|
||||
log := StructLog{pc, op, gas + cost, cost, memory.Data(), stack.Data(), nil, env.depth, err}
|
||||
return l.encoder.Encode(log)
|
||||
}
|
||||
func (l *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration) error {
|
||||
type endLog struct {
|
||||
Output string `json:"output"`
|
||||
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
|
||||
Time time.Duration `json:"time"`
|
||||
}
|
||||
|
||||
log := endLog{common.Bytes2Hex(output), math.HexOrDecimal64(gasUsed), t}
|
||||
return l.encoder.Encode(log)
|
||||
|
||||
}
|
||||
|
||||
// CaptureState logs a new structured log message and pushes it out to the environment
|
||||
//
|
||||
|
|
@ -184,6 +241,10 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
|
|||
l.logs = append(l.logs, log)
|
||||
return nil
|
||||
}
|
||||
func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration) error {
|
||||
fmt.Printf("0x%x", output)
|
||||
return nil
|
||||
}
|
||||
|
||||
// StructLogs returns a list of captured log entries
|
||||
func (l *StructLogger) StructLogs() []StructLog {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
|
|
@ -344,6 +345,12 @@ func (jst *JavascriptTracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode,
|
|||
return nil
|
||||
}
|
||||
|
||||
// CaptureEnd is called after the call finishes
|
||||
func (jst *JavascriptTracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration) error {
|
||||
//TODO! @Arachnid please figure out of there's anything we can use this method for
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetResult calls the Javascript 'result' function and returns its value, or any accumulated error
|
||||
func (jst *JavascriptTracer) GetResult() (result interface{}, err error) {
|
||||
if jst.err != nil {
|
||||
|
|
|
|||
Loading…
Reference in a new issue