Uh oh!
There was an error while loading. Please reload this page.
Detect and fail-back monitor-blocked un-forwarded HTLCs at close - #3989
Conversation
I've assigned @tankyleo as a reviewer! |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@## main #3989 +/- ##
==========================================
+ Coverage 88.97% 88.98% +0.01%
==========================================
Files 174 174 Lines 124161 124394 +233 Branches 124161 124394 +233 ==========================================
+ Hits 110470 110693 +223 - Misses 11216 11219 +3 - Partials 2475 2482 +7
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Uh oh!
There was an error while loading. Please reload this page.
ldk-reviews-bot
commented
Aug 5, 2025
👋 The first review has been submitted! Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer. |
54fff98 to
34abcf6CompareIf we have pending HTLCs which we intended to forward, but which were waiting on a `ChannelMonitorUpdate` to be forwarded when we closed, they will neither be in the `ChannelMonitor` nor in the `Channel` in a state which indicates they need to be failed (i.e. in the holding cell). As a result, we previously did not fail such HTLCs back immediately. Note that we cannot rely on the catch-all fail-back-before-channel-closure logic either as it is done by the `ChannelMonitor` that is unaware of these HTLCs. Here we fix this by detecting the specific case - HTLCs which are in `LocalSent` (i.e. the counterparty has not provided an RAA yet) and we have a blocked `ChannelMonitorUpdate` containing a remote commitment transaction update (which will always contain the HTLC). In such a case, we can be confident the counterparty does not have a commitment transaction containing the HTLC, and can fail it back immediately.
34abcf6 to
7c39480CompareTheBlueMatt
commented
Aug 5, 2025
Fixed handling the missing monitor update type: $ git diff-tree -U2 34abcf6603^1 7c394804b0
diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs
index 5a95295f8f..115b917649 100644
--- a/lightning/src/ln/channel.rs+++ b/lightning/src/ln/channel.rs@@ -5351,25 +5351,33 @@ where
for update in self.blocked_monitor_updates.iter() {
for update in update.update.updates.iter() {
- match update {- ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo {- htlc_outputs,+ let have_htlc = match update {+ ChannelMonitorUpdateStep::LatestCounterpartyCommitment {+ htlc_data,
..
} => {
- let have_htlc = htlc_outputs.iter().any(|(_, source)| {- source.as_ref().map(|s| &**s) == Some(&htlc.source)- });- debug_assert!(have_htlc);- if have_htlc {- dropped_outbound_htlcs.push((- htlc.source.clone(),- htlc.payment_hash,- counterparty_node_id,- self.channel_id,- ));- }- continue 'htlc_iter;+ let dust =+ htlc_data.dust_htlcs.iter().map(|(_, source)| source.as_ref());+ let nondust =+ htlc_data.nondust_htlc_sources.iter().map(|s| Some(s));+ dust.chain(nondust).any(|source| source == Some(&htlc.source))
},
- _ => {},+ ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo {+ htlc_outputs,+ ..+ } => htlc_outputs.iter().any(|(_, source)| {+ source.as_ref().map(|s| &**s) == Some(&htlc.source)+ }),+ _ => continue,+ };+ debug_assert!(have_htlc);+ if have_htlc {+ dropped_outbound_htlcs.push((+ htlc.source.clone(),+ htlc.payment_hash,+ counterparty_node_id,+ self.channel_id,+ ));
}
+ continue 'htlc_iter;
}
} |
If we have pending HTLCs which we intended to forward, but which were waiting on a
ChannelMonitorUpdateto be forwarded when we closed, they will neither be in theChannelMonitornor in theChannelin a state which indicates they need to be failed (i.e. in the holding cell). As a result, we previously did not fail such HTLCs back. Note that the catch-allfail-back-before-channel-closure logic is run by the ChannelMonitor so is also unaware of these HTLCs.
Here we fix this by detecting the specific case - HTLCs which are in
LocalSent(i.e. the counterparty has not provided an RAA yet) and we have a blockedChannelMonitorUpdatecontaining a remote commitment transaction update (which will always contain the HTLC).In such a case, we can be confident the counterparty does not have a commitment transaction containing the HTLC, and can fail it back immediately.