Skip to content

Commit ac80a3e

Browse files
committed
Periodically archive fully-resolved channel monitors
Previously, LDK was very conservative and kept channel monitors around ~forever or until the user manually decided to prune them. Recently it introduced the `ChainMonitor::archive_fully_resolved_monitors` method, which we now call periodically: every time a wallet sync succeeds, we check whether the latest archival height is 6 blocks in the past and call `archive_fully_resolved_monitors`. As this is not permanently persisted, we will always try to archive any pruned monitors when the first background sync after fresh initialization succeeds, ensuring we call it regularly also on short-lived sessions, e.g, on mobile.
1 parent 1eab306 commit ac80a3e

File tree

3 files changed

+42
-2
lines changed

3 files changed

+42
-2
lines changed

src/builder.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,7 @@ fn build_with_store_internal(
980980
let latest_fee_rate_cache_update_timestamp = Arc::new(RwLock::new(None));
981981
let latest_rgs_snapshot_timestamp = Arc::new(RwLock::new(None));
982982
let latest_node_announcement_broadcast_timestamp = Arc::new(RwLock::new(None));
983+
let latest_channel_monitor_archival_height = Arc::new(RwLock::new(None));
983984

984985
Ok(Node {
985986
runtime,
@@ -1011,6 +1012,7 @@ fn build_with_store_internal(
10111012
latest_fee_rate_cache_update_timestamp,
10121013
latest_rgs_snapshot_timestamp,
10131014
latest_node_announcement_broadcast_timestamp,
1015+
latest_channel_monitor_archival_height,
10141016
})
10151017
}
10161018

src/config.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ pub(crate) const DEFAULT_ESPLORA_SERVER_URL: &str = "https://blockstream.info/ap
2929
// The timeout after which we abandon retrying failed payments.
3030
pub(crate) const LDK_PAYMENT_RETRY_TIMEOUT: Duration = Duration::from_secs(10);
3131

32+
// The interval (in block height) after which we archive pruned channel monitors.
33+
pub(crate) const LDK_CHANNEL_MONITOR_ARCHIVAL_INTERVAL: u32 = 6;
34+
3235
// The time in-between peer reconnection attempts.
3336
pub(crate) const PEER_RECONNECTION_INTERVAL: Duration = Duration::from_secs(10);
3437

src/lib.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ pub use builder::BuildError;
122122
pub use builder::NodeBuilder as Builder;
123123

124124
use config::{
125-
NODE_ANN_BCAST_INTERVAL, PEER_RECONNECTION_INTERVAL, RGS_SYNC_INTERVAL,
126-
WALLET_SYNC_INTERVAL_MINIMUM_SECS,
125+
LDK_CHANNEL_MONITOR_ARCHIVAL_INTERVAL, NODE_ANN_BCAST_INTERVAL, PEER_RECONNECTION_INTERVAL,
126+
RGS_SYNC_INTERVAL, WALLET_SYNC_INTERVAL_MINIMUM_SECS,
127127
};
128128
use connection::ConnectionManager;
129129
use event::{EventHandler, EventQueue};
@@ -197,6 +197,7 @@ pub struct Node {
197197
latest_fee_rate_cache_update_timestamp: Arc<RwLock<Option<u64>>>,
198198
latest_rgs_snapshot_timestamp: Arc<RwLock<Option<u64>>>,
199199
latest_node_announcement_broadcast_timestamp: Arc<RwLock<Option<u64>>>,
200+
latest_channel_monitor_archival_height: Arc<RwLock<Option<u32>>>,
200201
}
201202

202203
impl Node {
@@ -342,10 +343,13 @@ impl Node {
342343

343344
let tx_sync = Arc::clone(&self.tx_sync);
344345
let sync_cman = Arc::clone(&self.channel_manager);
346+
let archive_cman = Arc::clone(&self.channel_manager);
345347
let sync_cmon = Arc::clone(&self.chain_monitor);
348+
let archive_cmon = Arc::clone(&self.chain_monitor);
346349
let sync_sweeper = Arc::clone(&self.output_sweeper);
347350
let sync_logger = Arc::clone(&self.logger);
348351
let sync_wallet_timestamp = Arc::clone(&self.latest_wallet_sync_timestamp);
352+
let sync_monitor_archival_height = Arc::clone(&self.latest_channel_monitor_archival_height);
349353
let mut stop_sync = self.stop_sender.subscribe();
350354
let wallet_sync_interval_secs =
351355
self.config.wallet_sync_interval_secs.max(WALLET_SYNC_INTERVAL_MINIMUM_SECS);
@@ -375,6 +379,12 @@ impl Node {
375379
let unix_time_secs_opt =
376380
SystemTime::now().duration_since(UNIX_EPOCH).ok().map(|d| d.as_secs());
377381
*sync_wallet_timestamp.write().unwrap() = unix_time_secs_opt;
382+
383+
periodically_archive_fully_resolved_monitors(
384+
Arc::clone(&archive_cman),
385+
Arc::clone(&archive_cmon),
386+
Arc::clone(&sync_monitor_archival_height)
387+
);
378388
}
379389
Err(e) => {
380390
log_error!(sync_logger, "Background sync of Lightning wallet failed: {}", e)
@@ -1077,14 +1087,17 @@ impl Node {
10771087
let wallet = Arc::clone(&self.wallet);
10781088
let tx_sync = Arc::clone(&self.tx_sync);
10791089
let sync_cman = Arc::clone(&self.channel_manager);
1090+
let archive_cman = Arc::clone(&self.channel_manager);
10801091
let sync_cmon = Arc::clone(&self.chain_monitor);
1092+
let archive_cmon = Arc::clone(&self.chain_monitor);
10811093
let sync_sweeper = Arc::clone(&self.output_sweeper);
10821094
let sync_logger = Arc::clone(&self.logger);
10831095
let confirmables = vec![
10841096
&*sync_cman as &(dyn Confirm + Sync + Send),
10851097
&*sync_cmon as &(dyn Confirm + Sync + Send),
10861098
&*sync_sweeper as &(dyn Confirm + Sync + Send),
10871099
];
1100+
let sync_monitor_archival_height = Arc::clone(&self.latest_channel_monitor_archival_height);
10881101

10891102
tokio::task::block_in_place(move || {
10901103
tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap().block_on(
@@ -1112,6 +1125,12 @@ impl Node {
11121125
"Sync of Lightning wallet finished in {}ms.",
11131126
now.elapsed().as_millis()
11141127
);
1128+
1129+
periodically_archive_fully_resolved_monitors(
1130+
archive_cman,
1131+
archive_cmon,
1132+
sync_monitor_archival_height,
1133+
);
11151134
Ok(())
11161135
},
11171136
Err(e) => {
@@ -1358,3 +1377,19 @@ pub struct NodeStatus {
13581377
/// Will be `None` if we have no public channels or we haven't broadcasted since the [`Node`] was initialized.
13591378
pub latest_node_announcement_broadcast_timestamp: Option<u64>,
13601379
}
1380+
1381+
fn periodically_archive_fully_resolved_monitors(
1382+
channel_manager: Arc<ChannelManager>, chain_monitor: Arc<ChainMonitor>,
1383+
latest_channel_monitor_archival_height: Arc<RwLock<Option<u32>>>,
1384+
) {
1385+
let mut latest_archival_height_lock = latest_channel_monitor_archival_height.write().unwrap();
1386+
let cur_height = channel_manager.current_best_block().height;
1387+
let should_archive = latest_archival_height_lock
1388+
.as_ref()
1389+
.map_or(true, |h| cur_height >= h + LDK_CHANNEL_MONITOR_ARCHIVAL_INTERVAL);
1390+
1391+
if should_archive {
1392+
chain_monitor.archive_fully_resolved_channel_monitors();
1393+
*latest_archival_height_lock = Some(cur_height);
1394+
}
1395+
}

0 commit comments

Comments
 (0)