Skip to content

Commit 6ac8b91

Browse files
committed
Implement sync_lightning_wallet for ChainSource::Electrum
1 parent af64dd9 commit 6ac8b91

File tree

2 files changed

+112
-5
lines changed

2 files changed

+112
-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

@@ -27,7 +30,7 @@ use bitcoin::{FeeRate, Network, Script, Transaction, Txid};
2730

2831
use std::collections::HashMap;
2932
use std::sync::Arc;
30-
use std::time::Duration;
33+
use std::time::{Duration, Instant};
3134

3235
const ELECTRUM_CLIENT_NUM_RETRIES: u8 = 3;
3336
const ELECTRUM_CLIENT_TIMEOUT_SECS: u8 = 20;
@@ -72,6 +75,40 @@ impl ElectrumRuntimeClient {
7275
Ok(Self { electrum_client, bdk_electrum_client, tx_sync, runtime, config, logger })
7376
}
7477

78+
pub(crate) async fn sync_confirmables(
79+
&self, confirmables: Vec<Arc<dyn Confirm + Sync + Send>>,
80+
) -> Result<(), Error> {
81+
let now = Instant::now();
82+
83+
let tx_sync = Arc::clone(&self.tx_sync);
84+
let spawn_fut = self.runtime.spawn_blocking(move || tx_sync.sync(confirmables));
85+
let timeout_fut =
86+
tokio::time::timeout(Duration::from_secs(LDK_WALLET_SYNC_TIMEOUT_SECS), spawn_fut);
87+
88+
let res = timeout_fut
89+
.await
90+
.map_err(|e| {
91+
log_error!(self.logger, "Sync of Lightning wallet timed out: {}", e);
92+
Error::TxSyncTimeout
93+
})?
94+
.map_err(|e| {
95+
log_error!(self.logger, "Sync of Lightning wallet failed: {}", e);
96+
Error::TxSyncFailed
97+
})?
98+
.map_err(|e| {
99+
log_error!(self.logger, "Sync of Lightning wallet failed: {}", e);
100+
Error::TxSyncFailed
101+
})?;
102+
103+
log_info!(
104+
self.logger,
105+
"Sync of Lightning wallet finished in {}ms.",
106+
now.elapsed().as_millis()
107+
);
108+
109+
Ok(res)
110+
}
111+
75112
pub(crate) async fn broadcast(&self, tx: Transaction) {
76113
let electrum_client = Arc::clone(&self.electrum_client);
77114

src/chain/mod.rs

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,77 @@ impl ChainSource {
817817

818818
res
819819
},
820-
Self::Electrum { .. } => todo!(),
820+
Self::Electrum {
821+
electrum_runtime_status,
822+
lightning_wallet_sync_status,
823+
kv_store,
824+
logger,
825+
node_metrics,
826+
..
827+
} => {
828+
let electrum_client: Arc<ElectrumRuntimeClient> = if let Some(client) =
829+
electrum_runtime_status.read().unwrap().client().as_ref()
830+
{
831+
Arc::clone(client)
832+
} else {
833+
debug_assert!(
834+
false,
835+
"We should have started the chain source before syncing the lightning wallet"
836+
);
837+
return Err(Error::TxSyncFailed);
838+
};
839+
840+
let sync_cman = Arc::clone(&channel_manager);
841+
let sync_cmon = Arc::clone(&chain_monitor);
842+
let sync_sweeper = Arc::clone(&output_sweeper);
843+
let confirmables = vec![
844+
sync_cman as Arc<dyn Confirm + Sync + Send>,
845+
sync_cmon as Arc<dyn Confirm + Sync + Send>,
846+
sync_sweeper as Arc<dyn Confirm + Sync + Send>,
847+
];
848+
849+
let receiver_res = {
850+
let mut status_lock = lightning_wallet_sync_status.lock().unwrap();
851+
status_lock.register_or_subscribe_pending_sync()
852+
};
853+
if let Some(mut sync_receiver) = receiver_res {
854+
log_info!(logger, "Sync in progress, skipping.");
855+
return sync_receiver.recv().await.map_err(|e| {
856+
debug_assert!(false, "Failed to receive wallet sync result: {:?}", e);
857+
log_error!(logger, "Failed to receive wallet sync result: {:?}", e);
858+
Error::TxSyncFailed
859+
})?;
860+
}
861+
862+
let res = electrum_client.sync_confirmables(confirmables).await;
863+
864+
if let Ok(_) = res {
865+
let unix_time_secs_opt =
866+
SystemTime::now().duration_since(UNIX_EPOCH).ok().map(|d| d.as_secs());
867+
{
868+
let mut locked_node_metrics = node_metrics.write().unwrap();
869+
locked_node_metrics.latest_lightning_wallet_sync_timestamp =
870+
unix_time_secs_opt;
871+
write_node_metrics(
872+
&*locked_node_metrics,
873+
Arc::clone(&kv_store),
874+
Arc::clone(&logger),
875+
)?;
876+
}
877+
878+
periodically_archive_fully_resolved_monitors(
879+
Arc::clone(&channel_manager),
880+
Arc::clone(&chain_monitor),
881+
Arc::clone(&kv_store),
882+
Arc::clone(&logger),
883+
Arc::clone(&node_metrics),
884+
)?;
885+
}
886+
887+
lightning_wallet_sync_status.lock().unwrap().propagate_result_to_subscribers(res);
888+
889+
res
890+
},
821891
Self::BitcoindRpc { .. } => {
822892
// In BitcoindRpc mode we sync lightning and onchain wallet in one go by via
823893
// `ChainPoller`. So nothing to do here.

0 commit comments

Comments
 (0)