core/vm: adds refund as part of the json standard trace

This commit is contained in:
Martin Holst Swende 2018-10-15 00:20:15 +02:00
parent 6566a0a3b8
commit 90f0d2c354
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
4 changed files with 62 additions and 46 deletions

View file

@ -45,14 +45,15 @@ func (l *JSONLogger) CaptureStart(from common.Address, to common.Address, create
// CaptureState outputs state information on the logger. // 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 { 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 {
log := vm.StructLog{ log := vm.StructLog{
Pc: pc, Pc: pc,
Op: op, Op: op,
Gas: gas, Gas: gas,
GasCost: cost, GasCost: cost,
MemorySize: memory.Len(), MemorySize: memory.Len(),
Storage: nil, Storage: nil,
Depth: depth, Depth: depth,
Err: err, RefundCounter: env.StateDB.GetRefund(),
Err: err,
} }
if !l.cfg.DisableMemory { if !l.cfg.DisableMemory {
log.Memory = memory.Data() log.Memory = memory.Data()

View file

@ -13,20 +13,22 @@ import (
var _ = (*structLogMarshaling)(nil) var _ = (*structLogMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (s StructLog) MarshalJSON() ([]byte, error) { func (s StructLog) MarshalJSON() ([]byte, error) {
type StructLog struct { type StructLog struct {
Pc uint64 `json:"pc"` Pc uint64 `json:"pc"`
Op OpCode `json:"op"` Op OpCode `json:"op"`
Gas math.HexOrDecimal64 `json:"gas"` Gas math.HexOrDecimal64 `json:"gas"`
GasCost math.HexOrDecimal64 `json:"gasCost"` GasCost math.HexOrDecimal64 `json:"gasCost"`
Memory hexutil.Bytes `json:"memory"` Memory hexutil.Bytes `json:"memory"`
MemorySize int `json:"memSize"` MemorySize int `json:"memSize"`
Stack []*math.HexOrDecimal256 `json:"stack"` Stack []*math.HexOrDecimal256 `json:"stack"`
Storage map[common.Hash]common.Hash `json:"-"` Storage map[common.Hash]common.Hash `json:"-"`
Depth int `json:"depth"` Depth int `json:"depth"`
Err error `json:"-"` RefundCounter uint64 `json:"refund"`
OpName string `json:"opName"` Err error `json:"-"`
ErrorString string `json:"error"` OpName string `json:"opName"`
ErrorString string `json:"error"`
} }
var enc StructLog var enc StructLog
enc.Pc = s.Pc enc.Pc = s.Pc
@ -43,24 +45,27 @@ func (s StructLog) MarshalJSON() ([]byte, error) {
} }
enc.Storage = s.Storage enc.Storage = s.Storage
enc.Depth = s.Depth enc.Depth = s.Depth
enc.RefundCounter = s.RefundCounter
enc.Err = s.Err enc.Err = s.Err
enc.OpName = s.OpName() enc.OpName = s.OpName()
enc.ErrorString = s.ErrorString() enc.ErrorString = s.ErrorString()
return json.Marshal(&enc) return json.Marshal(&enc)
} }
// UnmarshalJSON unmarshals from JSON.
func (s *StructLog) UnmarshalJSON(input []byte) error { func (s *StructLog) UnmarshalJSON(input []byte) error {
type StructLog struct { type StructLog struct {
Pc *uint64 `json:"pc"` Pc *uint64 `json:"pc"`
Op *OpCode `json:"op"` Op *OpCode `json:"op"`
Gas *math.HexOrDecimal64 `json:"gas"` Gas *math.HexOrDecimal64 `json:"gas"`
GasCost *math.HexOrDecimal64 `json:"gasCost"` GasCost *math.HexOrDecimal64 `json:"gasCost"`
Memory *hexutil.Bytes `json:"memory"` Memory *hexutil.Bytes `json:"memory"`
MemorySize *int `json:"memSize"` MemorySize *int `json:"memSize"`
Stack []*math.HexOrDecimal256 `json:"stack"` Stack []*math.HexOrDecimal256 `json:"stack"`
Storage map[common.Hash]common.Hash `json:"-"` Storage map[common.Hash]common.Hash `json:"-"`
Depth *int `json:"depth"` Depth *int `json:"depth"`
Err error `json:"-"` RefundCounter *uint64 `json:"refund"`
Err error `json:"-"`
} }
var dec StructLog var dec StructLog
if err := json.Unmarshal(input, &dec); err != nil { if err := json.Unmarshal(input, &dec); err != nil {
@ -96,6 +101,9 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
if dec.Depth != nil { if dec.Depth != nil {
s.Depth = *dec.Depth s.Depth = *dec.Depth
} }
if dec.RefundCounter != nil {
s.RefundCounter = *dec.RefundCounter
}
if dec.Err != nil { if dec.Err != nil {
s.Err = dec.Err s.Err = dec.Err
} }

View file

@ -56,16 +56,17 @@ type LogConfig struct {
// StructLog is emitted to the EVM each cycle and lists information about the current internal state // StructLog is emitted to the EVM each cycle and lists information about the current internal state
// prior to the execution of the statement. // prior to the execution of the statement.
type StructLog struct { type StructLog struct {
Pc uint64 `json:"pc"` Pc uint64 `json:"pc"`
Op OpCode `json:"op"` Op OpCode `json:"op"`
Gas uint64 `json:"gas"` Gas uint64 `json:"gas"`
GasCost uint64 `json:"gasCost"` GasCost uint64 `json:"gasCost"`
Memory []byte `json:"memory"` Memory []byte `json:"memory"`
MemorySize int `json:"memSize"` MemorySize int `json:"memSize"`
Stack []*big.Int `json:"stack"` Stack []*big.Int `json:"stack"`
Storage map[common.Hash]common.Hash `json:"-"` Storage map[common.Hash]common.Hash `json:"-"`
Depth int `json:"depth"` Depth int `json:"depth"`
Err error `json:"-"` RefundCounter uint64 `json:"refund"`
Err error `json:"-"`
} }
// overrides for gencodec // overrides for gencodec
@ -177,7 +178,7 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
storage = l.changedValues[contract.Address()].Copy() storage = l.changedValues[contract.Address()].Copy()
} }
// create a new snaptshot of the EVM. // create a new snaptshot of the EVM.
log := StructLog{pc, op, gas, cost, mem, memory.Len(), stck, storage, depth, err} log := StructLog{pc, op, gas, cost, mem, memory.Len(), stck, storage, depth, env.StateDB.GetRefund(), err}
l.logs = append(l.logs, log) l.logs = append(l.logs, log)
return nil return nil

View file

@ -290,11 +290,12 @@ type Tracer struct {
contractWrapper *contractWrapper // Wrapper around the contract object contractWrapper *contractWrapper // Wrapper around the contract object
dbWrapper *dbWrapper // Wrapper around the VM environment dbWrapper *dbWrapper // Wrapper around the VM environment
pcValue *uint // Swappable pc value wrapped by a log accessor pcValue *uint // Swappable pc value wrapped by a log accessor
gasValue *uint // Swappable gas value wrapped by a log accessor gasValue *uint // Swappable gas value wrapped by a log accessor
costValue *uint // Swappable cost value wrapped by a log accessor costValue *uint // Swappable cost value wrapped by a log accessor
depthValue *uint // Swappable depth value wrapped by a log accessor depthValue *uint // Swappable depth value wrapped by a log accessor
errorValue *string // Swappable error value wrapped by a log accessor errorValue *string // Swappable error value wrapped by a log accessor
refundValue *uint // Swappable refund value wrapped by a log accessor
ctx map[string]interface{} // Transaction context gathered throughout execution ctx map[string]interface{} // Transaction context gathered throughout execution
err error // Error, if one has occurred err error // Error, if one has occurred
@ -323,6 +324,7 @@ func New(code string) (*Tracer, error) {
gasValue: new(uint), gasValue: new(uint),
costValue: new(uint), costValue: new(uint),
depthValue: new(uint), depthValue: new(uint),
refundValue: new(uint),
} }
// Set up builtins for this environment // Set up builtins for this environment
tracer.vm.PushGlobalGoFunction("toHex", func(ctx *duktape.Context) int { tracer.vm.PushGlobalGoFunction("toHex", func(ctx *duktape.Context) int {
@ -442,6 +444,9 @@ func New(code string) (*Tracer, error) {
tracer.vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushUint(*tracer.depthValue); return 1 }) tracer.vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushUint(*tracer.depthValue); return 1 })
tracer.vm.PutPropString(logObject, "getDepth") tracer.vm.PutPropString(logObject, "getDepth")
tracer.vm.PushGoFunction(func(ctx *duktape.Context) int { ctx.PushUint(*tracer.refundValue); return 1 })
tracer.vm.PutPropString(logObject, "getRefund")
tracer.vm.PushGoFunction(func(ctx *duktape.Context) int { tracer.vm.PushGoFunction(func(ctx *duktape.Context) int {
if tracer.errorValue != nil { if tracer.errorValue != nil {
ctx.PushString(*tracer.errorValue) ctx.PushString(*tracer.errorValue)
@ -527,6 +532,7 @@ func (jst *Tracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost
*jst.gasValue = uint(gas) *jst.gasValue = uint(gas)
*jst.costValue = uint(cost) *jst.costValue = uint(cost)
*jst.depthValue = uint(depth) *jst.depthValue = uint(depth)
*jst.refundValue = uint(env.StateDB.GetRefund())
jst.errorValue = nil jst.errorValue = nil
if err != nil { if err != nil {