@@ -1515,6 +1515,19 @@ struct AsyncReceiveOffer {
1515
1515
offer_paths_request_attempts: u8,
1516
1516
}
1517
1517
1518
+ impl AsyncReceiveOffer {
1519
+ /// Removes the offer from our cache if it's expired.
1520
+ #[cfg(async_payments)]
1521
+ fn check_expire_offer(&mut self, duration_since_epoch: Duration) {
1522
+ if let Some(ref mut offer) = self.offer {
1523
+ if offer.is_expired_no_std(duration_since_epoch) {
1524
+ self.offer.take();
1525
+ self.offer_paths_request_attempts = 0;
1526
+ }
1527
+ }
1528
+ }
1529
+ }
1530
+
1518
1531
impl_writeable_tlv_based!(AsyncReceiveOffer, {
1519
1532
(0, offer, option),
1520
1533
(2, offer_paths_request_attempts, (static_value, 0)),
@@ -2429,6 +2442,8 @@ where
2429
2442
//
2430
2443
// `pending_async_payments_messages`
2431
2444
//
2445
+ // `async_receive_offer_cache`
2446
+ //
2432
2447
// `total_consistency_lock`
2433
2448
// |
2434
2449
// |__`forward_htlcs`
@@ -4849,6 +4864,60 @@ where
4849
4864
)
4850
4865
}
4851
4866
4867
+ #[cfg(async_payments)]
4868
+ fn check_refresh_async_receive_offer(&self) {
4869
+ if self.default_configuration.paths_to_static_invoice_server.is_empty() { return }
4870
+
4871
+ let expanded_key = &self.inbound_payment_key;
4872
+ let entropy = &*self.entropy_source;
4873
+ let duration_since_epoch = self.duration_since_epoch();
4874
+
4875
+ {
4876
+ let mut offer_cache = self.async_receive_offer_cache.lock().unwrap();
4877
+ offer_cache.check_expire_offer(duration_since_epoch);
4878
+
4879
+ if let Some(ref offer) = offer_cache.offer {
4880
+ // If we have more than three hours before our offer expires, don't bother requesting new
4881
+ // paths.
4882
+ const PATHS_EXPIRY_BUFFER: Duration = Duration::from_secs(60 * 60 * 3);
4883
+ let offer_expiry = offer.absolute_expiry().unwrap_or(Duration::MAX);
4884
+ if offer_expiry > duration_since_epoch.saturating_add(PATHS_EXPIRY_BUFFER) {
4885
+ return
4886
+ }
4887
+ }
4888
+
4889
+ const MAX_ATTEMPTS: u8 = 3;
4890
+ if offer_cache.offer_paths_request_attempts > MAX_ATTEMPTS { return }
4891
+ }
4892
+
4893
+ let reply_paths = {
4894
+ // We expect the static invoice server to respond quickly to our request for offer paths, but
4895
+ // add some buffer for no-std users that rely on block timestamps.
4896
+ const REPLY_PATH_RELATIVE_EXPIRY: Duration = Duration::from_secs(2 * 60 * 60);
4897
+ let nonce = Nonce::from_entropy_source(entropy);
4898
+ let context = MessageContext::AsyncPayments(AsyncPaymentsContext::OfferPaths {
4899
+ nonce,
4900
+ hmac: signer::hmac_for_offer_paths_context(nonce, expanded_key),
4901
+ path_absolute_expiry: duration_since_epoch.saturating_add(REPLY_PATH_RELATIVE_EXPIRY),
4902
+ });
4903
+ match self.create_blinded_paths(context) {
4904
+ Ok(paths) => paths,
4905
+ Err(()) => {
4906
+ log_error!(self.logger, "Failed to create blinded paths when requesting async receive offer paths");
4907
+ return
4908
+ }
4909
+ }
4910
+ };
4911
+
4912
+
4913
+ self.async_receive_offer_cache.lock().unwrap().offer_paths_request_attempts += 1;
4914
+ let message = AsyncPaymentsMessage::OfferPathsRequest(OfferPathsRequest {});
4915
+ queue_onion_message_with_reply_paths(
4916
+ message, &self.default_configuration.paths_to_static_invoice_server[..], reply_paths,
4917
+ &mut self.pending_async_payments_messages.lock().unwrap()
4918
+ );
4919
+ }
4920
+
4852
4921
#[cfg(async_payments)]
4853
4922
fn initiate_async_payment(
4854
4923
&self, invoice: &StaticInvoice, payment_id: PaymentId
@@ -6798,6 +6867,9 @@ where
6798
6867
duration_since_epoch, &self.pending_events
6799
6868
);
6800
6869
6870
+ #[cfg(async_payments)]
6871
+ self.check_refresh_async_receive_offer();
6872
+
6801
6873
// Technically we don't need to do this here, but if we have holding cell entries in a
6802
6874
// channel that need freeing, it's better to do that here and block a background task
6803
6875
// than block the message queueing pipeline.
@@ -12082,6 +12154,9 @@ where
12082
12154
return NotifyOption::SkipPersistHandleEvents;
12083
12155
//TODO: Also re-broadcast announcement_signatures
12084
12156
});
12157
+
12158
+ #[cfg(async_payments)]
12159
+ self.check_refresh_async_receive_offer();
12085
12160
res
12086
12161
}
12087
12162
0 commit comments