diff --git a/bindings/ldk_node.udl b/bindings/ldk_node.udl index caeb41975..4b72cb56b 100644 --- a/bindings/ldk_node.udl +++ b/bindings/ldk_node.udl @@ -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; diff --git a/src/chain/mod.rs b/src/chain/mod.rs index d96ab06ef..a2e01884a 100644 --- a/src/chain/mod.rs +++ b/src/chain/mod.rs @@ -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 { diff --git a/src/config.rs b/src/config.rs index d5094d31c..f04ff6243 100644 --- a/src/config.rs +++ b/src/config.rs @@ -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 /// @@ -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, @@ -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, +} + +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)] diff --git a/src/lib.rs b/src/lib.rs index a31b3701a..4eb1afe03 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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() { diff --git a/src/uniffi_types.rs b/src/uniffi_types.rs index 58c577f8e..410ce8531 100644 --- a/src/uniffi_types.rs +++ b/src/uniffi_types.rs @@ -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}; diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 0949cadd3..aac18225b 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -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) => { diff --git a/tests/integration_tests_rust.rs b/tests/integration_tests_rust.rs index 8dc0ca50a..a4d2c4233 100644 --- a/tests/integration_tests_rust.rs +++ b/tests/integration_tests_rust.rs @@ -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(); @@ -227,9 +225,7 @@ fn start_stop_reinit() { let test_sync_store: Arc = 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)); @@ -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;