@@ -1207,63 +1207,40 @@ impl<Env: Environment> Client<Env> {
12071207 . get ( & sender_chain_id)
12081208 . copied ( )
12091209 . unwrap_or ( BlockHeight :: ZERO ) ;
1210- let ( max_epoch, committees) = self . admin_committees ( ) . await ?;
1211-
1212- // Recursively collect all certificates we need, following
1213- // the chain of previous_message_blocks back to next_outbox_height.
1214- let mut certificates = BTreeMap :: new ( ) ;
1215- let mut current_height = height;
12161210
1217- // Stop if we've reached the height we've already processed.
1218- while current_height >= next_outbox_height {
1219- // Download the certificate for this height.
1220- let downloaded = self
1221- . requests_scheduler
1222- . download_certificates_by_heights (
1223- remote_node,
1224- sender_chain_id,
1225- vec ! [ current_height] ,
1226- )
1227- . await ?;
1228- let Some ( certificate) = downloaded. into_iter ( ) . next ( ) else {
1229- return Err ( chain_client:: Error :: CannotDownloadMissingSenderBlock {
1230- chain_id : sender_chain_id,
1231- height : current_height,
1232- } ) ;
1233- } ;
1211+ // Skip if we already have all certificates up to this height.
1212+ if height < next_outbox_height {
1213+ return Ok ( ( ) ) ;
1214+ }
12341215
1235- // Validate the certificate.
1236- Client :: < Env > :: check_certificate ( max_epoch, & committees, & certificate) ?
1237- . into_result ( ) ?;
1216+ let ( max_epoch, committees) = self . admin_committees ( ) . await ?;
12381217
1239- // Check if there's a previous message block to our chain.
1240- let block = certificate. block ( ) ;
1241- let next_height = block
1242- . body
1243- . previous_message_blocks
1244- . get ( & receiver_chain_id)
1245- . map ( |( _prev_hash, prev_height) | * prev_height) ;
1246-
1247- // Store this certificate.
1248- certificates. insert ( current_height, certificate) ;
1249-
1250- if let Some ( prev_height) = next_height {
1251- // Continue with the previous block.
1252- current_height = prev_height;
1253- } else {
1254- // No more dependencies.
1255- break ;
1256- }
1257- }
1218+ // Request the proxy to do the traversal and return the certificates
1219+ // in ascending height order, ready for processing.
1220+ let certificates = self
1221+ . requests_scheduler
1222+ . download_sender_certificates_for_receiver (
1223+ remote_node,
1224+ sender_chain_id,
1225+ receiver_chain_id,
1226+ height,
1227+ next_outbox_height,
1228+ )
1229+ . await ?;
12581230
12591231 if certificates. is_empty ( ) {
12601232 self . local_node
12611233 . retry_pending_cross_chain_requests ( sender_chain_id)
12621234 . await ?;
1235+ return Ok ( ( ) ) ;
12631236 }
12641237
1265- // Process certificates in ascending block height order (BTreeMap keeps them sorted).
1266- for certificate in certificates. into_values ( ) {
1238+ // Process certificates in ascending block height order (already sorted by proxy).
1239+ for certificate in certificates {
1240+ // Validate the certificate.
1241+ Client :: < Env > :: check_certificate ( max_epoch, & committees, & certificate) ?
1242+ . into_result ( ) ?;
1243+
12671244 self . receive_sender_certificate (
12681245 certificate,
12691246 ReceiveCertificateMode :: AlreadyChecked ,
0 commit comments