Skip to content

Commit be6687e

Browse files
lupin012claude
andcommitted
rpc, evm: align debug trace flags with execution-apis spec (#762)
Replace disableMemory/disableReturnData (opt-out, default ON) with enableMemory/enableReturnData (opt-in, default OFF) to match the ethereum/execution-apis#762 spec and Geth behavior. Also adds returnData emission to JsonStreamLogger which was previously missing. evm tool flags (--nomemory/--noreturndata) preserve existing behavior. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent f8fd26c commit be6687e

9 files changed

Lines changed: 121 additions & 26 deletions

File tree

CHANGELOG.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Changelog
2+
3+
## Unreleased
4+
5+
### Breaking Changes
6+
7+
#### `debug_trace*` RPC: `enableMemory` / `enableReturnData` replace `disableMemory` / `disableReturnData`
8+
9+
Aligns Erigon with the execution-apis specification ([ethereum/execution-apis#762](https://github.com/ethereum/execution-apis/pull/762)) and Geth behavior.
10+
11+
**What changed:**
12+
13+
| Field | Before (Erigon) | After (Erigon / Geth / Spec) |
14+
|-------|-----------------|------------------------------|
15+
| Memory in trace | `disableMemory` (default: included) | `enableMemory` (default: excluded) |
16+
| Return data in trace | `disableReturnData` (default: included) | `enableReturnData` (default: excluded) |
17+
18+
The change is **twofold**:
19+
1. The JSON key is renamed (`disable*``enable*`).
20+
2. The default value is inverted: previously memory and return data were **included** by default (opt-out model); now they are **excluded** by default (opt-in model), matching the spec and Geth.
21+
22+
**Migration:**
23+
24+
```jsonc
25+
// Before — disable memory explicitly
26+
{ "disableMemory": true }
27+
28+
// After — enable memory explicitly
29+
{ "enableMemory": true }
30+
31+
// Before — memory included by default (no flag needed)
32+
{}
33+
34+
// After — must opt in
35+
{ "enableMemory": true }
36+
```
37+
38+
Affected RPC methods: `debug_traceTransaction`, `debug_traceBlockByHash`, `debug_traceBlockByNumber`, `debug_traceCall`.

cmd/evm/internal/t8ntool/transition.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,10 @@ func Main(ctx *cli.Context) error {
121121
if ctx.Bool(TraceFlag.Name) {
122122
// Configure the EVM logger
123123
logConfig := &trace_logger.LogConfig{
124-
DisableStack: ctx.Bool(TraceDisableStackFlag.Name),
125-
DisableMemory: ctx.Bool(TraceDisableMemoryFlag.Name),
126-
DisableReturnData: ctx.Bool(TraceDisableReturnDataFlag.Name),
127-
Debug: true,
124+
DisableStack: ctx.Bool(TraceDisableStackFlag.Name),
125+
EnableMemory: !ctx.Bool(TraceDisableMemoryFlag.Name),
126+
EnableReturnData: !ctx.Bool(TraceDisableReturnDataFlag.Name),
127+
Debug: true,
128128
}
129129
var prevFile *os.File
130130
// This one closes the last file

cmd/evm/runner.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,11 @@ func runCmd(ctx *cli.Context) error {
151151
log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(ctx.Int(VerbosityFlag.Name)), log.StderrHandler))
152152
}
153153
logconfig := &logger.LogConfig{
154-
DisableMemory: ctx.Bool(DisableMemoryFlag.Name),
155-
DisableStack: ctx.Bool(DisableStackFlag.Name),
156-
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
157-
DisableReturnData: ctx.Bool(DisableReturnDataFlag.Name),
158-
Debug: ctx.Bool(DebugFlag.Name),
154+
EnableMemory: !ctx.Bool(DisableMemoryFlag.Name),
155+
DisableStack: ctx.Bool(DisableStackFlag.Name),
156+
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
157+
EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name),
158+
Debug: ctx.Bool(DebugFlag.Name),
159159
}
160160

161161
var (

cmd/evm/staterunner.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@ func stateTestCmd(ctx *cli.Context) error {
6868

6969
// Configure the EVM logger
7070
config := &logger.LogConfig{
71-
DisableMemory: ctx.Bool(DisableMemoryFlag.Name),
72-
DisableStack: ctx.Bool(DisableStackFlag.Name),
73-
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
74-
DisableReturnData: ctx.Bool(DisableReturnDataFlag.Name),
71+
EnableMemory: !ctx.Bool(DisableMemoryFlag.Name),
72+
DisableStack: ctx.Bool(DisableStackFlag.Name),
73+
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
74+
EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name),
7575
}
7676
cfg := vm.Config{}
7777
if machineFriendlyOutput {

execution/tests/state_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ func withTrace(t *testing.T, test func(vm.Config) error) {
174174
t.Error(err)
175175
buf := new(bytes.Buffer)
176176
w := bufio.NewWriter(buf)
177-
tracer := logger.NewJSONLogger(&logger.LogConfig{DisableMemory: true}, w)
177+
tracer := logger.NewJSONLogger(&logger.LogConfig{EnableMemory: false}, w)
178178
config.Tracer = tracer.Tracer().Hooks
179179
err2 := test(config)
180180
if !reflect.DeepEqual(err, err2) {

execution/tracing/tracers/logger/json_stream.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ func (l *JsonStreamLogger) OnOpcode(pc uint64, typ byte, gas, cost uint64, scope
196196
}
197197
l.stream.WriteArrayEnd()
198198
}
199-
if !l.cfg.DisableMemory {
199+
if l.cfg.EnableMemory {
200200
l.stream.WriteMore()
201201
l.stream.WriteObjectField("memory")
202202
l.stream.WriteArrayStart()
@@ -212,6 +212,11 @@ func (l *JsonStreamLogger) OnOpcode(pc uint64, typ byte, gas, cost uint64, scope
212212
}
213213
l.stream.WriteArrayEnd()
214214
}
215+
if l.cfg.EnableReturnData && len(rData) > 0 {
216+
l.stream.WriteMore()
217+
l.stream.WriteObjectField("returnData")
218+
l.stream.WriteString(l.hexWithPrefix(rData))
219+
}
215220
if outputStorage {
216221
l.stream.WriteMore()
217222
l.stream.WriteObjectField("storage")

execution/tracing/tracers/logger/json_stream_test.go

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ func (m *mockIBS) GetRefund() mdgas.MdGas { return mdgas.MdGas{} }
6666
// It closes the stream the same way ExecuteTraceTx does after execution.
6767
// storageKey/storageVal are pushed onto the stack for SSTORE (top=key, below=val).
6868
func captureOnOpcode(t *testing.T, cfg *LogConfig, memory []byte, storageKey, storageVal *common.Hash) map[string]json.RawMessage {
69+
return captureOnOpcodeWithReturnData(t, cfg, memory, nil, storageKey, storageVal)
70+
}
71+
72+
func captureOnOpcodeWithReturnData(t *testing.T, cfg *LogConfig, memory []byte, rData []byte, storageKey, storageVal *common.Hash) map[string]json.RawMessage {
6973
t.Helper()
7074
var buf bytes.Buffer
7175
stream := jsonstream.New(&buf)
@@ -84,7 +88,7 @@ func captureOnOpcode(t *testing.T, cfg *LogConfig, memory []byte, storageKey, st
8488
scope.stack = []uint256.Int{val, key} // bottom=val, top=key
8589
}
8690

87-
l.OnOpcode(0, byte(op), 100, 3, scope, nil, 1, nil)
91+
l.OnOpcode(0, byte(op), 100, 3, scope, rData, 1, nil)
8892

8993
// Mirror what ExecuteTraceTx does to close the stream after execution.
9094
stream.WriteArrayEnd()
@@ -153,7 +157,7 @@ func TestJsonStreamLogger_MemoryEncoding(t *testing.T) {
153157

154158
for _, tt := range tests {
155159
t.Run(tt.name, func(t *testing.T) {
156-
obj := captureOnOpcode(t, nil, tt.memory, nil, nil)
160+
obj := captureOnOpcode(t, &LogConfig{EnableMemory: true}, tt.memory, nil, nil)
157161
raw, ok := obj["memory"]
158162
if !ok {
159163
t.Fatal("missing 'memory' field")
@@ -201,6 +205,54 @@ func TestJsonStreamLogger_StorageEncoding(t *testing.T) {
201205
}
202206
}
203207

208+
// TestJsonStreamLogger_EnableMemory verifies that the memory field is present when
209+
// EnableMemory is true and absent when false (the default).
210+
func TestJsonStreamLogger_EnableMemory(t *testing.T) {
211+
mem := bytes.Repeat([]byte{0xab}, 32)
212+
213+
t.Run("enableMemory=true includes memory field", func(t *testing.T) {
214+
obj := captureOnOpcode(t, &LogConfig{EnableMemory: true}, mem, nil, nil)
215+
if _, ok := obj["memory"]; !ok {
216+
t.Error("expected 'memory' field to be present, but it was absent")
217+
}
218+
})
219+
220+
t.Run("enableMemory=false excludes memory field", func(t *testing.T) {
221+
obj := captureOnOpcode(t, &LogConfig{EnableMemory: false}, mem, nil, nil)
222+
if _, ok := obj["memory"]; ok {
223+
t.Error("expected 'memory' field to be absent, but it was present")
224+
}
225+
})
226+
}
227+
228+
// TestJsonStreamLogger_EnableReturnData verifies that the returnData field is present
229+
// when EnableReturnData is true and absent when false (the default).
230+
func TestJsonStreamLogger_EnableReturnData(t *testing.T) {
231+
rData := []byte{0xde, 0xad, 0xbe, 0xef}
232+
233+
t.Run("enableReturnData=true includes returnData field", func(t *testing.T) {
234+
obj := captureOnOpcodeWithReturnData(t, &LogConfig{EnableReturnData: true}, nil, rData, nil, nil)
235+
raw, ok := obj["returnData"]
236+
if !ok {
237+
t.Fatal("expected 'returnData' field to be present, but it was absent")
238+
}
239+
var got string
240+
if err := json.Unmarshal(raw, &got); err != nil {
241+
t.Fatalf("cannot parse returnData: %v", err)
242+
}
243+
if got != "0xdeadbeef" {
244+
t.Errorf("returnData: got %s, want 0xdeadbeef", got)
245+
}
246+
})
247+
248+
t.Run("enableReturnData=false excludes returnData field", func(t *testing.T) {
249+
obj := captureOnOpcodeWithReturnData(t, &LogConfig{EnableReturnData: false}, nil, rData, nil, nil)
250+
if _, ok := obj["returnData"]; ok {
251+
t.Error("expected 'returnData' field to be absent, but it was present")
252+
}
253+
})
254+
}
255+
204256
// TestStructLog_ErrorOmitempty verifies that the 'error' field is omitted from
205257
// MarshalJSON output when there is no error, and present when there is.
206258
func TestStructLog_ErrorOmitempty(t *testing.T) {

execution/tracing/tracers/logger/logger.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,12 @@ func (s Storage) Copy() Storage {
5252

5353
// LogConfig are the configuration options for structured logger the EVM
5454
type LogConfig struct {
55-
DisableMemory bool `json:"disableMemory"` // disable memory capture
56-
DisableStack bool `json:"disableStack"` // disable stack capture
57-
DisableStorage bool `json:"disableStorage"` // disable storage capture
58-
DisableReturnData bool `json:"disableReturnData"` // disable return data capture
59-
Debug bool `json:"debug"` // print output during capture end
60-
Limit int `json:"limit"` // maximum length of output, but zero means unlimited
55+
EnableMemory bool `json:"enableMemory"` // enable memory capture
56+
DisableStack bool `json:"disableStack"` // disable stack capture
57+
DisableStorage bool `json:"disableStorage"` // disable storage capture
58+
EnableReturnData bool `json:"enableReturnData"` // enable return data capture
59+
Debug bool `json:"debug"` // print output during capture end
60+
Limit int `json:"limit"` // maximum length of output, but zero means unlimited
6161
// Chain overrides, can be used to execute a trace using future fork rules
6262
Overrides *chain.Config `json:"overrides,omitempty"`
6363
}
@@ -194,7 +194,7 @@ func (l *StructLogger) OnOpcode(pc uint64, opcode byte, gas, cost uint64, scope
194194

195195
// Copy a snapshot of the current memory state to a new buffer
196196
var mem []byte
197-
if !l.cfg.DisableMemory {
197+
if l.cfg.EnableMemory {
198198
mem = make([]byte, len(memory))
199199
copy(mem, memory)
200200
}
@@ -236,7 +236,7 @@ func (l *StructLogger) OnOpcode(pc uint64, opcode byte, gas, cost uint64, scope
236236
storage = l.storage[contractAddr].Copy()
237237
}
238238
var rdata []byte
239-
if !l.cfg.DisableReturnData {
239+
if l.cfg.EnableReturnData {
240240
rdata = make([]byte, len(rData))
241241
copy(rdata, rData)
242242
}

execution/tracing/tracers/logger/logger_json.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func (l *JSONLogger) OnOpcode(pc uint64, typ byte, gas, cost uint64, scope traci
8181
RefundCounter: l.env.IntraBlockState.GetRefund().Total(),
8282
Err: err,
8383
}
84-
if !l.cfg.DisableMemory {
84+
if l.cfg.EnableMemory {
8585
log.Memory = memory
8686
}
8787
if !l.cfg.DisableStack {

0 commit comments

Comments
 (0)