Skip to content

feat: port erigontech/rpc-tests into block-aware compare configs#30

Open
kamilchodola wants to merge 2 commits into
mainfrom
feat/erigon-rpc-tests-import
Open

feat: port erigontech/rpc-tests into block-aware compare configs#30
kamilchodola wants to merge 2 commits into
mainfrom
feat/erigon-rpc-tests-import

Conversation

@kamilchodola

@kamilchodola kamilchodola commented Jul 24, 2026

Copy link
Copy Markdown

What

Ports the erigontech/rpc-tests corpus into json-bench compare configs — an importer plus generated mainnet configs.

compare is differential (each client's response is diffed against the others, not a golden file), so only the requests are ported. The value is coverage (100+ methods) and that every ported test is runnable on any synced node — no archive dependency.

Any-block normalization (the key)

Erigon's tests pin specific historical blocks (e.g. eth_getBalance @ block 17,000,000), answerable only by an archive node. The importer rewrites every test's block reference to a runnable target (latest by default):

  • block-number / block-tag args → target; eth_getLogs fromBlock/toBlock → target;
  • immutable fetch-by-hash (eth_getBlockByHash, eth_getTransactionByHash, receipts, …) kept as-is — any full node retains that data;
  • replay-by-hash (trace_transaction, debug_traceTransaction, debug_traceBlockByHash, ots_*Transaction, …) have no block arg to retarget and need archive replay → dropped (231, listed in the manifest).

Since compare hits all clients with the same request at once, latest is deterministic when they're parked at the same head; regenerate with --target-block <fixed> for moving-head/archive nodes.

Output

config calls notes
erigon-mainnet.yaml 577 core standard eth_/debug_ — compares cleanly cross-client
erigon-mainnet-divergent.yaml 337 non-standard namespaces / node-local / oracle — informational
erigon-mainnet-rules.yaml ignore totalDifficulty, error-code-only

914 runnable requests, all at latest.

Files

  • scripts/import_erigon_tests.py — the converter (block-arg map mirrors the comparator's blockArgIndex + eth_getLogs handling, extended).
  • scripts/import_erigon_tests.sh — clones rpc-tests at a pinned ref and regenerates.
  • config/compare/erigon/ — generated configs + rules + README.md + MANIFEST-mainnet.md.

Testing

  • Importer runs clean on the pinned corpus (214c137…): 914 runnable, 231 dropped (all hash-addressed replay, enumerated in the manifest).
  • Verified zero historical numeric blocks remain in core block-arg positions (eth_getBalance[addr, latest], eth_getBlockByNumber[latest, false], eth_getLogsfromBlock/toBlock: latest).
  • Generated configs + rules load in the compare runner end-to-end (parse OK; run proceeds to the RPC call — verified against an unreachable endpoint).
  • Not yet run against live multi-client nodes — follow-up is to point it at the same-block backups.

Notes

  • Importer needs python3 + pyyaml (dev-time only).
  • Provenance (source repo + commit) recorded in each config's description and the MANIFEST.

Adds an importer that converts the erigontech/rpc-tests corpus into json-bench
`compare` configs, plus the generated mainnet configs (1399 requests, 100+
methods).

compare is differential (client-vs-client, no golden file), so only the
requests are ported. The value is coverage and block-awareness: every request
is bucketed by what the target node must hold to answer it, so a run picks the
subset its node supports —

  stateless             chain-level, any node
  head                  latest/pending/safe/finalized, any synced node
  historical-immutable  numeric/hash block, block/tx/receipt/log/header/raw — full node
  historical-state      numeric/hash block, state (balance/code/call/trace) — ARCHIVE only
  divergent             erigon_/ots_/parity_/engine_/admin_/txpool_/trace_ + node-local — informational

A generated rules file (ignore totalDifficulty, error_code_only) damps benign
cross-client differences.

- scripts/import_erigon_tests.py — the converter (block-arg map mirrors the
  comparator's blockArgIndex + eth_getLogs handling, extended).
- scripts/import_erigon_tests.sh — clones rpc-tests at a pinned ref and regenerates.
- config/compare/erigon/ — generated mainnet configs + rules + README + MANIFEST.

Validated: generated configs load in the compare runner (clients + config +
rules parse; run proceeds to the RPC call).
…ndency)

Instead of preserving Erigon's pinned historical blocks and bucketing by node
capability (which left a large archive-only set), rewrite each test's block
reference to a runnable target (default 'latest'):

- block-number/tag args -> target; eth_getLogs fromBlock/toBlock -> target;
- immutable fetch-by-hash (getBlockByHash/getTransactionByHash/receipts) kept
  as-is (any full node retains it);
- replay-by-hash (trace_transaction, debug_traceTransaction,
  debug_traceBlockByHash, ots_*Transaction, …) have no block arg to retarget
  and need archive state -> dropped (231, listed in the manifest).

Buckets are now capability-free: erigon-<net>.yaml (core, cross-client-clean)
and erigon-<net>-divergent.yaml (informational). 914 runnable requests, all at
'latest'. Verified: zero historical numeric blocks remain in core block args;
configs load in the compare runner.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant