Skip to content

Commit d261724

Browse files
authored
Merge pull request #774 from tnull/2026-01-make-sync-timeouts-configurable
Make sync timeouts configurable
2 parents 5d83000 + 40c4b09 commit d261724

File tree

8 files changed

+149
-59
lines changed

8 files changed

+149
-59
lines changed

bindings/ldk_node.udl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,22 @@ dictionary BackgroundSyncConfig {
2626
u64 fee_rate_cache_update_interval_secs;
2727
};
2828

29+
dictionary SyncTimeoutsConfig {
30+
u64 onchain_wallet_sync_timeout_secs;
31+
u64 lightning_wallet_sync_timeout_secs;
32+
u64 fee_rate_cache_update_timeout_secs;
33+
u64 tx_broadcast_timeout_secs;
34+
u8 per_request_timeout_secs;
35+
};
36+
2937
dictionary EsploraSyncConfig {
3038
BackgroundSyncConfig? background_sync_config;
39+
SyncTimeoutsConfig timeouts_config;
3140
};
3241

3342
dictionary ElectrumSyncConfig {
3443
BackgroundSyncConfig? background_sync_config;
44+
SyncTimeoutsConfig timeouts_config;
3545
};
3646

3747
dictionary LSPS2ServiceConfig {

src/chain/bitcoind.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ use serde::Serialize;
3131

3232
use super::WalletSyncStatus;
3333
use crate::config::{
34-
BitcoindRestClientConfig, Config, FEE_RATE_CACHE_UPDATE_TIMEOUT_SECS, TX_BROADCAST_TIMEOUT_SECS,
34+
BitcoindRestClientConfig, Config, DEFAULT_FEE_RATE_CACHE_UPDATE_TIMEOUT_SECS,
35+
DEFAULT_TX_BROADCAST_TIMEOUT_SECS,
3536
};
3637
use crate::fee_estimator::{
3738
apply_post_estimation_adjustments, get_all_conf_targets, get_num_block_defaults_for_target,
@@ -466,7 +467,7 @@ impl BitcoindChainSource {
466467
macro_rules! get_fee_rate_update {
467468
($estimation_fut:expr) => {{
468469
let update_res = tokio::time::timeout(
469-
Duration::from_secs(FEE_RATE_CACHE_UPDATE_TIMEOUT_SECS),
470+
Duration::from_secs(DEFAULT_FEE_RATE_CACHE_UPDATE_TIMEOUT_SECS),
470471
$estimation_fut,
471472
)
472473
.await
@@ -584,7 +585,7 @@ impl BitcoindChainSource {
584585
for tx in &package {
585586
let txid = tx.compute_txid();
586587
let timeout_fut = tokio::time::timeout(
587-
Duration::from_secs(TX_BROADCAST_TIMEOUT_SECS),
588+
Duration::from_secs(DEFAULT_TX_BROADCAST_TIMEOUT_SECS),
588589
self.api_client.broadcast_transaction(tx),
589590
);
590591
match timeout_fut.await {

src/chain/electrum.rs

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@ use lightning::util::ser::Writeable;
2424
use lightning_transaction_sync::ElectrumSyncClient;
2525

2626
use super::WalletSyncStatus;
27-
use crate::config::{
28-
Config, ElectrumSyncConfig, BDK_CLIENT_STOP_GAP, BDK_WALLET_SYNC_TIMEOUT_SECS,
29-
FEE_RATE_CACHE_UPDATE_TIMEOUT_SECS, LDK_WALLET_SYNC_TIMEOUT_SECS, TX_BROADCAST_TIMEOUT_SECS,
30-
};
27+
use crate::config::{Config, ElectrumSyncConfig, BDK_CLIENT_STOP_GAP};
3128
use crate::error::Error;
3229
use crate::fee_estimator::{
3330
apply_post_estimation_adjustments, get_all_conf_targets, get_num_block_defaults_for_target,
@@ -41,7 +38,6 @@ use crate::NodeMetrics;
4138

4239
const BDK_ELECTRUM_CLIENT_BATCH_SIZE: usize = 5;
4340
const ELECTRUM_CLIENT_NUM_RETRIES: u8 = 3;
44-
const ELECTRUM_CLIENT_TIMEOUT_SECS: u8 = 10;
4541

4642
pub(super) struct ElectrumChainSource {
4743
server_url: String,
@@ -82,6 +78,7 @@ impl ElectrumChainSource {
8278
pub(super) fn start(&self, runtime: Arc<Runtime>) -> Result<(), Error> {
8379
self.electrum_runtime_status.write().unwrap().start(
8480
self.server_url.clone(),
81+
self.sync_config.clone(),
8582
Arc::clone(&runtime),
8683
Arc::clone(&self.config),
8784
Arc::clone(&self.logger),
@@ -318,13 +315,14 @@ impl ElectrumRuntimeStatus {
318315
}
319316

320317
pub(super) fn start(
321-
&mut self, server_url: String, runtime: Arc<Runtime>, config: Arc<Config>,
322-
logger: Arc<Logger>,
318+
&mut self, server_url: String, sync_config: ElectrumSyncConfig, runtime: Arc<Runtime>,
319+
config: Arc<Config>, logger: Arc<Logger>,
323320
) -> Result<(), Error> {
324321
match self {
325322
Self::Stopped { pending_registered_txs, pending_registered_outputs } => {
326323
let client = Arc::new(ElectrumRuntimeClient::new(
327-
server_url.clone(),
324+
server_url,
325+
sync_config,
328326
runtime,
329327
config,
330328
logger,
@@ -380,6 +378,7 @@ impl ElectrumRuntimeStatus {
380378

381379
struct ElectrumRuntimeClient {
382380
electrum_client: Arc<ElectrumClient>,
381+
sync_config: ElectrumSyncConfig,
383382
bdk_electrum_client: Arc<BdkElectrumClient<Arc<ElectrumClient>>>,
384383
tx_sync: Arc<ElectrumSyncClient<Arc<Logger>>>,
385384
runtime: Arc<Runtime>,
@@ -389,11 +388,12 @@ struct ElectrumRuntimeClient {
389388

390389
impl ElectrumRuntimeClient {
391390
fn new(
392-
server_url: String, runtime: Arc<Runtime>, config: Arc<Config>, logger: Arc<Logger>,
391+
server_url: String, sync_config: ElectrumSyncConfig, runtime: Arc<Runtime>,
392+
config: Arc<Config>, logger: Arc<Logger>,
393393
) -> Result<Self, Error> {
394394
let electrum_config = ElectrumConfigBuilder::new()
395395
.retry(ELECTRUM_CLIENT_NUM_RETRIES)
396-
.timeout(Some(ELECTRUM_CLIENT_TIMEOUT_SECS))
396+
.timeout(Some(sync_config.timeouts_config.per_request_timeout_secs))
397397
.build();
398398

399399
let electrum_client = Arc::new(
@@ -409,7 +409,15 @@ impl ElectrumRuntimeClient {
409409
Error::ConnectionFailed
410410
})?,
411411
);
412-
Ok(Self { electrum_client, bdk_electrum_client, tx_sync, runtime, config, logger })
412+
Ok(Self {
413+
electrum_client,
414+
sync_config,
415+
bdk_electrum_client,
416+
tx_sync,
417+
runtime,
418+
config,
419+
logger,
420+
})
413421
}
414422

415423
async fn sync_confirmables(
@@ -419,8 +427,12 @@ impl ElectrumRuntimeClient {
419427

420428
let tx_sync = Arc::clone(&self.tx_sync);
421429
let spawn_fut = self.runtime.spawn_blocking(move || tx_sync.sync(confirmables));
422-
let timeout_fut =
423-
tokio::time::timeout(Duration::from_secs(LDK_WALLET_SYNC_TIMEOUT_SECS), spawn_fut);
430+
let timeout_fut = tokio::time::timeout(
431+
Duration::from_secs(
432+
self.sync_config.timeouts_config.lightning_wallet_sync_timeout_secs,
433+
),
434+
spawn_fut,
435+
);
424436

425437
let res = timeout_fut
426438
.await
@@ -461,8 +473,10 @@ impl ElectrumRuntimeClient {
461473
true,
462474
)
463475
});
464-
let wallet_sync_timeout_fut =
465-
tokio::time::timeout(Duration::from_secs(BDK_WALLET_SYNC_TIMEOUT_SECS), spawn_fut);
476+
let wallet_sync_timeout_fut = tokio::time::timeout(
477+
Duration::from_secs(self.sync_config.timeouts_config.onchain_wallet_sync_timeout_secs),
478+
spawn_fut,
479+
);
466480

467481
wallet_sync_timeout_fut
468482
.await
@@ -490,8 +504,10 @@ impl ElectrumRuntimeClient {
490504
let spawn_fut = self.runtime.spawn_blocking(move || {
491505
bdk_electrum_client.sync(request, BDK_ELECTRUM_CLIENT_BATCH_SIZE, true)
492506
});
493-
let wallet_sync_timeout_fut =
494-
tokio::time::timeout(Duration::from_secs(BDK_WALLET_SYNC_TIMEOUT_SECS), spawn_fut);
507+
let wallet_sync_timeout_fut = tokio::time::timeout(
508+
Duration::from_secs(self.sync_config.timeouts_config.onchain_wallet_sync_timeout_secs),
509+
spawn_fut,
510+
);
495511

496512
wallet_sync_timeout_fut
497513
.await
@@ -517,8 +533,10 @@ impl ElectrumRuntimeClient {
517533

518534
let spawn_fut =
519535
self.runtime.spawn_blocking(move || electrum_client.transaction_broadcast(&tx));
520-
let timeout_fut =
521-
tokio::time::timeout(Duration::from_secs(TX_BROADCAST_TIMEOUT_SECS), spawn_fut);
536+
let timeout_fut = tokio::time::timeout(
537+
Duration::from_secs(self.sync_config.timeouts_config.tx_broadcast_timeout_secs),
538+
spawn_fut,
539+
);
522540

523541
match timeout_fut.await {
524542
Ok(res) => match res {
@@ -565,7 +583,9 @@ impl ElectrumRuntimeClient {
565583
let spawn_fut = self.runtime.spawn_blocking(move || electrum_client.batch_call(&batch));
566584

567585
let timeout_fut = tokio::time::timeout(
568-
Duration::from_secs(FEE_RATE_CACHE_UPDATE_TIMEOUT_SECS),
586+
Duration::from_secs(
587+
self.sync_config.timeouts_config.fee_rate_cache_update_timeout_secs,
588+
),
569589
spawn_fut,
570590
);
571591

src/chain/esplora.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,7 @@ use lightning::util::ser::Writeable;
1717
use lightning_transaction_sync::EsploraSyncClient;
1818

1919
use super::WalletSyncStatus;
20-
use crate::config::{
21-
Config, EsploraSyncConfig, BDK_CLIENT_CONCURRENCY, BDK_CLIENT_STOP_GAP,
22-
BDK_WALLET_SYNC_TIMEOUT_SECS, DEFAULT_ESPLORA_CLIENT_TIMEOUT_SECS,
23-
FEE_RATE_CACHE_UPDATE_TIMEOUT_SECS, LDK_WALLET_SYNC_TIMEOUT_SECS, TX_BROADCAST_TIMEOUT_SECS,
24-
};
20+
use crate::config::{Config, EsploraSyncConfig, BDK_CLIENT_CONCURRENCY, BDK_CLIENT_STOP_GAP};
2521
use crate::fee_estimator::{
2622
apply_post_estimation_adjustments, get_all_conf_targets, get_num_block_defaults_for_target,
2723
OnchainFeeEstimator,
@@ -51,7 +47,8 @@ impl EsploraChainSource {
5147
logger: Arc<Logger>, node_metrics: Arc<RwLock<NodeMetrics>>,
5248
) -> Self {
5349
let mut client_builder = esplora_client::Builder::new(&server_url);
54-
client_builder = client_builder.timeout(DEFAULT_ESPLORA_CLIENT_TIMEOUT_SECS);
50+
client_builder =
51+
client_builder.timeout(sync_config.timeouts_config.per_request_timeout_secs as u64);
5552

5653
for (header_name, header_value) in &headers {
5754
client_builder = client_builder.header(header_name, header_value);
@@ -183,14 +180,18 @@ impl EsploraChainSource {
183180
if incremental_sync {
184181
let sync_request = onchain_wallet.get_incremental_sync_request();
185182
let wallet_sync_timeout_fut = tokio::time::timeout(
186-
Duration::from_secs(BDK_WALLET_SYNC_TIMEOUT_SECS),
183+
Duration::from_secs(
184+
self.sync_config.timeouts_config.onchain_wallet_sync_timeout_secs,
185+
),
187186
self.esplora_client.sync(sync_request, BDK_CLIENT_CONCURRENCY),
188187
);
189188
get_and_apply_wallet_update!(wallet_sync_timeout_fut)
190189
} else {
191190
let full_scan_request = onchain_wallet.get_full_scan_request();
192191
let wallet_sync_timeout_fut = tokio::time::timeout(
193-
Duration::from_secs(BDK_WALLET_SYNC_TIMEOUT_SECS),
192+
Duration::from_secs(
193+
self.sync_config.timeouts_config.onchain_wallet_sync_timeout_secs,
194+
),
194195
self.esplora_client.full_scan(
195196
full_scan_request,
196197
BDK_CLIENT_STOP_GAP,
@@ -240,7 +241,9 @@ impl EsploraChainSource {
240241
];
241242

242243
let timeout_fut = tokio::time::timeout(
243-
Duration::from_secs(LDK_WALLET_SYNC_TIMEOUT_SECS),
244+
Duration::from_secs(
245+
self.sync_config.timeouts_config.lightning_wallet_sync_timeout_secs as u64,
246+
),
244247
self.tx_sync.sync(confirmables),
245248
);
246249
let now = Instant::now();
@@ -278,7 +281,9 @@ impl EsploraChainSource {
278281
pub(crate) async fn update_fee_rate_estimates(&self) -> Result<(), Error> {
279282
let now = Instant::now();
280283
let estimates = tokio::time::timeout(
281-
Duration::from_secs(FEE_RATE_CACHE_UPDATE_TIMEOUT_SECS),
284+
Duration::from_secs(
285+
self.sync_config.timeouts_config.fee_rate_cache_update_timeout_secs,
286+
),
282287
self.esplora_client.get_fee_estimates(),
283288
)
284289
.await
@@ -351,7 +356,7 @@ impl EsploraChainSource {
351356
for tx in &package {
352357
let txid = tx.compute_txid();
353358
let timeout_fut = tokio::time::timeout(
354-
Duration::from_secs(TX_BROADCAST_TIMEOUT_SECS),
359+
Duration::from_secs(self.sync_config.timeouts_config.tx_broadcast_timeout_secs),
355360
self.esplora_client.broadcast(tx),
356361
);
357362
match timeout_fut.await {

0 commit comments

Comments
 (0)