Skip to content
This repository was archived by the owner on Jan 16, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion crates/node/engine/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl EngineQueries {
// safe head on the L1.
if state.sync_state.unsafe_head().block_info.hash == B256::ZERO {
let forkchoice_state =
L2ForkchoiceState::current(rollup_config, client.l2_provider()).await?;
L2ForkchoiceState::current(rollup_config, client.l2_engine()).await?;
state.sync_state = EngineSyncState::new(
forkchoice_state.un_safe,
forkchoice_state.un_safe,
Expand Down
26 changes: 18 additions & 8 deletions crates/node/service/src/actors/sequencer/actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use op_alloy_network::Optimism;
use op_alloy_rpc_types_engine::OpExecutionPayloadEnvelope;
use std::{
sync::Arc,
time::{Duration, Instant},
time::{Duration, Instant, SystemTime, UNIX_EPOCH},
};
use tokio::{
select,
Expand Down Expand Up @@ -45,6 +45,8 @@ pub(super) struct SequencerActorState<AB: AttributesBuilder> {
pub builder: AB,
/// The [`L1OriginSelector`].
pub origin_selector: L1OriginSelector<DelayedL1OriginSelectorProvider>,
/// The ticker for building new blocks.
pub build_ticker: tokio::time::Interval,
/// The conductor RPC client.
pub conductor: Option<ConductorClient>,
/// Whether the sequencer is active. This is used inside communications between the sequencer
Expand Down Expand Up @@ -90,13 +92,15 @@ impl SequencerActorState<StatefulAttributesBuilder<AlloyChainProvider, AlloyL2Ch
let conductor = conductor_rpc_url.map(ConductorClient::new_http);

let builder = seq_builder.build();
let build_ticker = tokio::time::interval(Duration::from_secs(cfg.block_time));

let origin_selector = L1OriginSelector::new(cfg.clone(), l1_provider);

Self {
cfg,
builder,
origin_selector,
build_ticker,
conductor,
is_active: !sequencer_stopped,
is_recovery_mode: sequencer_recovery_mode,
Expand Down Expand Up @@ -365,6 +369,17 @@ impl<AB: AttributesBuilder> SequencerActorState<AB> {
);
}

let now =
SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards").as_secs();
let then = payload.execution_payload.timestamp() + self.cfg.block_time;
if then.saturating_sub(now) <= self.cfg.block_time {
warn!(
target: "sequencer",
"Next block timestamp is more than a block time away from now, building immediately"
);
self.build_ticker.reset_immediately();
}

self.schedule_gossip(ctx, payload).await
}

Expand Down Expand Up @@ -448,9 +463,6 @@ impl NodeActor for SequencerActor<SequencerBuilder> {
}

async fn start(mut self, mut ctx: Self::OutboundData) -> Result<(), Self::Error> {
let block_time = self.builder.rollup_cfg.block_time;
let mut build_ticker = tokio::time::interval(Duration::from_secs(block_time));

let mut state = SequencerActorState::new(self.builder, ctx.l1_head_rx.clone());

// Initialize metrics, if configured.
Expand Down Expand Up @@ -482,17 +494,15 @@ impl NodeActor for SequencerActor<SequencerBuilder> {

// Reset the build ticker if the sequencer's activity state has changed.
if is_sequencer_active != state.is_active {
build_ticker = tokio::time::interval(Duration::from_secs(
block_time,
));
state.build_ticker.reset_immediately();
}

// Update metrics, if configured.
#[cfg(feature = "metrics")]
state.update_metrics();
}
// The sequencer must be active to build new blocks.
_ = build_ticker.tick(), if state.is_active => {
_ = state.build_ticker.tick(), if state.is_active => {
state.build_block(&mut ctx, &mut self.unsafe_head_rx, state.is_recovery_mode).await?;
}
}
Expand Down