Skip to content

Commit e852dcd

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 3d87eae commit e852dcd

File tree

3 files changed

+127
-57
lines changed

3 files changed

+127
-57
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: 124 additions & 56 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,12 +209,14 @@ 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+
/// | 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 |
212220
///
213221
pub struct Config {
214222
/// The path where the underlying LDK and BDK persist their data.
@@ -219,6 +227,14 @@ pub struct Config {
219227
pub listening_address: Option<NetAddress>,
220228
/// The default CLTV expiry delta to be used for payments.
221229
pub default_cltv_expiry_delta: u32,
230+
/// The time in-between background sync attempts of the onchain wallet, in seconds.
231+
///
232+
/// **Note:** A minimum of 10 seconds is always enforced.
233+
pub onchain_wallet_sync_interval_secs: u64,
234+
/// The time in-between background sync attempts of the LDK wallet, in seconds.
235+
///
236+
/// **Note:** A minimum of 10 seconds is always enforced.
237+
pub wallet_sync_interval_secs: u64,
222238
/// The level at which we log messages.
223239
///
224240
/// Any messages below this level will be excluded from the logs.
@@ -232,6 +248,8 @@ impl Default for Config {
232248
network: DEFAULT_NETWORK,
233249
listening_address: Some(DEFAULT_LISTENING_ADDR.parse().unwrap()),
234250
default_cltv_expiry_delta: DEFAULT_CLTV_EXPIRY_DELTA,
251+
onchain_wallet_sync_interval_secs: DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS,
252+
wallet_sync_interval_secs: DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS,
235253
log_level: DEFAULT_LOG_LEVEL,
236254
}
237255
}
@@ -765,31 +783,38 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
765783

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

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

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

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

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

1082+
let event_handler = Arc::new(EventHandler::new(
1083+
Arc::clone(&self.wallet),
1084+
Arc::clone(&self.event_queue),
1085+
Arc::clone(&self.channel_manager),
1086+
Arc::clone(&self.network_graph),
1087+
Arc::clone(&self.keys_manager),
1088+
Arc::clone(&self.payment_store),
1089+
Arc::clone(&self.runtime),
1090+
Arc::clone(&self.logger),
1091+
Arc::clone(&self.config),
1092+
));
1093+
10261094
// Setup background processing
10271095
let background_persister = Arc::clone(&self.kv_store);
10281096
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)