@@ -259,7 +259,7 @@ impl ScrollRollupNodeConfig {
259259 ForkchoiceState :: from_provider ( & l2_provider) . await . unwrap_or_else ( chain_spec_fcs) ;
260260
261261 let genesis_hash = chain_spec. genesis_hash ( ) ;
262- let ( l1_start_block_number, l2_head_block_number) = db
262+ let ( l1_start_block_number, mut l2_head_block_number) = db
263263 . tx_mut ( move |tx| async move {
264264 // On startup we replay the latest batch of blocks from the database as such we set
265265 // the safe block hash to the latest block hash associated with the
@@ -268,24 +268,42 @@ impl ScrollRollupNodeConfig {
268268 tx. prepare_on_startup ( genesis_hash) . await ?;
269269
270270 let l2_head_block_number = tx. get_l2_head_block_number ( ) . await ?;
271- tx. purge_l1_message_to_l2_block_mappings ( Some ( l2_head_block_number + 1 ) ) . await ?;
272271
273272 Ok :: < _ , DatabaseError > ( ( l1_start_block_number, l2_head_block_number) )
274273 } )
275274 . await ?;
276275
277- // Update the head block info if available and ahead of finalized.
278- if l2_head_block_number > fcs. finalized_block_info ( ) . number {
279- let block = l2_provider
276+ // Loop to find the latest block that we have in the EN and purge L1 message mappings to
277+ // account for the startup block
278+ //
279+ // This is necessary as there is an edge case in which the EN may not have persisted the
280+ // latest block.
281+ let finalized_block_number = fcs. finalized_block_info ( ) . number ;
282+ while l2_head_block_number > finalized_block_number {
283+ tracing:: info!( target: "scroll::node::args" , ?l2_head_block_number, "Checking for L2 head block in EN" ) ;
284+
285+ // Check if the block exists in the EN and update the forkchoice state and L2 head block
286+ // number
287+ if let Some ( block) = l2_provider
280288 . get_block ( l2_head_block_number. into ( ) )
281289 . full ( )
282290 . await ?
283- . expect ( "latest block from db should exist" )
284- . into_consensus ( )
285- . map_transactions ( |tx| tx. inner . into_inner ( ) ) ;
286- let block_info: BlockInfo = ( & block) . into ( ) ;
291+ . map ( |b| b. into_consensus ( ) . map_transactions ( |tx| tx. inner . into_inner ( ) ) )
292+ {
293+ tracing:: info!( target: "scroll::node::args" , ?l2_head_block_number, "Found L2 head block in EN" ) ;
294+ let block_info: BlockInfo = ( & block) . into ( ) ;
295+ fcs. update ( Some ( block_info) , None , None ) ?;
296+ db. tx_mut ( move |tx| async move {
297+ tx. set_l2_head_block_number ( l2_head_block_number) . await ?;
298+ tx. purge_l1_message_to_l2_block_mappings ( Some ( l2_head_block_number + 1 ) ) . await
299+ } )
300+ . await ?;
301+ break ;
302+ }
287303
288- fcs. update ( Some ( block_info) , None , None ) ?;
304+ // Decrement the L2 head block number and try again
305+ tracing:: info!( target: "scroll::node::args" , ?l2_head_block_number, "L2 head block not found in EN, decrementing" ) ;
306+ l2_head_block_number -= 1 ;
289307 }
290308
291309 let chain_spec = Arc :: new ( chain_spec. clone ( ) ) ;
0 commit comments