fix(eth): trace_filter returns [] for null round ranges (#13483)

When all blocks in a trace_filter range are null rounds, the API was returning
JSON `null` instead of `[]` because the results slice was never initialised.
This commit is contained in:
Rod Vagg
2026-02-04 19:15:37 +11:00
committed by GitHub
parent 9a6894fc6e
commit 5f32d00550
3 changed files with 26 additions and 1 deletions

View File

@@ -16,6 +16,7 @@
- feat(cli): add --order-by-nonce flag to list messages sequentially when filtering by sender ([filecoin-project/lotus#13394](https://github.com/filecoin-project/lotus/pull/13394))
- fix(eth): use error code 3 for EExecutionReverted for Ethereum RPC tooling compatibility ([filecoin-project/lotus#13467](https://github.com/filecoin-project/lotus/pull/13467))
- BREAKING: RPC error codes changed - EActorNotFound (3→11), EExecutionReverted (11→3). Mismatched client/server versions will deserialize these errors as the wrong Go type, breaking errors.Is/As checks.
- fix(eth): trace_filter returns [] for null round ranges ([filecoin-project/lotus#13483](https://github.com/filecoin-project/lotus/pull/13483))
# Node v1.34.3 / 2025-12-03

View File

@@ -897,4 +897,28 @@ func TestTraceFilter(t *testing.T) {
traces, err = client.EthTraceFilter(ctx, filter)
require.NoError(t, err)
require.Len(t, traces, 3) // still the same traces as before
// Query ONLY the null round epochs - should return empty array [], not null
// Get the current block number via Eth API
currentBlock, err := client.EthBlockNumber(ctx)
require.NoError(t, err)
// The 2 null rounds are at currentBlock-2 and currentBlock-1
// (currentBlock is the first block mined after the nulls, then we waited for one more)
// With InjectNulls(2), the next block has 2 nulls before it, so:
// - currentBlock-2 = first null round
// - currentBlock-1 = second null round
// - currentBlock = first real block after nulls
nullStartNum := uint64(currentBlock) - 2
nullEndNum := uint64(currentBlock) - 1
nullStart := fmt.Sprintf("0x%x", nullStartNum)
nullEnd := fmt.Sprintf("0x%x", nullEndNum)
t.Logf("Testing null round range: %s to %s (block numbers %d to %d, current %d)", nullStart, nullEnd, nullStartNum, nullEndNum, currentBlock)
filter = ethtypes.EthTraceFilterCriteria{
FromBlock: &nullStart,
ToBlock: &nullEnd,
}
nullRoundTraces, err := client.EthTraceFilter(ctx, filter)
require.NoError(t, err)
require.NotNil(t, nullRoundTraces, "trace_filter should return [] not null for all-null-round ranges")
require.Empty(t, nullRoundTraces)
}

View File

@@ -278,7 +278,7 @@ func (e *ethTrace) EthTraceFilter(ctx context.Context, filter ethtypes.EthTraceF
return nil, xerrors.Errorf("cannot parse toBlock: %w", err)
}
var results []*ethtypes.EthTraceFilterResult
results := []*ethtypes.EthTraceFilterResult{}
if filter.Count != nil {
// If filter.Count is specified and it is 0, return an empty result set immediately.