Lesson 18 — Reading op-stack-on-reth — the anatomy of a Reth-based L2
Question
op-stack-on-reth = the canonical Reth-based L2. Reading it teaches the Reth extension pattern.
Principle (minimum model)
- Project structure.
crates/optimism/node+crates/optimism/chainspec+crates/optimism/executor. Each is a customisation of a slot. - Custom Consensus. OP-specific block-validation rules. Replaces Reth's default.
- Custom Executor. OP-specific tx processing (including L1 fee).
- Custom Chainspec. OP-specific genesis + forks + hardforks.
- RPC extensions. OP-specific JSON-RPC methods (
optimism_outputAtBlocketc). - NodeBuilder wiring. ~30 lines in
main.rsthat ties everything together. - Tracks Reth upstream. Bumps Reth version; runs the test suite; ships.
- Production status. OP Mainnet + Base + Zora all run op-stack-on-reth.
Worked example + steps
Reading op-stack-on-reth — the anatomy of a Reth-based L2
Optimism is the canonical "Reth-based L2." Its node code lives at paradigmxyz/reth/crates/optimism/. If Tempo's node crate looked anything like this, you'd already know how to read it. So that's the goal of this lesson: make the directory shape obvious.
1. Where to look
Browse: paradigmxyz/reth → crates/optimism/
You will see subcrates roughly along these lines (exact names drift across reth versions — verify in source):
| Subdirectory | What it owns |
|---|---|
chainspec/ | OP chain spec — forks, genesis, gas params, precompile schedule |
node/ | The top-level NodeBuilder wiring — "this is what an OP node is" |
evm/ | EVM config — custom precompiles, deposit-tx semantics, L1 cost logic |
payload/ | Payload builder — block production in sequencer mode |
consensus/ | Consensus engine for OP (delegates finality to L1) |
rpc/ | Custom RPC namespaces (optimism_* methods) |
txpool/ (or similar) | Deposit-tx-aware mempool policy |
hardforks/ | Bedrock, Canyon, Ecotone, Fjord, ... fork activation logic |
Find-in-repo. Don't trust the table above blindly. Navigate the actual repo and make your own table. Versions move — your table is what matters.
2. The dependency shape
Run cargo tree -p reth-optimism-node (the exact crate name varies; locate it in the workspace).
What you'll see:
reth-optimism-nodedepends onreth-node-builder,reth-chainspec,reth-evm,reth-payload-builder,reth-rpc-builder,revm,alloy-*- It also depends on its OP-specific siblings:
reth-optimism-chainspec,reth-optimism-evm,reth-optimism-payload-builder, ... - It does not depend on
reth-node-ethereum— that's the parallel mainnet node crate
The pattern: a chain's node crate is siblings with the Ethereum node crate, both consuming the same shared reth-core crates. That's the extension model in dependency form.
3. The "spine" you should be able to find in 5 minutes
For any Reth-based chain, you should be able to locate these five things in under 5 minutes of repo navigation:
- NodeBuilder composition — where the chain says "I want these components." Usually in
*-node/src/lib.rsornode/builder.rs. - ChainSpec — the consensus rule type. Usually in
*-chainspec/src/. - Executor / EVM config — usually in
*-evm/src/. - Payload builder — usually in
*-payload-builder/src/or*-payload/src/. - Genesis JSON — sometimes inline in the chainspec crate, sometimes a separate
.json.
If you can find those, you can read the chain.
4. Reading order for a first pass
Recommended sequence when reading any Reth-based chain for the first time:
README.md+Cargo.tomlat the chain root — establish what crates existchainspec/— read the fork activation list out loudnode/— read the NodeBuilder composition; this tells you what's customized- Each customized component crate, in the order it was named in the NodeBuilder
- Tests — especially state-transition tests; they encode the actual behavioral commitments
By the end of step 3 you know what's different. Steps 4–5 are reading the how.
5. What Tempo will probably look like
Working hypothesis (until Paradigm publishes Tempo's node crate):
- A
tempo-chainspeccrate with Tempo's fork heights, gas params, payment-specific precompiles - A
tempo-nodecrate composing the NodeBuilder - A
tempo-evmcrate with custom precompiles for payment primitives (FX rate oracle? settlement-proof verify? regulated-asset check?) - A
tempo-payload-buildercrate for the sequencer - A
tempo-poolcrate for payment-specific mempool policy (e.g., merchant authorization) - Optional:
tempo-consensusif Tempo doesn't use vanilla L1-anchored finality (it's an L1, so almost certainly yes)
When this lands, you read it the same way you'd read crates/optimism/.
6. Practice
Pick a Reth-based chain. Browse its repo. Build the table in §1 for that chain.
Candidates ranked by reading quality:
paradigmxyz/reth/crates/optimism/(largest, most polished)paradigmxyz/alphanet(smaller, R&D-flavored — easier to read end-to-end)SovaNetwork/sova-reth(Bitcoin angle — different chainspec shape)
Final check: in two sentences, describe the shape of a Reth-based chain repo, in words that would let a new hire find anything in 10 minutes. If you start with "it has a folder," start over and lead with the concept (extension via traits + NodeBuilder composition).
Summary (3 lines)
- op-stack-on-reth = canonical Reth-based L2. Custom Consensus / Executor / Chainspec / RPC; ~30-line NodeBuilder wiring.
- Production: OP Mainnet + Base + Zora.
- Reading it teaches the extension pattern. Next: custom Chainspec.