@@ -1849,100 +1849,39 @@ async fn test_batch_commit_gap() -> eyre::Result<()> {
18491849
18501850// Test that the chain orchestrator detects gaps in L1 messages, triggers a reset command to the
18511851// L1 watcher for self-healing and skips duplicate L1 messages received.
1852- // #[tokio::test]
1853- // async fn test_l1_message_gap() -> eyre::Result<()> {
1854- // reth_tracing::init_test_tracing();
1855- //
1856- // let (mut nodes, _tasks, _wallet) = setup_engine(
1857- // default_test_scroll_rollup_node_config(),
1858- // 1,
1859- // (*SCROLL_DEV).clone(),
1860- // false,
1861- // false,
1862- // )
1863- // .await?;
1864- // let node = nodes.pop().unwrap();
1865- //
1866- // // Get handles for sending L1 notifications and receiving commands
1867- // let l1_watcher_tx = node.inner.add_ons_handle.l1_watcher_tx.clone().unwrap();
1868- // let l1_watcher_command_rx = node.inner.add_ons_handle.l1_watcher_command_rx.clone();
1869- // let chain_orchestrator = node.inner.add_ons_handle.rollup_manager_handle.clone();
1870- //
1871- // // Get event listener to monitor chain orchestrator events
1872- // let mut events = chain_orchestrator.get_event_listener().await?;
1873- //
1874- // // Node is unsynced initially -> does not derive batches (which is what we want)
1875- //
1876- // // Send L1 message 1 to populate the database
1877- // let l1_message_0 = TxL1Message { queue_index: 0, ..Default::default() };
1878- // let l1_message_0_block_info = BlockInfo { number: 1, hash: B256::random() };
1879- // l1_watcher_tx
1880- // .send(Arc::new(L1Notification::L1Message {
1881- // message: l1_message_0.clone(),
1882- // block_info: l1_message_0_block_info,
1883- // block_timestamp: 0,
1884- // }))
1885- // .await?;
1886- // wait_for_event_5s(
1887- // &mut events,
1888- // ChainOrchestratorEvent::L1MessageCommitted(l1_message_0.queue_index),
1889- // )
1890- // .await?;
1891- //
1892- // // Send duplicate L1 message 0 - should be skipped and duplicate detected
1893- // l1_watcher_tx
1894- // .send(Arc::new(L1Notification::L1Message {
1895- // message: l1_message_0.clone(),
1896- // block_info: l1_message_0_block_info,
1897- // block_timestamp: 0,
1898- // }))
1899- // .await?;
1900- // wait_for_event_5s(
1901- // &mut events,
1902- // ChainOrchestratorEvent::L1MessageDuplicate(l1_message_0.queue_index),
1903- // )
1904- // .await?;
1905- //
1906- // // Send L1 message 2 - should trigger reset due to gap (missing L1 message 1)
1907- // let l1_message_3 = TxL1Message {
1908- // queue_index: 2, // Gap! Missing index 2
1909- // ..Default::default()
1910- // };
1911- // let l1_message_3_block_info = BlockInfo { number: 3, hash: B256::random() };
1912- // l1_watcher_tx
1913- // .send(Arc::new(L1Notification::L1Message {
1914- // message: l1_message_3.clone(),
1915- // block_info: l1_message_3_block_info,
1916- // block_timestamp: 0,
1917- // }))
1918- // .await?;
1919- // wait_for_event_5s(
1920- // &mut events,
1921- // ChainOrchestratorEvent::L1MessageGap {
1922- // missing_index: l1_message_3.queue_index,
1923- // l1_block_number_reset: l1_message_0_block_info.number,
1924- // },
1925- // )
1926- // .await?;
1927- //
1928- // let mut command_rx = l1_watcher_command_rx.lock().await;
1929- // let command = tokio::time::timeout(Duration::from_secs(5), command_rx.recv())
1930- // .await
1931- // .expect("should receive command within timeout")
1932- // .expect("should receive Some(command)");
1933- //
1934- // // Verify it's a ResetToBlock command with the correct block number
1935- // match command {
1936- // L1WatcherCommand::ResetToBlock { block, .. } => {
1937- // assert_eq!(
1938- // block, l1_message_0_block_info.number,
1939- // "Reset block should be the L1 block of the last known L1 message"
1940- // );
1941- // }
1942- // }
1943- //
1944- // Ok(())
1945- // }
1852+ #[ tokio:: test]
1853+ async fn test_l1_message_gap ( ) -> eyre:: Result < ( ) > {
1854+ reth_tracing:: init_test_tracing ( ) ;
1855+
1856+ let mut fixture = TestFixture :: builder ( ) . sequencer ( ) . build ( ) . await ?;
1857+
1858+ // Node is unsynced initially -> does not derive batches (which is what we want)
1859+
1860+ let to_address = Address :: random ( ) ;
1861+ let sender = Address :: random ( ) ;
1862+ // Send L1 message 0 to populate the database
1863+ fixture. l1 ( ) . add_message ( ) . queue_index ( 0 ) . to ( to_address) . sender ( sender) . at_block ( 1 ) . send ( ) . await ?;
1864+ fixture. expect_event ( ) . l1_message_committed ( ) . await ?;
1865+
1866+ // Send duplicate L1 message 0 - should be skipped and duplicate detected
1867+ fixture. l1 ( ) . add_message ( ) . queue_index ( 0 ) . to ( to_address) . sender ( sender) . at_block ( 1 ) . send ( ) . await ?;
1868+ fixture. expect_event ( ) . l1_message_duplicate ( 0 ) . await ?;
1869+
1870+ // Send L1 message 2 - should trigger reset due to gap (missing L1 message 1)
1871+ fixture. l1 ( ) . add_message ( ) . queue_index ( 2 ) . at_block ( 3 ) . send ( ) . await ?;
1872+ // Expect gap event: missing index 2, reset to L1 block 1 (where message 0 was committed)
1873+ fixture. expect_event ( ) . l1_message_gap ( 2 , 1 ) . await ?;
1874+
1875+ // Verify that a ResetToBlock command was sent to the L1 watcher
1876+ let command = fixture. expect_l1_watcher_command ( ) . await ?;
1877+ match command {
1878+ rollup_node_watcher:: L1WatcherCommand :: ResetToBlock { block, .. } => {
1879+ assert_eq ! ( block, 1 , "Reset block should be the L1 block of the last known L1 message" ) ;
1880+ }
1881+ }
1882+
1883+ Ok ( ( ) )
1884+ }
19461885
19471886// #[tokio::test]
19481887// async fn test_batch_revert_gap() -> eyre::Result<()> {
0 commit comments