Skip to content

Commit dbe4aad

Browse files
committed
Fail HTLCs which were removed from a channel but not persisted
When a channel is force-closed, if a `ChannelMonitor` update is completed but a `ChannelManager` persist has not yet happened, HTLCs which were removed in the latest (persisted) `ChannelMonitor` update will not be failed even though they do not appear in the commitment transaction which went on chain. This is because the `ChannelManager` thinks the `ChannelMonitor` is responsible for them (as it is stale), but the `ChannelMonitor` has no knowledge of the HTLC at all (as it is not stale). The fix for this is relatively simple - we need to check for this specific case and fail back such HTLCs when deserializing a `ChannelManager`
1 parent 0bb87dd commit dbe4aad

File tree

3 files changed

+100
-5
lines changed

3 files changed

+100
-5
lines changed

lightning/src/ln/channel.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5951,15 +5951,16 @@ impl<Signer: Sign> Channel<Signer> {
59515951
(monitor_update, dropped_outbound_htlcs)
59525952
}
59535953

5954-
pub fn inflight_htlc_sources(&self) -> impl Iterator<Item=&HTLCSource> {
5954+
pub fn inflight_htlc_sources(&self) -> impl Iterator<Item=(&HTLCSource, &PaymentHash)> {
59555955
self.holding_cell_htlc_updates.iter()
59565956
.flat_map(|htlc_update| {
59575957
match htlc_update {
5958-
HTLCUpdateAwaitingACK::AddHTLC { source, .. } => { Some(source) }
5959-
_ => None
5958+
HTLCUpdateAwaitingACK::AddHTLC { source, payment_hash, .. }
5959+
=> Some((source, payment_hash)),
5960+
_ => None,
59605961
}
59615962
})
5962-
.chain(self.pending_outbound_htlcs.iter().map(|htlc| &htlc.source))
5963+
.chain(self.pending_outbound_htlcs.iter().map(|htlc| (&htlc.source, &htlc.payment_hash)))
59635964
}
59645965
}
59655966

lightning/src/ln/channelmanager.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5728,7 +5728,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
57285728
let mut inflight_htlcs = InFlightHtlcs::new();
57295729

57305730
for chan in self.channel_state.lock().unwrap().by_id.values() {
5731-
for htlc_source in chan.inflight_htlc_sources() {
5731+
for (htlc_source, _) in chan.inflight_htlc_sources() {
57325732
if let HTLCSource::OutboundRoute { path, .. } = htlc_source {
57335733
inflight_htlcs.process_path(path, self.get_our_node_id());
57345734
}
@@ -5746,6 +5746,12 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
57465746
events.into_inner()
57475747
}
57485748

5749+
#[cfg(test)]
5750+
pub fn pop_pending_event(&self) -> Option<events::Event> {
5751+
let mut events = self.pending_events.lock().unwrap();
5752+
if events.is_empty() { None } else { Some(events.remove(0)) }
5753+
}
5754+
57495755
#[cfg(test)]
57505756
pub fn has_pending_payments(&self) -> bool {
57515757
!self.pending_outbound_payments.lock().unwrap().is_empty()
@@ -7206,6 +7212,25 @@ impl<'a, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
72067212
user_channel_id: channel.get_user_id(),
72077213
reason: ClosureReason::OutdatedChannelManager
72087214
});
7215+
for (channel_htlc_source, payment_hash) in channel.inflight_htlc_sources() {
7216+
let mut found_htlc = false;
7217+
for (monitor_htlc_source, _) in monitor.get_all_current_outbound_htlcs() {
7218+
if *channel_htlc_source == monitor_htlc_source { found_htlc = true; break; }
7219+
}
7220+
if !found_htlc {
7221+
// If we have some HTLCs in the channel which are not present in the newer
7222+
// ChannelMonitor, they have been removed and should be failed back to
7223+
// ensure we don't forget them entirely. Note that if the missing HTLC(s)
7224+
// were actually claimed we'd have generated and ensured the previous-hop
7225+
// claim update ChannelMonitor updates were persisted prior to persising
7226+
// the ChannelMonitor update for the forward leg, so attempting to fail the
7227+
// backwards leg of the HTLC will simply be rejected.
7228+
log_info!(args.logger,
7229+
"Failing HTLC with hash {} as it is missing in the ChannelMonitor for channel {} but was present in the (stale) ChannelManager",
7230+
log_bytes!(channel.channel_id()), log_bytes!(payment_hash.0));
7231+
failed_htlcs.push((channel_htlc_source.clone(), *payment_hash, channel.get_counterparty_node_id(), channel.channel_id()));
7232+
}
7233+
}
72097234
} else {
72107235
log_info!(args.logger, "Successfully loaded channel {}", log_bytes!(channel.channel_id()));
72117236
if let Some(short_channel_id) = channel.get_short_channel_id() {

lightning/src/ln/reload_tests.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,3 +933,72 @@ fn forwarded_payment_no_manager_persistence() {
933933
do_forwarded_payment_no_manager_persistence(true, false);
934934
do_forwarded_payment_no_manager_persistence(false, false);
935935
}
936+
937+
#[test]
938+
fn removed_payment_no_manager_persistence() {
939+
// If an HTLC is failed to us on a channel, and the ChannelMonitor persistence completes, but
940+
// the corresponding ChannelManager persistence does not, we need to ensure that the HTLC is
941+
// still failed back to the previous hop even though the ChannelMonitor now no longer is aware
942+
// of the HTLC. This was previously broken as no attempt was made to figure out which HTLCs
943+
// were left dangling when a channel was force-closed due to a stale ChannelManager.
944+
let chanmon_cfgs = create_chanmon_cfgs(3);
945+
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
946+
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
947+
948+
let persister;
949+
let new_chain_monitor;
950+
let nodes_1_deserialized;
951+
952+
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
953+
954+
let chan_id_1 = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
955+
let chan_id_2 = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2;
956+
957+
let (_, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000);
958+
959+
let node_encoded = nodes[1].node.encode();
960+
961+
nodes[2].node.fail_htlc_backwards(&payment_hash);
962+
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[2], [HTLCDestination::FailedPayment { payment_hash }]);
963+
check_added_monitors!(nodes[2], 1);
964+
let events = nodes[2].node.get_and_clear_pending_msg_events();
965+
assert_eq!(events.len(), 1);
966+
match &events[0] {
967+
MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { update_fail_htlcs, commitment_signed, .. }, .. } => {
968+
nodes[1].node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &update_fail_htlcs[0]);
969+
commitment_signed_dance!(nodes[1], nodes[2], commitment_signed, false);
970+
},
971+
_ => panic!("Unexpected event"),
972+
}
973+
974+
let chan_0_monitor_serialized = get_monitor!(nodes[1], chan_id_1).encode();
975+
let chan_1_monitor_serialized = get_monitor!(nodes[1], chan_id_2).encode();
976+
reload_node!(nodes[1], node_encoded, &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], persister, new_chain_monitor, nodes_1_deserialized);
977+
978+
match nodes[1].node.pop_pending_event().unwrap() {
979+
Event::ChannelClosed { ref reason, .. } => {
980+
assert_eq!(*reason, ClosureReason::OutdatedChannelManager);
981+
},
982+
_ => panic!("Unexpected event"),
983+
}
984+
985+
// Now that the ChannelManager has force-closed the channel which had the HTLC removed, it is
986+
// now forgotten everywhere. The ChannelManager should have, as a side-effect of reload,
987+
// learned that the HTLC is gone from the ChannelMonitor and added it to the to-fail-back set.
988+
nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), true);
989+
reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false));
990+
991+
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], [HTLCDestination::NextHopChannel { node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_id_2 }]);
992+
check_added_monitors!(nodes[1], 1);
993+
let events = nodes[1].node.get_and_clear_pending_msg_events();
994+
assert_eq!(events.len(), 1);
995+
match &events[0] {
996+
MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { update_fail_htlcs, commitment_signed, .. }, .. } => {
997+
nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &update_fail_htlcs[0]);
998+
commitment_signed_dance!(nodes[0], nodes[1], commitment_signed, false);
999+
},
1000+
_ => panic!("Unexpected event"),
1001+
}
1002+
1003+
expect_payment_failed!(nodes[0], payment_hash, false);
1004+
}

0 commit comments

Comments
 (0)