@@ -1115,8 +1115,9 @@ where
1115
1115
core:: mem:: take ( & mut self . pending_dns_onion_messages . lock ( ) . unwrap ( ) )
1116
1116
}
1117
1117
1118
- /// Sends out [`OfferPathsRequest`] onion messages if we are an often-offline recipient and are
1119
- /// configured to interactively build offers and static invoices with a static invoice server.
1118
+ /// Sends out [`OfferPathsRequest`] and [`ServeStaticInvoice`] onion messages if we are an
1119
+ /// often-offline recipient and are configured to interactively build offers and static invoices
1120
+ /// with a static invoice server.
1120
1121
///
1121
1122
/// # Usage
1122
1123
///
@@ -1125,11 +1126,13 @@ where
1125
1126
///
1126
1127
/// Errors if we failed to create blinded reply paths when sending an [`OfferPathsRequest`] message.
1127
1128
#[ cfg( async_payments) ]
1128
- pub ( crate ) fn check_refresh_async_receive_offers < ES : Deref > (
1129
- & self , peers : Vec < MessageForwardNode > , entropy : ES ,
1129
+ pub ( crate ) fn check_refresh_async_receive_offers < ES : Deref , R : Deref > (
1130
+ & self , peers : Vec < MessageForwardNode > , usable_channels : Vec < ChannelDetails > , entropy : ES ,
1131
+ router : R ,
1130
1132
) -> Result < ( ) , ( ) >
1131
1133
where
1132
1134
ES :: Target : EntropySource ,
1135
+ R :: Target : Router ,
1133
1136
{
1134
1137
// Terminate early if this node does not intend to receive async payments.
1135
1138
if self . paths_to_static_invoice_server . is_empty ( ) {
@@ -1155,7 +1158,7 @@ where
1155
1158
path_absolute_expiry : duration_since_epoch
1156
1159
. saturating_add ( TEMP_REPLY_PATH_RELATIVE_EXPIRY ) ,
1157
1160
} ) ;
1158
- let reply_paths = match self . create_blinded_paths ( peers, context) {
1161
+ let reply_paths = match self . create_blinded_paths ( peers. clone ( ) , context) {
1159
1162
Ok ( paths) => paths,
1160
1163
Err ( ( ) ) => {
1161
1164
return Err ( ( ) ) ;
@@ -1175,9 +1178,78 @@ where
1175
1178
) ;
1176
1179
}
1177
1180
1181
+ self . check_refresh_static_invoices ( peers, usable_channels, entropy, router) ;
1182
+
1178
1183
Ok ( ( ) )
1179
1184
}
1180
1185
1186
+ /// If a static invoice server has persisted an offer for us but the corresponding invoice is
1187
+ /// expiring soon, we need to refresh that invoice. Here we enqueue the onion messages that will
1188
+ /// be used to request invoice refresh, based on the offers provided by the cache.
1189
+ #[ cfg( async_payments) ]
1190
+ fn check_refresh_static_invoices < ES : Deref , R : Deref > (
1191
+ & self , peers : Vec < MessageForwardNode > , usable_channels : Vec < ChannelDetails > , entropy : ES ,
1192
+ router : R ,
1193
+ ) where
1194
+ ES :: Target : EntropySource ,
1195
+ R :: Target : Router ,
1196
+ {
1197
+ let duration_since_epoch = self . duration_since_epoch ( ) ;
1198
+
1199
+ let mut serve_static_invoice_messages = Vec :: new ( ) ;
1200
+ {
1201
+ let cache = self . async_receive_offer_cache . lock ( ) . unwrap ( ) ;
1202
+ for offer_and_metadata in cache. offers_needing_invoice_refresh ( duration_since_epoch) {
1203
+ let ( offer, offer_nonce, offer_created_at, update_static_invoice_path) =
1204
+ offer_and_metadata;
1205
+ let offer_id = offer. id ( ) ;
1206
+
1207
+ let ( serve_invoice_msg, reply_path_ctx) = match self
1208
+ . create_serve_static_invoice_message (
1209
+ offer. clone ( ) ,
1210
+ offer_nonce,
1211
+ offer_created_at,
1212
+ peers. clone ( ) ,
1213
+ usable_channels. clone ( ) ,
1214
+ update_static_invoice_path. clone ( ) ,
1215
+ & * entropy,
1216
+ & * router,
1217
+ ) {
1218
+ Ok ( ( msg, ctx) ) => ( msg, ctx) ,
1219
+ Err ( ( ) ) => continue ,
1220
+ } ;
1221
+ serve_static_invoice_messages. push ( ( serve_invoice_msg, reply_path_ctx, offer_id) ) ;
1222
+ }
1223
+ }
1224
+
1225
+ // Enqueue the new serve_static_invoice messages in a separate loop to avoid holding the offer
1226
+ // cache lock and the pending_async_payments_messages lock at the same time.
1227
+ for ( serve_invoice_msg, reply_path_ctx, offer_id) in serve_static_invoice_messages {
1228
+ let context = MessageContext :: AsyncPayments ( reply_path_ctx) ;
1229
+ let reply_paths = match self . create_blinded_paths ( peers. clone ( ) , context) {
1230
+ Ok ( paths) => paths,
1231
+ Err ( ( ) ) => continue ,
1232
+ } ;
1233
+
1234
+ {
1235
+ // We can't fail past this point, so indicate to the cache that we've requested an invoice
1236
+ // update.
1237
+ let mut cache = self . async_receive_offer_cache . lock ( ) . unwrap ( ) ;
1238
+ if cache. increment_invoice_update_attempts ( offer_id) . is_err ( ) {
1239
+ continue ;
1240
+ }
1241
+ }
1242
+
1243
+ let message = AsyncPaymentsMessage :: ServeStaticInvoice ( serve_invoice_msg) ;
1244
+ enqueue_onion_message_with_reply_paths (
1245
+ message,
1246
+ & self . paths_to_static_invoice_server ,
1247
+ reply_paths,
1248
+ & mut self . pending_async_payments_messages . lock ( ) . unwrap ( ) ,
1249
+ ) ;
1250
+ }
1251
+ }
1252
+
1181
1253
/// Handles an incoming [`OfferPaths`] message from the static invoice server, sending out
1182
1254
/// [`ServeStaticInvoice`] onion messages in response if we want to use the paths we've received
1183
1255
/// to build and cache an async receive offer.
0 commit comments