Summary
morph-reth currently assembles the standard reth Ethereum network and staged-sync pipeline, so the execution layer can import blocks on its own over EL P2P. For a sequencer-driven L2 this is not the behavior we want: canonical L2 blocks should only enter the execution layer through the custom L2 Engine API (driven by the sequencer / derivation pipeline), or through an explicit, operator-initiated block-sync/import step. Automatic EL-driven block sync should not be a live path in normal operation.
Why this is a problem
The Morph node keeps its own Tendermint state and L1 message pointers alongside the execution layer, and CLAUDE.md already states that the EL must not be synced independently of the consensus node. If the EL can advance on its own via P2P, it can move ahead of the consensus node without the node processing those blocks, which breaks the EL/CL coupling the architecture depends on.
Current behavior
crates/node/src/node.rs:69-92 wires the components with .network(EthereumNetworkBuilder::default()), i.e. the full upstream reth network.
- The node is launched through the standard reth launcher in
bin/morph-reth/src/main.rs:137-155, which builds the networked staged pipeline (headers/bodies downloaders) rather than an Engine-only path.
- There is no Morph-side switch that disables EL block sync; the only Noop in the add-ons is
NoopEngineApiBuilder in crates/node/src/add_ons.rs:40-81, which replaces the standard Engine API because Morph registers its own, and has nothing to do with P2P.
crates/node/src/validator.rs:866-871 documents that the block-input path (P2P sync, pipeline backfill) is expected and must not stall, which confirms the path is live rather than disabled.
Runtime evidence that P2P block input actually works end to end: cargo nextest run -p morph-node --features test-utils -E 'test(dual_node_reorg)' passes dual_node_reorg::sibling_reorg_converges_state_pool_and_reference_index, where a second node receives blocks over the simulated P2P network, executes them, and converges state, pool and reference index after a sibling reorg.
Expected behavior
In normal node operation, canonical L2 blocks should reach the execution layer only via:
- the custom L2 Engine API (
engine_newL2Block, engine_newL2BlockV2, engine_newSafeL2Block), or
- an explicit, operator-invoked import / block-sync command.
Automatic EL P2P block download and staged-sync advancement should be off by default. Transaction gossip can remain a separate decision.
Requested change
- Add an explicit configuration for Morph nodes that prevents the EL from advancing the chain on its own (no automatic headers/bodies download driving canonical head), while keeping the Engine API import path intact.
- Make the intended sync model explicit in the node assembly rather than relying on the operator not having peers.
- Document which path is authoritative, and keep any manual import/block-sync capability behind an explicit opt-in.
- Add a regression test asserting that, without Engine API input, a node with peers does not advance its canonical head on its own.
Notes
This issue is about the sync model, not about a specific crash. Please treat the current state as "not disabled" rather than "actively used in production": Morph's production topology drives block import through the consensus node and Engine API, but nothing in morph-reth currently prevents EL-driven sync from taking over.
Summary
morph-rethcurrently assembles the standard reth Ethereum network and staged-sync pipeline, so the execution layer can import blocks on its own over EL P2P. For a sequencer-driven L2 this is not the behavior we want: canonical L2 blocks should only enter the execution layer through the custom L2 Engine API (driven by the sequencer / derivation pipeline), or through an explicit, operator-initiated block-sync/import step. Automatic EL-driven block sync should not be a live path in normal operation.Why this is a problem
The Morph node keeps its own Tendermint state and L1 message pointers alongside the execution layer, and
CLAUDE.mdalready states that the EL must not be synced independently of the consensus node. If the EL can advance on its own via P2P, it can move ahead of the consensus node without the node processing those blocks, which breaks the EL/CL coupling the architecture depends on.Current behavior
crates/node/src/node.rs:69-92wires the components with.network(EthereumNetworkBuilder::default()), i.e. the full upstream reth network.bin/morph-reth/src/main.rs:137-155, which builds the networked staged pipeline (headers/bodies downloaders) rather than an Engine-only path.NoopEngineApiBuilderincrates/node/src/add_ons.rs:40-81, which replaces the standard Engine API because Morph registers its own, and has nothing to do with P2P.crates/node/src/validator.rs:866-871documents that the block-input path (P2P sync, pipeline backfill) is expected and must not stall, which confirms the path is live rather than disabled.Runtime evidence that P2P block input actually works end to end:
cargo nextest run -p morph-node --features test-utils -E 'test(dual_node_reorg)'passesdual_node_reorg::sibling_reorg_converges_state_pool_and_reference_index, where a second node receives blocks over the simulated P2P network, executes them, and converges state, pool and reference index after a sibling reorg.Expected behavior
In normal node operation, canonical L2 blocks should reach the execution layer only via:
engine_newL2Block,engine_newL2BlockV2,engine_newSafeL2Block), orAutomatic EL P2P block download and staged-sync advancement should be off by default. Transaction gossip can remain a separate decision.
Requested change
Notes
This issue is about the sync model, not about a specific crash. Please treat the current state as "not disabled" rather than "actively used in production": Morph's production topology drives block import through the consensus node and Engine API, but nothing in
morph-rethcurrently prevents EL-driven sync from taking over.