Skip to content

Commit 001463b

Browse files
committed
Support persisting ChannelMonitors after splicing
ChannelMonitors are persisted using the corresponding channel's funding outpoint for the key. This is fine for v1 channels since the funding output will never change. However, this is not the case for v2 channels since a splice will result in a new funding outpoint. Instead, use the channel id as the persistence key for v2 channels since this is fixed. For v1 channels, continue to use the funding outpoint for backwards compatibility. Any v1 channel upgraded to a v2 channel via splicing will continue to use the original funding outpoint as the persistence key.
1 parent ff1a2d9 commit 001463b

File tree

4 files changed

+78
-85
lines changed

4 files changed

+78
-85
lines changed

lightning/src/chain/chainmonitor.rs

+12-14
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@ pub trait Persist<ChannelSigner: EcdsaChannelSigner> {
104104
/// Persist a new channel's data in response to a [`chain::Watch::watch_channel`] call. This is
105105
/// called by [`ChannelManager`] for new channels, or may be called directly, e.g. on startup.
106106
///
107-
/// The data can be stored any way you want, but the identifier provided by LDK is the
108-
/// channel's outpoint (and it is up to you to maintain a correct mapping between the outpoint
109-
/// and the stored channel data). Note that you **must** persist every new monitor to disk.
107+
/// The data can be stored any way you want, so long as [`ChannelMonitor::persistence_key`] is
108+
/// used to maintain a correct mapping with the stored channel data. Note that you **must**
109+
/// persist every new monitor to disk.
110110
///
111111
/// The [`ChannelMonitor::get_latest_update_id`] uniquely links this call to [`ChainMonitor::channel_monitor_updated`].
112112
/// For [`Persist::persist_new_channel`], it is only necessary to call [`ChainMonitor::channel_monitor_updated`]
@@ -117,7 +117,7 @@ pub trait Persist<ChannelSigner: EcdsaChannelSigner> {
117117
///
118118
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
119119
/// [`Writeable::write`]: crate::util::ser::Writeable::write
120-
fn persist_new_channel(&self, channel_funding_outpoint: OutPoint, monitor: &ChannelMonitor<ChannelSigner>) -> ChannelMonitorUpdateStatus;
120+
fn persist_new_channel(&self, monitor: &ChannelMonitor<ChannelSigner>) -> ChannelMonitorUpdateStatus;
121121

122122
/// Update one channel's data. The provided [`ChannelMonitor`] has already applied the given
123123
/// update.
@@ -156,7 +156,7 @@ pub trait Persist<ChannelSigner: EcdsaChannelSigner> {
156156
/// [`ChannelMonitorUpdateStatus`] for requirements when returning errors.
157157
///
158158
/// [`Writeable::write`]: crate::util::ser::Writeable::write
159-
fn update_persisted_channel(&self, channel_funding_outpoint: OutPoint, monitor_update: Option<&ChannelMonitorUpdate>, monitor: &ChannelMonitor<ChannelSigner>) -> ChannelMonitorUpdateStatus;
159+
fn update_persisted_channel(&self, monitor_update: Option<&ChannelMonitorUpdate>, monitor: &ChannelMonitor<ChannelSigner>) -> ChannelMonitorUpdateStatus;
160160
/// Prevents the channel monitor from being loaded on startup.
161161
///
162162
/// Archiving the data in a backup location (rather than deleting it fully) is useful for
@@ -168,7 +168,7 @@ pub trait Persist<ChannelSigner: EcdsaChannelSigner> {
168168
/// the archive process. Additionally, because the archive operation could be retried on
169169
/// restart, this method must in that case be idempotent, ensuring it can handle scenarios where
170170
/// the monitor already exists in the archive.
171-
fn archive_persisted_channel(&self, channel_funding_outpoint: OutPoint);
171+
fn archive_persisted_channel(&self, monitor: &ChannelMonitor<ChannelSigner>);
172172
}
173173

174174
struct MonitorHolder<ChannelSigner: EcdsaChannelSigner> {
@@ -342,8 +342,7 @@ where C::Target: chain::Filter,
342342
// `ChannelMonitorUpdate` after a channel persist for a channel with the same
343343
// `latest_update_id`.
344344
let _pending_monitor_updates = monitor_state.pending_monitor_updates.lock().unwrap();
345-
let funding_txo = monitor.get_funding_txo().0;
346-
match self.persister.update_persisted_channel(funding_txo, None, monitor) {
345+
match self.persister.update_persisted_channel(None, monitor) {
347346
ChannelMonitorUpdateStatus::Completed =>
348347
log_trace!(logger, "Finished syncing Channel Monitor for channel {} for block-data",
349348
log_funding_info!(monitor)
@@ -642,7 +641,7 @@ where C::Target: chain::Filter,
642641
have_monitors_to_prune = true;
643642
}
644643
if needs_persistence {
645-
self.persister.update_persisted_channel(monitor_holder.monitor.get_funding_txo().0, None, &monitor_holder.monitor);
644+
self.persister.update_persisted_channel(None, &monitor_holder.monitor);
646645
}
647646
}
648647
if have_monitors_to_prune {
@@ -655,7 +654,7 @@ where C::Target: chain::Filter,
655654
"Archiving fully resolved ChannelMonitor for channel ID {}",
656655
channel_id
657656
);
658-
self.persister.archive_persisted_channel(monitor_holder.monitor.get_funding_txo().0);
657+
self.persister.archive_persisted_channel(&monitor_holder.monitor);
659658
false
660659
} else {
661660
true
@@ -769,7 +768,7 @@ where C::Target: chain::Filter,
769768
log_trace!(logger, "Got new ChannelMonitor for channel {}", log_funding_info!(monitor));
770769
let update_id = monitor.get_latest_update_id();
771770
let mut pending_monitor_updates = Vec::new();
772-
let persist_res = self.persister.persist_new_channel(monitor.get_funding_txo().0, &monitor);
771+
let persist_res = self.persister.persist_new_channel(&monitor);
773772
match persist_res {
774773
ChannelMonitorUpdateStatus::InProgress => {
775774
log_info!(logger, "Persistence of new ChannelMonitor for channel {} in progress", log_funding_info!(monitor));
@@ -825,17 +824,16 @@ where C::Target: chain::Filter,
825824
let update_res = monitor.update_monitor(update, &self.broadcaster, &self.fee_estimator, &self.logger);
826825

827826
let update_id = update.update_id;
828-
let funding_txo = monitor.get_funding_txo().0;
829827
let persist_res = if update_res.is_err() {
830828
// Even if updating the monitor returns an error, the monitor's state will
831829
// still be changed. Therefore, we should persist the updated monitor despite the error.
832830
// We don't want to persist a `monitor_update` which results in a failure to apply later
833831
// while reading `channel_monitor` with updates from storage. Instead, we should persist
834832
// the entire `channel_monitor` here.
835833
log_warn!(logger, "Failed to update ChannelMonitor for channel {}. Going ahead and persisting the entire ChannelMonitor", log_funding_info!(monitor));
836-
self.persister.update_persisted_channel(funding_txo, None, monitor)
834+
self.persister.update_persisted_channel(None, monitor)
837835
} else {
838-
self.persister.update_persisted_channel(funding_txo, Some(update), monitor)
836+
self.persister.update_persisted_channel(Some(update), monitor)
839837
};
840838
match persist_res {
841839
ChannelMonitorUpdateStatus::InProgress => {

lightning/src/chain/channelmonitor.rs

+21
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ use crate::chain::onchaintx::{ClaimEvent, FeerateStrategy, OnchainTxHandler};
4848
use crate::chain::package::{CounterpartyOfferedHTLCOutput, CounterpartyReceivedHTLCOutput, HolderFundingOutput, HolderHTLCOutput, PackageSolvingData, PackageTemplate, RevokedOutput, RevokedHTLCOutput};
4949
use crate::chain::Filter;
5050
use crate::util::logger::{Logger, Record};
51+
use crate::util::persist::MonitorName;
5152
use crate::util::ser::{Readable, ReadableArgs, RequiredWrapper, MaybeReadable, UpgradableRequired, Writer, Writeable, U48};
5253
use crate::util::byte_utils;
5354
use crate::events::{ClosureReason, Event, EventHandler, ReplayEvent};
@@ -1453,6 +1454,26 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
14531454
})
14541455
}
14551456

1457+
/// Returns a unique id for persisting the [`ChannelMonitor`], which may be useful as a key in a
1458+
/// key-value store.
1459+
///
1460+
/// Note: Previously, the funding outpoint was used in the [`Persist`] trait. However, since the
1461+
/// outpoint may change during splicing, using this method to obtain a unique key is recommended
1462+
/// instead. For v1 channels, the funding outpoint is still used for backwards compatibility,
1463+
/// whereas v2 channels use the channel id since it is fixed.
1464+
///
1465+
/// [`Persist`]: crate::chain::chainmonitor::Persist
1466+
pub fn persistence_key(&self) -> MonitorName {
1467+
let inner = self.inner.lock().unwrap();
1468+
let funding_outpoint = inner.original_funding_txo;
1469+
let channel_id = inner.channel_id;
1470+
if ChannelId::v1_from_funding_outpoint(funding_outpoint) == channel_id {
1471+
MonitorName::from(funding_outpoint)
1472+
} else {
1473+
MonitorName::from(channel_id)
1474+
}
1475+
}
1476+
14561477
#[cfg(test)]
14571478
fn provide_secret(&self, idx: u64, secret: [u8; 32]) -> Result<(), &'static str> {
14581479
self.inner.lock().unwrap().provide_secret(idx, secret)

lightning/src/util/persist.rs

+30-51
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,9 @@ impl<ChannelSigner: EcdsaChannelSigner, K: KVStore + ?Sized> Persist<ChannelSign
261261
// just shut down the node since we're not retrying persistence!
262262

263263
fn persist_new_channel(
264-
&self, funding_txo: OutPoint, monitor: &ChannelMonitor<ChannelSigner>,
264+
&self, monitor: &ChannelMonitor<ChannelSigner>,
265265
) -> chain::ChannelMonitorUpdateStatus {
266-
let monitor_name = MonitorName::from(funding_txo);
266+
let monitor_name = monitor.persistence_key();
267267
match self.write(
268268
CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE,
269269
CHANNEL_MONITOR_PERSISTENCE_SECONDARY_NAMESPACE,
@@ -276,10 +276,9 @@ impl<ChannelSigner: EcdsaChannelSigner, K: KVStore + ?Sized> Persist<ChannelSign
276276
}
277277

278278
fn update_persisted_channel(
279-
&self, funding_txo: OutPoint, _update: Option<&ChannelMonitorUpdate>,
280-
monitor: &ChannelMonitor<ChannelSigner>,
279+
&self, _update: Option<&ChannelMonitorUpdate>, monitor: &ChannelMonitor<ChannelSigner>,
281280
) -> chain::ChannelMonitorUpdateStatus {
282-
let monitor_name = MonitorName::from(funding_txo);
281+
let monitor_name = monitor.persistence_key();
283282
match self.write(
284283
CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE,
285284
CHANNEL_MONITOR_PERSISTENCE_SECONDARY_NAMESPACE,
@@ -291,8 +290,8 @@ impl<ChannelSigner: EcdsaChannelSigner, K: KVStore + ?Sized> Persist<ChannelSign
291290
}
292291
}
293292

294-
fn archive_persisted_channel(&self, funding_txo: OutPoint) {
295-
let monitor_name = MonitorName::from(funding_txo);
293+
fn archive_persisted_channel(&self, monitor: &ChannelMonitor<ChannelSigner>) {
294+
let monitor_name = monitor.persistence_key();
296295
let monitor = match self.read(
297296
CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE,
298297
CHANNEL_MONITOR_PERSISTENCE_SECONDARY_NAMESPACE,
@@ -334,21 +333,6 @@ where
334333
CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE,
335334
CHANNEL_MONITOR_PERSISTENCE_SECONDARY_NAMESPACE,
336335
)? {
337-
if stored_key.len() < 66 {
338-
return Err(io::Error::new(
339-
io::ErrorKind::InvalidData,
340-
"Stored key has invalid length",
341-
));
342-
}
343-
344-
let txid = Txid::from_str(stored_key.split_at(64).0).map_err(|_| {
345-
io::Error::new(io::ErrorKind::InvalidData, "Invalid tx ID in stored key")
346-
})?;
347-
348-
let index: u16 = stored_key.split_at(65).1.parse().map_err(|_| {
349-
io::Error::new(io::ErrorKind::InvalidData, "Invalid tx index in stored key")
350-
})?;
351-
352336
match <(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>)>::read(
353337
&mut io::Cursor::new(kv_store.read(
354338
CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE,
@@ -358,14 +342,14 @@ where
358342
(&*entropy_source, &*signer_provider),
359343
) {
360344
Ok((block_hash, channel_monitor)) => {
361-
if channel_monitor.get_funding_txo().0.txid != txid
362-
|| channel_monitor.get_funding_txo().0.index != index
363-
{
345+
let monitor_name = MonitorName::new(stored_key)?;
346+
if channel_monitor.persistence_key().as_str() != monitor_name.as_str() {
364347
return Err(io::Error::new(
365348
io::ErrorKind::InvalidData,
366349
"ChannelMonitor was stored under the wrong key",
367350
));
368351
}
352+
369353
res.push((block_hash, channel_monitor));
370354
},
371355
Err(_) => {
@@ -406,12 +390,13 @@ where
406390
/// - [`Persist::update_persisted_channel`], which persists only a [`ChannelMonitorUpdate`]
407391
///
408392
/// Whole [`ChannelMonitor`]s are stored in the [`CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE`],
409-
/// using the familiar encoding of an [`OutPoint`] (for example, `[SOME-64-CHAR-HEX-STRING]_1`).
393+
/// using the familiar encoding of an [`OutPoint`] (e.g., `[SOME-64-CHAR-HEX-STRING]_1`) for v1
394+
/// channels or a [`ChannelId`] (e.g., `[SOME-64-CHAR-HEX-STRING]`) for v2 channels.
410395
///
411396
/// Each [`ChannelMonitorUpdate`] is stored in a dynamic secondary namespace, as follows:
412397
///
413398
/// - primary namespace: [`CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE`]
414-
/// - secondary namespace: [the monitor's encoded outpoint name]
399+
/// - secondary namespace: [the monitor's encoded outpoint or channel id name]
415400
///
416401
/// Under that secondary namespace, each update is stored with a number string, like `21`, which
417402
/// represents its `update_id` value.
@@ -550,15 +535,17 @@ where
550535
/// [`io::ErrorKind::NotFound`] variant correctly. For more information, please see the
551536
/// documentation for [`MonitorUpdatingPersister`].
552537
///
553-
/// For `monitor_key`, channel storage keys be the channel's transaction ID and index, or
554-
/// [`OutPoint`], with an underscore `_` between them. For example, given:
538+
/// For `monitor_key`, channel storage keys can be the channel's funding [`OutPoint`], with an
539+
/// underscore `_` between txid and index for v1 channels. For example, given:
555540
///
556541
/// - Transaction ID: `deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef`
557542
/// - Index: `1`
558543
///
559544
/// The correct `monitor_key` would be:
560545
/// `deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_1`
561546
///
547+
/// For v2 channels, the hex-encoded [`ChannelId`] is used directly for `monitor_key` instead.
548+
///
562549
/// Loading a large number of monitors will be faster if done in parallel. You can use this
563550
/// function to accomplish this. Take care to limit the number of parallel readers.
564551
pub fn read_channel_monitor_with_updates(
@@ -604,7 +591,6 @@ where
604591
&self, monitor_name: &MonitorName,
605592
) -> Result<(BlockHash, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>), io::Error>
606593
{
607-
let outpoint: OutPoint = monitor_name.try_into()?;
608594
let mut monitor_cursor = io::Cursor::new(self.kv_store.read(
609595
CHANNEL_MONITOR_PERSISTENCE_PRIMARY_NAMESPACE,
610596
CHANNEL_MONITOR_PERSISTENCE_SECONDARY_NAMESPACE,
@@ -619,9 +605,7 @@ where
619605
(&*self.entropy_source, &*self.signer_provider),
620606
) {
621607
Ok((blockhash, channel_monitor)) => {
622-
if channel_monitor.get_funding_txo().0.txid != outpoint.txid
623-
|| channel_monitor.get_funding_txo().0.index != outpoint.index
624-
{
608+
if channel_monitor.persistence_key().as_str() != monitor_name.as_str() {
625609
log_error!(
626610
self.logger,
627611
"ChannelMonitor {} was stored under the wrong key!",
@@ -724,10 +708,10 @@ where
724708
/// Persists a new channel. This means writing the entire monitor to the
725709
/// parametrized [`KVStore`].
726710
fn persist_new_channel(
727-
&self, funding_txo: OutPoint, monitor: &ChannelMonitor<ChannelSigner>,
711+
&self, monitor: &ChannelMonitor<ChannelSigner>,
728712
) -> chain::ChannelMonitorUpdateStatus {
729713
// Determine the proper key for this monitor
730-
let monitor_name = MonitorName::from(funding_txo);
714+
let monitor_name = monitor.persistence_key();
731715
// Serialize and write the new monitor
732716
let mut monitor_bytes = Vec::with_capacity(
733717
MONITOR_UPDATING_PERSISTER_PREPEND_SENTINEL.len() + monitor.serialized_length(),
@@ -765,15 +749,14 @@ where
765749
/// `update` is `None`.
766750
/// - The update is at [`u64::MAX`], indicating an update generated by pre-0.1 LDK.
767751
fn update_persisted_channel(
768-
&self, funding_txo: OutPoint, update: Option<&ChannelMonitorUpdate>,
769-
monitor: &ChannelMonitor<ChannelSigner>,
752+
&self, update: Option<&ChannelMonitorUpdate>, monitor: &ChannelMonitor<ChannelSigner>,
770753
) -> chain::ChannelMonitorUpdateStatus {
771754
const LEGACY_CLOSED_CHANNEL_UPDATE_ID: u64 = u64::MAX;
772755
if let Some(update) = update {
756+
let monitor_name = monitor.persistence_key();
773757
let persist_update = update.update_id != LEGACY_CLOSED_CHANNEL_UPDATE_ID
774758
&& update.update_id % self.maximum_pending_updates != 0;
775759
if persist_update {
776-
let monitor_name = MonitorName::from(funding_txo);
777760
let update_name = UpdateName::from(update.update_id);
778761
match self.kv_store.write(
779762
CHANNEL_MONITOR_UPDATE_PERSISTENCE_PRIMARY_NAMESPACE,
@@ -795,7 +778,6 @@ where
795778
},
796779
}
797780
} else {
798-
let monitor_name = MonitorName::from(funding_txo);
799781
// In case of channel-close monitor update, we need to read old monitor before persisting
800782
// the new one in order to determine the cleanup range.
801783
let maybe_old_monitor = match monitor.get_latest_update_id() {
@@ -804,7 +786,7 @@ where
804786
};
805787

806788
// We could write this update, but it meets criteria of our design that calls for a full monitor write.
807-
let monitor_update_status = self.persist_new_channel(funding_txo, monitor);
789+
let monitor_update_status = self.persist_new_channel(monitor);
808790

809791
if let chain::ChannelMonitorUpdateStatus::Completed = monitor_update_status {
810792
let channel_closed_legacy =
@@ -835,12 +817,12 @@ where
835817
}
836818
} else {
837819
// There is no update given, so we must persist a new monitor.
838-
self.persist_new_channel(funding_txo, monitor)
820+
self.persist_new_channel(monitor)
839821
}
840822
}
841823

842-
fn archive_persisted_channel(&self, funding_txo: OutPoint) {
843-
let monitor_name = MonitorName::from(funding_txo);
824+
fn archive_persisted_channel(&self, monitor: &ChannelMonitor<ChannelSigner>) {
825+
let monitor_name = monitor.persistence_key();
844826
let monitor_key = monitor_name.as_str().to_string();
845827
let monitor = match self.read_channel_monitor_with_updates(monitor_key) {
846828
Ok((_block_hash, monitor)) => monitor,
@@ -901,14 +883,15 @@ where
901883
/// in functions that store or retrieve [`ChannelMonitor`] snapshots.
902884
/// It provides a consistent way to generate a unique key for channel
903885
/// monitors based on the channel's funding [`OutPoint`] for v1 channels or
904-
/// [`ChannelId`] for v2 channels.
886+
/// [`ChannelId`] for v2 channels. Use [`ChannelMonitor::persistence_key`] to
887+
/// obtain the correct `MonitorName`.
905888
///
906889
/// While users of the Lightning Dev Kit library generally won't need
907890
/// to interact with [`MonitorName`] directly, it can be useful for:
908891
/// - Custom persistence implementations
909892
/// - Debugging or logging channel monitor operations
910893
/// - Extending the functionality of the `MonitorUpdatingPersister`
911-
//
894+
///
912895
/// # Examples
913896
///
914897
/// ```
@@ -1402,10 +1385,6 @@ mod tests {
14021385
let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();
14031386
let cmu_map = nodes[1].chain_monitor.monitor_updates.lock().unwrap();
14041387
let cmu = &cmu_map.get(&added_monitors[0].1.channel_id()).unwrap()[0];
1405-
let txid =
1406-
Txid::from_str("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be")
1407-
.unwrap();
1408-
let test_txo = OutPoint { txid, index: 0 };
14091388

14101389
let ro_persister = MonitorUpdatingPersister {
14111390
kv_store: &TestStore::new(true),
@@ -1416,7 +1395,7 @@ mod tests {
14161395
broadcaster: node_cfgs[0].tx_broadcaster,
14171396
fee_estimator: node_cfgs[0].fee_estimator,
14181397
};
1419-
match ro_persister.persist_new_channel(test_txo, &added_monitors[0].1) {
1398+
match ro_persister.persist_new_channel(&added_monitors[0].1) {
14201399
ChannelMonitorUpdateStatus::UnrecoverableError => {
14211400
// correct result
14221401
},
@@ -1427,7 +1406,7 @@ mod tests {
14271406
panic!("Returned InProgress when shouldn't have")
14281407
},
14291408
}
1430-
match ro_persister.update_persisted_channel(test_txo, Some(cmu), &added_monitors[0].1) {
1409+
match ro_persister.update_persisted_channel(Some(cmu), &added_monitors[0].1) {
14311410
ChannelMonitorUpdateStatus::UnrecoverableError => {
14321411
// correct result
14331412
},

0 commit comments

Comments
 (0)