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.
Short answers (checked October 2026):
- Where the code is. op-reth moved out of
paradigmxyz/rethin Feb 2026 (reth PR #21532). Source:ethereum-optimism/optimism/rust/op-reth. - Entry point.
bin/src/main.rs→launch_node(builder, OpNode::new(args)). - Composition.
crates/node/src/node.rs:impl NodeTypes for OpNode,impl<N> Node<N> for OpNode(components_builder()/add_ons()), andOpNode::components().
What OP swaps, from OpNode::components():
| Slot | OP builder | What changes vs Ethereum |
|---|---|---|
| pool | OpPoolBuilder | OP tx validation (L1 data fee, L1 block info from the deposit tx) |
| payload | OpPayloadServiceBuilder | Sequencer block building |
| network | OpNetworkBuilder | Optional tx gossip (disable_txpool_gossip) |
| executor | OpExecutorBuilder | OP EVM: deposit txs, L1 fee |
| consensus | OpConsensusBuilder | OP header/body validation rules |
| add-ons | OpAddOns | RPC: OP behavior on standard namespaces + OP Engine API |
Principle (minimum model)
- Project structure.
crates/node+crates/chainspec+crates/evm(+payload,consensus,txpool,rpc) underrust/op-reth/. 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. OP behavior on standard namespaces (sequencer tx forwarding, OP receipt fields, OP
engine_*payloads,miner_/debug_/admin_extensions).optimism_*(e.g.optimism_outputAtBlock) is served by the rollup node (op-node/kona), not op-reth. - NodeBuilder wiring.
main.rscallslaunch_node(builder, OpNode::new(args)); the composition lives incrates/node/src/node.rs(OpNode::components()+impl Node<N> for OpNode). - Tracks Reth upstream. Pins its
reth-*crates to a single git ref (an upstream reth tag or a tag on OP's reth fork) inrust/Cargo.toml; bumps it, runs the test suite, ships. - Production status. Optimism's docs call op-reth the OP Stack's primary supported execution client (op-geth reached end of support on 2026-05-31).
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 lived in paradigmxyz/reth/crates/optimism/ until Feb 2026 (reth PR #21532); it now lives at ethereum-optimism/optimism/rust/op-reth, consuming reth crates as dependencies. Tempo's node is public too, and it is shaped the same way. So that's the goal of this lesson: make the directory shape obvious.
1. Where to look
Browse: ethereum-optimism/optimism → rust/op-reth/crates/
You will see subcrates roughly along these lines (exact names drift across 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/ | OP behavior on standard namespaces (eth_, debug_, engine_, miner_, admin_) + sequencer tx forwarding |
txpool/ | OP-aware mempool validation (L1 data fee) |
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 from the rust/ workspace of the Optimism monorepo.
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 — and it held even when op-reth moved to a different repo.
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/src/node.rs(op-reth:crates/node/src/node.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 looks like
Tempo's node is public at tempoxyz/tempo. The crates that map onto the spine:
crates/chainspec— Tempo hardfork configuration and chain speccrates/node— the NodeBuilder compositioncrates/evm— EVM configcrates/precompiles— Tempo's precompiles (TIP-20 tokens, stablecoin DEX, fee manager, ...)crates/payload— block buildingcrates/transaction-pool— Tempo's mempoolcrates/consensus— its own L1 consensus (Tempo is an L1, so no L1-anchored finality)
Read it the same way you'd read op-reth's crates/.
6. Practice
Pick a Reth-based chain. Browse its repo. Build the table in §1 for that chain.
Candidates ranked by reading quality:
ethereum-optimism/optimism/rust/op-reth/(largest, most polished)tempoxyz/tempo(active Reth-based L1 — compare what an L1 swaps vs an L2)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, now at
ethereum-optimism/optimism/rust/op-reth. Custom pool / payload / network / executor / consensus + RPC add-ons;launch_node(builder, OpNode::new(args)). - Composition lives in
crates/node/src/node.rs; op-reth is the OP Stack's primary supported execution client. - Reading it teaches the extension pattern. Next: custom Chainspec.