Skip to content

Commit b3b59e6

Browse files
Persist outbound channel info in inbound HTLCs
We need these fields to generate a correct PaymentForwarded event if we need to claim this inbound HTLC backwards after restart and it's already been claimed and removed on the outbound edge.
1 parent 70ae54f commit b3b59e6

2 files changed

Lines changed: 72 additions & 23 deletions

File tree

lightning/src/ln/channel.rs

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,32 @@ 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
@@ -328,11 +354,7 @@ enum InboundUpdateAdd {
328354
phantom_shared_secret: Option<[u8; 32]>,
329355
trampoline_shared_secret: Option<[u8; 32]>,
330356
blinded_failure: Option<BlindedFailure>,
331-
/// Useful for generating an accurate [`Event::PaymentForwarded`], if we need to claim this
332-
/// HTLC post-restart.
333-
///
334-
/// [`Event::PaymentForwarded`]: crate::events::Event::PaymentForwarded
335-
outbound_amt_msat: u64,
357+
outbound_hop: OutboundHop,
336358
},
337359
/// This HTLC was received pre-LDK 0.3, before we started persisting the onion for inbound
338360
/// committed HTLCs.
@@ -346,7 +368,7 @@ impl_writeable_tlv_based_enum_upgradable!(InboundUpdateAdd,
346368
(2, Legacy) => {},
347369
(4, Forwarded) => {
348370
(0, incoming_packet_shared_secret, required),
349-
(2, outbound_amt_msat, required),
371+
(2, outbound_hop, required),
350372
(4, phantom_shared_secret, option),
351373
(6, trampoline_shared_secret, option),
352374
(8, blinded_failure, option),
@@ -7948,15 +7970,15 @@ where
79487970
phantom_shared_secret,
79497971
trampoline_shared_secret,
79507972
blinded_failure,
7951-
outbound_amt_msat,
7973+
outbound_hop: OutboundHop { amt_msat, .. },
79527974
},
79537975
} => {
79547976
if htlc_resolution_in_holding_cell(htlc.htlc_id) {
79557977
return None;
79567978
}
79577979
// The reconstructed `HTLCPreviousHopData` is used to fail or claim the HTLC backwards
79587980
// post-restart, if it is missing in the outbound edge.
7959-
let hop_data = HTLCPreviousHopData {
7981+
let prev_hop_data = HTLCPreviousHopData {
79607982
prev_outbound_scid_alias,
79617983
user_channel_id: Some(user_channel_id),
79627984
htlc_id: htlc.htlc_id,
@@ -7969,7 +7991,7 @@ where
79697991
counterparty_node_id: Some(counterparty_node_id),
79707992
cltv_expiry: Some(htlc.cltv_expiry),
79717993
};
7972-
Some((htlc.payment_hash, hop_data, *outbound_amt_msat))
7994+
Some((htlc.payment_hash, prev_hop_data, *amt_msat))
79737995
},
79747996
_ => None,
79757997
})
@@ -8019,17 +8041,18 @@ where
80198041
/// This inbound HTLC was irrevocably forwarded to the outbound edge, so we no longer need to
80208042
/// persist its onion.
80218043
pub(super) fn prune_inbound_htlc_onion(
8022-
&mut self, htlc_id: u64, hop_data: &HTLCPreviousHopData, outbound_amt_msat: u64,
8044+
&mut self, htlc_id: u64, prev_hop_data: &HTLCPreviousHopData,
8045+
outbound_hop_data: OutboundHop,
80238046
) {
80248047
for htlc in self.context.pending_inbound_htlcs.iter_mut() {
80258048
if htlc.htlc_id == htlc_id {
80268049
if let InboundHTLCState::Committed { ref mut update_add_htlc } = htlc.state {
80278050
*update_add_htlc = InboundUpdateAdd::Forwarded {
8028-
incoming_packet_shared_secret: hop_data.incoming_packet_shared_secret,
8029-
phantom_shared_secret: hop_data.phantom_shared_secret,
8030-
trampoline_shared_secret: hop_data.trampoline_shared_secret,
8031-
blinded_failure: hop_data.blinded_failure,
8032-
outbound_amt_msat,
8051+
incoming_packet_shared_secret: prev_hop_data.incoming_packet_shared_secret,
8052+
phantom_shared_secret: prev_hop_data.phantom_shared_secret,
8053+
trampoline_shared_secret: prev_hop_data.trampoline_shared_secret,
8054+
blinded_failure: prev_hop_data.blinded_failure,
8055+
outbound_hop: outbound_hop_data,
80338056
};
80348057
return;
80358058
}

lightning/src/ln/channelmanager.rs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ use crate::ln::chan_utils::selected_commitment_sat_per_1000_weight;
5959
use crate::ln::channel::QuiescentAction;
6060
use crate::ln::channel::{
6161
self, hold_time_since, Channel, ChannelError, ChannelUpdateStatus, DisconnectResult,
62-
FundedChannel, FundingTxSigned, InboundV1Channel, OutboundV1Channel, PendingV2Channel,
63-
ReconnectionMsg, ShutdownResult, SpliceFundingFailed, StfuResponse, UpdateFulfillCommitFetch,
64-
WithChannelContext,
62+
FundedChannel, FundingTxSigned, InboundV1Channel, OutboundHop, OutboundV1Channel,
63+
PendingV2Channel, ReconnectionMsg, ShutdownResult, SpliceFundingFailed, StfuResponse,
64+
UpdateFulfillCommitFetch, WithChannelContext,
6565
};
6666
use crate::ln::channel_state::ChannelDetails;
6767
use crate::ln::funding::SpliceContribution;
@@ -1402,6 +1402,8 @@ enum PostMonitorUpdateChanResume {
14021402
Unblocked {
14031403
channel_id: ChannelId,
14041404
counterparty_node_id: PublicKey,
1405+
funding_txo: OutPoint,
1406+
user_channel_id: u128,
14051407
unbroadcasted_batch_funding_txid: Option<Txid>,
14061408
update_actions: Vec<MonitorUpdateCompletionAction>,
14071409
htlc_forwards: Option<PerSourcePendingForward>,
@@ -9582,8 +9584,8 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
95829584
/// Handles actions which need to complete after a [`ChannelMonitorUpdate`] has been applied
95839585
/// which can happen after the per-peer state lock has been dropped.
95849586
fn post_monitor_update_unlock(
9585-
&self, channel_id: ChannelId, counterparty_node_id: PublicKey,
9586-
unbroadcasted_batch_funding_txid: Option<Txid>,
9587+
&self, channel_id: ChannelId, counterparty_node_id: PublicKey, funding_txo: OutPoint,
9588+
user_channel_id: u128, unbroadcasted_batch_funding_txid: Option<Txid>,
95879589
update_actions: Vec<MonitorUpdateCompletionAction>,
95889590
htlc_forwards: Option<PerSourcePendingForward>,
95899591
decode_update_add_htlcs: Option<(u64, Vec<msgs::UpdateAddHTLC>)>,
@@ -9660,7 +9662,13 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
96609662
};
96619663
self.fail_htlc_backwards_internal(&failure.0, &failure.1, &failure.2, receiver, None);
96629664
}
9663-
self.prune_persisted_inbound_htlc_onions(committed_outbound_htlc_sources);
9665+
self.prune_persisted_inbound_htlc_onions(
9666+
channel_id,
9667+
counterparty_node_id,
9668+
funding_txo,
9669+
user_channel_id,
9670+
committed_outbound_htlc_sources,
9671+
);
96649672
}
96659673

96669674
fn handle_monitor_update_completion_actions<
@@ -10129,6 +10137,8 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1012910137
PostMonitorUpdateChanResume::Unblocked {
1013010138
channel_id: chan_id,
1013110139
counterparty_node_id,
10140+
funding_txo: chan.funding_outpoint(),
10141+
user_channel_id: chan.context.get_user_id(),
1013210142
unbroadcasted_batch_funding_txid,
1013310143
update_actions,
1013410144
htlc_forwards,
@@ -10144,7 +10154,9 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1014410154
/// HTLC set on `ChannelManager` read. If an HTLC has been irrevocably forwarded to the outbound
1014510155
/// edge, we no longer need to persist the inbound edge's onion and can prune it here.
1014610156
fn prune_persisted_inbound_htlc_onions(
10147-
&self, committed_outbound_htlc_sources: Vec<(HTLCPreviousHopData, u64)>,
10157+
&self, outbound_channel_id: ChannelId, outbound_node_id: PublicKey,
10158+
outbound_funding_txo: OutPoint, outbound_user_channel_id: u128,
10159+
committed_outbound_htlc_sources: Vec<(HTLCPreviousHopData, u64)>,
1014810160
) {
1014910161
let per_peer_state = self.per_peer_state.read().unwrap();
1015010162
for (source, outbound_amt_msat) in committed_outbound_htlc_sources {
@@ -10161,7 +10173,17 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1016110173
if let Some(chan) =
1016210174
peer_state.channel_by_id.get_mut(&source.channel_id).and_then(|c| c.as_funded_mut())
1016310175
{
10164-
chan.prune_inbound_htlc_onion(source.htlc_id, &source, outbound_amt_msat);
10176+
chan.prune_inbound_htlc_onion(
10177+
source.htlc_id,
10178+
&source,
10179+
OutboundHop {
10180+
amt_msat: outbound_amt_msat,
10181+
channel_id: outbound_channel_id,
10182+
node_id: outbound_node_id,
10183+
funding_txo: outbound_funding_txo,
10184+
user_channel_id: outbound_user_channel_id,
10185+
},
10186+
);
1016510187
}
1016610188
}
1016710189
}
@@ -10217,6 +10239,8 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1021710239
PostMonitorUpdateChanResume::Unblocked {
1021810240
channel_id,
1021910241
counterparty_node_id,
10242+
funding_txo,
10243+
user_channel_id,
1022010244
unbroadcasted_batch_funding_txid,
1022110245
update_actions,
1022210246
htlc_forwards,
@@ -10228,6 +10252,8 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1022810252
self.post_monitor_update_unlock(
1022910253
channel_id,
1023010254
counterparty_node_id,
10255+
funding_txo,
10256+
user_channel_id,
1023110257
unbroadcasted_batch_funding_txid,
1023210258
update_actions,
1023310259
htlc_forwards,

0 commit comments

Comments
 (0)