eth/tracers/logger: respect logging limit (#35349)

Necessary for building fuzzers that don't take 10s of seconds for
tracing a test
This commit is contained in:
Marius van der Wijden 2026-07-13 13:51:38 +02:00 committed by GitHub
parent 3140668d49
commit f9382c2d1b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 24 additions and 4 deletions

View file

@ -51,6 +51,19 @@ type Config struct {
Overrides *params.ChainConfig `json:"overrides,omitempty"`
}
// countingWriter wraps an io.Writer and records how many bytes have been
// written through it.
type countingWriter struct {
w io.Writer
n int
}
func (c *countingWriter) Write(p []byte) (int, error) {
n, err := c.w.Write(p)
c.n += n
return n, err
}
//go:generate go run github.com/fjl/gencodec -type StructLog -field-override structLogMarshaling -out gen_structlog.go
// StructLog is emitted to the EVM each cycle and lists information about the
@ -227,7 +240,7 @@ type StructLogger struct {
writer io.Writer // If set, the logger will stream instead of store logs
logs []json.RawMessage // buffer of json-encoded logs
resultSize int
resultSize int // total bytes of trace output
interrupt atomic.Bool // Atomic flag to signal execution interruption
reason atomic.Pointer[error] // Reason for the interruption, populated by Stop
@ -237,7 +250,7 @@ type StructLogger struct {
// NewStreamingStructLogger returns a new streaming logger.
func NewStreamingStructLogger(cfg *Config, writer io.Writer) *StructLogger {
l := NewStructLogger(cfg)
l.writer = writer
l.writer = &countingWriter{w: writer}
return l
}
@ -334,6 +347,7 @@ func (l *StructLogger) OnOpcode(pc uint64, opcode byte, gas, cost uint64, scope
return
}
log.Write(l.writer)
l.resultSize = l.writer.(*countingWriter).n
}
// OnExit is called a call frame finishes processing.

View file

@ -59,12 +59,14 @@ type jsonLogger struct {
cfg *Config
env *tracing.VMContext
hooks *tracing.Hooks
written *countingWriter
}
// NewJSONLogger creates a new EVM tracer that prints execution steps as JSON objects
// into the provided stream.
func NewJSONLogger(cfg *Config, writer io.Writer) *tracing.Hooks {
l := &jsonLogger{encoder: json.NewEncoder(writer), cfg: cfg}
cw := &countingWriter{w: writer}
l := &jsonLogger{encoder: json.NewEncoder(cw), cfg: cfg, written: cw}
if l.cfg == nil {
l.cfg = &Config{}
}
@ -81,7 +83,8 @@ func NewJSONLogger(cfg *Config, writer io.Writer) *tracing.Hooks {
// NewJSONLoggerWithCallFrames creates a new EVM tracer that prints execution steps as JSON objects
// into the provided stream. It also includes call frames in the output.
func NewJSONLoggerWithCallFrames(cfg *Config, writer io.Writer) *tracing.Hooks {
l := &jsonLogger{encoder: json.NewEncoder(writer), cfg: cfg}
cw := &countingWriter{w: writer}
l := &jsonLogger{encoder: json.NewEncoder(cw), cfg: cfg, written: cw}
if l.cfg == nil {
l.cfg = &Config{}
}
@ -102,6 +105,9 @@ func (l *jsonLogger) OnFault(pc uint64, op byte, gas uint64, cost uint64, scope
}
func (l *jsonLogger) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
if l.cfg.Limit != 0 && l.written.n > l.cfg.Limit {
return
}
memory := scope.MemoryData()
stack := scope.StackData()