eth/tracers, core/vm: remove time
from trace output and tracing interface (#1488)
This removes the 'time' field from logs, as well as from the tracer interface. This change makes the trace output deterministic. If a tracer needs the time they can measure it themselves. No need for evm to do this. Co-authored-by: Martin Holst Swende <martin@swende.se> Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
This commit is contained in:
parent
f8e000309c
commit
880535c730
@ -20,7 +20,6 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
|
|
||||||
@ -205,7 +204,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
|||||||
if evm.Config.Debug {
|
if evm.Config.Debug {
|
||||||
if evm.depth == 0 {
|
if evm.depth == 0 {
|
||||||
evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
|
evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
|
||||||
evm.Config.Tracer.CaptureEnd(ret, 0, 0, nil)
|
evm.Config.Tracer.CaptureEnd(ret, 0, nil)
|
||||||
} else {
|
} else {
|
||||||
evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
|
evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
|
||||||
evm.Config.Tracer.CaptureExit(ret, 0, nil)
|
evm.Config.Tracer.CaptureExit(ret, 0, nil)
|
||||||
@ -221,9 +220,9 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
|||||||
if evm.Config.Debug {
|
if evm.Config.Debug {
|
||||||
if evm.depth == 0 {
|
if evm.depth == 0 {
|
||||||
evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
|
evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
|
||||||
defer func(startGas uint64, startTime time.Time) { // Lazy evaluation of the parameters
|
defer func(startGas uint64) { // Lazy evaluation of the parameters
|
||||||
evm.Config.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err)
|
evm.Config.Tracer.CaptureEnd(ret, startGas-gas, err)
|
||||||
}(gas, time.Now())
|
}(gas)
|
||||||
} else {
|
} else {
|
||||||
// Handle tracer events for entering and exiting a call frame
|
// Handle tracer events for entering and exiting a call frame
|
||||||
evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
|
evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
|
||||||
@ -470,8 +469,6 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
start := time.Now()
|
|
||||||
|
|
||||||
ret, err := evm.interpreter.Run(contract, nil, false)
|
ret, err := evm.interpreter.Run(contract, nil, false)
|
||||||
|
|
||||||
// Check whether the max code size has been exceeded, assign err if the case.
|
// Check whether the max code size has been exceeded, assign err if the case.
|
||||||
@ -509,7 +506,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
|||||||
|
|
||||||
if evm.Config.Debug {
|
if evm.Config.Debug {
|
||||||
if evm.depth == 0 {
|
if evm.depth == 0 {
|
||||||
evm.Config.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err)
|
evm.Config.Tracer.CaptureEnd(ret, gas-contract.Gas, err)
|
||||||
} else {
|
} else {
|
||||||
evm.Config.Tracer.CaptureExit(ret, gas-contract.Gas, err)
|
evm.Config.Tracer.CaptureExit(ret, gas-contract.Gas, err)
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ package vm
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
)
|
)
|
||||||
@ -34,7 +33,7 @@ type EVMLogger interface {
|
|||||||
CaptureTxEnd(restGas uint64)
|
CaptureTxEnd(restGas uint64)
|
||||||
// Top call frame
|
// Top call frame
|
||||||
CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int)
|
CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int)
|
||||||
CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error)
|
CaptureEnd(output []byte, gasUsed uint64, err error)
|
||||||
// Rest of call frames
|
// Rest of call frames
|
||||||
CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int)
|
CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int)
|
||||||
CaptureExit(output []byte, gasUsed uint64, err error)
|
CaptureExit(output []byte, gasUsed uint64, err error)
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/dop251/goja"
|
"github.com/dop251/goja"
|
||||||
|
|
||||||
@ -278,9 +277,8 @@ func (t *jsTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnd is called after the call finishes to finalize the tracing.
|
// CaptureEnd is called after the call finishes to finalize the tracing.
|
||||||
func (t *jsTracer) CaptureEnd(output []byte, gasUsed uint64, duration time.Duration, err error) {
|
func (t *jsTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
|
||||||
t.ctx["output"] = t.vm.ToValue(output)
|
t.ctx["output"] = t.vm.ToValue(output)
|
||||||
t.ctx["time"] = t.vm.ToValue(duration.String())
|
|
||||||
t.ctx["gasUsed"] = t.vm.ToValue(gasUsed)
|
t.ctx["gasUsed"] = t.vm.ToValue(gasUsed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.ctx["error"] = t.vm.ToValue(err.Error())
|
t.ctx["error"] = t.vm.ToValue(err.Error())
|
||||||
|
@ -234,7 +234,6 @@
|
|||||||
input: call.input,
|
input: call.input,
|
||||||
output: call.output,
|
output: call.output,
|
||||||
error: call.error,
|
error: call.error,
|
||||||
time: call.time,
|
|
||||||
calls: call.calls,
|
calls: call.calls,
|
||||||
}
|
}
|
||||||
for (var key in sorted) {
|
for (var key in sorted) {
|
||||||
|
@ -73,7 +73,7 @@ func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCon
|
|||||||
tracer.CaptureTxStart(gasLimit)
|
tracer.CaptureTxStart(gasLimit)
|
||||||
tracer.CaptureStart(env, contract.Caller(), contract.Address(), false, []byte{}, startGas, value)
|
tracer.CaptureStart(env, contract.Caller(), contract.Address(), false, []byte{}, startGas, value)
|
||||||
ret, err := env.Interpreter().Run(contract, []byte{}, false)
|
ret, err := env.Interpreter().Run(contract, []byte{}, false)
|
||||||
tracer.CaptureEnd(ret, startGas-contract.Gas, 1, err)
|
tracer.CaptureEnd(ret, startGas-contract.Gas, err)
|
||||||
// Rest gas assumes no refund
|
// Rest gas assumes no refund
|
||||||
tracer.CaptureTxEnd(startGas - contract.Gas)
|
tracer.CaptureTxEnd(startGas - contract.Gas)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -193,7 +193,7 @@ func TestNoStepExec(t *testing.T) {
|
|||||||
}
|
}
|
||||||
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
|
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
|
||||||
tracer.CaptureStart(env, common.Address{}, common.Address{}, false, []byte{}, 1000, big.NewInt(0))
|
tracer.CaptureStart(env, common.Address{}, common.Address{}, false, []byte{}, 1000, big.NewInt(0))
|
||||||
tracer.CaptureEnd(nil, 0, 1, nil)
|
tracer.CaptureEnd(nil, 0, nil)
|
||||||
ret, err := tracer.GetResult()
|
ret, err := tracer.GetResult()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -18,7 +18,6 @@ package logger
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
@ -162,7 +161,7 @@ func (a *AccessListTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint6
|
|||||||
func (*AccessListTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
|
func (*AccessListTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*AccessListTracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {}
|
func (*AccessListTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {}
|
||||||
|
|
||||||
func (*AccessListTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
func (*AccessListTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
@ -220,7 +219,7 @@ func (l *StructLogger) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnd is called after the call finishes to finalize the tracing.
|
// CaptureEnd is called after the call finishes to finalize the tracing.
|
||||||
func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {
|
func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, err error) {
|
||||||
l.output = output
|
l.output = output
|
||||||
l.err = err
|
l.err = err
|
||||||
if l.cfg.Debug {
|
if l.cfg.Debug {
|
||||||
@ -386,7 +385,7 @@ func (t *mdLogger) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope
|
|||||||
fmt.Fprintf(t.out, "\nError: at pc=%d, op=%v: %v\n", pc, op, err)
|
fmt.Fprintf(t.out, "\nError: at pc=%d, op=%v: %v\n", pc, op, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *mdLogger) CaptureEnd(output []byte, gasUsed uint64, tm time.Duration, err error) {
|
func (t *mdLogger) CaptureEnd(output []byte, gasUsed uint64, err error) {
|
||||||
fmt.Fprintf(t.out, "\nOutput: `0x%x`\nConsumed gas: `%d`\nError: `%v`\n",
|
fmt.Fprintf(t.out, "\nOutput: `0x%x`\nConsumed gas: `%d`\nError: `%v`\n",
|
||||||
output, gasUsed, err)
|
output, gasUsed, err)
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
@ -80,18 +79,17 @@ func (l *JSONLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, sco
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnd is triggered at end of execution.
|
// CaptureEnd is triggered at end of execution.
|
||||||
func (l *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {
|
func (l *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, err error) {
|
||||||
type endLog struct {
|
type endLog struct {
|
||||||
Output string `json:"output"`
|
Output string `json:"output"`
|
||||||
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
|
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
|
||||||
Time time.Duration `json:"time"`
|
|
||||||
Err string `json:"error,omitempty"`
|
Err string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
var errMsg string
|
var errMsg string
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errMsg = err.Error()
|
errMsg = err.Error()
|
||||||
}
|
}
|
||||||
l.encoder.Encode(endLog{common.Bytes2Hex(output), math.HexOrDecimal64(gasUsed), t, errMsg})
|
l.encoder.Encode(endLog{common.Bytes2Hex(output), math.HexOrDecimal64(gasUsed), errMsg})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *JSONLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
func (l *JSONLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
||||||
|
@ -21,7 +21,6 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
@ -129,7 +128,7 @@ func (t *fourByteTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnd is called after the call finishes to finalize the tracing.
|
// CaptureEnd is called after the call finishes to finalize the tracing.
|
||||||
func (t *fourByteTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) {
|
func (t *fourByteTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*fourByteTracer) CaptureTxStart(gasLimit uint64) {}
|
func (*fourByteTracer) CaptureTxStart(gasLimit uint64) {}
|
||||||
|
@ -21,7 +21,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -142,7 +141,7 @@ func (t *callTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Ad
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnd is called after the call finishes to finalize the tracing.
|
// CaptureEnd is called after the call finishes to finalize the tracing.
|
||||||
func (t *callTracer) CaptureEnd(output []byte, gasUsed uint64, d time.Duration, err error) {
|
func (t *callTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
|
||||||
t.callstack[0].processOutput(output, err)
|
t.callstack[0].processOutput(output, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@ package native
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"math/big"
|
"math/big"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
@ -44,7 +43,7 @@ func (t *noopTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Ad
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnd is called after the call finishes to finalize the tracing.
|
// CaptureEnd is called after the call finishes to finalize the tracing.
|
||||||
func (t *noopTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) {
|
func (t *noopTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
|
// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
@ -82,7 +81,7 @@ func (t *prestateTracer) CaptureStart(env *vm.EVM, from common.Address, to commo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnd is called after the call finishes to finalize the tracing.
|
// CaptureEnd is called after the call finishes to finalize the tracing.
|
||||||
func (t *prestateTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) {
|
func (t *prestateTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
|
||||||
if t.create {
|
if t.create {
|
||||||
// Exclude created contract.
|
// Exclude created contract.
|
||||||
delete(t.prestate, t.to)
|
delete(t.prestate, t.to)
|
||||||
|
Loading…
Reference in New Issue
Block a user