Skip to content

Commit 1cf4858

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 6b772ae commit 1cf4858

File tree

2 files changed

+118
-50
lines changed

2 files changed

+118
-50
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
};
1113

1214
interface Builder {

src/lib.rs

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

116-
use logger::{log_error, log_info, FilesystemLogger, Logger};
116+
use logger::{log_error, log_info, log_trace, FilesystemLogger, Logger};
117117

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

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

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

@@ -194,6 +200,14 @@ pub struct Config {
194200
pub listening_address: Option<NetAddress>,
195201
/// The default CLTV expiry delta to be used for payments.
196202
pub default_cltv_expiry_delta: u32,
203+
/// The time in-between background sync attempts of the onchain wallet, in seconds.
204+
///
205+
/// **Note:** A minimum of 10 seconds is always enforced.
206+
pub onchain_wallet_sync_interval_secs: u64,
207+
/// The time in-between background sync attempts of the LDK wallet, in seconds.
208+
///
209+
/// **Note:** A minimum of 10 seconds is always enforced.
210+
pub wallet_sync_interval_secs: u64,
197211
}
198212

199213
impl Default for Config {
@@ -204,6 +218,8 @@ impl Default for Config {
204218
network: Network::Regtest,
205219
listening_address: Some("0.0.0.0:9735".parse().unwrap()),
206220
default_cltv_expiry_delta: 144,
221+
onchain_wallet_sync_interval_secs: DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS,
222+
wallet_sync_interval_secs: DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS,
207223
}
208224
}
209225
}
@@ -705,31 +721,38 @@ impl Node {
705721

706722
let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap();
707723

708-
let event_handler = Arc::new(EventHandler::new(
709-
Arc::clone(&self.wallet),
710-
Arc::clone(&self.event_queue),
711-
Arc::clone(&self.channel_manager),
712-
Arc::clone(&self.network_graph),
713-
Arc::clone(&self.keys_manager),
714-
Arc::clone(&self.payment_store),
715-
Arc::clone(&self.runtime),
716-
Arc::clone(&self.logger),
717-
Arc::clone(&self.config),
718-
));
719-
720724
// Setup wallet sync
721725
let wallet = Arc::clone(&self.wallet);
722-
let tx_sync = Arc::clone(&self.tx_sync);
723-
let sync_cman = Arc::clone(&self.channel_manager);
724-
let sync_cmon = Arc::clone(&self.chain_monitor);
725726
let sync_logger = Arc::clone(&self.logger);
726727
let mut stop_sync = self.stop_receiver.clone();
727728

729+
runtime.block_on(async move {
730+
let now = Instant::now();
731+
match wallet.sync().await {
732+
Ok(()) => {
733+
log_info!(
734+
sync_logger,
735+
"Initial sync of on-chain wallet finished in {}ms.",
736+
now.elapsed().as_millis()
737+
);
738+
Ok(())
739+
}
740+
Err(e) => {
741+
log_error!(sync_logger, "Intial sync of on-chain wallet failed: {}", e,);
742+
Err(e)
743+
}
744+
}
745+
})?;
746+
747+
let sync_logger = Arc::clone(&self.logger);
748+
let wallet = Arc::clone(&self.wallet);
728749
std::thread::spawn(move || {
729750
tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap().block_on(
730751
async move {
731-
let mut interval = tokio::time::interval(Duration::from_secs(30));
752+
let interval_secs = DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS.max(10);
753+
let mut interval = tokio::time::interval(Duration::from_secs(interval_secs));
732754
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
755+
interval.reset();
733756
loop {
734757
let now = Instant::now();
735758
tokio::select! {
@@ -738,7 +761,7 @@ impl Node {
738761
}
739762
_ = interval.tick() => {
740763
match wallet.sync().await {
741-
Ok(()) => log_info!(
764+
Ok(()) => log_trace!(
742765
sync_logger,
743766
"Background sync of on-chain wallet finished in {}ms.",
744767
now.elapsed().as_millis()
@@ -758,6 +781,68 @@ impl Node {
758781
);
759782
});
760783

784+
let tx_sync = Arc::clone(&self.tx_sync);
785+
let sync_cman = Arc::clone(&self.channel_manager);
786+
let sync_cmon = Arc::clone(&self.chain_monitor);
787+
let sync_logger = Arc::clone(&self.logger);
788+
runtime.block_on(async move {
789+
let now = Instant::now();
790+
let confirmables = vec![
791+
&*sync_cman as &(dyn Confirm + Sync + Send),
792+
&*sync_cmon as &(dyn Confirm + Sync + Send),
793+
];
794+
match tx_sync.sync(confirmables).await {
795+
Ok(()) => {
796+
log_info!(
797+
sync_logger,
798+
"Initial sync of Lightning wallet finished in {}ms.",
799+
now.elapsed().as_millis()
800+
);
801+
Ok(())
802+
}
803+
Err(e) => {
804+
log_error!(sync_logger, "Initial sync of Lightning wallet failed: {}", e);
805+
Err(e)
806+
}
807+
}
808+
})?;
809+
810+
let tx_sync = Arc::clone(&self.tx_sync);
811+
let sync_cman = Arc::clone(&self.channel_manager);
812+
let sync_cmon = Arc::clone(&self.chain_monitor);
813+
let sync_logger = Arc::clone(&self.logger);
814+
let mut stop_sync = self.stop_receiver.clone();
815+
runtime.spawn(async move {
816+
let interval_secs = DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS.max(10);
817+
let mut interval = tokio::time::interval(Duration::from_secs(interval_secs));
818+
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
819+
interval.reset();
820+
loop {
821+
let now = Instant::now();
822+
tokio::select! {
823+
_ = stop_sync.changed() => {
824+
return;
825+
}
826+
_ = interval.tick() => {
827+
let confirmables = vec![
828+
&*sync_cman as &(dyn Confirm + Sync + Send),
829+
&*sync_cmon as &(dyn Confirm + Sync + Send),
830+
];
831+
match tx_sync.sync(confirmables).await {
832+
Ok(()) => log_trace!(
833+
sync_logger,
834+
"Background sync of Lightning wallet finished in {}ms.",
835+
now.elapsed().as_millis()
836+
),
837+
Err(e) => {
838+
log_error!(sync_logger, "Background sync of Lightning wallet failed: {}", e)
839+
}
840+
}
841+
}
842+
}
843+
}
844+
});
845+
761846
if self.gossip_source.is_rgs() {
762847
let gossip_source = Arc::clone(&self.gossip_source);
763848
let gossip_sync_store = Arc::clone(&self.kv_store);
@@ -775,7 +860,7 @@ impl Node {
775860
let now = Instant::now();
776861
match gossip_source.update_rgs_snapshot().await {
777862
Ok(updated_timestamp) => {
778-
log_info!(
863+
log_trace!(
779864
gossip_sync_logger,
780865
"Background sync of RGS gossip data finished in {}ms.",
781866
now.elapsed().as_millis()
@@ -799,37 +884,6 @@ impl Node {
799884
});
800885
}
801886

802-
let sync_logger = Arc::clone(&self.logger);
803-
let mut stop_sync = self.stop_receiver.clone();
804-
runtime.spawn(async move {
805-
let mut interval = tokio::time::interval(Duration::from_secs(10));
806-
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
807-
loop {
808-
let now = Instant::now();
809-
tokio::select! {
810-
_ = stop_sync.changed() => {
811-
return;
812-
}
813-
_ = interval.tick() => {
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(()) => log_info!(
820-
sync_logger,
821-
"Background sync of Lightning wallet finished in {}ms.",
822-
now.elapsed().as_millis()
823-
),
824-
Err(e) => {
825-
log_error!(sync_logger, "Background sync of Lightning wallet failed: {}", e)
826-
}
827-
}
828-
}
829-
}
830-
}
831-
});
832-
833887
if let Some(listening_address) = &self.config.listening_address {
834888
// Setup networking
835889
let peer_manager_connection_handler = Arc::clone(&self.peer_manager);
@@ -963,6 +1017,18 @@ impl Node {
9631017
}
9641018
});
9651019

1020+
let event_handler = Arc::new(EventHandler::new(
1021+
Arc::clone(&self.wallet),
1022+
Arc::clone(&self.event_queue),
1023+
Arc::clone(&self.channel_manager),
1024+
Arc::clone(&self.network_graph),
1025+
Arc::clone(&self.keys_manager),
1026+
Arc::clone(&self.payment_store),
1027+
Arc::clone(&self.runtime),
1028+
Arc::clone(&self.logger),
1029+
Arc::clone(&self.config),
1030+
));
1031+
9661032
// Setup background processing
9671033
let background_persister = Arc::clone(&self.kv_store);
9681034
let background_event_handler = Arc::clone(&event_handler);

0 commit comments

Comments
 (0)