Skip to content

Commit 2b29c85

Browse files
committed
Allow stale ChannelMonitors if we are sure they don't have funds
In 601bf4b we started refusing to load `ChannelMonitor`s which were created prior to LDK 0.0.110 and which were last updated prior to LDK 0.0.116. While this is likely fine for nearly all of our users, there's some risk that some (like me) have ancient un-archived `ChannelMonitor`s. We do need to start auto-archiving `ChannelMonitor`s but for now we need some way for such users to at least not fail on startup. Sadly, ancient `ChannelMonitor`s often don't contain some of the data we need to accurately calculate `Balance`s, but in cases where they do, and where there are no claimable `Balance`s, we can be confident we don't need the `ChannelMonitor`s. Thus, here, we adapt the `ChannelMonitor` `Readable` implementation used in the persistence wrappers to detect this case and simply skip loading such `ChannelMonitor`s. Its not clear if this is sufficient, but its at least better than the current state of affairs after 601bf4b.
1 parent 2efb009 commit 2b29c85

File tree

2 files changed

+92
-28
lines changed

2 files changed

+92
-28
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,11 +1059,21 @@ impl Readable for IrrevocablyResolvedHTLC {
10591059
/// You MUST ensure that no ChannelMonitors for a given channel anywhere contain out-of-date
10601060
/// information and are actively monitoring the chain.
10611061
///
1062-
/// Note that the deserializer is only implemented for (BlockHash, ChannelMonitor), which
1063-
/// tells you the last block hash which was block_connect()ed. You MUST rescan any blocks along
1064-
/// the "reorg path" (ie disconnecting blocks until you find a common ancestor from both the
1065-
/// returned block hash and the the current chain and then reconnecting blocks to get to the
1066-
/// best chain) upon deserializing the object!
1062+
/// Like the [`ChannelManager`], deserialization is implemented for `(BlockHash, ChannelMonitor)`,
1063+
/// providing you with the last block hash which was connected before shutting down. You must begin
1064+
/// syncing the chain from that point, disconnecting and connecting blocks as required to get to
1065+
/// the best chain on startup. Note that all [`ChannelMonitor`]s passed to a [`ChainMonitor`] must
1066+
/// by synced as of the same block, so syncing must happen prior to [`ChainMonitor`]
1067+
/// initialization.
1068+
///
1069+
/// For those loading potentially-ancient [`ChannelMonitor`]s, deserialization is also implemented
1070+
/// for `Option<(BlockHash, ChannelMonitor)>`. LDK can no longer deserialize a [`ChannelMonitor`]
1071+
/// that was first created in LDK prior to 0.0.110 and last updated prior to LDK 0.0.116. In such
1072+
/// cases, the `Option<(..)>` deserialization option may return `Ok(None)` rather than failing to
1073+
/// deserialize, allowing you to differentiate between the two cases.
1074+
///
1075+
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
1076+
/// [`ChainMonitor`]: crate::chain::chainmonitor::ChainMonitor
10671077
pub struct ChannelMonitor<Signer: EcdsaChannelSigner> {
10681078
pub(crate) inner: Mutex<ChannelMonitorImpl<Signer>>,
10691079
}
@@ -6251,6 +6261,18 @@ const MAX_ALLOC_SIZE: usize = 64 * 1024;
62516261

62526262
impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP)>
62536263
for (BlockHash, ChannelMonitor<SP::EcdsaSigner>)
6264+
{
6265+
fn read<R: io::Read>(reader: &mut R, args: (&'a ES, &'b SP)) -> Result<Self, DecodeError> {
6266+
match <Option<Self>>::read(reader, args) {
6267+
Ok(Some(res)) => Ok(res),
6268+
Ok(None) => Err(DecodeError::UnknownRequiredFeature),
6269+
Err(e) => Err(e),
6270+
}
6271+
}
6272+
}
6273+
6274+
impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP)>
6275+
for Option<(BlockHash, ChannelMonitor<SP::EcdsaSigner>)>
62546276
{
62556277
#[rustfmt::skip]
62566278
fn read<R: io::Read>(reader: &mut R, args: (&'a ES, &'b SP)) -> Result<Self, DecodeError> {
@@ -6528,11 +6550,6 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
65286550
}
65296551

65306552
let channel_id = channel_id.unwrap_or(ChannelId::v1_from_funding_outpoint(outpoint));
6531-
if counterparty_node_id.is_none() {
6532-
panic!("Found monitor for channel {} with no updates since v0.0.118.\
6533-
These monitors are no longer supported.\
6534-
To continue, run a v0.1 release, send/route a payment over the channel or close it.", channel_id);
6535-
}
65366553

65376554
let (current_holder_commitment_tx, current_holder_htlc_data) = {
65386555
let holder_commitment_tx = onchain_tx_handler.current_holder_commitment_tx();
@@ -6586,7 +6603,8 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
65866603
(None, None)
65876604
};
65886605

6589-
Ok((best_block.block_hash, ChannelMonitor::from_impl(ChannelMonitorImpl {
6606+
let dummy_node_id = PublicKey::from_slice(&[2; 33]).unwrap();
6607+
let monitor = ChannelMonitor::from_impl(ChannelMonitorImpl {
65906608
funding: FundingScope {
65916609
channel_parameters,
65926610

@@ -6646,7 +6664,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
66466664
spendable_txids_confirmed: spendable_txids_confirmed.unwrap(),
66476665

66486666
best_block,
6649-
counterparty_node_id: counterparty_node_id.unwrap(),
6667+
counterparty_node_id: counterparty_node_id.unwrap_or(dummy_node_id),
66506668
initial_counterparty_commitment_info,
66516669
initial_counterparty_commitment_tx,
66526670
balances_empty_height,
@@ -6658,7 +6676,20 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
66586676
alternative_funding_confirmed,
66596677

66606678
written_by_0_1_or_later,
6661-
})))
6679+
});
6680+
6681+
if counterparty_node_id.is_none() {
6682+
if (holder_tx_signed || lockdown_from_offchain) && monitor.get_claimable_balances().is_empty() {
6683+
// If the monitor is no longer readable, but it is a candidate for archiving,
6684+
// return Ok(None) to allow it to be skipped and not loaded.
6685+
return Ok(None);
6686+
} else {
6687+
panic!("Found monitor for channel {channel_id} with no updates since v0.0.118.\
6688+
These monitors are no longer supported.\
6689+
To continue, run a v0.1 release, send/route a payment over the channel or close it.");
6690+
}
6691+
}
6692+
Ok(Some((best_block.block_hash, monitor)))
66626693
}
66636694
}
66646695

lightning/src/util/persist.rs

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -372,15 +372,15 @@ where
372372
CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE,
373373
CHANNEL_MONITOR_PERSISTENCE_SECONDARY_NAMESPACE,
374374
)? {
375-
match <(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>)>::read(
375+
match <Option<(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>)>>::read(
376376
&mut io::Cursor::new(kv_store.read(
377377
CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE,
378378
CHANNEL_MONITOR_PERSISTENCE_SECONDARY_NAMESPACE,
379379
&stored_key,
380380
)?),
381381
(&*entropy_source, &*signer_provider),
382382
) {
383-
Ok((block_hash, channel_monitor)) => {
383+
Ok(Some((block_hash, channel_monitor))) => {
384384
let monitor_name = MonitorName::from_str(&stored_key)?;
385385
if channel_monitor.persistence_key() != monitor_name {
386386
return Err(io::Error::new(
@@ -391,6 +391,7 @@ where
391391

392392
res.push((block_hash, channel_monitor));
393393
},
394+
Ok(None) => {},
394395
Err(_) => {
395396
return Err(io::Error::new(
396397
io::ErrorKind::InvalidData,
@@ -783,9 +784,12 @@ where
783784
let secondary = CHANNEL_MONITOR_PERSISTENCE_SECONDARY_NAMESPACE;
784785
let monitor_list = self.0.kv_store.list(primary, secondary).await?;
785786
let mut res = Vec::with_capacity(monitor_list.len());
786-
// TODO: Parallelize this loop
787787
for monitor_key in monitor_list {
788-
res.push(self.read_channel_monitor_with_updates(monitor_key.as_str()).await?)
788+
let result =
789+
self.0.maybe_read_channel_monitor_with_updates(monitor_key.as_str()).await?;
790+
if let Some(read_res) = result {
791+
res.push(read_res);
792+
}
789793
}
790794
Ok(res)
791795
}
@@ -923,8 +927,29 @@ where
923927
&self, monitor_key: &str,
924928
) -> Result<(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>), io::Error>
925929
{
930+
match self.maybe_read_channel_monitor_with_updates(monitor_key).await? {
931+
Some(res) => Ok(res),
932+
None => Err(io::Error::new(
933+
io::ErrorKind::InvalidData,
934+
"ChannelMonitor was stale, with no updates since LDK 0.0.118. \
935+
It cannot be read by modern versions of LDK, though also does not contain any funds left to sweep. \
936+
You should manually delete it instead",
937+
)),
938+
}
939+
}
940+
941+
async fn maybe_read_channel_monitor_with_updates(
942+
&self, monitor_key: &str,
943+
) -> Result<
944+
Option<(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>)>,
945+
io::Error,
946+
> {
926947
let monitor_name = MonitorName::from_str(monitor_key)?;
927-
let (block_hash, monitor) = self.read_monitor(&monitor_name, monitor_key).await?;
948+
let read_res = self.maybe_read_monitor(&monitor_name, monitor_key).await?;
949+
let (block_hash, monitor) = match read_res {
950+
Some(res) => res,
951+
None => return Ok(None),
952+
};
928953
let mut current_update_id = monitor.get_latest_update_id();
929954
// TODO: Parallelize this loop by speculatively reading a batch of updates
930955
loop {
@@ -955,14 +980,16 @@ where
955980
io::Error::new(io::ErrorKind::Other, "Monitor update failed")
956981
})?;
957982
}
958-
Ok((block_hash, monitor))
983+
Ok(Some((block_hash, monitor)))
959984
}
960985

961986
/// Read a channel monitor.
962-
async fn read_monitor(
987+
async fn maybe_read_monitor(
963988
&self, monitor_name: &MonitorName, monitor_key: &str,
964-
) -> Result<(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>), io::Error>
965-
{
989+
) -> Result<
990+
Option<(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>)>,
991+
io::Error,
992+
> {
966993
let primary = CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE;
967994
let secondary = CHANNEL_MONITOR_PERSISTENCE_SECONDARY_NAMESPACE;
968995
let monitor_bytes = self.kv_store.read(primary, secondary, monitor_key).await?;
@@ -971,11 +998,12 @@ where
971998
if monitor_cursor.get_ref().starts_with(MONITOR_UPDATING_PERSISTER_PREPEND_SENTINEL) {
972999
monitor_cursor.set_position(MONITOR_UPDATING_PERSISTER_PREPEND_SENTINEL.len() as u64);
9731000
}
974-
match <(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>)>::read(
1001+
match <Option<(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>)>>::read(
9751002
&mut monitor_cursor,
9761003
(&*self.entropy_source, &*self.signer_provider),
9771004
) {
978-
Ok((blockhash, channel_monitor)) => {
1005+
Ok(None) => Ok(None),
1006+
Ok(Some((blockhash, channel_monitor))) => {
9791007
if channel_monitor.persistence_key() != *monitor_name {
9801008
log_error!(
9811009
self.logger,
@@ -987,7 +1015,7 @@ where
9871015
"ChannelMonitor was stored under the wrong key",
9881016
))
9891017
} else {
990-
Ok((blockhash, channel_monitor))
1018+
Ok(Some((blockhash, channel_monitor)))
9911019
}
9921020
},
9931021
Err(e) => {
@@ -1027,9 +1055,14 @@ where
10271055
let monitor_keys = self.kv_store.list(primary, secondary).await?;
10281056
for monitor_key in monitor_keys {
10291057
let monitor_name = MonitorName::from_str(&monitor_key)?;
1030-
let (_, current_monitor) = self.read_monitor(&monitor_name, &monitor_key).await?;
1031-
let latest_update_id = current_monitor.get_latest_update_id();
1032-
self.cleanup_stale_updates_for_monitor_to(&monitor_key, latest_update_id).await?;
1058+
let maybe_monitor = self.maybe_read_monitor(&monitor_name, &monitor_key).await?;
1059+
if let Some((_, current_monitor)) = maybe_monitor {
1060+
let latest_update_id = current_monitor.get_latest_update_id();
1061+
self.cleanup_stale_updates_for_monitor_to(&monitor_key, latest_update_id).await?;
1062+
} else {
1063+
// TODO: Also clean up super stale monitors (created pre-0.0.110 and last updated
1064+
// pre-0.0.116).
1065+
}
10331066
}
10341067
Ok(())
10351068
}

0 commit comments

Comments
 (0)