eth/tracers, core/vm: remove time from trace output and tracing interface #26291 (#1311)

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: Sina Mahmoodi <itz.s1na@gmail.com>
This commit is contained in:
Daniel Liu 2025-09-09 09:26:10 +08:00 committed by GitHub
parent dd9fac6d41
commit 7d4d81f586
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 22 additions and 37 deletions

View file

@ -236,7 +236,7 @@ Gas used: %d
`, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC, initialGas-leftOverGas) `, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC, initialGas-leftOverGas)
} }
if tracer != nil { if tracer != nil {
tracer.CaptureEnd(ret, initialGas-leftOverGas, execTime, err) tracer.CaptureEnd(ret, initialGas-leftOverGas, err)
} else { } else {
fmt.Printf("%#x\n", ret) fmt.Printf("%#x\n", ret)
if err != nil { if err != nil {

View file

@ -19,7 +19,6 @@ package vm
import ( import (
"math/big" "math/big"
"sync/atomic" "sync/atomic"
"time"
"github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate" "github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
@ -196,7 +195,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
if debug { if 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)
@ -212,10 +211,9 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
if debug { if 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) { // Lazy evaluation of the parameters
defer func(startGas uint64, startTime time.Time) { // Lazy evaluation of the parameters evm.Config.Tracer.CaptureEnd(ret, startGas-gas, err)
evm.Config.Tracer.CaptureEnd(ret, startGas-gas, time.Since(startTime), err) }(gas)
}(gas, time.Now())
} 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)
@ -464,7 +462,6 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value) evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value)
} }
} }
start := time.Now()
ret, err := evm.interpreter.Run(contract, nil, false) ret, err := evm.interpreter.Run(contract, nil, false)
@ -503,7 +500,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
if evm.Config.Tracer != nil { if evm.Config.Tracer != nil {
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)
} }

View file

@ -18,7 +18,6 @@ package vm
import ( import (
"math/big" "math/big"
"time"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/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)

View file

@ -21,7 +21,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
"time"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/common/hexutil" "github.com/XinFinOrg/XDPoSChain/common/hexutil"
@ -284,9 +283,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())
if err != nil { if err != nil {
t.ctx["error"] = t.vm.ToValue(err.Error()) t.ctx["error"] = t.vm.ToValue(err.Error())
} }

View file

@ -233,7 +233,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) {

View file

@ -76,7 +76,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(contract.Gas) tracer.CaptureTxEnd(contract.Gas)
if err != nil { if err != nil {
@ -206,7 +206,7 @@ func TestNoStepExec(t *testing.T) {
} }
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100000)}, &dummyStatedb{}, nil, params.TestChainConfig, vm.Config{Tracer: tracer}) env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100000)}, &dummyStatedb{}, nil, params.TestChainConfig, vm.Config{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)

View file

@ -18,7 +18,6 @@ package logger
import ( import (
"math/big" "math/big"
"time"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/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) {
} }

View file

@ -24,7 +24,6 @@ import (
"math/big" "math/big"
"strings" "strings"
"sync/atomic" "sync/atomic"
"time"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/common/hexutil" "github.com/XinFinOrg/XDPoSChain/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: `%#x`\nConsumed gas: `%d`\nError: `%v`\n", fmt.Fprintf(t.out, "\nOutput: `%#x`\nConsumed gas: `%d`\nError: `%v`\n",
output, gasUsed, err) output, gasUsed, err)
} }

View file

@ -20,7 +20,6 @@ import (
"encoding/json" "encoding/json"
"io" "io"
"math/big" "math/big"
"time"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/common/math" "github.com/XinFinOrg/XDPoSChain/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) {

View file

@ -21,7 +21,6 @@ import (
"errors" "errors"
"math/big" "math/big"
"sync/atomic" "sync/atomic"
"time"
"github.com/XinFinOrg/XDPoSChain/accounts/abi" "github.com/XinFinOrg/XDPoSChain/accounts/abi"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/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, _ 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)
} }

View file

@ -6,7 +6,6 @@ import (
"math/big" "math/big"
"strings" "strings"
"sync/atomic" "sync/atomic"
"time"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core/vm" "github.com/XinFinOrg/XDPoSChain/core/vm"
@ -58,7 +57,7 @@ func (t *contractTracer) CaptureStart(env *vm.EVM, from common.Address, to commo
} }
} }
func (t *contractTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) { func (t *contractTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
} }
func (*contractTracer) CaptureTxStart(gasLimit uint64) {} func (*contractTracer) CaptureTxStart(gasLimit uint64) {}

View file

@ -19,7 +19,6 @@ package native
import ( import (
"encoding/json" "encoding/json"
"math/big" "math/big"
"time"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core/vm" "github.com/XinFinOrg/XDPoSChain/core/vm"
@ -67,9 +66,9 @@ func (t *muxTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Add
} }
// CaptureEnd is called after the call finishes to finalize the tracing. // CaptureEnd is called after the call finishes to finalize the tracing.
func (t *muxTracer) CaptureEnd(output []byte, gasUsed uint64, elapsed time.Duration, err error) { func (t *muxTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
for _, t := range t.tracers { for _, t := range t.tracers {
t.CaptureEnd(output, gasUsed, elapsed, err) t.CaptureEnd(output, gasUsed, err)
} }
} }

View file

@ -19,7 +19,6 @@ package native
import ( import (
"encoding/json" "encoding/json"
"math/big" "math/big"
"time"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core/vm" "github.com/XinFinOrg/XDPoSChain/core/vm"
@ -39,7 +38,8 @@ func newNoopTracer(ctx *tracers.Context, _ json.RawMessage) (tracers.Tracer, err
func (t *noopTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { func (t *noopTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
} }
func (t *noopTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration, err error) { // CaptureEnd is called after the call finishes to finalize the tracing.
func (t *noopTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
} }
func (t *noopTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { func (t *noopTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {

View file

@ -21,7 +21,6 @@ import (
"encoding/json" "encoding/json"
"math/big" "math/big"
"sync/atomic" "sync/atomic"
"time"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/common/hexutil" "github.com/XinFinOrg/XDPoSChain/common/hexutil"
@ -118,7 +117,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.config.DiffMode { if t.config.DiffMode {
return return
} }