rpc: prune-mode endpoint availability is largely untested (checkPruneHistory vs checkPruneBlocks)
RPCQA
### Context
#21965 reported that under `--prune.mode=blocks` the uncle endpoints rejected old blocks with `old data not available due to pruning`, even though all blocks were physically present. Root cause: they gated availability on `checkPruneHistory` (state-history prune boundary) instead of `checkPruneBlocks` (block-data boundary). Fixed by #21984 (main) and #22073 (release/3.5).
This was the second occurrence of the same defect class: `eth_block.go` and `eth_txs.go` had been migrated to `checkPruneBlocks` earlier, and the uncle endpoints were missed. #21984 shipped without a regression test, so nothing prevents a third occurrence.
### Current coverage
- **Unit tests**: only `eth_getBlockByNumber` has a gating test (`TestGetBlockByNumber_BlockPruneGating` in `rpc/jsonrpc/eth_block_test.go`), covering history-pruned-with-blocks-kept and minimal modes. There is no coverage for the six `checkPruneBlocks` sites in `eth_txs.go`, the four uncle endpoints that #21965 was actually about, or the `prune.BlocksMode` preset as such.
- **Wrong-helper risk**: `rpc/jsonrpc` currently has 48 `checkPruneHistory` call sites next to 15 `checkPruneBlocks` sites. Nothing pins which boundary each endpoint must use — a new endpoint that grabs the wrong helper ships silently, exactly how the uncle endpoints slipped through.
- **QA/CI**: no workflow asserts RPC availability against a pruned node. The RPC integration tests run against archive reference datadirs (`qa-rpc-integration-tests-remote` starts erigon with `--prune.mode=archive`), `qa-constrained-tip-tracking` uses `archive_node`, and the only pruned-mode run in the matrix (`qa-rpc-performance-comparison-tests`, `--prune.mode=minimal`) measures performance and asserts nothing about availability.
### Proposed work
1. Extend the `TestGetBlockByNumber_BlockPruneGating` pattern into a table-driven per-endpoint availability test over the named presets in `db/kv/prune/storage_mode.go` (`ArchiveMode`, `FullMode`, `BlocksMode`, `MinimalMode`): block-data endpoints (`eth_getBlockBy*`, `eth_getTransactionBy*`, `eth_getBlockTransactionCountBy*`, `eth_getUncle*`) must serve old blocks whenever blocks are retained, and state-requiring endpoints must return `state.PrunedError` outside the history window. The harness already exists (`execmoduletester.WithPruneMode`).
2. Audit the remaining `checkPruneHistory` call sites that serve block or receipt data rather than state (e.g. `otterscan_block_details.go`, `erigon_receipts.go`) and either migrate them to the correct boundary or document why history gating is genuinely required. Note that the receipts contract depends on persisted receipts vs re-execution, so it needs per-config care rather than a blanket rule.
3. Add a pruned-mode leg to the QA RPC integration tests (at least `--prune.mode=blocks`), or a post-sync availability check that asserts genesis and mid-history blocks are served in blocks mode. This is the level that would have caught #21965 before release, since the unit harness cannot exercise the snapshot/OtterSync path the report came through.
1 条评论