Skip to content

Commit 744664e

Browse files
committed
Immediately archive ChannelMonitors for inbound unfuned channels
If a peer opens a channel to us, but never actually broadcasts the funding transaction, we'll still keep a `ChannelMonitor` around for the channel. While we maybe shouldn't do this either, when the channel ultimately times out 2016 blocks later, we should at least immediately archive the `ChannelMonitor`, which we do here. Fixes #3384
1 parent 5ae19b4 commit 744664e

File tree

2 files changed

+66
-10
lines changed

2 files changed

+66
-10
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2571,6 +2571,16 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
25712571
let current_height = self.current_best_block().height;
25722572
let mut inner = self.inner.lock().unwrap();
25732573

2574+
if inner.is_closed_without_updates()
2575+
&& is_all_funds_claimed
2576+
&& !inner.funding_spend_seen
2577+
{
2578+
// We closed the channel without ever advancing it and didn't have any funds in it.
2579+
// We should immediately archive this monitor as there's nothing for us to ever do with
2580+
// it.
2581+
return (true, false);
2582+
}
2583+
25742584
if is_all_funds_claimed && !inner.funding_spend_seen {
25752585
debug_assert!(false, "We should see funding spend by the time a monitor clears out");
25762586
is_all_funds_claimed = false;
@@ -3044,7 +3054,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
30443054
transaction_fee_satoshis,
30453055
}
30463056
})
3047-
.collect();
3057+
.collect::<Vec<_>>();
30483058
let confirmed_balance_candidate_index = core::iter::once(&us.funding)
30493059
.chain(us.pending_funding.iter())
30503060
.enumerate()
@@ -3057,14 +3067,25 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
30573067
})
30583068
.map(|(idx, _)| idx)
30593069
.expect("We must have one FundingScope that is confirmed");
3060-
res.push(Balance::ClaimableOnChannelClose {
3061-
balance_candidates,
3062-
confirmed_balance_candidate_index,
3063-
outbound_payment_htlc_rounded_msat,
3064-
outbound_forwarded_htlc_rounded_msat,
3065-
inbound_claiming_htlc_rounded_msat,
3066-
inbound_htlc_rounded_msat,
3067-
});
3070+
3071+
// Only push a primary balance if either the channel isn't closed or we've advanced the
3072+
// channel state machine at least once (implying there are multiple previous commitment
3073+
// transactions) or we actually have a balance.
3074+
// Avoiding including a `Balance` if none of these are true allows us to prune monitors
3075+
// for chanels that were opened inbound to us but where the funding transaction never
3076+
// confirmed at all.
3077+
if !us.is_closed_without_updates()
3078+
|| balance_candidates.iter().any(|bal| bal.amount_satoshis != 0)
3079+
{
3080+
res.push(Balance::ClaimableOnChannelClose {
3081+
balance_candidates,
3082+
confirmed_balance_candidate_index,
3083+
outbound_payment_htlc_rounded_msat,
3084+
outbound_forwarded_htlc_rounded_msat,
3085+
inbound_claiming_htlc_rounded_msat,
3086+
inbound_htlc_rounded_msat,
3087+
});
3088+
}
30683089
}
30693090

30703091
res
@@ -4352,6 +4373,16 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
43524373
} else { ret }
43534374
}
43544375

4376+
/// Returns true if the channel has been closed (i.e. no further updates are allowed) and no
4377+
/// commitment state updates ever happened.
4378+
fn is_closed_without_updates(&self) -> bool {
4379+
let mut commitment_not_advanced =
4380+
self.current_counterparty_commitment_number == INITIAL_COMMITMENT_NUMBER;
4381+
commitment_not_advanced &=
4382+
self.current_holder_commitment_number == INITIAL_COMMITMENT_NUMBER;
4383+
(self.holder_tx_signed || self.lockdown_from_offchain) && commitment_not_advanced
4384+
}
4385+
43554386
fn no_further_updates_allowed(&self) -> bool {
43564387
self.funding_spend_seen || self.lockdown_from_offchain || self.holder_tx_signed
43574388
}

lightning/src/ln/functional_tests.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use crate::chain::channelmonitor::{
1818
Balance, ANTI_REORG_DELAY, CLTV_CLAIM_BUFFER, COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE,
1919
LATENCY_GRACE_PERIOD_BLOCKS,
2020
};
21+
use crate::chain::transaction::OutPoint;
2122
use crate::chain::{ChannelMonitorUpdateStatus, Confirm, Listen, Watch};
2223
use crate::events::{
2324
ClosureReason, Event, HTLCHandlingFailureType, PathFailure, PaymentFailureReason,
@@ -6631,9 +6632,13 @@ pub fn test_channel_conf_timeout() {
66316632

66326633
let node_a_id = nodes[0].node.get_our_node_id();
66336634

6634-
let _funding_tx =
6635+
let funding_tx =
66356636
create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 1_000_000, 100_000);
66366637

6638+
// Inbound channels which haven't advanced state at all and never were funded will generate
6639+
// claimable `Balance`s until they're closed.
6640+
assert!(!nodes[1].chain_monitor.chain_monitor.get_claimable_balances(&[]).is_empty());
6641+
66376642
// The outbound node should wait forever for confirmation:
66386643
// This matches `channel::FUNDING_CONF_DEADLINE_BLOCKS` and BOLT 2's suggested timeout, thus is
66396644
// copied here instead of directly referencing the constant.
@@ -6645,6 +6650,10 @@ pub fn test_channel_conf_timeout() {
66456650
check_added_monitors(&nodes[1], 0);
66466651
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
66476652

6653+
nodes[1].chain_monitor.chain_monitor.archive_fully_resolved_channel_monitors();
6654+
assert_eq!(nodes[1].chain_monitor.chain_monitor.list_monitors().len(), 1);
6655+
assert!(!nodes[1].chain_monitor.chain_monitor.get_claimable_balances(&[]).is_empty());
6656+
66486657
connect_blocks(&nodes[1], 1);
66496658
check_added_monitors(&nodes[1], 1);
66506659
check_closed_event!(nodes[1], 1, ClosureReason::FundingTimedOut, [node_a_id], 1000000);
@@ -6663,6 +6672,22 @@ pub fn test_channel_conf_timeout() {
66636672
},
66646673
_ => panic!("Unexpected event"),
66656674
}
6675+
6676+
// Once an inbound never-confirmed channel is closed, it will no longer generate any claimable
6677+
// `Balance`s.
6678+
assert!(nodes[1].chain_monitor.chain_monitor.get_claimable_balances(&[]).is_empty());
6679+
6680+
// Once the funding times out the monitor should be immediately archived.
6681+
nodes[1].chain_monitor.chain_monitor.archive_fully_resolved_channel_monitors();
6682+
assert_eq!(nodes[1].chain_monitor.chain_monitor.list_monitors().len(), 0);
6683+
assert!(nodes[1].chain_monitor.chain_monitor.get_claimable_balances(&[]).is_empty());
6684+
6685+
// Remove the corresponding outputs and transactions the chain source is
6686+
// watching. This is to make sure the `Drop` function assertions pass.
6687+
nodes[1].chain_source.remove_watched_txn_and_outputs(
6688+
OutPoint { txid: funding_tx.compute_txid(), index: 0 },
6689+
funding_tx.output[0].script_pubkey.clone(),
6690+
);
66666691
}
66676692

66686693
#[xtest(feature = "_externalize_tests")]

0 commit comments

Comments
 (0)