@@ -12657,6 +12657,99 @@ where
12657
12657
fn handle_offer_paths(
12658
12658
&self, _message: OfferPaths, _context: AsyncPaymentsContext, _responder: Option<Responder>,
12659
12659
) -> Option<(ServeStaticInvoice, ResponseInstruction)> {
12660
+ #[cfg(async_payments)] {
12661
+ let expanded_key = &self.inbound_payment_key;
12662
+ let entropy = &*self.entropy_source;
12663
+ let secp_ctx = &self.secp_ctx;
12664
+ let duration_since_epoch = self.duration_since_epoch();
12665
+
12666
+ match _context {
12667
+ AsyncPaymentsContext::OfferPaths { nonce, hmac, path_absolute_expiry } => {
12668
+ if let Err(()) = signer::verify_offer_paths_context(nonce, hmac, expanded_key) {
12669
+ return None
12670
+ }
12671
+ if duration_since_epoch > path_absolute_expiry { return None }
12672
+ },
12673
+ _ => return None
12674
+ }
12675
+
12676
+ if !self.async_receive_offer_cache.lock().unwrap().should_refresh_offer(duration_since_epoch) {
12677
+ return None
12678
+ }
12679
+
12680
+ // Require at least two hours before we'll need to start the process of creating a new offer.
12681
+ const MIN_OFFER_PATHS_RELATIVE_EXPIRY: Duration =
12682
+ Duration::from_secs(2 * 60 * 60).saturating_add(AsyncReceiveOffer::OFFER_RELATIVE_EXPIRY_BUFFER);
12683
+ let min_offer_paths_absolute_expiry =
12684
+ duration_since_epoch.saturating_add(MIN_OFFER_PATHS_RELATIVE_EXPIRY);
12685
+ let offer_paths_absolute_expiry =
12686
+ _message.paths_absolute_expiry.unwrap_or(Duration::from_secs(u64::MAX));
12687
+ if offer_paths_absolute_expiry < min_offer_paths_absolute_expiry {
12688
+ log_error!(self.logger, "Received offer paths with too-soon absolute Unix epoch expiry: {}", offer_paths_absolute_expiry.as_secs());
12689
+ return None
12690
+ }
12691
+
12692
+ // Expire the offer at the same time as the static invoice so we automatically refresh both
12693
+ // at the same time.
12694
+ let offer_and_invoice_absolute_expiry = Duration::from_secs(core::cmp::min(
12695
+ offer_paths_absolute_expiry.as_secs(),
12696
+ duration_since_epoch.saturating_add(STATIC_INVOICE_DEFAULT_RELATIVE_EXPIRY).as_secs()
12697
+ ));
12698
+
12699
+ let (offer, offer_nonce) = {
12700
+ let (offer_builder, offer_nonce) =
12701
+ match self.create_async_receive_offer_builder(_message.paths) {
12702
+ Ok((builder, nonce)) => (builder, nonce),
12703
+ Err(e) => {
12704
+ log_error!(self.logger, "Failed to create offer builder when replying to OfferPaths message: {:?}", e);
12705
+ return None
12706
+ },
12707
+ };
12708
+ match offer_builder.absolute_expiry(offer_and_invoice_absolute_expiry).build() {
12709
+ Ok(offer) => (offer, offer_nonce),
12710
+ Err(e) => {
12711
+ log_error!(self.logger, "Failed to build offer when replying to OfferPaths message: {:?}", e);
12712
+ return None
12713
+ },
12714
+ }
12715
+ };
12716
+
12717
+ let static_invoice_relative_expiry =
12718
+ offer_and_invoice_absolute_expiry.saturating_sub(duration_since_epoch);
12719
+ let static_invoice = {
12720
+ let invoice_res = self.create_static_invoice_builder(
12721
+ &offer, offer_nonce, Some(static_invoice_relative_expiry )
12722
+ ).and_then(|builder| builder.build_and_sign(secp_ctx));
12723
+ match invoice_res {
12724
+ Ok(invoice) => invoice,
12725
+ Err(e) => {
12726
+ log_error!(self.logger, "Failed to create static invoice when replying to OfferPaths message: {:?}", e);
12727
+ return None
12728
+ },
12729
+ }
12730
+ };
12731
+
12732
+ let invoice_persisted_paths = {
12733
+ let nonce = Nonce::from_entropy_source(entropy);
12734
+ let hmac = signer::hmac_for_static_invoice_persisted_context(nonce, expanded_key);
12735
+ let context = MessageContext::AsyncPayments(AsyncPaymentsContext::StaticInvoicePersisted {
12736
+ offer, nonce, hmac,
12737
+ path_absolute_expiry: duration_since_epoch.saturating_add(REPLY_PATH_RELATIVE_EXPIRY)
12738
+ });
12739
+ match self.create_blinded_paths(context) {
12740
+ Ok(paths) => paths,
12741
+ Err(()) => {
12742
+ log_error!(self.logger, "Failed to create blinded paths when replying to OfferPaths message");
12743
+ return None
12744
+ },
12745
+ }
12746
+ };
12747
+
12748
+ let reply = ServeStaticInvoice { invoice: static_invoice, invoice_persisted_paths };
12749
+ return _responder.map(|responder| (reply, responder.respond()))
12750
+ }
12751
+
12752
+ #[cfg(not(async_payments))]
12660
12753
None
12661
12754
}
12662
12755
0 commit comments