@@ -1128,8 +1128,9 @@ where
1128
1128
core:: mem:: take ( & mut self . pending_dns_onion_messages . lock ( ) . unwrap ( ) )
1129
1129
}
1130
1130
1131
- /// Sends out [`OfferPathsRequest`] onion messages if we are an often-offline recipient and are
1132
- /// configured to interactively build offers and static invoices with a static invoice server.
1131
+ /// Sends out [`OfferPathsRequest`] and [`ServeStaticInvoice`] onion messages if we are an
1132
+ /// often-offline recipient and are configured to interactively build offers and static invoices
1133
+ /// with a static invoice server.
1133
1134
///
1134
1135
/// # Usage
1135
1136
///
@@ -1141,9 +1142,14 @@ where
1141
1142
///
1142
1143
/// Errors if we failed to create blinded reply paths when sending an [`OfferPathsRequest`] message.
1143
1144
#[ cfg( async_payments) ]
1144
- pub ( crate ) fn check_refresh_async_receive_offers (
1145
- & self , peers : Vec < MessageForwardNode > , timer_tick_occurred : bool ,
1146
- ) -> Result < ( ) , ( ) > {
1145
+ pub ( crate ) fn check_refresh_async_receive_offers < ES : Deref , R : Deref > (
1146
+ & self , peers : Vec < MessageForwardNode > , usable_channels : Vec < ChannelDetails > , entropy : ES ,
1147
+ router : R , timer_tick_occurred : bool ,
1148
+ ) -> Result < ( ) , ( ) >
1149
+ where
1150
+ ES :: Target : EntropySource ,
1151
+ R :: Target : Router ,
1152
+ {
1147
1153
// Terminate early if this node does not intend to receive async payments.
1148
1154
if self . paths_to_static_invoice_server . is_empty ( ) {
1149
1155
return Ok ( ( ) ) ;
@@ -1165,7 +1171,7 @@ where
1165
1171
path_absolute_expiry : duration_since_epoch
1166
1172
. saturating_add ( TEMP_REPLY_PATH_RELATIVE_EXPIRY ) ,
1167
1173
} ) ;
1168
- let reply_paths = match self . create_blinded_paths ( peers, context) {
1174
+ let reply_paths = match self . create_blinded_paths ( peers. clone ( ) , context) {
1169
1175
Ok ( paths) => paths,
1170
1176
Err ( ( ) ) => {
1171
1177
return Err ( ( ) ) ;
@@ -1187,9 +1193,85 @@ where
1187
1193
) ;
1188
1194
}
1189
1195
1196
+ self . check_refresh_static_invoices ( peers, usable_channels, entropy, router) ;
1197
+
1190
1198
Ok ( ( ) )
1191
1199
}
1192
1200
1201
+ /// If a static invoice server has persisted an offer for us but the corresponding invoice is
1202
+ /// expiring soon, we need to refresh that invoice. Here we enqueue the onion messages that will
1203
+ /// be used to request invoice refresh, based on the offers provided by the cache.
1204
+ #[ cfg( async_payments) ]
1205
+ fn check_refresh_static_invoices < ES : Deref , R : Deref > (
1206
+ & self , peers : Vec < MessageForwardNode > , usable_channels : Vec < ChannelDetails > , entropy : ES ,
1207
+ router : R ,
1208
+ ) where
1209
+ ES :: Target : EntropySource ,
1210
+ R :: Target : Router ,
1211
+ {
1212
+ let duration_since_epoch = self . duration_since_epoch ( ) ;
1213
+
1214
+ let mut serve_static_invoice_messages = Vec :: new ( ) ;
1215
+ {
1216
+ let cache = self . async_receive_offer_cache . lock ( ) . unwrap ( ) ;
1217
+ for offer_and_metadata in cache. offers_needing_invoice_refresh ( duration_since_epoch) {
1218
+ let ( offer, offer_nonce, offer_created_at, update_static_invoice_path) =
1219
+ offer_and_metadata;
1220
+ let offer_id = offer. id ( ) ;
1221
+
1222
+ let ( serve_invoice_msg, reply_path_ctx) = match self
1223
+ . create_serve_static_invoice_message (
1224
+ offer. clone ( ) ,
1225
+ offer_nonce,
1226
+ offer_created_at,
1227
+ peers. clone ( ) ,
1228
+ usable_channels. clone ( ) ,
1229
+ update_static_invoice_path. clone ( ) ,
1230
+ & * entropy,
1231
+ & * router,
1232
+ ) {
1233
+ Ok ( ( msg, ctx) ) => ( msg, ctx) ,
1234
+ Err ( ( ) ) => continue ,
1235
+ } ;
1236
+ serve_static_invoice_messages. push ( (
1237
+ serve_invoice_msg,
1238
+ update_static_invoice_path. clone ( ) ,
1239
+ reply_path_ctx,
1240
+ offer_id,
1241
+ ) ) ;
1242
+ }
1243
+ }
1244
+
1245
+ // Enqueue the new serve_static_invoice messages in a separate loop to avoid holding the offer
1246
+ // cache lock and the pending_async_payments_messages lock at the same time.
1247
+ for ( serve_invoice_msg, serve_invoice_path, reply_path_ctx, offer_id) in
1248
+ serve_static_invoice_messages
1249
+ {
1250
+ let context = MessageContext :: AsyncPayments ( reply_path_ctx) ;
1251
+ let reply_paths = match self . create_blinded_paths ( peers. clone ( ) , context) {
1252
+ Ok ( paths) => paths,
1253
+ Err ( ( ) ) => continue ,
1254
+ } ;
1255
+
1256
+ {
1257
+ // We can't fail past this point, so indicate to the cache that we've requested an invoice
1258
+ // update.
1259
+ let mut cache = self . async_receive_offer_cache . lock ( ) . unwrap ( ) ;
1260
+ if cache. increment_invoice_update_attempts ( offer_id) . is_err ( ) {
1261
+ continue ;
1262
+ }
1263
+ }
1264
+
1265
+ let message = AsyncPaymentsMessage :: ServeStaticInvoice ( serve_invoice_msg) ;
1266
+ enqueue_onion_message_with_reply_paths (
1267
+ message,
1268
+ & [ serve_invoice_path. into_reply_path ( ) ] ,
1269
+ reply_paths,
1270
+ & mut self . pending_async_payments_messages . lock ( ) . unwrap ( ) ,
1271
+ ) ;
1272
+ }
1273
+ }
1274
+
1193
1275
/// Handles an incoming [`OfferPaths`] message from the static invoice server, sending out
1194
1276
/// [`ServeStaticInvoice`] onion messages in response if we want to use the paths we've received
1195
1277
/// to build and cache an async receive offer.
0 commit comments