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

Allow disabling wallet background syncing #508

Merged
merged 1 commit into from
Mar 28, 2025
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
6 changes: 5 additions & 1 deletion bindings/ldk_node.udl
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@ dictionary AnchorChannelsConfig {
u64 per_channel_reserve_sats;
};

dictionary EsploraSyncConfig {
dictionary BackgroundSyncConfig {
u64 onchain_wallet_sync_interval_secs;
u64 lightning_wallet_sync_interval_secs;
u64 fee_rate_cache_update_interval_secs;
};

dictionary EsploraSyncConfig {
BackgroundSyncConfig? background_sync_config;
};

dictionary LSPS2ServiceConfig {
string? require_token;
boolean advertise_service;
Expand Down
107 changes: 59 additions & 48 deletions src/chain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,57 +207,68 @@ impl ChainSource {
) {
match self {
Self::Esplora { sync_config, logger, .. } => {
// Setup syncing intervals
let onchain_wallet_sync_interval_secs = sync_config
.onchain_wallet_sync_interval_secs
.max(WALLET_SYNC_INTERVAL_MINIMUM_SECS);
let mut onchain_wallet_sync_interval =
tokio::time::interval(Duration::from_secs(onchain_wallet_sync_interval_secs));
onchain_wallet_sync_interval
.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);

let fee_rate_cache_update_interval_secs = sync_config
.fee_rate_cache_update_interval_secs
.max(WALLET_SYNC_INTERVAL_MINIMUM_SECS);
let mut fee_rate_update_interval =
tokio::time::interval(Duration::from_secs(fee_rate_cache_update_interval_secs));
// When starting up, we just blocked on updating, so skip the first tick.
fee_rate_update_interval.reset();
fee_rate_update_interval
.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);

let lightning_wallet_sync_interval_secs = sync_config
.lightning_wallet_sync_interval_secs
.max(WALLET_SYNC_INTERVAL_MINIMUM_SECS);
let mut lightning_wallet_sync_interval =
tokio::time::interval(Duration::from_secs(lightning_wallet_sync_interval_secs));
lightning_wallet_sync_interval
.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
// Setup syncing intervals if enabled
if let Some(background_sync_config) = sync_config.background_sync_config {
let onchain_wallet_sync_interval_secs = background_sync_config
.onchain_wallet_sync_interval_secs
.max(WALLET_SYNC_INTERVAL_MINIMUM_SECS);
let mut onchain_wallet_sync_interval = tokio::time::interval(
Duration::from_secs(onchain_wallet_sync_interval_secs),
);
onchain_wallet_sync_interval
.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);

let fee_rate_cache_update_interval_secs = background_sync_config
.fee_rate_cache_update_interval_secs
.max(WALLET_SYNC_INTERVAL_MINIMUM_SECS);
let mut fee_rate_update_interval = tokio::time::interval(Duration::from_secs(
fee_rate_cache_update_interval_secs,
));
// When starting up, we just blocked on updating, so skip the first tick.
fee_rate_update_interval.reset();
fee_rate_update_interval
.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);

let lightning_wallet_sync_interval_secs = background_sync_config
.lightning_wallet_sync_interval_secs
.max(WALLET_SYNC_INTERVAL_MINIMUM_SECS);
let mut lightning_wallet_sync_interval = tokio::time::interval(
Duration::from_secs(lightning_wallet_sync_interval_secs),
);
lightning_wallet_sync_interval
.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);

// Start the syncing loop.
loop {
tokio::select! {
_ = stop_sync_receiver.changed() => {
log_trace!(
logger,
"Stopping background syncing on-chain wallet.",
);
return;
}
_ = onchain_wallet_sync_interval.tick() => {
let _ = self.sync_onchain_wallet().await;
}
_ = fee_rate_update_interval.tick() => {
let _ = self.update_fee_rate_estimates().await;
}
_ = lightning_wallet_sync_interval.tick() => {
let _ = self.sync_lightning_wallet(
Arc::clone(&channel_manager),
Arc::clone(&chain_monitor),
Arc::clone(&output_sweeper),
).await;
// Start the syncing loop.
loop {
tokio::select! {
_ = stop_sync_receiver.changed() => {
log_trace!(
logger,
"Stopping background syncing on-chain wallet.",
);
return;
}
_ = onchain_wallet_sync_interval.tick() => {
let _ = self.sync_onchain_wallet().await;
}
_ = fee_rate_update_interval.tick() => {
let _ = self.update_fee_rate_estimates().await;
}
_ = lightning_wallet_sync_interval.tick() => {
let _ = self.sync_lightning_wallet(
Arc::clone(&channel_manager),
Arc::clone(&chain_monitor),
Arc::clone(&output_sweeper),
).await;
}
}
}
} else {
// Background syncing is disabled
log_info!(
logger, "Background syncing disabled. Manual syncing required for onchain wallet, lightning wallet, and fee rate updates.",
);
return;
}
},
Self::BitcoindRpc {
Expand Down
35 changes: 29 additions & 6 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ pub(crate) fn default_user_config(config: &Config) -> UserConfig {
user_config
}

/// Options related to syncing the Lightning and on-chain wallets via an Esplora backend.
/// Options related to background syncing the Lightning and on-chain wallets.
///
/// ### Defaults
///
Expand All @@ -292,22 +292,24 @@ pub(crate) fn default_user_config(config: &Config) -> UserConfig {
/// | `lightning_wallet_sync_interval_secs` | 30 |
/// | `fee_rate_cache_update_interval_secs` | 600 |
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct EsploraSyncConfig {
pub struct BackgroundSyncConfig {
/// The time in-between background sync attempts of the onchain wallet, in seconds.
///
/// **Note:** A minimum of 10 seconds is always enforced.
/// **Note:** A minimum of 10 seconds is enforced when background syncing is enabled.
pub onchain_wallet_sync_interval_secs: u64,

/// The time in-between background sync attempts of the LDK wallet, in seconds.
///
/// **Note:** A minimum of 10 seconds is always enforced.
/// **Note:** A minimum of 10 seconds is enforced when background syncing is enabled.
pub lightning_wallet_sync_interval_secs: u64,

/// The time in-between background update attempts to our fee rate cache, in seconds.
///
/// **Note:** A minimum of 10 seconds is always enforced.
/// **Note:** A minimum of 10 seconds is enforced when background syncing is enabled.
pub fee_rate_cache_update_interval_secs: u64,
}

impl Default for EsploraSyncConfig {
impl Default for BackgroundSyncConfig {
fn default() -> Self {
Self {
onchain_wallet_sync_interval_secs: DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS,
Expand All @@ -317,6 +319,27 @@ impl Default for EsploraSyncConfig {
}
}

/// Configuration for syncing with an Esplora backend.
///
/// Background syncing is enabled by default, using the default values specified in
/// [`BackgroundSyncConfig`].
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct EsploraSyncConfig {
/// Background sync configuration.
///
/// If set to `None`, background syncing will be disabled. Users will need to manually
/// sync via `Node::sync_wallets` for the wallets and fee rate updates.
///
/// [`Node::sync_wallets`]: crate::Node::sync_wallets
pub background_sync_config: Option<BackgroundSyncConfig>,
}

impl Default for EsploraSyncConfig {
fn default() -> Self {
Self { background_sync_config: Some(BackgroundSyncConfig::default()) }
}
}

/// Options which apply on a per-channel basis and may change at runtime or based on negotiation
/// with our counterparty.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
Expand Down
13 changes: 6 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1219,14 +1219,13 @@ impl Node {
/// 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 the
/// respective config object, e.g., via
/// [`EsploraSyncConfig::onchain_wallet_sync_interval_secs`] and
/// [`EsploraSyncConfig::lightning_wallet_sync_interval_secs`]. Therefore, using this blocking
/// sync method is almost always redundant and should be avoided where possible.
/// **Note:** The wallets are regularly synced in the background if background syncing is enabled
/// via [`EsploraSyncConfig::background_sync_config`]. Therefore, using this blocking sync method
/// is almost always redundant when background syncing is enabled and should be avoided where possible.
/// However, if background syncing is disabled (i.e., `background_sync_config` is set to `None`),
/// this method must be called manually to keep wallets in sync with the chain state.
///
/// [`EsploraSyncConfig::onchain_wallet_sync_interval_secs`]: crate::config::EsploraSyncConfig::onchain_wallet_sync_interval_secs
/// [`EsploraSyncConfig::lightning_wallet_sync_interval_secs`]: crate::config::EsploraSyncConfig::lightning_wallet_sync_interval_secs
/// [`EsploraSyncConfig::background_sync_config`]: crate::config::EsploraSyncConfig::background_sync_config
pub fn sync_wallets(&self) -> Result<(), Error> {
let rt_lock = self.runtime.read().unwrap();
if rt_lock.is_none() {
Expand Down
3 changes: 2 additions & 1 deletion src/uniffi_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
// Make sure to add any re-exported items that need to be used in uniffi below.

pub use crate::config::{
default_config, AnchorChannelsConfig, EsploraSyncConfig, MaxDustHTLCExposure,
default_config, AnchorChannelsConfig, BackgroundSyncConfig, EsploraSyncConfig,
MaxDustHTLCExposure,
};
pub use crate::graph::{ChannelInfo, ChannelUpdateInfo, NodeAnnouncementInfo, NodeInfo};
pub use crate::liquidity::{LSPS1OrderStatus, LSPS2ServiceConfig, OnchainPaymentInfo, PaymentInfo};
Expand Down
4 changes: 1 addition & 3 deletions tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,7 @@ pub(crate) fn setup_node(
match chain_source {
TestChainSource::Esplora(electrsd) => {
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
let mut sync_config = EsploraSyncConfig::default();
sync_config.onchain_wallet_sync_interval_secs = 100000;
sync_config.lightning_wallet_sync_interval_secs = 100000;
let sync_config = EsploraSyncConfig { background_sync_config: None };
builder.set_chain_source_esplora(esplora_url.clone(), Some(sync_config));
},
TestChainSource::BitcoindRpc(bitcoind) => {
Expand Down
12 changes: 3 additions & 9 deletions tests/integration_tests_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,7 @@ fn multi_hop_sending() {
let mut nodes = Vec::new();
for _ in 0..5 {
let config = random_config(true);
let mut sync_config = EsploraSyncConfig::default();
sync_config.onchain_wallet_sync_interval_secs = 100000;
sync_config.lightning_wallet_sync_interval_secs = 100000;
let sync_config = EsploraSyncConfig { background_sync_config: None };
setup_builder!(builder, config.node_config);
builder.set_chain_source_esplora(esplora_url.clone(), Some(sync_config));
let node = builder.build().unwrap();
Expand Down Expand Up @@ -227,9 +225,7 @@ fn start_stop_reinit() {
let test_sync_store: Arc<dyn KVStore + Sync + Send> =
Arc::new(TestSyncStore::new(config.node_config.storage_dir_path.clone().into()));

let mut sync_config = EsploraSyncConfig::default();
sync_config.onchain_wallet_sync_interval_secs = 100000;
sync_config.lightning_wallet_sync_interval_secs = 100000;
let sync_config = EsploraSyncConfig { background_sync_config: None };
setup_builder!(builder, config.node_config);
builder.set_chain_source_esplora(esplora_url.clone(), Some(sync_config));

Expand Down Expand Up @@ -1048,9 +1044,7 @@ fn lsps2_client_service_integration() {

let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());

let mut sync_config = EsploraSyncConfig::default();
sync_config.onchain_wallet_sync_interval_secs = 100000;
sync_config.lightning_wallet_sync_interval_secs = 100000;
let sync_config = EsploraSyncConfig { background_sync_config: None };

// Setup three nodes: service, client, and payer
let channel_opening_fee_ppm = 10_000;
Expand Down