You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently the tester only runs against the last --num-blocks (default 32) from tip and covers block/tx/receipt retrieval, getLogs, trace_block, and debug_traceTransaction with callTracer. This is a good smoke test of the read path near tip, but it misses several dimensions where clients actually diverge: historical state, EVM execution on historical state, deeper tracing, and error-path parity. Below is a list of proposed additions, roughly by priority.
1. Historical sampling mode
Everything runs against recently-cached, near-tip state. Bugs in static files, pruned history, tx/receipt index rebuilding, and pre-fork-era encodings are invisible.
Add a --historical mode that samples blocks at log-spaced offsets from head (head-128, head-1k, head-10k, head-100k, head-1M, capped at genesis) plus a few uniform-random blocks, and runs the existing per-block suite there. Log-spacing is cheap and crosses cache/static-file/db boundaries.
Support a pinned corpus of "interesting" blocks per chain (e.g. fork transition blocks, the merge block, first 4844 block, first 7702 tx, empty blocks, blocks with uncles, one block per tx type). Deterministic and catches encoding edge cases random sampling misses. Could be a simple --blocks <list|file> flag.
2. State methods
Only eth_getBalance and eth_getTransactionCount (for tx senders) are covered today.
eth_getCode and eth_getStorageAt for addresses derived from receipt logs at that block
eth_getProof at historical blocks — the single best archive-correctness probe
3. Execution methods
No EVM execution is exercised at all.
Replay a block's own transactions as eth_call at the parent block and diff the results — classic archive-node differential test, inputs are free
eth_estimateGas / eth_createAccessList on the same synthesized calls
Optionally eth_simulateV1 for a block's tx list
4. Deeper tracing
Only callTracer and parity trace_block today. callTracer is the least sensitive tracer.
debug_traceBlockByNumber / debug_traceBlockByHash — also cross-checks block-level vs tx-level tracing consistency
prestateTracer — surfaces state-read divergence that callTracer hides
Default structlog tracer on a small sample of txs (expensive, but the strongest differ)
trace_replayBlockTransactions with stateDiff
trace_filter over the block range — the range-indexed counterpart to getLogs and historically a rich source of client bugs
5. Error/miss-path parity
All queries use data known to exist. Clients diverge a lot on the miss path (null vs error, error codes per EIP-1474).
Nonexistent tx hash, future block number, out-of-range tx index — assert both sides return the same null/error shape
A few invalid-params calls asserting matching error codes
6. getLogs improvements
Multi-topic filters (topic1-3, OR lists) and blockHash-based filters
Surface when the "max results exceeded" pagination fired on only one side. The retry helper transparently paginates per node, so a server-side ordering/limit bug can be laundered into a passing comparison of client-side concatenations.
7. Block ID/tag coverage
Only numeric block IDs are used.
earliest (exercises genesis retrieval)
safe / finalized comparison when both nodes share a CL view
Block-hash BlockId with requireCanonical
8. Misc cheap additions
eth_feeHistory over a historical range (fully deterministic)
eth_getUncleByBlockHashAndIndex (the count is already fetched)
Filter APIs (eth_newFilter / eth_getFilterLogs) if the stateful surface matters
9. Structural improvements
Smarter default tx sampling: instead of the first tx per block (disproportionately the same searcher on mainnet), sample one tx per type present in the block (legacy/2930/1559/4844/7702). Better coverage than --use-all-txes at a fraction of the cost.
Reorg guard: fetch_block treats rpc2 as truth with no canonical-agreement check, so a tip reorg mid-run diffs everything downstream with a confusing report. Re-fetch by hash from both sides and skip/retry on mismatch.
wait_for_readiness underflows on young chains (common - (block_size_range - 1)) and re-parses CliArgs internally.
The rpc!/rpc_raw! macros make most of the method additions one-liners, and the historical mode is essentially calling run() with additional ranges.
Currently the tester only runs against the last
--num-blocks(default 32) from tip and covers block/tx/receipt retrieval,getLogs,trace_block, anddebug_traceTransactionwith callTracer. This is a good smoke test of the read path near tip, but it misses several dimensions where clients actually diverge: historical state, EVM execution on historical state, deeper tracing, and error-path parity. Below is a list of proposed additions, roughly by priority.1. Historical sampling mode
Everything runs against recently-cached, near-tip state. Bugs in static files, pruned history, tx/receipt index rebuilding, and pre-fork-era encodings are invisible.
--historicalmode that samples blocks at log-spaced offsets from head (head-128,head-1k,head-10k,head-100k,head-1M, capped at genesis) plus a few uniform-random blocks, and runs the existing per-block suite there. Log-spacing is cheap and crosses cache/static-file/db boundaries.--blocks <list|file>flag.2. State methods
Only
eth_getBalanceandeth_getTransactionCount(for tx senders) are covered today.eth_getCodeandeth_getStorageAtfor addresses derived from receipt logs at that blocketh_getProofat historical blocks — the single best archive-correctness probe3. Execution methods
No EVM execution is exercised at all.
eth_callat the parent block and diff the results — classic archive-node differential test, inputs are freeeth_estimateGas/eth_createAccessListon the same synthesized callseth_simulateV1for a block's tx list4. Deeper tracing
Only callTracer and parity
trace_blocktoday. callTracer is the least sensitive tracer.debug_traceBlockByNumber/debug_traceBlockByHash— also cross-checks block-level vs tx-level tracing consistencytrace_replayBlockTransactionswithstateDifftrace_filterover the block range — the range-indexed counterpart togetLogsand historically a rich source of client bugs5. Error/miss-path parity
All queries use data known to exist. Clients diverge a lot on the miss path (null vs error, error codes per EIP-1474).
6. getLogs improvements
blockHash-based filters7. Block ID/tag coverage
Only numeric block IDs are used.
earliest(exercises genesis retrieval)safe/finalizedcomparison when both nodes share a CL viewBlockIdwithrequireCanonical8. Misc cheap additions
eth_feeHistoryover a historical range (fully deterministic)eth_getUncleByBlockHashAndIndex(the count is already fetched)debug_getRawBlock/debug_getRawHeader/debug_getRawReceipts— raw-encoding parity catches bugs JSON normalization hideseth_chainIdsanity check at startupeth_newFilter/eth_getFilterLogs) if the stateful surface matters9. Structural improvements
--use-all-txesat a fraction of the cost.fetch_blocktreats rpc2 as truth with no canonical-agreement check, so a tip reorg mid-run diffs everything downstream with a confusing report. Re-fetch by hash from both sides and skip/retry on mismatch.wait_for_readinessunderflows on young chains (common - (block_size_range - 1)) and re-parsesCliArgsinternally.The
rpc!/rpc_raw!macros make most of the method additions one-liners, and the historical mode is essentially callingrun()with additional ranges.