Skip to content

Commit 2587e2d

Browse files
committed
Enforce successful initial wallet sync and make sync interval configurable
So far we'd immediately start background syncing upon `start()` which would work fine, except when these initial syncs failed, in which case we'd use our fallback fee. This might lead to being disconnected from peers as our fallback values are likely out of current fee ranges. To mitigate this we here simply enforce that the initial syncs in `start()` are successful and hence we'd at least once got a recent fee estimation update. Moreover, we make the background syncing intervals configurable, however enforcing a floor of 10 seconds.
1 parent d80aceb commit 2587e2d

File tree

3 files changed

+121
-52
lines changed

3 files changed

+121
-52
lines changed

bindings/ldk_node.udl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ dictionary Config {
77
Network network;
88
NetAddress? listening_address;
99
u32 default_cltv_expiry_delta;
10+
u64 onchain_wallet_sync_interval_secs;
11+
u64 wallet_sync_interval_secs;
1012
LogLevel log_level;
1113
};
1214

src/lib.rs

Lines changed: 116 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ use types::{
112112
pub use types::{ChannelDetails, ChannelId, PeerDetails, UserChannelId};
113113
use wallet::Wallet;
114114

115-
use logger::{log_error, log_info, FilesystemLogger, Logger};
115+
use logger::{log_error, log_info, log_trace, FilesystemLogger, Logger};
116116

117117
use lightning::chain::keysinterface::EntropySource;
118118
use lightning::chain::{chainmonitor, BestBlock, Confirm, Watch};
@@ -167,9 +167,15 @@ const BDK_CLIENT_STOP_GAP: usize = 20;
167167
// The number of concurrent requests made against the API provider.
168168
const BDK_CLIENT_CONCURRENCY: u8 = 8;
169169

170+
// The default time in-between LDK wallet sync attempts.
171+
const DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS: u64 = 60;
172+
170173
// The timeout after which we abandon retrying failed payments.
171174
const LDK_PAYMENT_RETRY_TIMEOUT: Duration = Duration::from_secs(10);
172175

176+
// The default time in-between LDK wallet sync attempts.
177+
const DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS: u64 = 20;
178+
173179
// The time in-between peer reconnection attempts.
174180
const PEER_RECONNECTION_INTERVAL: Duration = Duration::from_secs(10);
175181

@@ -195,6 +201,14 @@ pub struct Config {
195201
pub listening_address: Option<NetAddress>,
196202
/// The default CLTV expiry delta to be used for payments.
197203
pub default_cltv_expiry_delta: u32,
204+
/// The time in-between background sync attempts of the onchain wallet, in seconds.
205+
///
206+
/// **Note:** A minimum of 10 seconds is always enforced.
207+
pub onchain_wallet_sync_interval_secs: u64,
208+
/// The time in-between background sync attempts of the LDK wallet, in seconds.
209+
///
210+
/// **Note:** A minimum of 10 seconds is always enforced.
211+
pub wallet_sync_interval_secs: u64,
198212
/// The level at which we log messages.
199213
///
200214
/// Any messages below this level will be excluded from the logs.
@@ -209,6 +223,8 @@ impl Default for Config {
209223
network: Network::Regtest,
210224
listening_address: Some("0.0.0.0:9735".parse().unwrap()),
211225
default_cltv_expiry_delta: 144,
226+
onchain_wallet_sync_interval_secs: DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS,
227+
wallet_sync_interval_secs: DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS,
212228
log_level: LogLevel::Debug,
213229
}
214230
}
@@ -729,31 +745,38 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
729745

730746
let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap();
731747

732-
let event_handler = Arc::new(EventHandler::new(
733-
Arc::clone(&self.wallet),
734-
Arc::clone(&self.event_queue),
735-
Arc::clone(&self.channel_manager),
736-
Arc::clone(&self.network_graph),
737-
Arc::clone(&self.keys_manager),
738-
Arc::clone(&self.payment_store),
739-
Arc::clone(&self.runtime),
740-
Arc::clone(&self.logger),
741-
Arc::clone(&self.config),
742-
));
743-
744748
// Setup wallet sync
745749
let wallet = Arc::clone(&self.wallet);
746-
let tx_sync = Arc::clone(&self.tx_sync);
747-
let sync_cman = Arc::clone(&self.channel_manager);
748-
let sync_cmon = Arc::clone(&self.chain_monitor);
749750
let sync_logger = Arc::clone(&self.logger);
750751
let mut stop_sync = self.stop_receiver.clone();
751752

753+
runtime.block_on(async move {
754+
let now = Instant::now();
755+
match wallet.sync().await {
756+
Ok(()) => {
757+
log_info!(
758+
sync_logger,
759+
"Initial sync of on-chain wallet finished in {}ms.",
760+
now.elapsed().as_millis()
761+
);
762+
Ok(())
763+
}
764+
Err(e) => {
765+
log_error!(sync_logger, "Initial sync of on-chain wallet failed: {}", e,);
766+
Err(e)
767+
}
768+
}
769+
})?;
770+
771+
let sync_logger = Arc::clone(&self.logger);
772+
let wallet = Arc::clone(&self.wallet);
752773
std::thread::spawn(move || {
753774
tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap().block_on(
754775
async move {
755-
let mut interval = tokio::time::interval(Duration::from_secs(30));
776+
let interval_secs = DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS.max(10);
777+
let mut interval = tokio::time::interval(Duration::from_secs(interval_secs));
756778
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
779+
interval.reset();
757780
loop {
758781
let now = Instant::now();
759782
tokio::select! {
@@ -762,7 +785,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
762785
}
763786
_ = interval.tick() => {
764787
match wallet.sync().await {
765-
Ok(()) => log_info!(
788+
Ok(()) => log_trace!(
766789
sync_logger,
767790
"Background sync of on-chain wallet finished in {}ms.",
768791
now.elapsed().as_millis()
@@ -782,6 +805,68 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
782805
);
783806
});
784807

808+
let tx_sync = Arc::clone(&self.tx_sync);
809+
let sync_cman = Arc::clone(&self.channel_manager);
810+
let sync_cmon = Arc::clone(&self.chain_monitor);
811+
let sync_logger = Arc::clone(&self.logger);
812+
runtime.block_on(async move {
813+
let now = Instant::now();
814+
let confirmables = vec![
815+
&*sync_cman as &(dyn Confirm + Sync + Send),
816+
&*sync_cmon as &(dyn Confirm + Sync + Send),
817+
];
818+
match tx_sync.sync(confirmables).await {
819+
Ok(()) => {
820+
log_info!(
821+
sync_logger,
822+
"Initial sync of Lightning wallet finished in {}ms.",
823+
now.elapsed().as_millis()
824+
);
825+
Ok(())
826+
}
827+
Err(e) => {
828+
log_error!(sync_logger, "Initial sync of Lightning wallet failed: {}", e);
829+
Err(e)
830+
}
831+
}
832+
})?;
833+
834+
let tx_sync = Arc::clone(&self.tx_sync);
835+
let sync_cman = Arc::clone(&self.channel_manager);
836+
let sync_cmon = Arc::clone(&self.chain_monitor);
837+
let sync_logger = Arc::clone(&self.logger);
838+
let mut stop_sync = self.stop_receiver.clone();
839+
runtime.spawn(async move {
840+
let interval_secs = DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS.max(10);
841+
let mut interval = tokio::time::interval(Duration::from_secs(interval_secs));
842+
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
843+
interval.reset();
844+
loop {
845+
let now = Instant::now();
846+
tokio::select! {
847+
_ = stop_sync.changed() => {
848+
return;
849+
}
850+
_ = interval.tick() => {
851+
let confirmables = vec![
852+
&*sync_cman as &(dyn Confirm + Sync + Send),
853+
&*sync_cmon as &(dyn Confirm + Sync + Send),
854+
];
855+
match tx_sync.sync(confirmables).await {
856+
Ok(()) => log_trace!(
857+
sync_logger,
858+
"Background sync of Lightning wallet finished in {}ms.",
859+
now.elapsed().as_millis()
860+
),
861+
Err(e) => {
862+
log_error!(sync_logger, "Background sync of Lightning wallet failed: {}", e)
863+
}
864+
}
865+
}
866+
}
867+
}
868+
});
869+
785870
if self.gossip_source.is_rgs() {
786871
let gossip_source = Arc::clone(&self.gossip_source);
787872
let gossip_sync_store = Arc::clone(&self.kv_store);
@@ -799,7 +884,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
799884
let now = Instant::now();
800885
match gossip_source.update_rgs_snapshot().await {
801886
Ok(updated_timestamp) => {
802-
log_info!(
887+
log_trace!(
803888
gossip_sync_logger,
804889
"Background sync of RGS gossip data finished in {}ms.",
805890
now.elapsed().as_millis()
@@ -823,37 +908,6 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
823908
});
824909
}
825910

826-
let sync_logger = Arc::clone(&self.logger);
827-
let mut stop_sync = self.stop_receiver.clone();
828-
runtime.spawn(async move {
829-
let mut interval = tokio::time::interval(Duration::from_secs(10));
830-
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
831-
loop {
832-
let now = Instant::now();
833-
tokio::select! {
834-
_ = stop_sync.changed() => {
835-
return;
836-
}
837-
_ = interval.tick() => {
838-
let confirmables = vec![
839-
&*sync_cman as &(dyn Confirm + Sync + Send),
840-
&*sync_cmon as &(dyn Confirm + Sync + Send),
841-
];
842-
match tx_sync.sync(confirmables).await {
843-
Ok(()) => log_info!(
844-
sync_logger,
845-
"Background sync of Lightning wallet finished in {}ms.",
846-
now.elapsed().as_millis()
847-
),
848-
Err(e) => {
849-
log_error!(sync_logger, "Background sync of Lightning wallet failed: {}", e)
850-
}
851-
}
852-
}
853-
}
854-
}
855-
});
856-
857911
if let Some(listening_address) = &self.config.listening_address {
858912
// Setup networking
859913
let peer_manager_connection_handler = Arc::clone(&self.peer_manager);
@@ -987,6 +1041,18 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
9871041
}
9881042
});
9891043

1044+
let event_handler = Arc::new(EventHandler::new(
1045+
Arc::clone(&self.wallet),
1046+
Arc::clone(&self.event_queue),
1047+
Arc::clone(&self.channel_manager),
1048+
Arc::clone(&self.network_graph),
1049+
Arc::clone(&self.keys_manager),
1050+
Arc::clone(&self.payment_store),
1051+
Arc::clone(&self.runtime),
1052+
Arc::clone(&self.logger),
1053+
Arc::clone(&self.config),
1054+
));
1055+
9901056
// Setup background processing
9911057
let background_persister = Arc::clone(&self.kv_store);
9921058
let background_event_handler = Arc::clone(&event_handler);

src/test/functional_tests.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,9 +375,10 @@ fn onchain_spend_receive() {
375375

376376
#[test]
377377
fn sign_verify_msg() {
378-
let (_, electrsd) = setup_bitcoind_and_electrsd();
378+
let (_bitcoind, electrsd) = setup_bitcoind_and_electrsd();
379379
let esplora_url = electrsd.esplora_url.as_ref().unwrap();
380-
let node = Builder::from_config(random_config(esplora_url)).build();
380+
let config = random_config(esplora_url);
381+
let node = Builder::from_config(config).build();
381382

382383
node.start().unwrap();
383384

0 commit comments

Comments
 (0)