Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/qa-rpc-integration-tests-gnosis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ jobs:
uses: actions/cache@v5
with:
path: ${{ runner.workspace }}/rpc-tests
key: rpc-tests-${{ runner.os }}-${{ runner.arch }}-v2.7.0
key: rpc-tests-${{ runner.os }}-${{ runner.arch }}-v2.8.1

- name: Run RPC Integration Tests
id: test_step
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/qa-rpc-integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ jobs:
uses: actions/cache@v5
with:
path: ${{ runner.workspace }}/rpc-tests
key: rpc-tests-${{ runner.os }}-${{ runner.arch }}-v2.7.0
key: rpc-tests-${{ runner.os }}-${{ runner.arch }}-v2.8.1

- name: Run RPC Integration Tests
id: test_step
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scripts/run_rpc_tests_ethereum.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ DISABLED_TEST_LIST=(
DISABLED_TESTS=$(IFS=,; echo "${DISABLED_TEST_LIST[*]}")

# Call the main test runner script with the required and optional parameters
"$(dirname "$0")/run_rpc_tests.sh" mainnet v2.7.0 "$DISABLED_TESTS" "$WORKSPACE" "$RESULT_DIR"
"$(dirname "$0")/run_rpc_tests.sh" mainnet v2.8.1 "$DISABLED_TESTS" "$WORKSPACE" "$RESULT_DIR"
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ DISABLED_TEST_LIST=(
DISABLED_TESTS=$(IFS=,; echo "${DISABLED_TEST_LIST[*]}")

# Call the main test runner script with the required and optional parameters
"$(dirname "$0")/run_rpc_tests.sh" mainnet v2.7.0 "$DISABLED_TESTS" "$WORKSPACE" "$RESULT_DIR" "latest" "$REFERENCE_HOST" "do-not-compare-error-message" "$DUMP_RESPONSE"
"$(dirname "$0")/run_rpc_tests.sh" mainnet v2.8.1 "$DISABLED_TESTS" "$WORKSPACE" "$RESULT_DIR" "latest" "$REFERENCE_HOST" "do-not-compare-error-message" "$DUMP_RESPONSE"
2 changes: 1 addition & 1 deletion .github/workflows/scripts/run_rpc_tests_gnosis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ DISABLED_TEST_LIST=(
DISABLED_TESTS=$(IFS=,; echo "${DISABLED_TEST_LIST[*]}")

# Call the main test runner script with the required and optional parameters
"$(dirname "$0")/run_rpc_tests.sh" gnosis v2.7.0 "$DISABLED_TESTS" "$WORKSPACE" "$RESULT_DIR"
"$(dirname "$0")/run_rpc_tests.sh" gnosis v2.8.1 "$DISABLED_TESTS" "$WORKSPACE" "$RESULT_DIR"

Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ DISABLED_TEST_LIST=(
DISABLED_TESTS=$(IFS=,; echo "${DISABLED_TEST_LIST[*]}")

# Call the main test runner script with the required and optional parameters
"$(dirname "$0")/run_rpc_tests.sh" mainnet v2.7.0 "$DISABLED_TESTS" "$WORKSPACE" "$RESULT_DIR"
"$(dirname "$0")/run_rpc_tests.sh" mainnet v2.8.1 "$DISABLED_TESTS" "$WORKSPACE" "$RESULT_DIR"
39 changes: 39 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,44 @@
# Changelog

## [3.5.0] – 2026-04-25

### Breaking Changes

#### `debug_trace*` RPC: `enableMemory` / `enableReturnData` replace `disableMemory` / `disableReturnData`

Aligns Erigon with the execution-apis specification ([ethereum/execution-apis#762](https://github.com/ethereum/execution-apis/pull/762)) and Geth behavior.

**What changed:**

| Field | Before (Erigon) | After (Erigon / Geth / Spec) |
|-------|-----------------|------------------------------|
| Memory in trace | `disableMemory` (default: included) | `enableMemory` (default: excluded) |
| Return data in trace | `disableReturnData` (default: included) | `enableReturnData` (default: excluded) |

The change is **twofold**:
1. The JSON key is renamed (`disable*` → `enable*`).
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.

**Migration:**

```jsonc
// Before — disable memory explicitly
{ "disableMemory": true }

// After — enable memory explicitly
{ "enableMemory": true }

// Before — memory included by default (no flag needed)
{}

// After — must opt in
{ "enableMemory": true }
```

Affected RPC methods: `debug_traceTransaction`, `debug_traceBlockByHash`, `debug_traceBlockByNumber`, `debug_traceCall`.

---

## [3.3.0] – 2025-11-17

### Added
Expand Down
8 changes: 4 additions & 4 deletions cmd/evm/internal/t8ntool/transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,10 @@ func Main(ctx *cli.Context) error {
if ctx.Bool(TraceFlag.Name) {
// Configure the EVM logger
logConfig := &trace_logger.LogConfig{
DisableStack: ctx.Bool(TraceDisableStackFlag.Name),
DisableMemory: ctx.Bool(TraceDisableMemoryFlag.Name),
DisableReturnData: ctx.Bool(TraceDisableReturnDataFlag.Name),
Debug: true,
DisableStack: ctx.Bool(TraceDisableStackFlag.Name),
EnableMemory: !ctx.Bool(TraceDisableMemoryFlag.Name),
EnableReturnData: !ctx.Bool(TraceDisableReturnDataFlag.Name),
Debug: true,
}
var prevFile *os.File
// This one closes the last file
Expand Down
10 changes: 5 additions & 5 deletions cmd/evm/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,11 @@ func runCmd(ctx *cli.Context) error {
log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(ctx.Int(VerbosityFlag.Name)), log.StderrHandler))
}
logconfig := &logger.LogConfig{
DisableMemory: ctx.Bool(DisableMemoryFlag.Name),
DisableStack: ctx.Bool(DisableStackFlag.Name),
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
DisableReturnData: ctx.Bool(DisableReturnDataFlag.Name),
Debug: ctx.Bool(DebugFlag.Name),
EnableMemory: !ctx.Bool(DisableMemoryFlag.Name),
DisableStack: ctx.Bool(DisableStackFlag.Name),
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name),
Debug: ctx.Bool(DebugFlag.Name),
}

var (
Expand Down
8 changes: 4 additions & 4 deletions cmd/evm/staterunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ func stateTestCmd(ctx *cli.Context) error {

// Configure the EVM logger
config := &logger.LogConfig{
DisableMemory: ctx.Bool(DisableMemoryFlag.Name),
DisableStack: ctx.Bool(DisableStackFlag.Name),
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
DisableReturnData: ctx.Bool(DisableReturnDataFlag.Name),
EnableMemory: !ctx.Bool(DisableMemoryFlag.Name),
DisableStack: ctx.Bool(DisableStackFlag.Name),
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name),
}
cfg := vm.Config{}
if machineFriendlyOutput {
Expand Down
2 changes: 1 addition & 1 deletion execution/tests/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ func withTrace(t *testing.T, test func(vm.Config) error) {
t.Error(err)
buf := new(bytes.Buffer)
w := bufio.NewWriter(buf)
tracer := logger.NewJSONLogger(&logger.LogConfig{DisableMemory: true}, w)
tracer := logger.NewJSONLogger(&logger.LogConfig{EnableMemory: false}, w)
config.Tracer = tracer.Tracer().Hooks
err2 := test(config)
if !reflect.DeepEqual(err, err2) {
Expand Down
8 changes: 7 additions & 1 deletion execution/tracing/tracers/logger/json_stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/holiman/uint256"

"github.com/erigontech/erigon/common"
"github.com/erigontech/erigon/common/hexutil"
"github.com/erigontech/erigon/execution/tracing"
"github.com/erigontech/erigon/execution/tracing/tracers"
"github.com/erigontech/erigon/execution/types"
Expand Down Expand Up @@ -196,7 +197,7 @@ func (l *JsonStreamLogger) OnOpcode(pc uint64, typ byte, gas, cost uint64, scope
}
l.stream.WriteArrayEnd()
}
if !l.cfg.DisableMemory {
if l.cfg.EnableMemory {
l.stream.WriteMore()
l.stream.WriteObjectField("memory")
l.stream.WriteArrayStart()
Expand All @@ -212,6 +213,11 @@ func (l *JsonStreamLogger) OnOpcode(pc uint64, typ byte, gas, cost uint64, scope
}
l.stream.WriteArrayEnd()
}
if l.cfg.EnableReturnData && len(rData) > 0 {
l.stream.WriteMore()
l.stream.WriteObjectField("returnData")
l.stream.WriteString(hexutil.Encode(rData))
}
if outputStorage {
l.stream.WriteMore()
l.stream.WriteObjectField("storage")
Expand Down
56 changes: 54 additions & 2 deletions execution/tracing/tracers/logger/json_stream_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ func (m *mockIBS) GetRefund() mdgas.MdGas { return mdgas.MdGas{} }
// It closes the stream the same way ExecuteTraceTx does after execution.
// storageKey/storageVal are pushed onto the stack for SSTORE (top=key, below=val).
func captureOnOpcode(t *testing.T, cfg *LogConfig, memory []byte, storageKey, storageVal *common.Hash) map[string]json.RawMessage {
return captureOnOpcodeWithReturnData(t, cfg, memory, nil, storageKey, storageVal)
}

func captureOnOpcodeWithReturnData(t *testing.T, cfg *LogConfig, memory []byte, rData []byte, storageKey, storageVal *common.Hash) map[string]json.RawMessage {
t.Helper()
var buf bytes.Buffer
stream := jsonstream.New(&buf)
Expand All @@ -84,7 +88,7 @@ func captureOnOpcode(t *testing.T, cfg *LogConfig, memory []byte, storageKey, st
scope.stack = []uint256.Int{val, key} // bottom=val, top=key
}

l.OnOpcode(0, byte(op), 100, 3, scope, nil, 1, nil)
l.OnOpcode(0, byte(op), 100, 3, scope, rData, 1, nil)

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

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
obj := captureOnOpcode(t, nil, tt.memory, nil, nil)
obj := captureOnOpcode(t, &LogConfig{EnableMemory: true}, tt.memory, nil, nil)
raw, ok := obj["memory"]
if !ok {
t.Fatal("missing 'memory' field")
Expand Down Expand Up @@ -201,6 +205,54 @@ func TestJsonStreamLogger_StorageEncoding(t *testing.T) {
}
}

// TestJsonStreamLogger_EnableMemory verifies that the memory field is present when
// EnableMemory is true and absent when false (the default).
func TestJsonStreamLogger_EnableMemory(t *testing.T) {
mem := bytes.Repeat([]byte{0xab}, 32)

t.Run("enableMemory=true includes memory field", func(t *testing.T) {
obj := captureOnOpcode(t, &LogConfig{EnableMemory: true}, mem, nil, nil)
if _, ok := obj["memory"]; !ok {
t.Error("expected 'memory' field to be present, but it was absent")
}
})

t.Run("enableMemory=false excludes memory field", func(t *testing.T) {
obj := captureOnOpcode(t, &LogConfig{EnableMemory: false}, mem, nil, nil)
if _, ok := obj["memory"]; ok {
t.Error("expected 'memory' field to be absent, but it was present")
}
})
}

// TestJsonStreamLogger_EnableReturnData verifies that the returnData field is present
// when EnableReturnData is true and absent when false (the default).
func TestJsonStreamLogger_EnableReturnData(t *testing.T) {
rData := []byte{0xde, 0xad, 0xbe, 0xef}

t.Run("enableReturnData=true includes returnData field", func(t *testing.T) {
obj := captureOnOpcodeWithReturnData(t, &LogConfig{EnableReturnData: true}, nil, rData, nil, nil)
raw, ok := obj["returnData"]
if !ok {
t.Fatal("expected 'returnData' field to be present, but it was absent")
}
var got string
if err := json.Unmarshal(raw, &got); err != nil {
t.Fatalf("cannot parse returnData: %v", err)
}
if got != "0xdeadbeef" {
t.Errorf("returnData: got %s, want 0xdeadbeef", got)
}
})

t.Run("enableReturnData=false excludes returnData field", func(t *testing.T) {
obj := captureOnOpcodeWithReturnData(t, &LogConfig{EnableReturnData: false}, nil, rData, nil, nil)
if _, ok := obj["returnData"]; ok {
t.Error("expected 'returnData' field to be absent, but it was present")
}
})
}

// TestStructLog_ErrorOmitempty verifies that the 'error' field is omitted from
// MarshalJSON output when there is no error, and present when there is.
func TestStructLog_ErrorOmitempty(t *testing.T) {
Expand Down
16 changes: 8 additions & 8 deletions execution/tracing/tracers/logger/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ func (s Storage) Copy() Storage {

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

// Copy a snapshot of the current memory state to a new buffer
var mem []byte
if !l.cfg.DisableMemory {
if l.cfg.EnableMemory {
mem = make([]byte, len(memory))
copy(mem, memory)
}
Expand Down Expand Up @@ -236,7 +236,7 @@ func (l *StructLogger) OnOpcode(pc uint64, opcode byte, gas, cost uint64, scope
storage = l.storage[contractAddr].Copy()
}
var rdata []byte
if !l.cfg.DisableReturnData {
if l.cfg.EnableReturnData {
rdata = make([]byte, len(rData))
copy(rdata, rData)
}
Expand Down
5 changes: 4 additions & 1 deletion execution/tracing/tracers/logger/logger_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (l *JSONLogger) OnOpcode(pc uint64, typ byte, gas, cost uint64, scope traci
RefundCounter: l.env.IntraBlockState.GetRefund().Total(),
Err: err,
}
if !l.cfg.DisableMemory {
if l.cfg.EnableMemory {
log.Memory = memory
}
if !l.cfg.DisableStack {
Expand All @@ -92,6 +92,9 @@ func (l *JSONLogger) OnOpcode(pc uint64, typ byte, gas, cost uint64, scope traci
}
log.Stack = logstack
}
if l.cfg.EnableReturnData {
log.ReturnData = rData
}
_ = l.encoder.Encode(log)
}

Expand Down
Loading