Skip to content

Commit 6749a07

Browse files
committed
Only generate a post-close lock ChannelMonitorUpdate if we need one
If a channel is closed on startup, but we find that the `ChannelMonitor` isn't aware of this, we generate a `ChannelMonitorUpdate` containing a `ChannelMonitorUpdateStep::ChannelForceClosed`. This ensures that the `ChannelMonitor` will not accept any future updates in case we somehow load up a previous `ChannelManager` (though that really shouldn't happen). Previously, we'd apply this update only if we detected that the `ChannelManager` had not yet informed the `ChannelMonitor` about the channel's closure, even if the `ChannelMonitor` would already refuse any other updates because it detected a channel closure on chain. This doesn't accomplish anything but an extra I/O write, so we remove it here. Further, a user reported that, in regtest, they could: (a) coop close a channel (not generating a `ChannelMonitorUpdate`) (b) wait just under 4032 blocks (on regtest, taking only a day) (c) restart the `ChannelManager`, generating the above update (d) connect a block or two (during the startup sequence), making the `ChannelMonitor` eligible for archival, (d) restart the `ChannelManager` again (without applying the update from (c), but after having archived the `ChannelMonitor`, leading to a failure to deserialize as we have a pending `ChannelMonitorUpdate` for a `ChannelMonitor` that has been archived. Though it seems very unlikely this would happen on mainnet, it is theoretically possible.
1 parent 653c482 commit 6749a07

File tree

2 files changed

+16
-8
lines changed

2 files changed

+16
-8
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1737,10 +1737,14 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
17371737
self.inner.lock().unwrap().get_cur_holder_commitment_number()
17381738
}
17391739

1740-
/// Gets whether we've been notified that this channel is closed by the `ChannelManager` (i.e.
1741-
/// via a [`ChannelMonitorUpdateStep::ChannelForceClosed`]).
1742-
pub(crate) fn offchain_closed(&self) -> bool {
1743-
self.inner.lock().unwrap().lockdown_from_offchain
1740+
/// Fetches whether this monitor has marked the channel as closed and will refuse any further
1741+
/// updates to the commitment transactions.
1742+
///
1743+
/// It can be marked closed in a few different ways, including via a
1744+
/// [`ChannelMonitorUpdateStep::ChannelForceClosed`] or if the channel has been closed
1745+
/// on-chain.
1746+
pub(crate) fn no_further_updates_allowed(&self) -> bool {
1747+
self.inner.lock().unwrap().no_further_updates_allowed()
17441748
}
17451749

17461750
/// Gets the `node_id` of the counterparty for this channel.
@@ -3278,12 +3282,16 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
32783282
}
32793283
}
32803284

3281-
if ret.is_ok() && (self.funding_spend_seen || self.lockdown_from_offchain || self.holder_tx_signed) && is_pre_close_update {
3285+
if ret.is_ok() && self.no_further_updates_allowed() && is_pre_close_update {
32823286
log_error!(logger, "Refusing Channel Monitor Update as counterparty attempted to update commitment after funding was spent");
32833287
Err(())
32843288
} else { ret }
32853289
}
32863290

3291+
fn no_further_updates_allowed(&self) -> bool {
3292+
self.funding_spend_seen || self.lockdown_from_offchain || self.holder_tx_signed
3293+
}
3294+
32873295
fn get_latest_update_id(&self) -> u64 {
32883296
self.latest_update_id
32893297
}
@@ -4227,7 +4235,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
42274235
}
42284236
}
42294237

4230-
if self.lockdown_from_offchain || self.funding_spend_seen || self.holder_tx_signed {
4238+
if self.no_further_updates_allowed() {
42314239
// Fail back HTLCs on backwards channels if they expire within
42324240
// `LATENCY_GRACE_PERIOD_BLOCKS` blocks and the channel is closed (i.e. we're at a
42334241
// point where no further off-chain updates will be accepted). If we haven't seen the

lightning/src/ln/channelmanager.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13364,8 +13364,8 @@ where
1336413364
// claim.
1336513365
// Note that a `ChannelMonitor` is created with `update_id` 0 and after we
1336613366
// provide it with a closure update its `update_id` will be at 1.
13367-
if !monitor.offchain_closed() || monitor.get_latest_update_id() > 1 {
13368-
should_queue_fc_update = !monitor.offchain_closed();
13367+
if !monitor.no_further_updates_allowed() || monitor.get_latest_update_id() > 1 {
13368+
should_queue_fc_update = !monitor.no_further_updates_allowed();
1336913369
let mut latest_update_id = monitor.get_latest_update_id();
1337013370
if should_queue_fc_update {
1337113371
latest_update_id += 1;

0 commit comments

Comments
 (0)