Skip to content

Commit 1323533

Browse files
committed
Implement sync_lightning_wallet for ChainSource::Electrum
1 parent 0d4506f commit 1323533

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
@@ -758,7 +758,76 @@ impl ChainSource {
758758

759759
res
760760
},
761-
Self::Electrum { .. } => todo!(),
761+
Self::Electrum {
762+
electrum_runtime_client,
763+
lightning_wallet_sync_status,
764+
kv_store,
765+
logger,
766+
node_metrics,
767+
..
768+
} => {
769+
let electrum_client: Arc<ElectrumRuntimeClient> =
770+
if let Some(client) = electrum_runtime_client.read().unwrap().as_ref() {
771+
Arc::clone(client)
772+
} else {
773+
debug_assert!(
774+
false,
775+
"We should have started the chain source before syncing the lightning wallet"
776+
);
777+
return Err(Error::FeerateEstimationUpdateFailed);
778+
};
779+
780+
let sync_cman = Arc::clone(&channel_manager);
781+
let sync_cmon = Arc::clone(&chain_monitor);
782+
let sync_sweeper = Arc::clone(&output_sweeper);
783+
let confirmables = vec![
784+
sync_cman as Arc<dyn Confirm + Sync + Send>,
785+
sync_cmon as Arc<dyn Confirm + Sync + Send>,
786+
sync_sweeper as Arc<dyn Confirm + Sync + Send>,
787+
];
788+
789+
let receiver_res = {
790+
let mut status_lock = lightning_wallet_sync_status.lock().unwrap();
791+
status_lock.register_or_subscribe_pending_sync()
792+
};
793+
if let Some(mut sync_receiver) = receiver_res {
794+
log_info!(logger, "Sync in progress, skipping.");
795+
return sync_receiver.recv().await.map_err(|e| {
796+
debug_assert!(false, "Failed to receive wallet sync result: {:?}", e);
797+
log_error!(logger, "Failed to receive wallet sync result: {:?}", e);
798+
Error::WalletOperationFailed
799+
})?;
800+
}
801+
802+
let res = electrum_client.sync_confirmables(confirmables).await;
803+
804+
if let Ok(_) = res {
805+
let unix_time_secs_opt =
806+
SystemTime::now().duration_since(UNIX_EPOCH).ok().map(|d| d.as_secs());
807+
{
808+
let mut locked_node_metrics = node_metrics.write().unwrap();
809+
locked_node_metrics.latest_lightning_wallet_sync_timestamp =
810+
unix_time_secs_opt;
811+
write_node_metrics(
812+
&*locked_node_metrics,
813+
Arc::clone(&kv_store),
814+
Arc::clone(&logger),
815+
)?;
816+
}
817+
818+
periodically_archive_fully_resolved_monitors(
819+
Arc::clone(&channel_manager),
820+
Arc::clone(&chain_monitor),
821+
Arc::clone(&kv_store),
822+
Arc::clone(&logger),
823+
Arc::clone(&node_metrics),
824+
)?;
825+
}
826+
827+
lightning_wallet_sync_status.lock().unwrap().propagate_result_to_subscribers(res);
828+
829+
res
830+
},
762831
Self::BitcoindRpc { .. } => {
763832
// In BitcoindRpc mode we sync lightning and onchain wallet in one go by via
764833
// `ChainPoller`. So nothing to do here.

0 commit comments

Comments
 (0)