Skip to content

Commit cee6119

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 f4d3ca8 commit cee6119

File tree

3 files changed

+128
-58
lines changed

3 files changed

+128
-58
lines changed

bindings/ldk_node.udl

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

src/lib.rs

Lines changed: 125 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ use types::{
118118
pub use types::{ChannelDetails, ChannelId, PeerDetails, UserChannelId};
119119
use wallet::Wallet;
120120

121-
use logger::{log_error, log_info, FilesystemLogger, Logger};
121+
use logger::{log_error, log_info, log_trace, FilesystemLogger, Logger};
122122

123123
use lightning::chain::keysinterface::EntropySource;
124124
use lightning::chain::{chainmonitor, BestBlock, Confirm, Watch};
@@ -183,9 +183,15 @@ const BDK_CLIENT_STOP_GAP: usize = 20;
183183
// The number of concurrent requests made against the API provider.
184184
const BDK_CLIENT_CONCURRENCY: u8 = 8;
185185

186+
// The default time in-between LDK wallet sync attempts.
187+
const DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS: u64 = 60;
188+
186189
// The timeout after which we abandon retrying failed payments.
187190
const LDK_PAYMENT_RETRY_TIMEOUT: Duration = Duration::from_secs(10);
188191

192+
// The default time in-between LDK wallet sync attempts.
193+
const DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS: u64 = 20;
194+
189195
// The time in-between peer reconnection attempts.
190196
const PEER_RECONNECTION_INTERVAL: Duration = Duration::from_secs(10);
191197

@@ -203,13 +209,15 @@ const WALLET_KEYS_SEED_LEN: usize = 64;
203209
///
204210
/// ### Defaults
205211
///
206-
/// | Parameter | Value |
207-
/// |-----------------------------|------------------|
208-
/// | `storage_dir_path` | /tmp/ldk_node/ |
209-
/// | `network` | Network::Bitcoin |
210-
/// | `listening_address` | 0.0.0.0:9735 |
211-
/// | `default_cltv_expiry_delta` | 144 |
212-
/// | `log_level` | `Debug` |
212+
/// | Parameter | Value |
213+
/// |-------------------------------------|------------------|
214+
/// | `storage_dir_path` | /tmp/ldk_node/ |
215+
/// | `network` | Network::Bitcoin |
216+
/// | `listening_address` | 0.0.0.0:9735 |
217+
/// | `default_cltv_expiry_delta` | 144 |
218+
/// | `onchain_wallet_sync_interval_secs` | 60 |
219+
/// | `wallet_sync_interval_secs` | 20 |
220+
/// | `log_level` | `Debug` |
213221
///
214222
pub struct Config {
215223
/// The path where the underlying LDK and BDK persist their data.
@@ -220,6 +228,14 @@ pub struct Config {
220228
pub listening_address: Option<NetAddress>,
221229
/// The default CLTV expiry delta to be used for payments.
222230
pub default_cltv_expiry_delta: u32,
231+
/// The time in-between background sync attempts of the onchain wallet, in seconds.
232+
///
233+
/// **Note:** A minimum of 10 seconds is always enforced.
234+
pub onchain_wallet_sync_interval_secs: u64,
235+
/// The time in-between background sync attempts of the LDK wallet, in seconds.
236+
///
237+
/// **Note:** A minimum of 10 seconds is always enforced.
238+
pub wallet_sync_interval_secs: u64,
223239
/// The level at which we log messages.
224240
///
225241
/// Any messages below this level will be excluded from the logs.
@@ -233,6 +249,8 @@ impl Default for Config {
233249
network: DEFAULT_NETWORK,
234250
listening_address: Some(DEFAULT_LISTENING_ADDR.parse().unwrap()),
235251
default_cltv_expiry_delta: DEFAULT_CLTV_EXPIRY_DELTA,
252+
onchain_wallet_sync_interval_secs: DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS,
253+
wallet_sync_interval_secs: DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS,
236254
log_level: DEFAULT_LOG_LEVEL,
237255
}
238256
}
@@ -766,31 +784,38 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
766784

767785
let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap();
768786

769-
let event_handler = Arc::new(EventHandler::new(
770-
Arc::clone(&self.wallet),
771-
Arc::clone(&self.event_queue),
772-
Arc::clone(&self.channel_manager),
773-
Arc::clone(&self.network_graph),
774-
Arc::clone(&self.keys_manager),
775-
Arc::clone(&self.payment_store),
776-
Arc::clone(&self.runtime),
777-
Arc::clone(&self.logger),
778-
Arc::clone(&self.config),
779-
));
780-
781787
// Setup wallet sync
782788
let wallet = Arc::clone(&self.wallet);
783-
let tx_sync = Arc::clone(&self.tx_sync);
784-
let sync_cman = Arc::clone(&self.channel_manager);
785-
let sync_cmon = Arc::clone(&self.chain_monitor);
786789
let sync_logger = Arc::clone(&self.logger);
787790
let mut stop_sync = self.stop_receiver.clone();
788791

792+
runtime.block_on(async move {
793+
let now = Instant::now();
794+
match wallet.sync().await {
795+
Ok(()) => {
796+
log_info!(
797+
sync_logger,
798+
"Initial sync of on-chain wallet finished in {}ms.",
799+
now.elapsed().as_millis()
800+
);
801+
Ok(())
802+
}
803+
Err(e) => {
804+
log_error!(sync_logger, "Initial sync of on-chain wallet failed: {}", e,);
805+
Err(e)
806+
}
807+
}
808+
})?;
809+
810+
let sync_logger = Arc::clone(&self.logger);
811+
let wallet = Arc::clone(&self.wallet);
789812
std::thread::spawn(move || {
790813
tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap().block_on(
791814
async move {
792-
let mut interval = tokio::time::interval(Duration::from_secs(30));
815+
let interval_secs = DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS.max(10);
816+
let mut interval = tokio::time::interval(Duration::from_secs(interval_secs));
793817
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
818+
interval.reset();
794819
loop {
795820
let now = Instant::now();
796821
tokio::select! {
@@ -799,7 +824,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
799824
}
800825
_ = interval.tick() => {
801826
match wallet.sync().await {
802-
Ok(()) => log_info!(
827+
Ok(()) => log_trace!(
803828
sync_logger,
804829
"Background sync of on-chain wallet finished in {}ms.",
805830
now.elapsed().as_millis()
@@ -819,6 +844,68 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
819844
);
820845
});
821846

847+
let tx_sync = Arc::clone(&self.tx_sync);
848+
let sync_cman = Arc::clone(&self.channel_manager);
849+
let sync_cmon = Arc::clone(&self.chain_monitor);
850+
let sync_logger = Arc::clone(&self.logger);
851+
runtime.block_on(async move {
852+
let now = Instant::now();
853+
let confirmables = vec![
854+
&*sync_cman as &(dyn Confirm + Sync + Send),
855+
&*sync_cmon as &(dyn Confirm + Sync + Send),
856+
];
857+
match tx_sync.sync(confirmables).await {
858+
Ok(()) => {
859+
log_info!(
860+
sync_logger,
861+
"Initial sync of Lightning wallet finished in {}ms.",
862+
now.elapsed().as_millis()
863+
);
864+
Ok(())
865+
}
866+
Err(e) => {
867+
log_error!(sync_logger, "Initial sync of Lightning wallet failed: {}", e);
868+
Err(e)
869+
}
870+
}
871+
})?;
872+
873+
let tx_sync = Arc::clone(&self.tx_sync);
874+
let sync_cman = Arc::clone(&self.channel_manager);
875+
let sync_cmon = Arc::clone(&self.chain_monitor);
876+
let sync_logger = Arc::clone(&self.logger);
877+
let mut stop_sync = self.stop_receiver.clone();
878+
runtime.spawn(async move {
879+
let interval_secs = DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS.max(10);
880+
let mut interval = tokio::time::interval(Duration::from_secs(interval_secs));
881+
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
882+
interval.reset();
883+
loop {
884+
let now = Instant::now();
885+
tokio::select! {
886+
_ = stop_sync.changed() => {
887+
return;
888+
}
889+
_ = interval.tick() => {
890+
let confirmables = vec![
891+
&*sync_cman as &(dyn Confirm + Sync + Send),
892+
&*sync_cmon as &(dyn Confirm + Sync + Send),
893+
];
894+
match tx_sync.sync(confirmables).await {
895+
Ok(()) => log_trace!(
896+
sync_logger,
897+
"Background sync of Lightning wallet finished in {}ms.",
898+
now.elapsed().as_millis()
899+
),
900+
Err(e) => {
901+
log_error!(sync_logger, "Background sync of Lightning wallet failed: {}", e)
902+
}
903+
}
904+
}
905+
}
906+
}
907+
});
908+
822909
if self.gossip_source.is_rgs() {
823910
let gossip_source = Arc::clone(&self.gossip_source);
824911
let gossip_sync_store = Arc::clone(&self.kv_store);
@@ -836,7 +923,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
836923
let now = Instant::now();
837924
match gossip_source.update_rgs_snapshot().await {
838925
Ok(updated_timestamp) => {
839-
log_info!(
926+
log_trace!(
840927
gossip_sync_logger,
841928
"Background sync of RGS gossip data finished in {}ms.",
842929
now.elapsed().as_millis()
@@ -860,37 +947,6 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
860947
});
861948
}
862949

863-
let sync_logger = Arc::clone(&self.logger);
864-
let mut stop_sync = self.stop_receiver.clone();
865-
runtime.spawn(async move {
866-
let mut interval = tokio::time::interval(Duration::from_secs(10));
867-
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
868-
loop {
869-
let now = Instant::now();
870-
tokio::select! {
871-
_ = stop_sync.changed() => {
872-
return;
873-
}
874-
_ = interval.tick() => {
875-
let confirmables = vec![
876-
&*sync_cman as &(dyn Confirm + Sync + Send),
877-
&*sync_cmon as &(dyn Confirm + Sync + Send),
878-
];
879-
match tx_sync.sync(confirmables).await {
880-
Ok(()) => log_info!(
881-
sync_logger,
882-
"Background sync of Lightning wallet finished in {}ms.",
883-
now.elapsed().as_millis()
884-
),
885-
Err(e) => {
886-
log_error!(sync_logger, "Background sync of Lightning wallet failed: {}", e)
887-
}
888-
}
889-
}
890-
}
891-
}
892-
});
893-
894950
if let Some(listening_address) = &self.config.listening_address {
895951
// Setup networking
896952
let peer_manager_connection_handler = Arc::clone(&self.peer_manager);
@@ -1024,6 +1080,18 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
10241080
}
10251081
});
10261082

1083+
let event_handler = Arc::new(EventHandler::new(
1084+
Arc::clone(&self.wallet),
1085+
Arc::clone(&self.event_queue),
1086+
Arc::clone(&self.channel_manager),
1087+
Arc::clone(&self.network_graph),
1088+
Arc::clone(&self.keys_manager),
1089+
Arc::clone(&self.payment_store),
1090+
Arc::clone(&self.runtime),
1091+
Arc::clone(&self.logger),
1092+
Arc::clone(&self.config),
1093+
));
1094+
10271095
// Setup background processing
10281096
let background_persister = Arc::clone(&self.kv_store);
10291097
let background_event_handler = Arc::clone(&event_handler);

src/test/functional_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ fn onchain_spend_receive() {
390390

391391
#[test]
392392
fn sign_verify_msg() {
393-
let (_, electrsd) = setup_bitcoind_and_electrsd();
393+
let (_bitcoind, electrsd) = setup_bitcoind_and_electrsd();
394394
let esplora_url = format!("http://{}", electrsd.esplora_url.as_ref().unwrap());
395395
let config = random_config();
396396
let builder = Builder::from_config(config.clone());

0 commit comments

Comments
 (0)