@@ -50,10 +50,10 @@ use crate::ln::channel_state::{
5050 OutboundHTLCDetails, OutboundHTLCStateDetails,
5151};
5252use crate::ln::channelmanager::{
53- self, ChannelReadyOrder, FundingConfirmedMessage, HTLCFailureMsg, HTLCPreviousHopData ,
54- HTLCSource, OpenChannelMessage, PaymentClaimDetails, PendingHTLCInfo, PendingHTLCStatus ,
55- RAACommitmentOrder, SentHTLCId, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT ,
56- MIN_CLTV_EXPIRY_DELTA,
53+ self, BlindedFailure, ChannelReadyOrder, FundingConfirmedMessage, HTLCFailureMsg,
54+ HTLCPreviousHopData, HTLCSource, OpenChannelMessage, PaymentClaimDetails, PendingHTLCInfo,
55+ PendingHTLCStatus, RAACommitmentOrder, SentHTLCId, BREAKDOWN_TIMEOUT,
56+ MAX_LOCAL_BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA,
5757};
5858use crate::ln::funding::{FundingTxInput, SpliceContribution};
5959use crate::ln::interactivetxs::{
@@ -308,27 +308,53 @@ impl InboundHTLCState {
308308 }
309309}
310310
311+ /// Information about the outbound hop for a forwarded HTLC. Useful for generating an accurate
312+ /// [`Event::PaymentForwarded`] if we need to claim this HTLC post-restart.
313+ ///
314+ /// [`Event::PaymentForwarded`]: crate::events::Event::PaymentForwarded
315+ #[derive(Debug, Copy, Clone)]
316+ pub(super) struct OutboundHop {
317+ /// The amount forwarded outbound.
318+ pub(super) amt_msat: u64,
319+ /// The outbound channel this HTLC was forwarded over.
320+ pub(super) channel_id: ChannelId,
321+ /// The next-hop recipient of this HTLC.
322+ pub(super) node_id: PublicKey,
323+ /// The outbound channel's funding outpoint.
324+ pub(super) funding_txo: OutPoint,
325+ /// The outbound channel's user channel ID.
326+ pub(super) user_channel_id: u128,
327+ }
328+
329+ impl_writeable_tlv_based!(OutboundHop, {
330+ (0, amt_msat, required),
331+ (2, channel_id, required),
332+ (4, node_id, required),
333+ (6, funding_txo, required),
334+ (8, user_channel_id, required),
335+ });
336+
311337/// A field of `InboundHTLCState::Committed` containing the HTLC's `update_add_htlc` message. If
312338/// the HTLC is a forward and gets irrevocably committed to the outbound edge, we convert to
313339/// `InboundUpdateAdd::Forwarded`, thus pruning the onion and not persisting it on every
314340/// `ChannelManager` persist.
315341///
316342/// Useful for reconstructing the pending HTLC set on startup.
317343#[derive(Debug, Clone)]
318- pub(super) enum InboundUpdateAdd {
344+ enum InboundUpdateAdd {
319345 /// The inbound committed HTLC's update_add_htlc message.
320346 WithOnion { update_add_htlc: msgs::UpdateAddHTLC },
321347 /// This inbound HTLC is a forward that was irrevocably committed to the outbound edge, allowing
322348 /// its onion to be pruned and no longer persisted.
349+ ///
350+ /// Contains data that is useful if we need to fail or claim this HTLC backwards after a restart
351+ /// and it's missing in the outbound edge.
323352 Forwarded {
324- /// Useful if we need to fail or claim this HTLC backwards after restart, if it's missing in the
325- /// outbound edge.
326- hop_data: HTLCPreviousHopData,
327- /// Useful if we need to claim this HTLC backwards after a restart and it's missing in the
328- /// outbound edge, to generate an accurate [`Event::PaymentForwarded`].
329- ///
330- /// [`Event::PaymentForwarded`]: crate::events::Event::PaymentForwarded
331- outbound_amt_msat: u64,
353+ incoming_packet_shared_secret: [u8; 32],
354+ phantom_shared_secret: Option<[u8; 32]>,
355+ trampoline_shared_secret: Option<[u8; 32]>,
356+ blinded_failure: Option<BlindedFailure>,
357+ outbound_hop: OutboundHop,
332358 },
333359 /// This HTLC was received pre-LDK 0.3, before we started persisting the onion for inbound
334360 /// committed HTLCs.
@@ -341,8 +367,11 @@ impl_writeable_tlv_based_enum_upgradable!(InboundUpdateAdd,
341367 },
342368 (2, Legacy) => {},
343369 (4, Forwarded) => {
344- (0, hop_data, required),
345- (2, outbound_amt_msat, required),
370+ (0, incoming_packet_shared_secret, required),
371+ (2, outbound_hop, required),
372+ (4, phantom_shared_secret, option),
373+ (6, trampoline_shared_secret, option),
374+ (8, blinded_failure, option),
346375 },
347376);
348377
@@ -7878,10 +7907,35 @@ where
78787907 Ok(())
78797908 }
78807909
7881- /// Useful for reconstructing the set of pending HTLCs when deserializing the `ChannelManager`.
7882- pub(super) fn inbound_committed_unresolved_htlcs(
7910+ /// Returns true if any committed inbound HTLCs were received pre-LDK 0.3 and cannot be used
7911+ /// during `ChannelManager` deserialization to reconstruct the set of pending HTLCs.
7912+ pub(super) fn has_legacy_inbound_htlcs(&self) -> bool {
7913+ self.context.pending_inbound_htlcs.iter().any(|htlc| {
7914+ matches!(
7915+ &htlc.state,
7916+ InboundHTLCState::Committed { update_add_htlc: InboundUpdateAdd::Legacy }
7917+ )
7918+ })
7919+ }
7920+
7921+ /// Returns committed inbound HTLCs whose onion has not yet been decoded and processed. Useful
7922+ /// for reconstructing the set of pending HTLCs when deserializing the `ChannelManager`.
7923+ pub(super) fn inbound_htlcs_pending_decode(
7924+ &self,
7925+ ) -> impl Iterator<Item = msgs::UpdateAddHTLC> + '_ {
7926+ self.context.pending_inbound_htlcs.iter().filter_map(|htlc| match &htlc.state {
7927+ InboundHTLCState::Committed {
7928+ update_add_htlc: InboundUpdateAdd::WithOnion { update_add_htlc },
7929+ } => Some(update_add_htlc.clone()),
7930+ _ => None,
7931+ })
7932+ }
7933+
7934+ /// Returns committed inbound HTLCs that have been forwarded but not yet fully resolved. Useful
7935+ /// when reconstructing the set of pending HTLCs when deserializing the `ChannelManager`.
7936+ pub(super) fn inbound_forwarded_htlcs(
78837937 &self,
7884- ) -> Vec< (PaymentHash, InboundUpdateAdd)> {
7938+ ) -> impl Iterator<Item = (PaymentHash, HTLCPreviousHopData, OutboundHop)> + '_ {
78857939 // We don't want to return an HTLC as needing processing if it already has a resolution that's
78867940 // pending in the holding cell.
78877941 let htlc_resolution_in_holding_cell = |id: u64| -> bool {
@@ -7895,19 +7949,45 @@ where
78957949 })
78967950 };
78977951
7898- self.context
7899- .pending_inbound_htlcs
7900- .iter()
7901- .filter_map(|htlc| match &htlc.state {
7902- InboundHTLCState::Committed { update_add_htlc } => {
7903- if htlc_resolution_in_holding_cell(htlc.htlc_id) {
7904- return None;
7905- }
7906- Some((htlc.payment_hash, update_add_htlc.clone()))
7907- },
7908- _ => None,
7909- })
7910- .collect()
7952+ let prev_outbound_scid_alias = self.context.outbound_scid_alias();
7953+ let user_channel_id = self.context.get_user_id();
7954+ let channel_id = self.context.channel_id();
7955+ let outpoint = self.funding_outpoint();
7956+ let counterparty_node_id = self.context.get_counterparty_node_id();
7957+
7958+ self.context.pending_inbound_htlcs.iter().filter_map(move |htlc| match &htlc.state {
7959+ InboundHTLCState::Committed {
7960+ update_add_htlc:
7961+ InboundUpdateAdd::Forwarded {
7962+ incoming_packet_shared_secret,
7963+ phantom_shared_secret,
7964+ trampoline_shared_secret,
7965+ blinded_failure,
7966+ outbound_hop,
7967+ },
7968+ } => {
7969+ if htlc_resolution_in_holding_cell(htlc.htlc_id) {
7970+ return None;
7971+ }
7972+ // The reconstructed `HTLCPreviousHopData` is used to fail or claim the HTLC backwards
7973+ // post-restart, if it is missing in the outbound edge.
7974+ let prev_hop_data = HTLCPreviousHopData {
7975+ prev_outbound_scid_alias,
7976+ user_channel_id: Some(user_channel_id),
7977+ htlc_id: htlc.htlc_id,
7978+ incoming_packet_shared_secret: *incoming_packet_shared_secret,
7979+ phantom_shared_secret: *phantom_shared_secret,
7980+ trampoline_shared_secret: *trampoline_shared_secret,
7981+ blinded_failure: *blinded_failure,
7982+ channel_id,
7983+ outpoint,
7984+ counterparty_node_id: Some(counterparty_node_id),
7985+ cltv_expiry: Some(htlc.cltv_expiry),
7986+ };
7987+ Some((htlc.payment_hash, prev_hop_data, *outbound_hop))
7988+ },
7989+ _ => None,
7990+ })
79117991 }
79127992
79137993 /// Useful when reconstructing the set of pending HTLC forwards when deserializing the
@@ -7954,12 +8034,19 @@ where
79548034 /// This inbound HTLC was irrevocably forwarded to the outbound edge, so we no longer need to
79558035 /// persist its onion.
79568036 pub(super) fn prune_inbound_htlc_onion(
7957- &mut self, htlc_id: u64, hop_data: HTLCPreviousHopData, outbound_amt_msat: u64,
8037+ &mut self, htlc_id: u64, prev_hop_data: &HTLCPreviousHopData,
8038+ outbound_hop_data: OutboundHop,
79588039 ) {
79598040 for htlc in self.context.pending_inbound_htlcs.iter_mut() {
79608041 if htlc.htlc_id == htlc_id {
79618042 if let InboundHTLCState::Committed { ref mut update_add_htlc } = htlc.state {
7962- *update_add_htlc = InboundUpdateAdd::Forwarded { hop_data, outbound_amt_msat };
8043+ *update_add_htlc = InboundUpdateAdd::Forwarded {
8044+ incoming_packet_shared_secret: prev_hop_data.incoming_packet_shared_secret,
8045+ phantom_shared_secret: prev_hop_data.phantom_shared_secret,
8046+ trampoline_shared_secret: prev_hop_data.trampoline_shared_secret,
8047+ blinded_failure: prev_hop_data.blinded_failure,
8048+ outbound_hop: outbound_hop_data,
8049+ };
79638050 return;
79648051 }
79658052 }
0 commit comments