Move `[u8; 32]` wrapper types to a common module
[rust-lightning] / lightning / src / ln / channelmanager.rs
index 210515236342303576f6ae373d6788d697b75eed..7bc62463b36feb7a271294f309edf34a9ec8367e 100644 (file)
@@ -32,7 +32,7 @@ use bitcoin::secp256k1::Secp256k1;
 use bitcoin::{secp256k1, Sequence};
 
 use crate::blinded_path::{BlindedPath, NodeIdLookUp};
-use crate::blinded_path::payment::{PaymentConstraints, ReceiveTlvs};
+use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentConstraints, PaymentContext, ReceiveTlvs};
 use crate::chain;
 use crate::chain::{Confirm, ChannelMonitorUpdateStatus, Watch, BestBlock};
 use crate::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator};
@@ -42,7 +42,8 @@ use crate::events;
 use crate::events::{Event, EventHandler, EventsProvider, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination, PaymentFailureReason};
 // Since this struct is returned in `list_channels` methods, expose it here in case users want to
 // construct one themselves.
-use crate::ln::{inbound_payment, ChannelId, PaymentHash, PaymentPreimage, PaymentSecret};
+use crate::ln::inbound_payment;
+use crate::ln::types::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret};
 use crate::ln::channel::{self, Channel, ChannelPhase, ChannelContext, ChannelError, ChannelUpdateStatus, ShutdownResult, UnfundedChannelContext, UpdateFulfillCommitFetch, OutboundV1Channel, InboundV1Channel, WithChannelContext};
 pub use crate::ln::channel::{InboundHTLCDetails, InboundHTLCStateDetails, OutboundHTLCDetails, OutboundHTLCStateDetails};
 use crate::ln::features::{Bolt12InvoiceFeatures, ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
@@ -155,6 +156,11 @@ pub enum PendingHTLCRouting {
                /// [`Event::PaymentClaimable::onion_fields`] as
                /// [`RecipientOnionFields::payment_metadata`].
                payment_metadata: Option<Vec<u8>>,
+               /// The context of the payment included by the recipient in a blinded path, or `None` if a
+               /// blinded path was not used.
+               ///
+               /// Used in part to determine the [`events::PaymentPurpose`].
+               payment_context: Option<PaymentContext>,
                /// CLTV expiry of the received HTLC.
                ///
                /// Used to track when we should expire pending HTLCs that go unclaimed.
@@ -917,9 +923,9 @@ impl <SP: Deref> PeerState<SP> where SP::Target: SignerProvider {
                        match phase {
                                ChannelPhase::Funded(_) | ChannelPhase::UnfundedOutboundV1(_) => true,
                                ChannelPhase::UnfundedInboundV1(_) => false,
-                               #[cfg(dual_funding)]
+                               #[cfg(any(dual_funding, splicing))]
                                ChannelPhase::UnfundedOutboundV2(_) => true,
-                               #[cfg(dual_funding)]
+                               #[cfg(any(dual_funding, splicing))]
                                ChannelPhase::UnfundedInboundV2(_) => false,
                        }
                )
@@ -1382,7 +1388,7 @@ where
 ///
 /// ```
 /// # use bitcoin::secp256k1::PublicKey;
-/// # use lightning::ln::ChannelId;
+/// # use lightning::ln::types::ChannelId;
 /// # use lightning::ln::channelmanager::AChannelManager;
 /// # use lightning::events::{Event, EventsProvider};
 /// #
@@ -1454,12 +1460,12 @@ where
 /// // On the event processing thread
 /// channel_manager.process_pending_events(&|event| match event {
 ///     Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose {
-///         PaymentPurpose::InvoicePayment { payment_preimage: Some(payment_preimage), .. } => {
+///         PaymentPurpose::Bolt11InvoicePayment { payment_preimage: Some(payment_preimage), .. } => {
 ///             assert_eq!(payment_hash, known_payment_hash);
 ///             println!("Claiming payment {}", payment_hash);
 ///             channel_manager.claim_funds(payment_preimage);
 ///         },
-///         PaymentPurpose::InvoicePayment { payment_preimage: None, .. } => {
+///         PaymentPurpose::Bolt11InvoicePayment { payment_preimage: None, .. } => {
 ///             println!("Unknown payment hash: {}", payment_hash);
 ///         },
 ///         PaymentPurpose::SpontaneousPayment(payment_preimage) => {
@@ -1467,6 +1473,8 @@ where
 ///             println!("Claiming spontaneous payment {}", payment_hash);
 ///             channel_manager.claim_funds(payment_preimage);
 ///         },
+///         // ...
+/// #         _ => {},
 ///     },
 ///     Event::PaymentClaimed { payment_hash, amount_msat, .. } => {
 ///         assert_eq!(payment_hash, known_payment_hash);
@@ -1483,7 +1491,7 @@ where
 ///
 /// ```
 /// # use lightning::events::{Event, EventsProvider};
-/// # use lightning::ln::PaymentHash;
+/// # use lightning::ln::types::PaymentHash;
 /// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails, RecipientOnionFields, Retry};
 /// # use lightning::routing::router::RouteParameters;
 /// #
@@ -1554,11 +1562,11 @@ where
 /// // On the event processing thread
 /// channel_manager.process_pending_events(&|event| match event {
 ///     Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose {
-///         PaymentPurpose::InvoicePayment { payment_preimage: Some(payment_preimage), .. } => {
+///         PaymentPurpose::Bolt12OfferPayment { payment_preimage: Some(payment_preimage), .. } => {
 ///             println!("Claiming payment {}", payment_hash);
 ///             channel_manager.claim_funds(payment_preimage);
 ///         },
-///         PaymentPurpose::InvoicePayment { payment_preimage: None, .. } => {
+///         PaymentPurpose::Bolt12OfferPayment { payment_preimage: None, .. } => {
 ///             println!("Unknown payment hash: {}", payment_hash);
 ///         },
 ///         // ...
@@ -1694,25 +1702,31 @@ where
 /// #
 /// # fn example<T: AChannelManager>(channel_manager: T, refund: &Refund) {
 /// # let channel_manager = channel_manager.get_cm();
-/// match channel_manager.request_refund_payment(refund) {
-///     Ok(()) => println!("Requesting payment for refund"),
-///     Err(e) => println!("Unable to request payment for refund: {:?}", e),
-/// }
+/// let known_payment_hash = match channel_manager.request_refund_payment(refund) {
+///     Ok(invoice) => {
+///         let payment_hash = invoice.payment_hash();
+///         println!("Requesting refund payment {}", payment_hash);
+///         payment_hash
+///     },
+///     Err(e) => panic!("Unable to request payment for refund: {:?}", e),
+/// };
 ///
 /// // On the event processing thread
 /// channel_manager.process_pending_events(&|event| match event {
 ///     Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose {
-///            PaymentPurpose::InvoicePayment { payment_preimage: Some(payment_preimage), .. } => {
+///            PaymentPurpose::Bolt12RefundPayment { payment_preimage: Some(payment_preimage), .. } => {
+///             assert_eq!(payment_hash, known_payment_hash);
 ///             println!("Claiming payment {}", payment_hash);
 ///             channel_manager.claim_funds(payment_preimage);
 ///         },
-///            PaymentPurpose::InvoicePayment { payment_preimage: None, .. } => {
+///            PaymentPurpose::Bolt12RefundPayment { payment_preimage: None, .. } => {
 ///             println!("Unknown payment hash: {}", payment_hash);
 ///            },
 ///         // ...
 /// #         _ => {},
 ///     },
 ///     Event::PaymentClaimed { payment_hash, amount_msat, .. } => {
+///         assert_eq!(payment_hash, known_payment_hash);
 ///         println!("Claimed {} msats", amount_msat);
 ///     },
 ///     // ...
@@ -2773,11 +2787,11 @@ macro_rules! convert_chan_phase_err {
                        ChannelPhase::UnfundedInboundV1(channel) => {
                                convert_chan_phase_err!($self, $err, channel, $channel_id, UNFUNDED_CHANNEL)
                        },
-                       #[cfg(dual_funding)]
+                       #[cfg(any(dual_funding, splicing))]
                        ChannelPhase::UnfundedOutboundV2(channel) => {
                                convert_chan_phase_err!($self, $err, channel, $channel_id, UNFUNDED_CHANNEL)
                        },
-                       #[cfg(dual_funding)]
+                       #[cfg(any(dual_funding, splicing))]
                        ChannelPhase::UnfundedInboundV2(channel) => {
                                convert_chan_phase_err!($self, $err, channel, $channel_id, UNFUNDED_CHANNEL)
                        },
@@ -3652,8 +3666,8 @@ where
                                                // Unfunded channel has no update
                                                (None, chan_phase.context().get_counterparty_node_id())
                                        },
-                                       // TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed.
-                                       #[cfg(dual_funding)]
+                                       // TODO(dual_funding): Combine this match arm with above once #[cfg(any(dual_funding, splicing))] is removed.
+                                       #[cfg(any(dual_funding, splicing))]
                                        ChannelPhase::UnfundedOutboundV2(_) | ChannelPhase::UnfundedInboundV2(_) => {
                                                self.finish_close_channel(chan_phase.context_mut().force_shutdown(false, closure_reason));
                                                // Unfunded channel has no update
@@ -5328,16 +5342,17 @@ where
                                                                }
                                                        }) => {
                                                                let blinded_failure = routing.blinded_failure();
-                                                               let (cltv_expiry, onion_payload, payment_data, phantom_shared_secret, mut onion_fields) = match routing {
+                                                               let (cltv_expiry, onion_payload, payment_data, payment_context, phantom_shared_secret, mut onion_fields) = match routing {
                                                                        PendingHTLCRouting::Receive {
-                                                                               payment_data, payment_metadata, incoming_cltv_expiry, phantom_shared_secret,
-                                                                               custom_tlvs, requires_blinded_error: _
+                                                                               payment_data, payment_metadata, payment_context,
+                                                                               incoming_cltv_expiry, phantom_shared_secret, custom_tlvs,
+                                                                               requires_blinded_error: _
                                                                        } => {
                                                                                let _legacy_hop_data = Some(payment_data.clone());
                                                                                let onion_fields = RecipientOnionFields { payment_secret: Some(payment_data.payment_secret),
                                                                                                payment_metadata, custom_tlvs };
                                                                                (incoming_cltv_expiry, OnionPayload::Invoice { _legacy_hop_data },
-                                                                                       Some(payment_data), phantom_shared_secret, onion_fields)
+                                                                                       Some(payment_data), payment_context, phantom_shared_secret, onion_fields)
                                                                        },
                                                                        PendingHTLCRouting::ReceiveKeysend {
                                                                                payment_data, payment_preimage, payment_metadata,
@@ -5349,7 +5364,7 @@ where
                                                                                        custom_tlvs,
                                                                                };
                                                                                (incoming_cltv_expiry, OnionPayload::Spontaneous(payment_preimage),
-                                                                                       payment_data, None, onion_fields)
+                                                                                       payment_data, None, None, onion_fields)
                                                                        },
                                                                        _ => {
                                                                                panic!("short_channel_id == 0 should imply any pending_forward entries are of type Receive");
@@ -5414,10 +5429,7 @@ where
                                                                macro_rules! check_total_value {
                                                                        ($purpose: expr) => {{
                                                                                let mut payment_claimable_generated = false;
-                                                                               let is_keysend = match $purpose {
-                                                                                       events::PaymentPurpose::SpontaneousPayment(_) => true,
-                                                                                       events::PaymentPurpose::InvoicePayment { .. } => false,
-                                                                               };
+                                                                               let is_keysend = $purpose.is_keysend();
                                                                                let mut claimable_payments = self.claimable_payments.lock().unwrap();
                                                                                if claimable_payments.pending_claiming_payments.contains_key(&payment_hash) {
                                                                                        fail_htlc!(claimable_htlc, payment_hash);
@@ -5531,10 +5543,11 @@ where
                                                                                                                fail_htlc!(claimable_htlc, payment_hash);
                                                                                                        }
                                                                                                }
-                                                                                               let purpose = events::PaymentPurpose::InvoicePayment {
-                                                                                                       payment_preimage: payment_preimage.clone(),
-                                                                                                       payment_secret: payment_data.payment_secret,
-                                                                                               };
+                                                                                               let purpose = events::PaymentPurpose::from_parts(
+                                                                                                       payment_preimage,
+                                                                                                       payment_data.payment_secret,
+                                                                                                       payment_context,
+                                                                                               );
                                                                                                check_total_value!(purpose);
                                                                                        },
                                                                                        OnionPayload::Spontaneous(preimage) => {
@@ -5557,10 +5570,11 @@ where
                                                                                                &payment_hash, payment_data.total_msat, inbound_payment.get().min_value_msat.unwrap());
                                                                                        fail_htlc!(claimable_htlc, payment_hash);
                                                                                } else {
-                                                                                       let purpose = events::PaymentPurpose::InvoicePayment {
-                                                                                               payment_preimage: inbound_payment.get().payment_preimage,
-                                                                                               payment_secret: payment_data.payment_secret,
-                                                                                       };
+                                                                                       let purpose = events::PaymentPurpose::from_parts(
+                                                                                               inbound_payment.get().payment_preimage,
+                                                                                               payment_data.payment_secret,
+                                                                                               payment_context,
+                                                                                       );
                                                                                        let payment_claimable_generated = check_total_value!(purpose);
                                                                                        if payment_claimable_generated {
                                                                                                inbound_payment.remove_entry();
@@ -5881,12 +5895,12 @@ where
                                                                process_unfunded_channel_tick(chan_id, &mut chan.context, &mut chan.unfunded_context,
                                                                        pending_msg_events, counterparty_node_id)
                                                        },
-                                                       #[cfg(dual_funding)]
+                                                       #[cfg(any(dual_funding, splicing))]
                                                        ChannelPhase::UnfundedInboundV2(chan) => {
                                                                process_unfunded_channel_tick(chan_id, &mut chan.context, &mut chan.unfunded_context,
                                                                        pending_msg_events, counterparty_node_id)
                                                        },
-                                                       #[cfg(dual_funding)]
+                                                       #[cfg(any(dual_funding, splicing))]
                                                        ChannelPhase::UnfundedOutboundV2(chan) => {
                                                                process_unfunded_channel_tick(chan_id, &mut chan.context, &mut chan.unfunded_context,
                                                                        pending_msg_events, counterparty_node_id)
@@ -7058,8 +7072,8 @@ where
                                                num_unfunded_channels += 1;
                                        }
                                },
-                               // TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed.
-                               #[cfg(dual_funding)]
+                               // TODO(dual_funding): Combine this match arm with above once #[cfg(any(dual_funding, splicing))] is removed.
+                               #[cfg(any(dual_funding, splicing))]
                                ChannelPhase::UnfundedInboundV2(chan) => {
                                        // Only inbound V2 channels that are not 0conf and that we do not contribute to will be
                                        // included in the unfunded count.
@@ -7072,8 +7086,8 @@ where
                                        // Outbound channels don't contribute to the unfunded count in the DoS context.
                                        continue;
                                },
-                               // TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed.
-                               #[cfg(dual_funding)]
+                               // TODO(dual_funding): Combine this match arm with above once #[cfg(any(dual_funding, splicing))] is removed.
+                               #[cfg(any(dual_funding, splicing))]
                                ChannelPhase::UnfundedOutboundV2(_) => {
                                        // Outbound channels don't contribute to the unfunded count in the DoS context.
                                        continue;
@@ -7500,7 +7514,7 @@ where
                                                finish_shutdown = Some(chan.context_mut().force_shutdown(false, ClosureReason::CounterpartyCoopClosedUnfundedChannel));
                                        },
                                        // TODO(dual_funding): Combine this match arm with above.
-                                       #[cfg(dual_funding)]
+                                       #[cfg(any(dual_funding, splicing))]
                                        ChannelPhase::UnfundedInboundV2(_) | ChannelPhase::UnfundedOutboundV2(_) => {
                                                let context = phase.context_mut();
                                                log_error!(self.logger, "Immediately closing unfunded channel {} as peer asked to cooperatively shut it down (which is unnecessary)", &msg.channel_id);
@@ -8744,14 +8758,7 @@ where
                        .map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?;
 
                let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
-               if offer.paths().is_empty() {
-                       let message = new_pending_onion_message(
-                               OffersMessage::InvoiceRequest(invoice_request),
-                               Destination::Node(offer.signing_pubkey()),
-                               Some(reply_path),
-                       );
-                       pending_offers_messages.push(message);
-               } else {
+               if !offer.paths().is_empty() {
                        // Send as many invoice requests as there are paths in the offer (with an upper bound).
                        // Using only one path could result in a failure if the path no longer exists. But only
                        // one invoice for a given payment id will be paid, even if more than one is received.
@@ -8764,6 +8771,16 @@ where
                                );
                                pending_offers_messages.push(message);
                        }
+               } else if let Some(signing_pubkey) = offer.signing_pubkey() {
+                       let message = new_pending_onion_message(
+                               OffersMessage::InvoiceRequest(invoice_request),
+                               Destination::Node(signing_pubkey),
+                               Some(reply_path),
+                       );
+                       pending_offers_messages.push(message);
+               } else {
+                       debug_assert!(false);
+                       return Err(Bolt12SemanticError::MissingSigningPubkey);
                }
 
                Ok(())
@@ -8774,7 +8791,7 @@ where
        ///
        /// The resulting invoice uses a [`PaymentHash`] recognized by the [`ChannelManager`] and a
        /// [`BlindedPath`] containing the [`PaymentSecret`] needed to reconstruct the corresponding
-       /// [`PaymentPreimage`].
+       /// [`PaymentPreimage`]. It is returned purely for informational purposes.
        ///
        /// # Limitations
        ///
@@ -8791,7 +8808,9 @@ where
        ///   the invoice.
        ///
        /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
-       pub fn request_refund_payment(&self, refund: &Refund) -> Result<(), Bolt12SemanticError> {
+       pub fn request_refund_payment(
+               &self, refund: &Refund
+       ) -> Result<Bolt12Invoice, Bolt12SemanticError> {
                let expanded_key = &self.inbound_payment_key;
                let entropy = &*self.entropy_source;
                let secp_ctx = &self.secp_ctx;
@@ -8807,7 +8826,10 @@ where
 
                match self.create_inbound_payment(Some(amount_msats), relative_expiry, None) {
                        Ok((payment_hash, payment_secret)) => {
-                               let payment_paths = self.create_blinded_payment_paths(amount_msats, payment_secret)
+                               let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
+                               let payment_paths = self.create_blinded_payment_paths(
+                                       amount_msats, payment_secret, payment_context
+                               )
                                        .map_err(|_| Bolt12SemanticError::MissingPaths)?;
 
                                #[cfg(feature = "std")]
@@ -8830,7 +8852,7 @@ where
                                let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
                                if refund.paths().is_empty() {
                                        let message = new_pending_onion_message(
-                                               OffersMessage::Invoice(invoice),
+                                               OffersMessage::Invoice(invoice.clone()),
                                                Destination::Node(refund.payer_id()),
                                                Some(reply_path),
                                        );
@@ -8846,7 +8868,7 @@ where
                                        }
                                }
 
-                               Ok(())
+                               Ok(invoice)
                        },
                        Err(()) => Err(Bolt12SemanticError::InvalidAmount),
                }
@@ -8858,10 +8880,9 @@ where
        /// This differs from [`create_inbound_payment_for_hash`] only in that it generates the
        /// [`PaymentHash`] and [`PaymentPreimage`] for you.
        ///
-       /// The [`PaymentPreimage`] will ultimately be returned to you in the [`PaymentClaimable`], which
-       /// will have the [`PaymentClaimable::purpose`] be [`PaymentPurpose::InvoicePayment`] with
-       /// its [`PaymentPurpose::InvoicePayment::payment_preimage`] field filled in. That should then be
-       /// passed directly to [`claim_funds`].
+       /// The [`PaymentPreimage`] will ultimately be returned to you in the [`PaymentClaimable`] event, which
+       /// will have the [`PaymentClaimable::purpose`] return `Some` for [`PaymentPurpose::preimage`]. That
+       /// should then be passed directly to [`claim_funds`].
        ///
        /// See [`create_inbound_payment_for_hash`] for detailed documentation on behavior and requirements.
        ///
@@ -8881,8 +8902,7 @@ where
        /// [`claim_funds`]: Self::claim_funds
        /// [`PaymentClaimable`]: events::Event::PaymentClaimable
        /// [`PaymentClaimable::purpose`]: events::Event::PaymentClaimable::purpose
-       /// [`PaymentPurpose::InvoicePayment`]: events::PaymentPurpose::InvoicePayment
-       /// [`PaymentPurpose::InvoicePayment::payment_preimage`]: events::PaymentPurpose::InvoicePayment::payment_preimage
+       /// [`PaymentPurpose::preimage`]: events::PaymentPurpose::preimage
        /// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash
        pub fn create_inbound_payment(&self, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32,
                min_final_cltv_expiry_delta: Option<u16>) -> Result<(PaymentHash, PaymentSecret), ()> {
@@ -8973,7 +8993,7 @@ where
        /// Creates multi-hop blinded payment paths for the given `amount_msats` by delegating to
        /// [`Router::create_blinded_payment_paths`].
        fn create_blinded_payment_paths(
-               &self, amount_msats: u64, payment_secret: PaymentSecret
+               &self, amount_msats: u64, payment_secret: PaymentSecret, payment_context: PaymentContext
        ) -> Result<Vec<(BlindedPayInfo, BlindedPath)>, ()> {
                let secp_ctx = &self.secp_ctx;
 
@@ -8987,6 +9007,7 @@ where
                                max_cltv_expiry,
                                htlc_minimum_msat: 1,
                        },
+                       payment_context,
                };
                self.router.create_blinded_payment_paths(
                        payee_node_id, first_hops, payee_tlvs, amount_msats, secp_ctx
@@ -9449,7 +9470,7 @@ where
                                                // Retain unfunded channels.
                                                ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) => true,
                                                // TODO(dual_funding): Combine this match arm with above.
-                                               #[cfg(dual_funding)]
+                                               #[cfg(any(dual_funding, splicing))]
                                                ChannelPhase::UnfundedOutboundV2(_) | ChannelPhase::UnfundedInboundV2(_) => true,
                                                ChannelPhase::Funded(channel) => {
                                                        let res = f(channel);
@@ -9755,18 +9776,21 @@ where
                         msg.channel_id.clone())), *counterparty_node_id);
        }
 
+       #[cfg(splicing)]
        fn handle_splice(&self, counterparty_node_id: &PublicKey, msg: &msgs::Splice) {
                let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close(
                        "Splicing not supported".to_owned(),
                         msg.channel_id.clone())), *counterparty_node_id);
        }
 
+       #[cfg(splicing)]
        fn handle_splice_ack(&self, counterparty_node_id: &PublicKey, msg: &msgs::SpliceAck) {
                let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close(
                        "Splicing not supported (splice_ack)".to_owned(),
                         msg.channel_id.clone())), *counterparty_node_id);
        }
 
+       #[cfg(splicing)]
        fn handle_splice_locked(&self, counterparty_node_id: &PublicKey, msg: &msgs::SpliceLocked) {
                let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close(
                        "Splicing not supported (splice_locked)".to_owned(),
@@ -9924,11 +9948,11 @@ where
                                                ChannelPhase::UnfundedInboundV1(chan) => {
                                                        &mut chan.context
                                                },
-                                               #[cfg(dual_funding)]
+                                               #[cfg(any(dual_funding, splicing))]
                                                ChannelPhase::UnfundedOutboundV2(chan) => {
                                                        &mut chan.context
                                                },
-                                               #[cfg(dual_funding)]
+                                               #[cfg(any(dual_funding, splicing))]
                                                ChannelPhase::UnfundedInboundV2(chan) => {
                                                        &mut chan.context
                                                },
@@ -10089,8 +10113,8 @@ where
                                                        });
                                                }
 
-                                               // TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed.
-                                               #[cfg(dual_funding)]
+                                               // TODO(dual_funding): Combine this match arm with above once #[cfg(any(dual_funding, splicing))] is removed.
+                                               #[cfg(any(dual_funding, splicing))]
                                                ChannelPhase::UnfundedOutboundV2(chan) => {
                                                        pending_msg_events.push(events::MessageSendEvent::SendOpenChannelV2 {
                                                                node_id: chan.context.get_counterparty_node_id(),
@@ -10105,8 +10129,8 @@ where
                                                        debug_assert!(false);
                                                }
 
-                                               // TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed.
-                                               #[cfg(dual_funding)]
+                                               // TODO(dual_funding): Combine this match arm with above once #[cfg(any(dual_funding, splicing))] is removed.
+                                               #[cfg(any(dual_funding, splicing))]
                                                ChannelPhase::UnfundedInboundV2(channel) => {
                                                        // Since unfunded inbound channel maps are cleared upon disconnecting a peer,
                                                        // they are not persisted and won't be recovered after a crash.
@@ -10209,7 +10233,7 @@ where
                                                        return;
                                                }
                                        },
-                                       #[cfg(dual_funding)]
+                                       #[cfg(any(dual_funding, splicing))]
                                        Some(ChannelPhase::UnfundedOutboundV2(ref mut chan)) => {
                                                if let Ok(msg) = chan.maybe_handle_error_without_close(self.chain_hash, &self.fee_estimator) {
                                                        peer_state.pending_msg_events.push(events::MessageSendEvent::SendOpenChannelV2 {
@@ -10220,7 +10244,7 @@ where
                                                }
                                        },
                                        None | Some(ChannelPhase::UnfundedInboundV1(_) | ChannelPhase::Funded(_)) => (),
-                                       #[cfg(dual_funding)]
+                                       #[cfg(any(dual_funding, splicing))]
                                        Some(ChannelPhase::UnfundedInboundV2(_)) => (),
                                }
                        }
@@ -10340,8 +10364,12 @@ where
                                        },
                                };
 
+                               let payment_context = PaymentContext::Bolt12Offer(Bolt12OfferContext {
+                                       offer_id: invoice_request.offer_id,
+                                       invoice_request: invoice_request.fields(),
+                               });
                                let payment_paths = match self.create_blinded_payment_paths(
-                                       amount_msats, payment_secret
+                                       amount_msats, payment_secret, payment_context
                                ) {
                                        Ok(payment_paths) => payment_paths,
                                        Err(()) => {
@@ -10668,6 +10696,7 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting,
                (3, payment_metadata, option),
                (5, custom_tlvs, optional_vec),
                (7, requires_blinded_error, (default_value, false)),
+               (9, payment_context, option),
        },
        (2, ReceiveKeysend) => {
                (0, payment_preimage, required),
@@ -10783,7 +10812,9 @@ impl_writeable_tlv_based!(HTLCPreviousHopData, {
 impl Writeable for ClaimableHTLC {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
                let (payment_data, keysend_preimage) = match &self.onion_payload {
-                       OnionPayload::Invoice { _legacy_hop_data } => (_legacy_hop_data.as_ref(), None),
+                       OnionPayload::Invoice { _legacy_hop_data } => {
+                               (_legacy_hop_data.as_ref(), None)
+                       },
                        OnionPayload::Spontaneous(preimage) => (None, Some(preimage)),
                };
                write_tlv_fields!(writer, {
@@ -11028,9 +11059,10 @@ where
                        best_block.block_hash.write(writer)?;
                }
 
+               let per_peer_state = self.per_peer_state.write().unwrap();
+
                let mut serializable_peer_count: u64 = 0;
                {
-                       let per_peer_state = self.per_peer_state.read().unwrap();
                        let mut number_of_funded_channels = 0;
                        for (_, peer_state_mutex) in per_peer_state.iter() {
                                let mut peer_state_lock = peer_state_mutex.lock().unwrap();
@@ -11077,8 +11109,6 @@ where
                        decode_update_add_htlcs_opt = Some(decode_update_add_htlcs);
                }
 
-               let per_peer_state = self.per_peer_state.write().unwrap();
-
                let pending_inbound_payments = self.pending_inbound_payments.lock().unwrap();
                let claimable_payments = self.claimable_payments.lock().unwrap();
                let pending_outbound_payments = self.pending_outbound_payments.pending_outbound_payments.lock().unwrap();
@@ -11525,9 +11555,10 @@ where
                                                }
                                        }
                                } else {
-                                       log_info!(logger, "Successfully loaded channel {} at update_id {} against monitor at update id {}",
+                                       channel.on_startup_drop_completed_blocked_mon_updates_through(&logger, monitor.get_latest_update_id());
+                                       log_info!(logger, "Successfully loaded channel {} at update_id {} against monitor at update id {} with {} blocked updates",
                                                &channel.context.channel_id(), channel.context.get_latest_monitor_update_id(),
-                                               monitor.get_latest_update_id());
+                                               monitor.get_latest_update_id(), channel.blocked_monitor_updates_pending());
                                        if let Some(short_channel_id) = channel.context.get_short_channel_id() {
                                                short_to_chan_info.insert(short_channel_id, (channel.context.get_counterparty_node_id(), channel.context.channel_id()));
                                        }
@@ -11852,6 +11883,7 @@ where
                                        log_error!(logger, " client applications must ensure that ChannelMonitor data is always available and the latest to avoid funds loss!");
                                        log_error!(logger, " Without the latest ChannelMonitor we cannot continue without risking funds.");
                                        log_error!(logger, " Please ensure the chain::Watch API requirements are met and file a bug report at https://github.com/lightningdevkit/rust-lightning");
+                                       log_error!(logger, " Pending in-flight updates are: {:?}", chan_in_flight_updates);
                                        return Err(DecodeError::InvalidValue);
                                }
                        }
@@ -12072,7 +12104,7 @@ where
                                let purpose = match &htlcs[0].onion_payload {
                                        OnionPayload::Invoice { _legacy_hop_data } => {
                                                if let Some(hop_data) = _legacy_hop_data {
-                                                       events::PaymentPurpose::InvoicePayment {
+                                                       events::PaymentPurpose::Bolt11InvoicePayment {
                                                                payment_preimage: match pending_inbound_payments.get(&payment_hash) {
                                                                        Some(inbound_payment) => inbound_payment.payment_preimage,
                                                                        None => match inbound_payment::verify(payment_hash, &hop_data, 0, &expanded_inbound_key, &args.logger) {
@@ -12327,8 +12359,7 @@ mod tests {
        use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
        use core::sync::atomic::Ordering;
        use crate::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, ClosureReason};
-       use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
-       use crate::ln::ChannelId;
+       use crate::ln::types::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret};
        use crate::ln::channelmanager::{create_recv_pending_htlc_info, HTLCForwardInfo, inbound_payment, PaymentId, PaymentSendFailure, RecipientOnionFields, InterceptId};
        use crate::ln::functional_test_utils::*;
        use crate::ln::msgs::{self, ErrorAction};