Skip to content

Commit c99d3d7

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 3f36890 commit c99d3d7

File tree

7 files changed

+256
-190
lines changed

7 files changed

+256
-190
lines changed

lightning-persister/src/test_utils.rs

+1-2
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

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

107-
/// The update ID used for a [`ChannelMonitorUpdate`] that is either:
108-
///
109-
/// (1) attempting to force close the channel by broadcasting our latest commitment transaction or
110-
/// (2) providing a preimage (after the channel has been force closed) from a forward link that
111-
/// allows us to spend an HTLC output on this channel's (the backward link's) broadcasted
112-
/// commitment transaction.
113-
///
114-
/// No other [`ChannelMonitorUpdate`]s are allowed after force-close.
115-
pub const CLOSED_CHANNEL_UPDATE_ID: u64 = core::u64::MAX;
105+
/// LDK prior to 0.1 used this constant as the [`ChannelMonitorUpdate::update_id`] for any
106+
/// [`ChannelMonitorUpdate`]s which were generated after the channel was closed.
107+
const LEGACY_CLOSED_CHANNEL_UPDATE_ID: u64 = core::u64::MAX;
116108

117109
impl Writeable for ChannelMonitorUpdate {
118110
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
@@ -1553,6 +1545,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
15531545

15541546
/// Gets the update_id from the latest ChannelMonitorUpdate which was applied to this
15551547
/// ChannelMonitor.
1548+
///
1549+
/// Note that for channels closed prior to LDK 0.1, this may return [`u64::MAX`].
15561550
pub fn get_latest_update_id(&self) -> u64 {
15571551
self.inner.lock().unwrap().get_latest_update_id()
15581552
}
@@ -3116,11 +3110,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
31163110
F::Target: FeeEstimator,
31173111
L::Target: Logger,
31183112
{
3119-
if self.latest_update_id == CLOSED_CHANNEL_UPDATE_ID && updates.update_id == CLOSED_CHANNEL_UPDATE_ID {
3120-
log_info!(logger, "Applying post-force-closed update to monitor {} with {} change(s).",
3113+
if self.latest_update_id == LEGACY_CLOSED_CHANNEL_UPDATE_ID && updates.update_id == LEGACY_CLOSED_CHANNEL_UPDATE_ID {
3114+
log_info!(logger, "Applying pre-0.1 post-force-closed update to monitor {} with {} change(s).",
31213115
log_funding_info!(self), updates.updates.len());
3122-
} else if updates.update_id == CLOSED_CHANNEL_UPDATE_ID {
3123-
log_info!(logger, "Applying force close update to monitor {} with {} change(s).",
3116+
} else if updates.update_id == LEGACY_CLOSED_CHANNEL_UPDATE_ID {
3117+
log_info!(logger, "Applying pre-0.1 force close update to monitor {} with {} change(s).",
31243118
log_funding_info!(self), updates.updates.len());
31253119
} else {
31263120
log_info!(logger, "Applying update to monitor {}, bringing update_id from {} to {} with {} change(s).",
@@ -3143,14 +3137,14 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
31433137
// The `ChannelManager` may also queue redundant `ChannelForceClosed` updates if it still
31443138
// thinks the channel needs to have its commitment transaction broadcast, so we'll allow
31453139
// them as well.
3146-
if updates.update_id == CLOSED_CHANNEL_UPDATE_ID {
3140+
if updates.update_id == LEGACY_CLOSED_CHANNEL_UPDATE_ID || self.lockdown_from_offchain {
31473141
assert_eq!(updates.updates.len(), 1);
31483142
match updates.updates[0] {
31493143
ChannelMonitorUpdateStep::ChannelForceClosed { .. } => {},
31503144
// We should have already seen a `ChannelForceClosed` update if we're trying to
31513145
// provide a preimage at this point.
31523146
ChannelMonitorUpdateStep::PaymentPreimage { .. } =>
3153-
debug_assert_eq!(self.latest_update_id, CLOSED_CHANNEL_UPDATE_ID),
3147+
debug_assert!(self.lockdown_from_offchain),
31543148
_ => {
31553149
log_error!(logger, "Attempted to apply post-force-close ChannelMonitorUpdate of type {}", updates.updates[0].variant_name());
31563150
panic!("Attempted to apply post-force-close ChannelMonitorUpdate that wasn't providing a payment preimage");
@@ -3230,17 +3224,29 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
32303224
self.counterparty_commitment_txs_from_update(updates);
32313225
}
32323226

3233-
// If the updates succeeded and we were in an already closed channel state, then there's no
3234-
// need to refuse any updates we expect to receive afer seeing a confirmed commitment.
3235-
if ret.is_ok() && updates.update_id == CLOSED_CHANNEL_UPDATE_ID && self.latest_update_id == updates.update_id {
3236-
return Ok(());
3237-
}
3238-
32393227
self.latest_update_id = updates.update_id;
32403228

3241-
// Refuse updates after we've detected a spend onchain, but only if we haven't processed a
3242-
// force closed monitor update yet.
3243-
if ret.is_ok() && self.funding_spend_seen && self.latest_update_id != CLOSED_CHANNEL_UPDATE_ID {
3229+
// Refuse updates after we've detected a spend onchain (or if the channel was otherwise
3230+
// closed), but only if the update isn't the kind of update we expect to see after channel
3231+
// closure.
3232+
let mut is_pre_close_update = false;
3233+
for update in updates.updates.iter() {
3234+
match update {
3235+
ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { .. }
3236+
|ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { .. }
3237+
|ChannelMonitorUpdateStep::ShutdownScript { .. }
3238+
|ChannelMonitorUpdateStep::CommitmentSecret { .. } =>
3239+
is_pre_close_update = true,
3240+
// After a channel is closed, we don't communicate with our peer about it, so the
3241+
// only things we will update is getting a new preimage (from a different channel)
3242+
// or being told that the channel is closed. All other updates are generated while
3243+
// talking to our peer.
3244+
ChannelMonitorUpdateStep::PaymentPreimage { .. } => {},
3245+
ChannelMonitorUpdateStep::ChannelForceClosed { .. } => {},
3246+
}
3247+
}
3248+
3249+
if ret.is_ok() && (self.funding_spend_seen || self.lockdown_from_offchain) && is_pre_close_update {
32443250
log_error!(logger, "Refusing Channel Monitor Update as counterparty attempted to update commitment after funding was spent");
32453251
Err(())
32463252
} else { ret }

lightning/src/ln/channel.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use crate::ln::chan_utils;
4545
use crate::ln::onion_utils::HTLCFailReason;
4646
use crate::chain::BestBlock;
4747
use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBoundedFeeEstimator};
48-
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS, CLOSED_CHANNEL_UPDATE_ID};
48+
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS};
4949
use crate::chain::transaction::{OutPoint, TransactionData};
5050
use crate::sign::ecdsa::EcdsaChannelSigner;
5151
use crate::sign::{EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient};
@@ -3656,7 +3656,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
36563656
// monitor update to the user, even if we return one).
36573657
// See test_duplicate_chan_id and test_pre_lockin_no_chan_closed_update for more.
36583658
if !self.channel_state.is_pre_funded_state() {
3659-
self.latest_monitor_update_id = CLOSED_CHANNEL_UPDATE_ID;
3659+
self.latest_monitor_update_id += 1;
36603660
Some((self.get_counterparty_node_id(), funding_txo, self.channel_id(), ChannelMonitorUpdate {
36613661
update_id: self.latest_monitor_update_id,
36623662
counterparty_node_id: Some(self.counterparty_node_id),

0 commit comments

Comments
 (0)