aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Holst Swende <martin@swende.se>2018-10-23 22:28:18 +0800
committerFelix Lange <fjl@users.noreply.github.com>2018-10-23 22:28:18 +0800
commit4c0883e20d78b987dc95acd46498f326626aaee3 (patch)
tree056c6ae87ae9e4746affe66058396162910021fa
parent3088c122d8497acf176f03a3f19f6292e817cab7 (diff)
downloadgo-tangerine-4c0883e20d78b987dc95acd46498f326626aaee3.tar.gz
go-tangerine-4c0883e20d78b987dc95acd46498f326626aaee3.tar.zst
go-tangerine-4c0883e20d78b987dc95acd46498f326626aaee3.zip
core/vm: adds refund as part of the json standard trace (#17910)
This adds the global accumulated refund counter to the standard json output as a numeric json value. Previously this was not very interesting since it was not used much, but with the new sstore gas changes the value is a lot more interesting from a consensus investigation perspective.
-rw-r--r--cmd/evm/json_logger.go17
-rw-r--r--core/vm/gen_structlog.go52
-rw-r--r--core/vm/logger.go23
-rw-r--r--core/vm/logger_test.go11
-rw-r--r--eth/tracers/tracer.go16
-rw-r--r--eth/tracers/tracer_test.go11
6 files changed, 79 insertions, 51 deletions
diff --git a/cmd/evm/json_logger.go b/cmd/evm/json_logger.go
index f16424fbe..50cb4f0e4 100644
--- a/cmd/evm/json_logger.go
+++ b/cmd/evm/json_logger.go
@@ -45,14 +45,15 @@ func (l *JSONLogger) CaptureStart(from common.Address, to common.Address, create
// 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 {
log := vm.StructLog{
- Pc: pc,
- Op: op,
- Gas: gas,
- GasCost: cost,
- MemorySize: memory.Len(),
- Storage: nil,
- Depth: depth,
- Err: err,
+ Pc: pc,
+ Op: op,
+ Gas: gas,
+ GasCost: cost,
+ MemorySize: memory.Len(),
+ Storage: nil,
+ Depth: depth,
+ RefundCounter: env.StateDB.GetRefund(),
+ Err: err,
}
if !l.cfg.DisableMemory {
log.Memory = memory.Data()
diff --git a/core/vm/gen_structlog.go b/core/vm/gen_structlog.go
index ade3ca631..726012e59 100644
--- a/core/vm/gen_structlog.go
+++ b/core/vm/gen_structlog.go
@@ -13,20 +13,22 @@ import (
var _ = (*structLogMarshaling)(nil)
+// MarshalJSON marshals as JSON.
func (s StructLog) MarshalJSON() ([]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"`
- MemorySize int `json:"memSize"`
- Stack []*math.HexOrDecimal256 `json:"stack"`
- Storage map[common.Hash]common.Hash `json:"-"`
- Depth int `json:"depth"`
- Err error `json:"-"`
- OpName string `json:"opName"`
- ErrorString string `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"`
+ RefundCounter uint64 `json:"refund"`
+ Err error `json:"-"`
+ OpName string `json:"opName"`
+ ErrorString string `json:"error"`
}
var enc StructLog
enc.Pc = s.Pc
@@ -43,24 +45,27 @@ func (s StructLog) MarshalJSON() ([]byte, error) {
}
enc.Storage = s.Storage
enc.Depth = s.Depth
+ enc.RefundCounter = s.RefundCounter
enc.Err = s.Err
enc.OpName = s.OpName()
enc.ErrorString = s.ErrorString()
return json.Marshal(&enc)
}
+// UnmarshalJSON unmarshals from JSON.
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"`
- MemorySize *int `json:"memSize"`
- Stack []*math.HexOrDecimal256 `json:"stack"`
- Storage map[common.Hash]common.Hash `json:"-"`
- Depth *int `json:"depth"`
- Err error `json:"-"`
+ 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"`
+ RefundCounter *uint64 `json:"refund"`
+ Err error `json:"-"`
}
var dec StructLog
if err := json.Unmarshal(input, &dec); err != nil {
@@ -96,6 +101,9 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
if dec.Depth != nil {
s.Depth = *dec.Depth
}
+ if dec.RefundCounter != nil {
+ s.RefundCounter = *dec.RefundCounter
+ }
if dec.Err != nil {
s.Err = dec.Err
}
diff --git a/core/vm/logger.go b/core/vm/logger.go
index 85acb8d6d..1733bf270 100644
--- a/core/vm/logger.go
+++ b/core/vm/logger.go
@@ -56,16 +56,17 @@ 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"`
- MemorySize int `json:"memSize"`
- Stack []*big.Int `json:"stack"`
- Storage map[common.Hash]common.Hash `json:"-"`
- Depth int `json:"depth"`
- Err error `json:"-"`
+ 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"`
+ RefundCounter uint64 `json:"refund"`
+ Err error `json:"-"`
}
// 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()
}
// 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)
return nil
diff --git a/core/vm/logger_test.go b/core/vm/logger_test.go
index cdbb70dc4..cba7c7a0e 100644
--- a/core/vm/logger_test.go
+++ b/core/vm/logger_test.go
@@ -21,6 +21,7 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/params"
)
@@ -41,9 +42,15 @@ func (d *dummyContractRef) SetBalance(*big.Int) {}
func (d *dummyContractRef) SetNonce(uint64) {}
func (d *dummyContractRef) Balance() *big.Int { return new(big.Int) }
+type dummyStatedb struct {
+ state.StateDB
+}
+
+func (dummyStatedb) GetRefund() uint64 { return 1337 }
+
func TestStoreCapture(t *testing.T) {
var (
- env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
+ env = NewEVM(Context{}, &dummyStatedb{}, params.TestChainConfig, Config{})
logger = NewStructLogger(nil)
mem = NewMemory()
stack = newstack()
@@ -51,9 +58,7 @@ func TestStoreCapture(t *testing.T) {
)
stack.push(big.NewInt(1))
stack.push(big.NewInt(0))
-
var index common.Hash
-
logger.CaptureState(env, 0, SSTORE, 0, 0, mem, stack, contract, 0, nil)
if len(logger.changedValues[contract.Address()]) == 0 {
t.Fatalf("expected exactly 1 changed value on address %x, got %d", contract.Address(), len(logger.changedValues[contract.Address()]))
diff --git a/eth/tracers/tracer.go b/eth/tracers/tracer.go
index b519236f2..3533a831f 100644
--- a/eth/tracers/tracer.go
+++ b/eth/tracers/tracer.go
@@ -290,11 +290,12 @@ type Tracer struct {
contractWrapper *contractWrapper // Wrapper around the contract object
dbWrapper *dbWrapper // Wrapper around the VM environment
- pcValue *uint // Swappable pc 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
- depthValue *uint // Swappable depth value wrapped by a log accessor
- errorValue *string // Swappable error 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
+ costValue *uint // Swappable cost 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
+ refundValue *uint // Swappable refund value wrapped by a log accessor
ctx map[string]interface{} // Transaction context gathered throughout execution
err error // Error, if one has occurred
@@ -323,6 +324,7 @@ func New(code string) (*Tracer, error) {
gasValue: new(uint),
costValue: new(uint),
depthValue: new(uint),
+ refundValue: new(uint),
}
// Set up builtins for this environment
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.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 {
if tracer.errorValue != nil {
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.costValue = uint(cost)
*jst.depthValue = uint(depth)
+ *jst.refundValue = uint(env.StateDB.GetRefund())
jst.errorValue = nil
if err != nil {
diff --git a/eth/tracers/tracer_test.go b/eth/tracers/tracer_test.go
index 58b624724..52f29c83f 100644
--- a/eth/tracers/tracer_test.go
+++ b/eth/tracers/tracer_test.go
@@ -25,6 +25,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
)
@@ -43,8 +44,14 @@ func (account) ReturnGas(*big.Int) {}
func (account) SetCode(common.Hash, []byte) {}
func (account) ForEachStorage(cb func(key, value common.Hash) bool) {}
+type dummyStatedb struct {
+ state.StateDB
+}
+
+func (dummyStatedb) GetRefund() uint64 { return 1337 }
+
func runTrace(tracer *Tracer) (json.RawMessage, error) {
- env := vm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, nil, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
+ env := vm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
contract := vm.NewContract(account{}, account{}, big.NewInt(0), 10000)
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
@@ -126,7 +133,7 @@ func TestHaltBetweenSteps(t *testing.T) {
t.Fatal(err)
}
- env := vm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, nil, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
+ env := vm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
contract := vm.NewContract(&account{}, &account{}, big.NewInt(0), 0)
tracer.CaptureState(env, 0, 0, 0, 0, nil, nil, contract, 0, nil)