@@ -279,6 +279,39 @@ impl ExecutionBridge {
279279 }
280280 }
281281
282+ /// Restore the last block hash from storage on node restart.
283+ ///
284+ /// This MUST be called after node restart when blocks already exist in storage.
285+ /// It ensures that the next block's parent_hash correctly references the latest
286+ /// stored block's hash, maintaining proper chain connectivity.
287+ ///
288+ /// # Arguments
289+ ///
290+ /// * `latest_block_hash` - The hash of the latest block in storage
291+ ///
292+ /// # Note
293+ ///
294+ /// This method should be called AFTER `set_genesis_block_hash` during node
295+ /// initialization. If there are blocks beyond genesis in storage, this method
296+ /// should be called to update `last_block_hash` to the latest block's hash.
297+ pub fn restore_last_block_hash ( & self , latest_block_hash : B256 ) {
298+ match self . last_block_hash . write ( ) {
299+ Ok ( mut guard) => {
300+ * guard = latest_block_hash;
301+ info ! (
302+ latest_block_hash = %latest_block_hash,
303+ "Execution bridge restored last block hash from storage (node restart recovery)"
304+ ) ;
305+ }
306+ Err ( e) => {
307+ warn ! (
308+ error = %e,
309+ "Failed to restore last block hash - lock poisoned, next block may have incorrect parent_hash"
310+ ) ;
311+ }
312+ }
313+ }
314+
282315 /// Validate a transaction for mempool CheckTx
283316 ///
284317 /// This is called by workers before accepting transactions into batches.
@@ -830,4 +863,47 @@ mod tests {
830863
831864 assert_eq ! ( bridge. gas_limit( ) , 50_000_000 ) ;
832865 }
866+
867+ #[ tokio:: test]
868+ async fn test_restore_last_block_hash ( ) {
869+ let ( bridge, _temp_dir) = create_default_bridge ( ) . unwrap ( ) ;
870+
871+ // Initially should be B256::ZERO
872+ let initial_hash = bridge. last_block_hash . read ( ) . map ( |guard| * guard) . unwrap ( ) ;
873+ assert_eq ! ( initial_hash, B256 :: ZERO ) ;
874+
875+ // Restore to a specific block hash (simulating node restart recovery)
876+ let latest_block_hash = B256 :: from ( [ 0xABu8 ; 32 ] ) ;
877+ bridge. restore_last_block_hash ( latest_block_hash) ;
878+
879+ // Should now be updated to the restored hash
880+ let restored_hash = bridge. last_block_hash . read ( ) . map ( |guard| * guard) . unwrap ( ) ;
881+ assert_eq ! (
882+ restored_hash, latest_block_hash,
883+ "restore_last_block_hash should update last_block_hash to the latest block's hash"
884+ ) ;
885+ }
886+
887+ #[ tokio:: test]
888+ async fn test_restore_overrides_genesis_hash ( ) {
889+ let ( bridge, _temp_dir) = create_default_bridge ( ) . unwrap ( ) ;
890+
891+ // First set genesis hash (simulating initial node startup)
892+ let genesis_hash = B256 :: from ( [ 0x01u8 ; 32 ] ) ;
893+ bridge. set_genesis_block_hash ( genesis_hash) ;
894+
895+ let after_genesis = bridge. last_block_hash . read ( ) . map ( |guard| * guard) . unwrap ( ) ;
896+ assert_eq ! ( after_genesis, genesis_hash) ;
897+
898+ // Now restore to latest block hash (simulating node restart with existing blocks)
899+ let latest_block_hash = B256 :: from ( [ 0xFFu8 ; 32 ] ) ;
900+ bridge. restore_last_block_hash ( latest_block_hash) ;
901+
902+ // Should be updated to the latest, not genesis
903+ let after_restore = bridge. last_block_hash . read ( ) . map ( |guard| * guard) . unwrap ( ) ;
904+ assert_eq ! (
905+ after_restore, latest_block_hash,
906+ "restore_last_block_hash should override any previously set hash"
907+ ) ;
908+ }
833909}
0 commit comments