Skip to content

Commit 4264f06

Browse files
committed
Implement sync_lightning_wallet for ChainSource::Electrum
1 parent 969b408 commit 4264f06

File tree

2 files changed

+111
-5
lines changed

2 files changed

+111
-5
lines changed

src/chain/electrum.rs

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@
55
// http://opensource.org/licenses/MIT>, at your option. You may not use this file except in
66
// accordance with one or both of these licenses.
77

8-
use crate::config::{Config, FEE_RATE_CACHE_UPDATE_TIMEOUT_SECS, TX_BROADCAST_TIMEOUT_SECS};
8+
use crate::config::{
9+
Config, FEE_RATE_CACHE_UPDATE_TIMEOUT_SECS, LDK_WALLET_SYNC_TIMEOUT_SECS,
10+
TX_BROADCAST_TIMEOUT_SECS,
11+
};
912
use crate::error::Error;
1013
use crate::fee_estimator::{
1114
apply_post_estimation_adjustments, get_all_conf_targets, get_num_block_defaults_for_target,
1215
ConfirmationTarget,
1316
};
14-
use crate::logger::{log_bytes, log_error, log_trace, LdkLogger, Logger};
17+
use crate::logger::{log_bytes, log_error, log_info, log_trace, LdkLogger, Logger};
1518

16-
use lightning::chain::{Filter, WatchedOutput};
19+
use lightning::chain::{Confirm, Filter, WatchedOutput};
1720
use lightning::util::ser::Writeable;
1821
use lightning_transaction_sync::ElectrumSyncClient;
1922

@@ -25,7 +28,7 @@ use bitcoin::{FeeRate, Network, Script, Transaction, Txid};
2528

2629
use std::collections::HashMap;
2730
use std::sync::Arc;
28-
use std::time::Duration;
31+
use std::time::{Duration, Instant};
2932

3033
pub(crate) struct ElectrumRuntimeClient {
3134
electrum_client: Arc<ElectrumClient>,
@@ -59,6 +62,40 @@ impl ElectrumRuntimeClient {
5962
Ok(Self { electrum_client, bdk_electrum_client, tx_sync, runtime, config, logger })
6063
}
6164

65+
pub(crate) async fn sync_confirmables(
66+
&self, confirmables: Vec<Arc<dyn Confirm + Sync + Send>>,
67+
) -> Result<(), Error> {
68+
let now = Instant::now();
69+
70+
let tx_sync = Arc::clone(&self.tx_sync);
71+
let spawn_fut = self.runtime.spawn_blocking(move || tx_sync.sync(confirmables));
72+
let timeout_fut =
73+
tokio::time::timeout(Duration::from_secs(LDK_WALLET_SYNC_TIMEOUT_SECS), spawn_fut);
74+
75+
let res = timeout_fut
76+
.await
77+
.map_err(|e| {
78+
log_error!(self.logger, "Sync of Lightning wallet timed out: {}", e);
79+
Error::TxSyncTimeout
80+
})?
81+
.map_err(|e| {
82+
log_error!(self.logger, "Sync of Lightning wallet failed: {}", e);
83+
Error::TxSyncFailed
84+
})?
85+
.map_err(|e| {
86+
log_error!(self.logger, "Sync of Lightning wallet failed: {}", e);
87+
Error::TxSyncFailed
88+
})?;
89+
90+
log_info!(
91+
self.logger,
92+
"Sync of Lightning wallet finished in {}ms.",
93+
now.elapsed().as_millis()
94+
);
95+
96+
Ok(res)
97+
}
98+
6299
pub(crate) async fn broadcast(&self, tx: Transaction) {
63100
let electrum_client = Arc::clone(&self.electrum_client);
64101

src/chain/mod.rs

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -740,7 +740,76 @@ impl ChainSource {
740740

741741
res
742742
},
743-
Self::Electrum { .. } => todo!(),
743+
Self::Electrum {
744+
electrum_runtime_client,
745+
lightning_wallet_sync_status,
746+
kv_store,
747+
logger,
748+
node_metrics,
749+
..
750+
} => {
751+
let electrum_client: Arc<ElectrumRuntimeClient> =
752+
if let Some(client) = electrum_runtime_client.read().unwrap().as_ref() {
753+
Arc::clone(client)
754+
} else {
755+
debug_assert!(
756+
false,
757+
"We should have started the chain source before syncing the lightning wallet"
758+
);
759+
return Err(Error::FeerateEstimationUpdateFailed);
760+
};
761+
762+
let sync_cman = Arc::clone(&channel_manager);
763+
let sync_cmon = Arc::clone(&chain_monitor);
764+
let sync_sweeper = Arc::clone(&output_sweeper);
765+
let confirmables = vec![
766+
sync_cman as Arc<dyn Confirm + Sync + Send>,
767+
sync_cmon as Arc<dyn Confirm + Sync + Send>,
768+
sync_sweeper as Arc<dyn Confirm + Sync + Send>,
769+
];
770+
771+
let receiver_res = {
772+
let mut status_lock = lightning_wallet_sync_status.lock().unwrap();
773+
status_lock.register_or_subscribe_pending_sync()
774+
};
775+
if let Some(mut sync_receiver) = receiver_res {
776+
log_info!(logger, "Sync in progress, skipping.");
777+
return sync_receiver.recv().await.map_err(|e| {
778+
debug_assert!(false, "Failed to receive wallet sync result: {:?}", e);
779+
log_error!(logger, "Failed to receive wallet sync result: {:?}", e);
780+
Error::WalletOperationFailed
781+
})?;
782+
}
783+
784+
let res = electrum_client.sync_confirmables(confirmables).await;
785+
786+
if let Ok(_) = res {
787+
let unix_time_secs_opt =
788+
SystemTime::now().duration_since(UNIX_EPOCH).ok().map(|d| d.as_secs());
789+
{
790+
let mut locked_node_metrics = node_metrics.write().unwrap();
791+
locked_node_metrics.latest_lightning_wallet_sync_timestamp =
792+
unix_time_secs_opt;
793+
write_node_metrics(
794+
&*locked_node_metrics,
795+
Arc::clone(&kv_store),
796+
Arc::clone(&logger),
797+
)?;
798+
}
799+
800+
periodically_archive_fully_resolved_monitors(
801+
Arc::clone(&channel_manager),
802+
Arc::clone(&chain_monitor),
803+
Arc::clone(&kv_store),
804+
Arc::clone(&logger),
805+
Arc::clone(&node_metrics),
806+
)?;
807+
}
808+
809+
lightning_wallet_sync_status.lock().unwrap().propagate_result_to_subscribers(res);
810+
811+
res
812+
},
744813
Self::BitcoindRpc { .. } => {
745814
// In BitcoindRpc mode we sync lightning and onchain wallet in one go by via
746815
// `ChainPoller`. So nothing to do here.

0 commit comments

Comments
 (0)