Skip to content

Commit b9ccd0e

Browse files
committed
Remove sync_wallets from hot paths
sync_wallets() issues serial HTTP requests to Esplora (fee rate estimation, lightning tx sync across multiple block heights, BDK wallet sync). This blocks the NAPI thread for a few seconds via runtime.block_on(), which prevents the JS event loop from polling nextEvent() for incoming HTLCs. The 10+ second payment latency observed traces directly to this: the sender's HTLC sits unprocessed while the receiver node grinds through chain sync before the webhook handler can start its event loop. Removed sync_wallets from start_receiving, receive_payment, get_invoice, and execute_payment. Receiving HTLCs only needs a peer connection and channel manager, both provided by node.start(). Sending payments routes via the gossip graph with fee rates already cached by node.start(). Also disabled background wallet syncing (the 30s/80s interval loop). For a webhook-based node that lives 40-60s, the immediate first tick just competes with the peer handler for Esplora bandwidth. LDK uses highest_seen_timestamp (set via best_block_updated) for inbound payment verification with a 2-hour grace window. A stale chain tip could cause valid payments to be rejected as expired. The platform's 30-minute ping cron calls sync_wallets via the balance handler, which keeps the timestamp well within that window. get_balance() also syncs explicitly before reading UTXOs.
1 parent 2d9803c commit b9ccd0e

1 file changed

Lines changed: 9 additions & 20 deletions

File tree

src/lib.rs

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use ldk_node::{
4242
hashes::{Hash, sha256},
4343
secp256k1::PublicKey,
4444
},
45-
config::Config,
45+
config::{Config, EsploraSyncConfig},
4646
generate_entropy_mnemonic,
4747
lightning::ln::channelmanager::PaymentId,
4848
lightning::sign::{KeysManager as LdkKeysManager, NodeSigner, Recipient},
@@ -507,7 +507,12 @@ impl MdkNode {
507507

508508
let mut builder = Builder::from_config(config);
509509
builder.set_network(network);
510-
builder.set_chain_source_esplora(options.esplora_url, None);
510+
// Disable background wallet syncing. These nodes are intended to be short
511+
// lived and are kept in sync via other means.
512+
let esplora_sync_config = EsploraSyncConfig {
513+
background_sync_config: None,
514+
};
515+
builder.set_chain_source_esplora(options.esplora_url, Some(esplora_sync_config));
511516
builder.set_gossip_source_rgs(options.rgs_url);
512517
builder.set_entropy_bip39_mnemonic(mnemonic, None);
513518
let logger_arc = Arc::clone(logger_instance());
@@ -679,6 +684,7 @@ impl MdkNode {
679684
///
680685
/// If `splice.enabled` is set on construction (the default), also spawns
681686
/// the auto-splice background task on the dedicated splice runtime.
687+
/// Start the node. Call once before polling for events.
682688
#[napi]
683689
pub fn start_receiving(&self) -> napi::Result<()> {
684690
self.node().start().map_err(|e| {
@@ -708,6 +714,7 @@ impl MdkNode {
708714
}
709715

710716
Ok(())
717+
})
711718
}
712719

713720
/// Get the next payment event without ACKing it.
@@ -1050,11 +1057,6 @@ impl MdkNode {
10501057
return received_payments;
10511058
}
10521059

1053-
if let Err(err) = self.node().sync_wallets() {
1054-
eprintln!("[lightning-js] Failed to sync wallets: {err}");
1055-
panic!("failed to sync wallets: {err}");
1056-
}
1057-
10581060
let start_sync_at = std::time::Instant::now();
10591061
let mut last_event_time = start_sync_at;
10601062

@@ -1181,10 +1183,6 @@ impl MdkNode {
11811183
eprintln!("[lightning-js] Failed to start node for get_invoice: {err}");
11821184
panic!("failed to start node for get_invoice: {err}");
11831185
}
1184-
if let Err(err) = self.node().sync_wallets() {
1185-
eprintln!("[lightning-js] Failed to sync wallets: {err}");
1186-
panic!("failed to sync wallets: {err}");
1187-
}
11881186

11891187
let result = self.get_invoice_impl(Some(amount), description, expiry_secs);
11901188

@@ -1487,15 +1485,6 @@ impl MdkNode {
14871485
napi::Error::new(Status::GenericFailure, format!("failed to start node: {e}"))
14881486
})?;
14891487

1490-
// Sync wallets
1491-
if let Err(e) = self.node().sync_wallets() {
1492-
let _ = self.node().stop();
1493-
return Err(napi::Error::new(
1494-
Status::GenericFailure,
1495-
format!("failed to sync wallets: {e}"),
1496-
));
1497-
}
1498-
14991488
let result = self.execute_payment_impl(&payment_target, wait_secs);
15001489
let _ = self.node().stop();
15011490
result

0 commit comments

Comments
 (0)