From 9a44e1035ed72eec121cf6fbe38761eea20e09c6 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Wed, 21 Jun 2017 14:52:31 +0200 Subject: [PATCH] cmd/evm, core/vm: add --nomemory, --nostack to evm (#14617) --- cmd/evm/json_logger.go | 33 ++++++++++++++++++++------------- cmd/evm/main.go | 10 ++++++++++ cmd/evm/runner.go | 10 +++++++--- core/vm/gen_structlog.go | 26 +++++++++++++++----------- core/vm/logger.go | 36 ++++++++++++++++-------------------- 5 files changed, 68 insertions(+), 47 deletions(-) diff --git a/cmd/evm/json_logger.go b/cmd/evm/json_logger.go index a84d5daeb..d61981062 100644 --- a/cmd/evm/json_logger.go +++ b/cmd/evm/json_logger.go @@ -28,25 +28,32 @@ import ( type JSONLogger struct { encoder *json.Encoder + cfg *vm.LogConfig } -func NewJSONLogger(writer io.Writer) *JSONLogger { - return &JSONLogger{json.NewEncoder(writer)} +func NewJSONLogger(cfg *vm.LogConfig, writer io.Writer) *JSONLogger { + return &JSONLogger{json.NewEncoder(writer), cfg} } // CaptureState outputs state information on the logger. func (l *JSONLogger) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error { - return l.encoder.Encode(vm.StructLog{ - Pc: pc, - Op: op, - Gas: gas + cost, - GasCost: cost, - Memory: memory.Data(), - Stack: stack.Data(), - Storage: nil, - Depth: depth, - Err: err, - }) + log := vm.StructLog{ + Pc: pc, + Op: op, + Gas: gas + cost, + GasCost: cost, + MemorySize: memory.Len(), + Storage: nil, + Depth: depth, + Err: err, + } + if !l.cfg.DisableMemory { + log.Memory = memory.Data() + } + if !l.cfg.DisableStack { + log.Stack = stack.Data() + } + return l.encoder.Encode(log) } // CaptureEnd is triggered at end of execution. diff --git a/cmd/evm/main.go b/cmd/evm/main.go index 48a1b92cb..1892ae3d3 100644 --- a/cmd/evm/main.go +++ b/cmd/evm/main.go @@ -102,6 +102,14 @@ var ( Name: "sender", Usage: "The transaction origin", } + DisableMemoryFlag = cli.BoolFlag{ + Name: "nomemory", + Usage: "disable memory output", + } + DisableStackFlag = cli.BoolFlag{ + Name: "nostack", + Usage: "disable stack output", + } ) func init() { @@ -123,6 +131,8 @@ func init() { GenesisFlag, MachineFlag, SenderFlag, + DisableMemoryFlag, + DisableStackFlag, } app.Commands = []cli.Command{ compileCommand, diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index b1fb8998f..2ce0920f6 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -73,6 +73,10 @@ func runCmd(ctx *cli.Context) error { glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name))) log.Root().SetHandler(glogger) + logconfig := &vm.LogConfig{ + DisableMemory: ctx.GlobalBool(DisableMemoryFlag.Name), + DisableStack: ctx.GlobalBool(DisableStackFlag.Name), + } var ( tracer vm.Tracer @@ -82,12 +86,12 @@ func runCmd(ctx *cli.Context) error { sender = common.StringToAddress("sender") ) if ctx.GlobalBool(MachineFlag.Name) { - tracer = NewJSONLogger(os.Stdout) + tracer = NewJSONLogger(logconfig, os.Stdout) } else if ctx.GlobalBool(DebugFlag.Name) { - debugLogger = vm.NewStructLogger(nil) + debugLogger = vm.NewStructLogger(logconfig) tracer = debugLogger } else { - debugLogger = vm.NewStructLogger(nil) + debugLogger = vm.NewStructLogger(logconfig) } if ctx.GlobalString(GenesisFlag.Name) != "" { gen := readGenesis(ctx.GlobalString(GenesisFlag.Name)) diff --git a/core/vm/gen_structlog.go b/core/vm/gen_structlog.go index 1c86b2256..88df942dc 100644 --- a/core/vm/gen_structlog.go +++ b/core/vm/gen_structlog.go @@ -18,12 +18,12 @@ func (s StructLog) MarshalJSON() ([]byte, error) { Gas math.HexOrDecimal64 `json:"gas"` GasCost math.HexOrDecimal64 `json:"gasCost"` Memory hexutil.Bytes `json:"memory"` + MemorySize int `json:"memSize"` Stack []*math.HexOrDecimal256 `json:"stack"` Storage map[common.Hash]common.Hash `json:"-"` Depth int `json:"depth"` Err error `json:"error"` OpName string `json:"opName"` - MemorySize int `json:"memSize"` } var enc StructLog enc.Pc = s.Pc @@ -31,6 +31,7 @@ func (s StructLog) MarshalJSON() ([]byte, error) { enc.Gas = math.HexOrDecimal64(s.Gas) enc.GasCost = math.HexOrDecimal64(s.GasCost) enc.Memory = s.Memory + enc.MemorySize = s.MemorySize if s.Stack != nil { enc.Stack = make([]*math.HexOrDecimal256, len(s.Stack)) for k, v := range s.Stack { @@ -41,21 +42,21 @@ func (s StructLog) MarshalJSON() ([]byte, error) { enc.Depth = s.Depth enc.Err = s.Err enc.OpName = s.OpName() - enc.MemorySize = s.MemorySize() return json.Marshal(&enc) } func (s *StructLog) UnmarshalJSON(input []byte) error { type StructLog struct { - Pc *uint64 `json:"pc"` - Op *OpCode `json:"op"` - Gas *math.HexOrDecimal64 `json:"gas"` - GasCost *math.HexOrDecimal64 `json:"gasCost"` - Memory hexutil.Bytes `json:"memory"` - Stack []*math.HexOrDecimal256 `json:"stack"` - Storage map[common.Hash]common.Hash `json:"-"` - Depth *int `json:"depth"` - Err *error `json:"error"` + Pc *uint64 `json:"pc"` + Op *OpCode `json:"op"` + Gas *math.HexOrDecimal64 `json:"gas"` + GasCost *math.HexOrDecimal64 `json:"gasCost"` + Memory hexutil.Bytes `json:"memory"` + MemorySize *int `json:"memSize"` + Stack []*math.HexOrDecimal256 `json:"stack"` + Storage map[common.Hash]common.Hash `json:"-"` + Depth *int `json:"depth"` + Err *error `json:"error"` } var dec StructLog if err := json.Unmarshal(input, &dec); err != nil { @@ -76,6 +77,9 @@ func (s *StructLog) UnmarshalJSON(input []byte) error { if dec.Memory != nil { s.Memory = dec.Memory } + if dec.MemorySize != nil { + s.MemorySize = *dec.MemorySize + } if dec.Stack != nil { s.Stack = make([]*big.Int, len(dec.Stack)) for k, v := range dec.Stack { diff --git a/core/vm/logger.go b/core/vm/logger.go index 405ab169c..17a9c9ec3 100644 --- a/core/vm/logger.go +++ b/core/vm/logger.go @@ -54,35 +54,31 @@ type LogConfig struct { // StructLog is emitted to the EVM each cycle and lists information about the current internal state // prior to the execution of the statement. type StructLog struct { - Pc uint64 `json:"pc"` - Op OpCode `json:"op"` - Gas uint64 `json:"gas"` - GasCost uint64 `json:"gasCost"` - Memory []byte `json:"memory"` - Stack []*big.Int `json:"stack"` - Storage map[common.Hash]common.Hash `json:"-"` - Depth int `json:"depth"` - Err error `json:"error"` + Pc uint64 `json:"pc"` + Op OpCode `json:"op"` + Gas uint64 `json:"gas"` + GasCost uint64 `json:"gasCost"` + Memory []byte `json:"memory"` + MemorySize int `json:"memSize"` + Stack []*big.Int `json:"stack"` + Storage map[common.Hash]common.Hash `json:"-"` + Depth int `json:"depth"` + Err error `json:"error"` } // overrides for gencodec type structLogMarshaling struct { - Stack []*math.HexOrDecimal256 - Gas math.HexOrDecimal64 - GasCost math.HexOrDecimal64 - Memory hexutil.Bytes - OpName string `json:"opName"` - MemorySize int `json:"memSize"` + Stack []*math.HexOrDecimal256 + Gas math.HexOrDecimal64 + GasCost math.HexOrDecimal64 + Memory hexutil.Bytes + OpName string `json:"opName"` } func (s *StructLog) OpName() string { return s.Op.String() } -func (s *StructLog) MemorySize() int { - return len(s.Memory) -} - // Tracer is used to collect execution traces from an EVM transaction // execution. CaptureState is called for each step of the VM with the // current VM state. @@ -181,7 +177,7 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui } } // create a new snaptshot of the EVM. - log := StructLog{pc, op, gas, cost, mem, stck, storage, env.depth, err} + log := StructLog{pc, op, gas, cost, mem, memory.Len(), stck, storage, depth, err} l.logs = append(l.logs, log) return nil