Skip to content

Commit 946bc8b

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 946bc8b

File tree

2 files changed

+85
-27
lines changed

2 files changed

+85
-27
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,11 +1059,18 @@ 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.
10671074
pub struct ChannelMonitor<Signer: EcdsaChannelSigner> {
10681075
pub(crate) inner: Mutex<ChannelMonitorImpl<Signer>>,
10691076
}
@@ -6251,6 +6258,18 @@ const MAX_ALLOC_SIZE: usize = 64 * 1024;
62516258

62526259
impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP)>
62536260
for (BlockHash, ChannelMonitor<SP::EcdsaSigner>)
6261+
{
6262+
fn read<R: io::Read>(reader: &mut R, args: (&'a ES, &'b SP)) -> Result<Self, DecodeError> {
6263+
match <Option<Self>>::read(reader, args) {
6264+
Ok(Some(res)) => Ok(res),
6265+
Ok(None) => Err(DecodeError::UnknownRequiredFeature),
6266+
Err(e) => Err(e),
6267+
}
6268+
}
6269+
}
6270+
6271+
impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP)>
6272+
for Option<(BlockHash, ChannelMonitor<SP::EcdsaSigner>)>
62546273
{
62556274
#[rustfmt::skip]
62566275
fn read<R: io::Read>(reader: &mut R, args: (&'a ES, &'b SP)) -> Result<Self, DecodeError> {
@@ -6528,11 +6547,6 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
65286547
}
65296548

65306549
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-
}
65366550

65376551
let (current_holder_commitment_tx, current_holder_htlc_data) = {
65386552
let holder_commitment_tx = onchain_tx_handler.current_holder_commitment_tx();
@@ -6586,7 +6600,8 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
65866600
(None, None)
65876601
};
65886602

6589-
Ok((best_block.block_hash, ChannelMonitor::from_impl(ChannelMonitorImpl {
6603+
let dummy_node_id = PublicKey::from_slice(&[2; 33]).unwrap();
6604+
let monitor = ChannelMonitor::from_impl(ChannelMonitorImpl {
65906605
funding: FundingScope {
65916606
channel_parameters,
65926607

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

66486663
best_block,
6649-
counterparty_node_id: counterparty_node_id.unwrap(),
6664+
counterparty_node_id: counterparty_node_id.unwrap_or(dummy_node_id),
66506665
initial_counterparty_commitment_info,
66516666
initial_counterparty_commitment_tx,
66526667
balances_empty_height,
@@ -6658,7 +6673,20 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
66586673
alternative_funding_confirmed,
66596674

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

lightning/src/util/persist.rs

Lines changed: 44 additions & 14 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,11 @@ 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 = self.maybe_read_channel_monitor_with_updates(monitor_key.as_str()).await?;
789+
if let Some(read_res) = result {
790+
res.push(read_res);
791+
}
789792
}
790793
Ok(res)
791794
}
@@ -922,9 +925,30 @@ where
922925
pub async fn read_channel_monitor_with_updates(
923926
&self, monitor_key: &str,
924927
) -> Result<(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>), io::Error>
928+
{
929+
match self.maybe_read_channel_monitor_with_updates(monitor_key).await? {
930+
Some(res) => Ok(res),
931+
None => {
932+
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+
942+
async fn maybe_read_channel_monitor_with_updates(
943+
&self, monitor_key: &str,
944+
) -> Result<Option<(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>)>, io::Error>
925945
{
926946
let monitor_name = MonitorName::from_str(monitor_key)?;
927-
let (block_hash, monitor) = self.read_monitor(&monitor_name, monitor_key).await?;
947+
let read_res = self.maybe_read_monitor(&monitor_name, monitor_key).await?;
948+
let (block_hash, monitor) = match read_res {
949+
Some(res) => res,
950+
None => return Ok(None),
951+
};
928952
let mut current_update_id = monitor.get_latest_update_id();
929953
// TODO: Parallelize this loop by speculatively reading a batch of updates
930954
loop {
@@ -955,13 +979,13 @@ where
955979
io::Error::new(io::ErrorKind::Other, "Monitor update failed")
956980
})?;
957981
}
958-
Ok((block_hash, monitor))
982+
Ok(Some((block_hash, monitor)))
959983
}
960984

961985
/// Read a channel monitor.
962-
async fn read_monitor(
986+
async fn maybe_read_monitor(
963987
&self, monitor_name: &MonitorName, monitor_key: &str,
964-
) -> Result<(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>), io::Error>
988+
) -> Result<Option<(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>)>, io::Error>
965989
{
966990
let primary = CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE;
967991
let secondary = CHANNEL_MONITOR_PERSISTENCE_SECONDARY_NAMESPACE;
@@ -971,11 +995,12 @@ where
971995
if monitor_cursor.get_ref().starts_with(MONITOR_UPDATING_PERSISTER_PREPEND_SENTINEL) {
972996
monitor_cursor.set_position(MONITOR_UPDATING_PERSISTER_PREPEND_SENTINEL.len() as u64);
973997
}
974-
match <(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>)>::read(
998+
match <Option<(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>)>>::read(
975999
&mut monitor_cursor,
9761000
(&*self.entropy_source, &*self.signer_provider),
9771001
) {
978-
Ok((blockhash, channel_monitor)) => {
1002+
Ok(None) => Ok(None),
1003+
Ok(Some((blockhash, channel_monitor))) => {
9791004
if channel_monitor.persistence_key() != *monitor_name {
9801005
log_error!(
9811006
self.logger,
@@ -987,7 +1012,7 @@ where
9871012
"ChannelMonitor was stored under the wrong key",
9881013
))
9891014
} else {
990-
Ok((blockhash, channel_monitor))
1015+
Ok(Some((blockhash, channel_monitor)))
9911016
}
9921017
},
9931018
Err(e) => {
@@ -1027,9 +1052,14 @@ where
10271052
let monitor_keys = self.kv_store.list(primary, secondary).await?;
10281053
for monitor_key in monitor_keys {
10291054
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?;
1055+
let maybe_monitor = self.maybe_read_monitor(&monitor_name, &monitor_key).await?;
1056+
if let Some((_, current_monitor)) = maybe_monitor {
1057+
let latest_update_id = current_monitor.get_latest_update_id();
1058+
self.cleanup_stale_updates_for_monitor_to(&monitor_key, latest_update_id).await?;
1059+
} else {
1060+
// TODO: Also clean up super stale monitors (created pre-0.0.110 and last updated
1061+
// pre-0.0.116).
1062+
}
10331063
}
10341064
Ok(())
10351065
}

0 commit comments

Comments
 (0)