Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 11 additions & 19 deletions crates/node/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

use crate::{
ZoneEngine,
replication::{broadcast_persisted_blocks, import_leader_blocks},
replication::{broadcast_persisted_blocks, run_block_sync},
rpc::{ZoneRpc, ZoneRpcApi, rpc_connection_config, start_private_rpc},
};
use alloy_primitives::Address;
Expand Down Expand Up @@ -557,25 +557,17 @@ where
events,
} = handle.into_parts();

match role {
Role::Leader => {
task_executor.spawn_critical_task(
"zone-p2p-block-broadcast",
broadcast_persisted_blocks(provider, commands),
);
// Leaders do not receive block messages. Dropping this receiver is harmless: the
// runtime only emits BlockReceived on followers.
drop(events);
}
Role::Follower => {
// Keep the command sender alive so the runtime's command loop remains available
// for later ACK/backfill commands even though followers send nothing in this PR.
task_executor.spawn_critical_task(
"zone-p2p-block-import",
import_leader_blocks(provider, engine, events, commands),
);
}
if role == Role::Leader {
// Only a leader can build + broadcast blocks
task_executor.spawn_critical_task(
"zone-p2p-block-broadcast",
broadcast_persisted_blocks(provider.clone(), commands.clone()),
);
}
task_executor.spawn_critical_task(
"zone-p2p-block-sync",
run_block_sync(provider, engine, events, commands),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 [SECURITY] Leader backfill advances the execution head without reconciling ZoneEngine state

Spawning run_block_sync for leaders lets P2P imports advance the provider/EL head through the Reth engine handle, but that path cannot update ZoneEngine::last_header, DepositQueue, or the TIP-403 policy-cache baseline. A valid imported block can leave the sequencer believing it is still at the old parent, causing duplicate L1 reprocessing attempts, competing blocks, or persistent leader liveness failure.

Recommended Fix: Disable leader P2P import while ZoneEngine is active, run recovery before starting/seeding the sequencer state, or add an atomic reconciliation API that advances last_header, confirms queued L1 blocks, and updates the policy cache through imported history.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is TBD, leader backfill needs slightly different code, will be in a follow-up PR.

);

task_executor.spawn_critical_with_graceful_shutdown_signal(
"zone-p2p",
Expand Down
Loading
Loading