Correctness engineering

A local Ethereum cache must understand canonical state

Latency is easy to improve if stale or orphaned results are acceptable. Production RPC caching is harder: every reusable result needs a block context and an invalidation policy.

Block-aware cache keys

RPC Relay combines the method and parameters with a scope, block number, and observed block hash. Static metadata, explicit historical reads, finalized reads, safe reads, and latest-state reads are treated differently.

eth_getBalance:[address,"latest"]:block=25584564:hash=0x32bd…:scope=latest

Safe-head validation

Two independent upstreams may report different moving safe tips without either being wrong. The validator chooses the lower shared safe height, fetches that exact block from both providers, and compares the hashes. It does not mistake different tip timing for a reorg.

Reorg detection

A same-height block with a different hash is a replacement. A consecutive next block whose parent does not equal the previous hash breaks the canonical link. A multi-block forward jump is not automatically a reorg because the new block’s parent naturally is not the much older cached head.

Invalidation and fallback

Volatile

Latest and safe entries are invalidated when the canonical relationship changes.

Finalized

Entries at or below the configured finalized boundary survive volatile invalidation.

Stale-if-error

Finalized/static data can outlive provider failure; volatile stale data has a tight bounded window.

RPC Relay currently defines its local finalized boundary 64 blocks behind the multi-upstream validated safe head. This is a product policy, not a universal Ethereum finality definition.

What operators should monitor

Reorg count, invalidated entries, safe-head validation failures, observed head, canonical safe head, stale responses, provider failures, and fallback usage should all be visible. RPC Relay exposes these through localhost health, metrics, and diagnostic endpoints.