Skip to content

Commit 1c5b4c1

Browse files
authored
Merge pull request #3355 from TheBlueMatt/2024-10-mon-ids-after-close
2 parents 41f0623 + 4582b20 commit 1c5b4c1

File tree

12 files changed

+604
-431
lines changed

12 files changed

+604
-431
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

+41-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
}
@@ -1717,6 +1711,12 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
17171711
self.inner.lock().unwrap().get_cur_holder_commitment_number()
17181712
}
17191713

1714+
/// Gets whether we've been notified that this channel is closed by the `ChannelManager` (i.e.
1715+
/// via a [`ChannelMonitorUpdateStep::ChannelForceClosed`]).
1716+
pub(crate) fn offchain_closed(&self) -> bool {
1717+
self.inner.lock().unwrap().lockdown_from_offchain
1718+
}
1719+
17201720
/// Gets the `node_id` of the counterparty for this channel.
17211721
///
17221722
/// Will be `None` for channels constructed on LDK versions prior to 0.0.110 and always `Some`
@@ -3110,11 +3110,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
31103110
F::Target: FeeEstimator,
31113111
L::Target: Logger,
31123112
{
3113-
if self.latest_update_id == CLOSED_CHANNEL_UPDATE_ID && updates.update_id == CLOSED_CHANNEL_UPDATE_ID {
3114-
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).",
31153115
log_funding_info!(self), updates.updates.len());
3116-
} else if updates.update_id == CLOSED_CHANNEL_UPDATE_ID {
3117-
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).",
31183118
log_funding_info!(self), updates.updates.len());
31193119
} else {
31203120
log_info!(logger, "Applying update to monitor {}, bringing update_id from {} to {} with {} change(s).",
@@ -3137,14 +3137,14 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
31373137
// The `ChannelManager` may also queue redundant `ChannelForceClosed` updates if it still
31383138
// thinks the channel needs to have its commitment transaction broadcast, so we'll allow
31393139
// them as well.
3140-
if updates.update_id == CLOSED_CHANNEL_UPDATE_ID {
3140+
if updates.update_id == LEGACY_CLOSED_CHANNEL_UPDATE_ID || self.lockdown_from_offchain {
31413141
assert_eq!(updates.updates.len(), 1);
31423142
match updates.updates[0] {
31433143
ChannelMonitorUpdateStep::ChannelForceClosed { .. } => {},
31443144
// We should have already seen a `ChannelForceClosed` update if we're trying to
31453145
// provide a preimage at this point.
31463146
ChannelMonitorUpdateStep::PaymentPreimage { .. } =>
3147-
debug_assert_eq!(self.latest_update_id, CLOSED_CHANNEL_UPDATE_ID),
3147+
debug_assert!(self.lockdown_from_offchain),
31483148
_ => {
31493149
log_error!(logger, "Attempted to apply post-force-close ChannelMonitorUpdate of type {}", updates.updates[0].variant_name());
31503150
panic!("Attempted to apply post-force-close ChannelMonitorUpdate that wasn't providing a payment preimage");
@@ -3224,17 +3224,29 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
32243224
self.counterparty_commitment_txs_from_update(updates);
32253225
}
32263226

3227-
// If the updates succeeded and we were in an already closed channel state, then there's no
3228-
// need to refuse any updates we expect to receive afer seeing a confirmed commitment.
3229-
if ret.is_ok() && updates.update_id == CLOSED_CHANNEL_UPDATE_ID && self.latest_update_id == updates.update_id {
3230-
return Ok(());
3231-
}
3232-
32333227
self.latest_update_id = updates.update_id;
32343228

3235-
// Refuse updates after we've detected a spend onchain, but only if we haven't processed a
3236-
// force closed monitor update yet.
3237-
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 {
32383250
log_error!(logger, "Refusing Channel Monitor Update as counterparty attempted to update commitment after funding was spent");
32393251
Err(())
32403252
} 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)