@@ -20,7 +20,7 @@ use rollup_node_primitives::{
2020use rollup_node_providers:: L1MessageProvider ;
2121use rollup_node_sequencer:: { Sequencer , SequencerEvent } ;
2222use rollup_node_signer:: { SignatureAsBytes , SignerEvent , SignerHandle } ;
23- use rollup_node_watcher:: L1Notification ;
23+ use rollup_node_watcher:: { L1Notification , L1WatcherHandle } ;
2424use scroll_alloy_consensus:: { ScrollTxEnvelope , TxL1Message } ;
2525use scroll_alloy_hardforks:: ScrollHardforks ;
2626use scroll_alloy_network:: Scroll ;
@@ -35,7 +35,7 @@ use scroll_network::{
3535 BlockImportOutcome , NewBlockWithPeer , ScrollNetwork , ScrollNetworkManagerEvent ,
3636} ;
3737use std:: { collections:: VecDeque , sync:: Arc , time:: Instant , vec} ;
38- use tokio:: sync:: mpsc:: { self , Receiver , UnboundedReceiver } ;
38+ use tokio:: sync:: mpsc:: { self , UnboundedReceiver } ;
3939
4040mod config;
4141pub use config:: ChainOrchestratorConfig ;
@@ -115,8 +115,8 @@ pub struct ChainOrchestrator<
115115 database : Arc < Database > ,
116116 /// The current sync state of the [`ChainOrchestrator`].
117117 sync_state : SyncState ,
118- /// A receiver for [`L1Notification`]s from the [`rollup_node_watcher::L1Watcher`].
119- l1_notification_rx : Receiver < Arc < L1Notification > > ,
118+ /// A handle for the [`rollup_node_watcher::L1Watcher`].
119+ l1_watcher : L1WatcherHandle ,
120120 /// The network manager that manages the scroll p2p network.
121121 network : ScrollNetwork < N > ,
122122 /// The consensus algorithm used by the rollup node.
@@ -150,7 +150,7 @@ impl<
150150 config : ChainOrchestratorConfig < ChainSpec > ,
151151 block_client : Arc < FullBlockClient < <N as BlockDownloaderProvider >:: Client > > ,
152152 l2_provider : L2P ,
153- l1_notification_rx : Receiver < Arc < L1Notification > > ,
153+ l1_watcher : L1WatcherHandle ,
154154 network : ScrollNetwork < N > ,
155155 consensus : Box < dyn Consensus + ' static > ,
156156 engine : Engine < EC > ,
@@ -167,7 +167,7 @@ impl<
167167 database,
168168 config,
169169 sync_state : SyncState :: default ( ) ,
170- l1_notification_rx ,
170+ l1_watcher ,
171171 network,
172172 consensus,
173173 engine,
@@ -224,7 +224,7 @@ impl<
224224 let res = self . handle_network_event( event) . await ;
225225 self . handle_outcome( res) ;
226226 }
227- Some ( notification) = self . l1_notification_rx . recv( ) , if self . sync_state. l2( ) . is_synced( ) && self . derivation_pipeline. is_empty( ) => {
227+ Some ( notification) = self . l1_watcher . l1_notification_receiver ( ) . recv( ) , if self . sync_state. l2( ) . is_synced( ) && self . derivation_pipeline. is_empty( ) => {
228228 let res = self . handle_l1_notification( notification) . await ;
229229 self . handle_outcome( res) ;
230230 }
@@ -401,6 +401,30 @@ impl<
401401 let _ = sender. send ( l1_message) ;
402402 }
403403 } ,
404+ ChainOrchestratorCommand :: RevertToL1Block ( ( block_number, tx) ) => {
405+ self . sync_state . l1_mut ( ) . set_syncing ( ) ;
406+ let unwind_result = self . database . unwind ( block_number) . await ?;
407+
408+ // Check if the unwind impacts the fcs safe head.
409+ if let Some ( block_info) = unwind_result. l2_safe_block_info {
410+ // If the new safe head is above the current finalized head, update the fcs safe
411+ // head to the new safe head.
412+ if block_info. number >= self . engine . fcs ( ) . finalized_block_info ( ) . number {
413+ self . engine . update_fcs ( None , Some ( block_info) , None ) . await ?;
414+ } else {
415+ // Otherwise, update the fcs safe head to the finalized head.
416+ self . engine
417+ . update_fcs ( None , Some ( * self . engine . fcs ( ) . finalized_block_info ( ) ) , None )
418+ . await ?;
419+ }
420+ }
421+
422+ // Revert the L1 watcher to the specified block.
423+ self . l1_watcher . revert_to_l1_block ( block_number) ;
424+
425+ self . notify ( ChainOrchestratorEvent :: UnwoundToL1Block ( block_number) ) ;
426+ let _ = tx. send ( true ) ;
427+ }
404428 #[ cfg( feature = "test-utils" ) ]
405429 ChainOrchestratorCommand :: SetGossip ( ( enabled, tx) ) => {
406430 self . network . handle ( ) . set_gossip ( enabled) . await ;
0 commit comments