@@ -36,7 +36,7 @@ use scroll_network::{
3636 BlockImportOutcome , NewBlockWithPeer , ScrollNetwork , ScrollNetworkManagerEvent ,
3737} ;
3838use std:: { collections:: VecDeque , sync:: Arc , time:: Instant , vec} ;
39- use tokio:: sync:: mpsc:: { self , Receiver , UnboundedReceiver } ;
39+ use tokio:: sync:: mpsc:: { self , UnboundedReceiver } ;
4040
4141mod config;
4242pub use config:: ChainOrchestratorConfig ;
@@ -110,8 +110,6 @@ pub struct ChainOrchestrator<
110110 database : Arc < Database > ,
111111 /// The current sync state of the [`ChainOrchestrator`].
112112 sync_state : SyncState ,
113- /// A receiver for [`L1Notification`]s from the [`rollup_node_watcher::L1Watcher`].
114- l1_notification_rx : Receiver < Arc < L1Notification > > ,
115113 /// Handle to send commands to the L1 watcher (e.g., for gap recovery).
116114 l1_watcher_handle : L1WatcherHandle ,
117115 /// The network manager that manages the scroll p2p network.
@@ -147,7 +145,6 @@ impl<
147145 config : ChainOrchestratorConfig < ChainSpec > ,
148146 block_client : Arc < FullBlockClient < <N as BlockDownloaderProvider >:: Client > > ,
149147 l2_provider : L2P ,
150- l1_notification_rx : Receiver < Arc < L1Notification > > ,
151148 l1_watcher_handle : L1WatcherHandle ,
152149 network : ScrollNetwork < N > ,
153150 consensus : Box < dyn Consensus + ' static > ,
@@ -165,7 +162,6 @@ impl<
165162 database,
166163 config,
167164 sync_state : SyncState :: default ( ) ,
168- l1_notification_rx,
169165 l1_watcher_handle,
170166 network,
171167 consensus,
@@ -223,7 +219,7 @@ impl<
223219 let res = self . handle_network_event( event) . await ;
224220 self . handle_outcome( res) ;
225221 }
226- Some ( notification) = self . l1_notification_rx . recv( ) , if self . sync_state. l2( ) . is_synced( ) && self . derivation_pipeline. is_empty( ) => {
222+ Some ( notification) = self . l1_watcher_handle . l1_notification_receiver ( ) . recv( ) , if self . sync_state. l2( ) . is_synced( ) && self . derivation_pipeline. is_empty( ) => {
227223 let res = self . handle_l1_notification( notification) . await ;
228224 self . handle_outcome( res) ;
229225 }
@@ -532,7 +528,6 @@ impl<
532528 // Query database for the L1 block of the last known batch
533529 let reset_block =
534530 self . database . get_last_batch_commit_l1_block ( ) . await ?. unwrap_or ( 0 ) ;
535- // TODO: handle None case (no batches in DB)
536531
537532 tracing:: warn!(
538533 target: "scroll::chain_orchestrator" ,
@@ -542,7 +537,7 @@ impl<
542537 ) ;
543538
544539 // Trigger gap recovery
545- self . trigger_gap_recovery ( reset_block, "batch commit gap" ) . await ? ;
540+ self . l1_watcher_handle . trigger_gap_recovery ( reset_block) . await ;
546541
547542 // Return no event, recovery will re-process
548543 Ok ( None )
@@ -569,7 +564,6 @@ impl<
569564 // Query database for the L1 block of the last known L1 message
570565 let reset_block =
571566 self . database . get_last_l1_message_l1_block ( ) . await ?. unwrap_or ( 0 ) ;
572- // TODO: handle None case (no messages in DB)
573567
574568 tracing:: warn!(
575569 target: "scroll::chain_orchestrator" ,
@@ -579,7 +573,7 @@ impl<
579573 ) ;
580574
581575 // Trigger gap recovery
582- self . trigger_gap_recovery ( reset_block, "L1 message queue gap" ) . await ? ;
576+ self . l1_watcher_handle . trigger_gap_recovery ( reset_block) . await ;
583577
584578 // Return no event, recovery will re-process
585579 Ok ( None )
@@ -881,47 +875,6 @@ impl<
881875 Ok ( Some ( event) )
882876 }
883877
884- /// Triggers gap recovery by resetting the L1 watcher to a specific block with a fresh channel.
885- ///
886- /// This method is called when a gap is detected in batch commits or L1 messages.
887- /// It will:
888- /// 1. Create a fresh notification channel
889- /// 2. Send a reset command to the L1 watcher with the new sender
890- /// 3. Replace the orchestrator's receiver with the new one
891- /// 4. The old channel and any stale notifications are automatically discarded
892- ///
893- /// # Arguments
894- /// * `reset_block` - The L1 block number to reset to (last known good state)
895- /// * `gap_type` - Description of the gap type for logging
896- async fn trigger_gap_recovery (
897- & mut self ,
898- reset_block : u64 ,
899- gap_type : & str ,
900- ) -> Result < ( ) , ChainOrchestratorError > {
901- // Create a fresh notification channel
902- // Use the same capacity as the original channel
903- let capacity = self . l1_notification_rx . max_capacity ( ) ;
904- let ( new_tx, new_rx) = mpsc:: channel ( capacity) ;
905-
906- // Send reset command with the new sender and wait for confirmation
907- self . l1_watcher_handle . reset_to_block ( reset_block, new_tx) . await . map_err ( |err| {
908- ChainOrchestratorError :: GapResetError ( format ! ( "Failed to reset L1 watcher: {:?}" , err) )
909- } ) ?;
910-
911- // Replace the receiver with the fresh channel
912- // The old channel is automatically dropped, discarding all stale notifications
913- self . l1_notification_rx = new_rx;
914-
915- tracing:: info!(
916- target: "scroll::chain_orchestrator" ,
917- "Gap recovery complete for {} at block {}, fresh channel established" ,
918- gap_type,
919- reset_block
920- ) ;
921-
922- Ok ( ( ) )
923- }
924-
925878 async fn handle_network_event (
926879 & mut self ,
927880 event : ScrollNetworkManagerEvent ,
0 commit comments