Why Multi-Client Differential Auditing Beats Single-Repo Code Review
Ethereum's upcoming Fusaka upgrade (combining the Osaka Execution Layer hardfork and Fulu Consensus Layer hardfork) introduces EIP-7594 (PeerDAS), EIP-7825 (Transaction Gas Limit Cap = 16,777,216), EIP-7883 (ModExp Gas Increase), and EIP-7934 (RLP Execution Block Size Limit).
When you read a single client in isolation, subtle deviations from the specification look intentional. When you compare all 7 Execution Layer clients (go-ethereum, reth, nethermind, besu, erigon, ethereumjs, ethrex) and all 7 Consensus Layer clients (lighthouse, prysm, teku, lodestar, nimbus-eth2, grandine, ethlambda) side by side against the official specification, discrepancies jump out immediately.
Case Study 1: engine_getBlobsV2 Pre-Osaka Error Code & Syncing Checks
According to execution-apis/src/engine/osaka.md#engine_getblobsv2:
- Clients MUST return
-38005: Unsupported forkif the head block timestamp has not reached Osaka. - Clients MUST return
nullwhen syncing. - Clients MUST operate in all-or-nothing mode: if any requested versioned hash is missing or belongs to a v0 sidecar without
128cell proofs, the entire response must benull.
By building a 7-client conformance matrix, we verified how each client handles > 128 hashes (-38004: Too large request), BlobSidecarVersion1 cell proof counts (CELLS_PER_EXT_BLOB = 128), and pre-Osaka fallback behavior.
Case Study 2: PeerDAS DataColumnSidecar Inclusion Proof & Custody Group Sorting
In specs/fulu/das-core.md:
-
get_custody_groups(node_id, custody_group_count)increments auint256counter modularly (UINT256_MAX -> 0), deduplicates group indices moduloNUMBER_OF_CUSTODY_GROUPS(128), and returnssorted(custody_groups). - Every
DataColumnSidecargossip message ondata_column_sidecar_{subnet_id}must verify both the depth-4 Merkle inclusion proof againstsigned_block_header.message.body_root(generalized index27) and the proposer signature before entering fork-choice data availability checks.
Differential matrices turn specification text into deterministic assertions across Go, Rust, C#, Java, Nim, and TypeScript.
Top comments (0)