Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Periodically archive fully resolved channel monitors #307

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -979,6 +979,7 @@ fn build_with_store_internal(
let latest_fee_rate_cache_update_timestamp = Arc::new(RwLock::new(None));
let latest_rgs_snapshot_timestamp = Arc::new(RwLock::new(None));
let latest_node_announcement_broadcast_timestamp = Arc::new(RwLock::new(None));
let latest_channel_monitor_archival_height = Arc::new(RwLock::new(None));

Ok(Node {
runtime,
Expand Down Expand Up @@ -1010,6 +1011,7 @@ fn build_with_store_internal(
latest_fee_rate_cache_update_timestamp,
latest_rgs_snapshot_timestamp,
latest_node_announcement_broadcast_timestamp,
latest_channel_monitor_archival_height,
})
}

Expand Down
3 changes: 3 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ pub(crate) const DEFAULT_ESPLORA_SERVER_URL: &str = "https://blockstream.info/ap
// The timeout after which we abandon retrying failed payments.
pub(crate) const LDK_PAYMENT_RETRY_TIMEOUT: Duration = Duration::from_secs(10);

// The interval (in block height) after which we retry archiving fully resolved channel monitors.
pub(crate) const RESOLVED_CHANNEL_MONITOR_ARCHIVAL_INTERVAL: u32 = 6;

// The time in-between peer reconnection attempts.
pub(crate) const PEER_RECONNECTION_INTERVAL: Duration = Duration::from_secs(10);

Expand Down
77 changes: 75 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ pub use builder::BuildError;
pub use builder::NodeBuilder as Builder;

use config::{
NODE_ANN_BCAST_INTERVAL, PEER_RECONNECTION_INTERVAL, RGS_SYNC_INTERVAL,
NODE_ANN_BCAST_INTERVAL, PEER_RECONNECTION_INTERVAL,
RESOLVED_CHANNEL_MONITOR_ARCHIVAL_INTERVAL, RGS_SYNC_INTERVAL,
WALLET_SYNC_INTERVAL_MINIMUM_SECS,
};
use connection::ConnectionManager;
Expand Down Expand Up @@ -198,6 +199,7 @@ pub struct Node {
latest_fee_rate_cache_update_timestamp: Arc<RwLock<Option<u64>>>,
latest_rgs_snapshot_timestamp: Arc<RwLock<Option<u64>>>,
latest_node_announcement_broadcast_timestamp: Arc<RwLock<Option<u64>>>,
latest_channel_monitor_archival_height: Arc<RwLock<Option<u32>>>,
}

impl Node {
Expand Down Expand Up @@ -343,10 +345,13 @@ impl Node {

let tx_sync = Arc::clone(&self.tx_sync);
let sync_cman = Arc::clone(&self.channel_manager);
let archive_cman = Arc::clone(&self.channel_manager);
let sync_cmon = Arc::clone(&self.chain_monitor);
let archive_cmon = Arc::clone(&self.chain_monitor);
let sync_sweeper = Arc::clone(&self.output_sweeper);
let sync_logger = Arc::clone(&self.logger);
let sync_wallet_timestamp = Arc::clone(&self.latest_wallet_sync_timestamp);
let sync_monitor_archival_height = Arc::clone(&self.latest_channel_monitor_archival_height);
let mut stop_sync = self.stop_sender.subscribe();
let wallet_sync_interval_secs =
self.config.wallet_sync_interval_secs.max(WALLET_SYNC_INTERVAL_MINIMUM_SECS);
Expand Down Expand Up @@ -376,6 +381,12 @@ impl Node {
let unix_time_secs_opt =
SystemTime::now().duration_since(UNIX_EPOCH).ok().map(|d| d.as_secs());
*sync_wallet_timestamp.write().unwrap() = unix_time_secs_opt;

periodically_archive_fully_resolved_monitors(
Arc::clone(&archive_cman),
Arc::clone(&archive_cmon),
Arc::clone(&sync_monitor_archival_height)
);
}
Err(e) => {
log_error!(sync_logger, "Background sync of Lightning wallet failed: {}", e)
Expand Down Expand Up @@ -1113,7 +1124,8 @@ impl Node {
}
}

/// Manually sync the LDK and BDK wallets with the current chain state.
/// Manually sync the LDK and BDK wallets with the current chain state and update the fee rate
/// cache.
///
/// **Note:** The wallets are regularly synced in the background, which is configurable via
/// [`Config::onchain_wallet_sync_interval_secs`] and [`Config::wallet_sync_interval_secs`].
Expand All @@ -1128,14 +1140,22 @@ impl Node {
let wallet = Arc::clone(&self.wallet);
let tx_sync = Arc::clone(&self.tx_sync);
let sync_cman = Arc::clone(&self.channel_manager);
let archive_cman = Arc::clone(&self.channel_manager);
let sync_cmon = Arc::clone(&self.chain_monitor);
let archive_cmon = Arc::clone(&self.chain_monitor);
let fee_estimator = Arc::clone(&self.fee_estimator);
let sync_sweeper = Arc::clone(&self.output_sweeper);
let sync_logger = Arc::clone(&self.logger);
let confirmables = vec![
&*sync_cman as &(dyn Confirm + Sync + Send),
&*sync_cmon as &(dyn Confirm + Sync + Send),
&*sync_sweeper as &(dyn Confirm + Sync + Send),
];
let sync_wallet_timestamp = Arc::clone(&self.latest_wallet_sync_timestamp);
let sync_fee_rate_update_timestamp =
Arc::clone(&self.latest_fee_rate_cache_update_timestamp);
let sync_onchain_wallet_timestamp = Arc::clone(&self.latest_onchain_wallet_sync_timestamp);
let sync_monitor_archival_height = Arc::clone(&self.latest_channel_monitor_archival_height);

tokio::task::block_in_place(move || {
tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap().block_on(
Expand All @@ -1148,13 +1168,38 @@ impl Node {
"Sync of on-chain wallet finished in {}ms.",
now.elapsed().as_millis()
);
let unix_time_secs_opt = SystemTime::now()
.duration_since(UNIX_EPOCH)
.ok()
.map(|d| d.as_secs());
*sync_onchain_wallet_timestamp.write().unwrap() = unix_time_secs_opt;
},
Err(e) => {
log_error!(sync_logger, "Sync of on-chain wallet failed: {}", e);
return Err(e);
},
};

let now = Instant::now();
match fee_estimator.update_fee_estimates().await {
Ok(()) => {
log_info!(
sync_logger,
"Fee rate cache update finished in {}ms.",
now.elapsed().as_millis()
);
let unix_time_secs_opt = SystemTime::now()
.duration_since(UNIX_EPOCH)
.ok()
.map(|d| d.as_secs());
*sync_fee_rate_update_timestamp.write().unwrap() = unix_time_secs_opt;
},
Err(e) => {
log_error!(sync_logger, "Fee rate cache update failed: {}", e,);
return Err(e);
},
}

let now = Instant::now();
match tx_sync.sync(confirmables).await {
Ok(()) => {
Expand All @@ -1163,6 +1208,18 @@ impl Node {
"Sync of Lightning wallet finished in {}ms.",
now.elapsed().as_millis()
);

let unix_time_secs_opt = SystemTime::now()
.duration_since(UNIX_EPOCH)
.ok()
.map(|d| d.as_secs());
*sync_wallet_timestamp.write().unwrap() = unix_time_secs_opt;

periodically_archive_fully_resolved_monitors(
tnull marked this conversation as resolved.
Show resolved Hide resolved
archive_cman,
archive_cmon,
sync_monitor_archival_height,
);
Ok(())
},
Err(e) => {
Expand Down Expand Up @@ -1486,3 +1543,19 @@ pub(crate) fn total_anchor_channels_reserve_sats(
* anchor_channels_config.per_channel_reserve_sats
})
}

fn periodically_archive_fully_resolved_monitors(
channel_manager: Arc<ChannelManager>, chain_monitor: Arc<ChainMonitor>,
latest_channel_monitor_archival_height: Arc<RwLock<Option<u32>>>,
) {
let mut latest_archival_height_lock = latest_channel_monitor_archival_height.write().unwrap();
let cur_height = channel_manager.current_best_block().height;
let should_archive = latest_archival_height_lock
.as_ref()
.map_or(true, |h| cur_height >= h + RESOLVED_CHANNEL_MONITOR_ARCHIVAL_INTERVAL);
tnull marked this conversation as resolved.
Show resolved Hide resolved

if should_archive {
chain_monitor.archive_fully_resolved_channel_monitors();
tnull marked this conversation as resolved.
Show resolved Hide resolved
*latest_archival_height_lock = Some(cur_height);
}
}
Loading