@@ -1116,8 +1116,9 @@ where
11161116 core:: mem:: take ( & mut self . pending_dns_onion_messages . lock ( ) . unwrap ( ) )
11171117 }
11181118
1119- /// Sends out [`OfferPathsRequest`] onion messages if we are an often-offline recipient and are
1120- /// configured to interactively build offers and static invoices with a static invoice server.
1119+ /// Sends out [`OfferPathsRequest`] and [`ServeStaticInvoice`] onion messages if we are an
1120+ /// often-offline recipient and are configured to interactively build offers and static invoices
1121+ /// with a static invoice server.
11211122 ///
11221123 /// # Usage
11231124 ///
@@ -1126,11 +1127,13 @@ where
11261127 ///
11271128 /// Errors if we failed to create blinded reply paths when sending an [`OfferPathsRequest`] message.
11281129 #[ cfg( async_payments) ]
1129- pub ( crate ) fn check_refresh_async_receive_offers < ES : Deref > (
1130- & self , peers : Vec < MessageForwardNode > , entropy : ES ,
1130+ pub ( crate ) fn check_refresh_async_receive_offers < ES : Deref , R : Deref > (
1131+ & self , peers : Vec < MessageForwardNode > , usable_channels : Vec < ChannelDetails > , entropy : ES ,
1132+ router : R ,
11311133 ) -> Result < ( ) , ( ) >
11321134 where
11331135 ES :: Target : EntropySource ,
1136+ R :: Target : Router ,
11341137 {
11351138 // Terminate early if this node does not intend to receive async payments.
11361139 if self . paths_to_static_invoice_server . is_empty ( ) {
@@ -1157,7 +1160,7 @@ where
11571160 path_absolute_expiry : duration_since_epoch
11581161 . saturating_add ( TEMP_REPLY_PATH_RELATIVE_EXPIRY ) ,
11591162 } ) ;
1160- let reply_paths = match self . create_blinded_paths ( peers, context) {
1163+ let reply_paths = match self . create_blinded_paths ( peers. clone ( ) , context) {
11611164 Ok ( paths) => paths,
11621165 Err ( ( ) ) => {
11631166 return Err ( ( ) ) ;
@@ -1179,9 +1182,85 @@ where
11791182 ) ;
11801183 }
11811184
1185+ self . check_refresh_static_invoices ( peers, usable_channels, entropy, router) ;
1186+
11821187 Ok ( ( ) )
11831188 }
11841189
1190+ /// If a static invoice server has persisted an offer for us but the corresponding invoice is
1191+ /// expiring soon, we need to refresh that invoice. Here we enqueue the onion messages that will
1192+ /// be used to request invoice refresh, based on the offers provided by the cache.
1193+ #[ cfg( async_payments) ]
1194+ fn check_refresh_static_invoices < ES : Deref , R : Deref > (
1195+ & self , peers : Vec < MessageForwardNode > , usable_channels : Vec < ChannelDetails > , entropy : ES ,
1196+ router : R ,
1197+ ) where
1198+ ES :: Target : EntropySource ,
1199+ R :: Target : Router ,
1200+ {
1201+ let duration_since_epoch = self . duration_since_epoch ( ) ;
1202+
1203+ let mut serve_static_invoice_messages = Vec :: new ( ) ;
1204+ {
1205+ let cache = self . async_receive_offer_cache . lock ( ) . unwrap ( ) ;
1206+ for offer_and_metadata in cache. offers_needing_invoice_refresh ( duration_since_epoch) {
1207+ let ( offer, offer_nonce, offer_created_at, update_static_invoice_path) =
1208+ offer_and_metadata;
1209+ let offer_id = offer. id ( ) ;
1210+
1211+ let ( serve_invoice_msg, reply_path_ctx) = match self
1212+ . create_serve_static_invoice_message (
1213+ offer. clone ( ) ,
1214+ offer_nonce,
1215+ offer_created_at,
1216+ peers. clone ( ) ,
1217+ usable_channels. clone ( ) ,
1218+ update_static_invoice_path. clone ( ) ,
1219+ & * entropy,
1220+ & * router,
1221+ ) {
1222+ Ok ( ( msg, ctx) ) => ( msg, ctx) ,
1223+ Err ( ( ) ) => continue ,
1224+ } ;
1225+ serve_static_invoice_messages. push ( (
1226+ serve_invoice_msg,
1227+ update_static_invoice_path. clone ( ) ,
1228+ reply_path_ctx,
1229+ offer_id,
1230+ ) ) ;
1231+ }
1232+ }
1233+
1234+ // Enqueue the new serve_static_invoice messages in a separate loop to avoid holding the offer
1235+ // cache lock and the pending_async_payments_messages lock at the same time.
1236+ for ( serve_invoice_msg, serve_invoice_path, reply_path_ctx, offer_id) in
1237+ serve_static_invoice_messages
1238+ {
1239+ let context = MessageContext :: AsyncPayments ( reply_path_ctx) ;
1240+ let reply_paths = match self . create_blinded_paths ( peers. clone ( ) , context) {
1241+ Ok ( paths) => paths,
1242+ Err ( ( ) ) => continue ,
1243+ } ;
1244+
1245+ {
1246+ // We can't fail past this point, so indicate to the cache that we've requested an invoice
1247+ // update.
1248+ let mut cache = self . async_receive_offer_cache . lock ( ) . unwrap ( ) ;
1249+ if cache. increment_invoice_update_attempts ( offer_id) . is_err ( ) {
1250+ continue ;
1251+ }
1252+ }
1253+
1254+ let message = AsyncPaymentsMessage :: ServeStaticInvoice ( serve_invoice_msg) ;
1255+ enqueue_onion_message_with_reply_paths (
1256+ message,
1257+ & [ serve_invoice_path. into_reply_path ( ) ] ,
1258+ reply_paths,
1259+ & mut self . pending_async_payments_messages . lock ( ) . unwrap ( ) ,
1260+ ) ;
1261+ }
1262+ }
1263+
11851264 /// Handles an incoming [`OfferPaths`] message from the static invoice server, sending out
11861265 /// [`ServeStaticInvoice`] onion messages in response if we want to use the paths we've received
11871266 /// to build and cache an async receive offer.
0 commit comments