Skip to content

Commit 94a50a0

Browse files
committed
Stop using a constant for monitor update_ids after closure
Because `ChannelManager` doesn't have a corresponding `Channel` after the channels are closed, we'd always used an `update_id` of `u64::MAX` for any `ChannelMonitorUpdate`s we need to build after the channel is closed. This completely breaks the abstraction of `update_id`s and leaks into persistence logic - because we might have more than one `ChannelMonitorUpdate` with the same (`u64::MAX`) value, suddenly instead of being able to safely use `update_id` as IDs, the `MonitorUpdatingPersister` has to have special logic to handle this. Worse, because we don't have a unique ID with which to refer to post-close `ChannelMonitorUpdate`s we cannot track when they complete async persistence. This means we cannot properly support async persist for forwarded payments where the inbound edge has hit the chain prior to the preimage coming to us. Here we rectify this by using consistent `update_id`s even after a channel has closed. In order to do so we have to keep some state for all channels for which the `ChannelMonitor` has not been archived (after which point we can be confident we will not need to update them). While this violates our long-standing policy of having no state at all in `ChannelManager`s for closed channels, its only a `(ChannelId, u64)` pair per channel, so shouldn't be problematic for any of our users (as they already store a whole honkin `ChannelMonitor` for these channels anyway). While limited changes are made to the connection-count-limiting logic, reviewers should carefully analyze the interactions the new map created here has with that logic.
1 parent 78221cc commit 94a50a0

File tree

7 files changed

+250
-191
lines changed

7 files changed

+250
-191
lines changed

lightning-persister/src/test_utils.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use lightning::chain::channelmonitor::CLOSED_CHANNEL_UPDATE_ID;
21
use lightning::events::ClosureReason;
32
use lightning::ln::functional_test_utils::{
43
connect_block, create_announced_chan_between_nodes, create_chanmon_cfgs, create_dummy_block,
@@ -168,5 +167,5 @@ pub(crate) fn do_test_store<K: KVStore>(store_0: &K, store_1: &K) {
168167
check_added_monitors!(nodes[1], 1);
169168

170169
// Make sure everything is persisted as expected after close.
171-
check_persisted_data!(CLOSED_CHANNEL_UPDATE_ID);
170+
check_persisted_data!(11);
172171
}

lightning/src/chain/channelmonitor.rs

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,9 @@ pub struct ChannelMonitorUpdate {
8888
/// [`ChannelMonitorUpdateStatus::InProgress`] have been applied to all copies of a given
8989
/// ChannelMonitor when ChannelManager::channel_monitor_updated is called.
9090
///
91-
/// The only instances we allow where update_id values are not strictly increasing have a
92-
/// special update ID of [`CLOSED_CHANNEL_UPDATE_ID`]. This update ID is used for updates that
93-
/// will force close the channel by broadcasting the latest commitment transaction or
94-
/// special post-force-close updates, like providing preimages necessary to claim outputs on the
95-
/// broadcast commitment transaction. See its docs for more details.
91+
/// Note that for [`ChannelMonitorUpdate]`s generated on LDK versions prior to 0.1 after the
92+
/// channel was closed, this value may be [`u64::MAX`]. In that case, multiple updates may
93+
/// appear with the same ID, and all should be replayed.
9694
///
9795
/// [`ChannelMonitorUpdateStatus::InProgress`]: super::ChannelMonitorUpdateStatus::InProgress
9896
pub update_id: u64,
@@ -103,16 +101,6 @@ pub struct ChannelMonitorUpdate {
103101
pub channel_id: Option<ChannelId>,
104102
}
105103

106-
/// The update ID used for a [`ChannelMonitorUpdate`] that is either:
107-
///
108-
/// (1) attempting to force close the channel by broadcasting our latest commitment transaction or
109-
/// (2) providing a preimage (after the channel has been force closed) from a forward link that
110-
/// allows us to spend an HTLC output on this channel's (the backward link's) broadcasted
111-
/// commitment transaction.
112-
///
113-
/// No other [`ChannelMonitorUpdate`]s are allowed after force-close.
114-
pub const CLOSED_CHANNEL_UPDATE_ID: u64 = core::u64::MAX;
115-
116104
impl Writeable for ChannelMonitorUpdate {
117105
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
118106
write_ver_prefix!(w, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
@@ -1528,6 +1516,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
15281516

15291517
/// Gets the update_id from the latest ChannelMonitorUpdate which was applied to this
15301518
/// ChannelMonitor.
1519+
///
1520+
/// Note that for channels closed prior to LDK 0.1, this may return [`u64::MAX`].
15311521
pub fn get_latest_update_id(&self) -> u64 {
15321522
self.inner.lock().unwrap().get_latest_update_id()
15331523
}
@@ -3078,11 +3068,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
30783068
F::Target: FeeEstimator,
30793069
L::Target: Logger,
30803070
{
3081-
if self.latest_update_id == CLOSED_CHANNEL_UPDATE_ID && updates.update_id == CLOSED_CHANNEL_UPDATE_ID {
3082-
log_info!(logger, "Applying post-force-closed update to monitor {} with {} change(s).",
3071+
if self.latest_update_id == u64::MAX && updates.update_id == u64::MAX {
3072+
log_info!(logger, "Applying pre-0.1 post-force-closed update to monitor {} with {} change(s).",
30833073
log_funding_info!(self), updates.updates.len());
3084-
} else if updates.update_id == CLOSED_CHANNEL_UPDATE_ID {
3085-
log_info!(logger, "Applying force close update to monitor {} with {} change(s).",
3074+
} else if updates.update_id == u64::MAX {
3075+
log_info!(logger, "Applying pre-0.1 force close update to monitor {} with {} change(s).",
30863076
log_funding_info!(self), updates.updates.len());
30873077
} else {
30883078
log_info!(logger, "Applying update to monitor {}, bringing update_id from {} to {} with {} change(s).",
@@ -3105,14 +3095,14 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
31053095
// The `ChannelManager` may also queue redundant `ChannelForceClosed` updates if it still
31063096
// thinks the channel needs to have its commitment transaction broadcast, so we'll allow
31073097
// them as well.
3108-
if updates.update_id == CLOSED_CHANNEL_UPDATE_ID {
3098+
if updates.update_id == u64::MAX || self.lockdown_from_offchain {
31093099
assert_eq!(updates.updates.len(), 1);
31103100
match updates.updates[0] {
31113101
ChannelMonitorUpdateStep::ChannelForceClosed { .. } => {},
31123102
// We should have already seen a `ChannelForceClosed` update if we're trying to
31133103
// provide a preimage at this point.
31143104
ChannelMonitorUpdateStep::PaymentPreimage { .. } =>
3115-
debug_assert_eq!(self.latest_update_id, CLOSED_CHANNEL_UPDATE_ID),
3105+
debug_assert!(self.lockdown_from_offchain),
31163106
_ => {
31173107
log_error!(logger, "Attempted to apply post-force-close ChannelMonitorUpdate of type {}", updates.updates[0].variant_name());
31183108
panic!("Attempted to apply post-force-close ChannelMonitorUpdate that wasn't providing a payment preimage");
@@ -3192,17 +3182,24 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
31923182
self.counterparty_commitment_txs_from_update(updates);
31933183
}
31943184

3195-
// If the updates succeeded and we were in an already closed channel state, then there's no
3196-
// need to refuse any updates we expect to receive afer seeing a confirmed commitment.
3197-
if ret.is_ok() && updates.update_id == CLOSED_CHANNEL_UPDATE_ID && self.latest_update_id == updates.update_id {
3198-
return Ok(());
3199-
}
3200-
32013185
self.latest_update_id = updates.update_id;
32023186

3203-
// Refuse updates after we've detected a spend onchain, but only if we haven't processed a
3204-
// force closed monitor update yet.
3205-
if ret.is_ok() && self.funding_spend_seen && self.latest_update_id != CLOSED_CHANNEL_UPDATE_ID {
3187+
// Refuse updates after we've detected a spend onchain (or are otherwise closed), but only
3188+
// if the update isn't the kind of update we expect to see after channel closure.
3189+
let mut is_pre_close_update = false;
3190+
for update in updates.updates.iter() {
3191+
match update {
3192+
ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { .. }
3193+
|ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. }
3194+
|ChannelMonitorUpdateStep::ShutdownScript { .. }
3195+
|ChannelMonitorUpdateStep::CommitmentSecret { .. } =>
3196+
is_pre_close_update = true,
3197+
ChannelMonitorUpdateStep::PaymentPreimage { .. } => {},
3198+
ChannelMonitorUpdateStep::ChannelForceClosed { .. } => {},
3199+
}
3200+
}
3201+
3202+
if ret.is_ok() && (self.funding_spend_seen || self.lockdown_from_offchain) && is_pre_close_update {
32063203
log_error!(logger, "Refusing Channel Monitor Update as counterparty attempted to update commitment after funding was spent");
32073204
Err(())
32083205
} else { ret }

lightning/src/ln/channel.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use crate::ln::chan_utils;
4444
use crate::ln::onion_utils::HTLCFailReason;
4545
use crate::chain::BestBlock;
4646
use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBoundedFeeEstimator};
47-
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS, CLOSED_CHANNEL_UPDATE_ID};
47+
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS};
4848
use crate::chain::transaction::{OutPoint, TransactionData};
4949
use crate::sign::ecdsa::EcdsaChannelSigner;
5050
use crate::sign::{EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient};
@@ -3509,7 +3509,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
35093509
// monitor update to the user, even if we return one).
35103510
// See test_duplicate_chan_id and test_pre_lockin_no_chan_closed_update for more.
35113511
if !self.channel_state.is_pre_funded_state() {
3512-
self.latest_monitor_update_id = CLOSED_CHANNEL_UPDATE_ID;
3512+
self.latest_monitor_update_id += 1;
35133513
Some((self.get_counterparty_node_id(), funding_txo, self.channel_id(), ChannelMonitorUpdate {
35143514
update_id: self.latest_monitor_update_id,
35153515
counterparty_node_id: Some(self.counterparty_node_id),

0 commit comments

Comments
 (0)