Skip to content

Commit 546948e

Browse files
fix(electrum): always enable domain validation internally
1 parent 1dc41d0 commit 546948e

File tree

3 files changed

+158
-26
lines changed

3 files changed

+158
-26
lines changed

src/commands.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
//! All optional args are defined in the structs below.
1313
//! All subcommands are defined in the below enums.
1414
15-
#![allow(clippy::large_enum_variant)]
1615
use bdk_wallet::bitcoin::{
1716
Address, Network, OutPoint, ScriptBuf,
1817
bip32::{DerivationPath, Xpriv},
@@ -270,6 +269,7 @@ pub struct WalletOpts {
270269
#[cfg(feature = "electrum")]
271270
#[arg(env = "ELECTRUM_BATCH_SIZE", short = 'b', long, default_value = "10")]
272271
pub batch_size: usize,
272+
273273
/// Esplora parallel requests.
274274
#[cfg(feature = "esplora")]
275275
#[arg(
@@ -480,8 +480,11 @@ pub enum OnlineWalletSubCommand {
480480
stop_gap: usize,
481481
},
482482
/// Syncs with the chosen blockchain server.
483-
Sync,
484-
/// Broadcasts a transaction to the network. Takes either a raw transaction or a PSBT to extract.
483+
Sync {
484+
#[command(flatten)]
485+
wallet_opts: WalletOpts,
486+
},
487+
485488
Broadcast {
486489
/// Sets the PSBT to sign.
487490
#[arg(

src/handlers.rs

Lines changed: 142 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//! Command Handlers
1010
//!
1111
//! This module describes all the command handling logic used by bdk-cli.
12+
1213
use crate::commands::OfflineWalletSubCommand::*;
1314
use crate::commands::*;
1415
use crate::config::{WalletConfig, WalletConfigInner};
@@ -694,8 +695,85 @@ pub(crate) async fn handle_online_wallet_subcommand(
694695
}
695696
Ok(serde_json::to_string_pretty(&json!({}))?)
696697
}
697-
Sync => {
698-
sync_wallet(client, wallet).await?;
698+
699+
#[cfg(any(feature = "electrum", feature = "esplora"))]
700+
let request = wallet
701+
.start_sync_with_revealed_spks()
702+
.inspect(|item, progress| {
703+
let pc = (100 * progress.consumed()) as f32 / progress.total() as f32;
704+
eprintln!("[ SCANNING {pc:03.0}% ] {item}");
705+
});
706+
707+
match client {
708+
#[cfg(feature = "electrum")]
709+
Electrum { client, batch_size } => {
710+
// Populate the electrum client's transaction cache so it doesn't re-download transaction we
711+
// already have.
712+
client
713+
.populate_tx_cache(wallet.tx_graph().full_txs().map(|tx_node| tx_node.tx));
714+
715+
let update = client.sync(request, batch_size, false)?;
716+
wallet.apply_update(update)?;
717+
}
718+
#[cfg(feature = "esplora")]
719+
Esplora {
720+
client,
721+
parallel_requests,
722+
} => {
723+
let update = client
724+
.sync(request, parallel_requests)
725+
.await
726+
.map_err(|e| *e)?;
727+
wallet.apply_update(update)?;
728+
}
729+
#[cfg(feature = "rpc")]
730+
RpcClient { client } => {
731+
let blockchain_info = client.get_blockchain_info()?;
732+
let wallet_cp = wallet.latest_checkpoint();
733+
734+
// reload the last 200 blocks in case of a reorg
735+
let emitter_height = wallet_cp.height().saturating_sub(200);
736+
let mut emitter = Emitter::new(
737+
&*client,
738+
wallet_cp,
739+
emitter_height,
740+
wallet
741+
.tx_graph()
742+
.list_canonical_txs(
743+
wallet.local_chain(),
744+
wallet.local_chain().tip().block_id(),
745+
CanonicalizationParams::default(),
746+
)
747+
.filter(|tx| tx.chain_position.is_unconfirmed()),
748+
);
749+
750+
while let Some(block_event) = emitter.next_block()? {
751+
if block_event.block_height() % 10_000 == 0 {
752+
let percent_done = f64::from(block_event.block_height())
753+
/ f64::from(blockchain_info.headers as u32)
754+
* 100f64;
755+
println!(
756+
"Applying block at height: {}, {:.2}% done.",
757+
block_event.block_height(),
758+
percent_done
759+
);
760+
}
761+
762+
wallet.apply_block_connected_to(
763+
&block_event.block,
764+
block_event.block_height(),
765+
block_event.connected_to(),
766+
)?;
767+
}
768+
769+
let mempool_txs = emitter.mempool()?;
770+
wallet.apply_unconfirmed_txs(mempool_txs.update);
771+
}
772+
#[cfg(feature = "cbf")]
773+
KyotoClient { client } => {
774+
sync_kyoto_client(wallet, client).await?;
775+
}
776+
}
699777
Ok(serde_json::to_string_pretty(&json!({}))?)
700778
}
701779
Broadcast { psbt, tx } => {
@@ -715,7 +793,68 @@ pub(crate) async fn handle_online_wallet_subcommand(
715793
(Some(_), Some(_)) => panic!("Both `psbt` and `tx` options not allowed"),
716794
(None, None) => panic!("Missing `psbt` and `tx` option"),
717795
};
718-
let txid = broadcast_transaction(client, tx).await?;
796+
797+
let txid = match client {
798+
#[cfg(feature = "electrum")]
799+
Electrum {
800+
client,
801+
batch_size: _,
802+
} => client
803+
.transaction_broadcast(&tx)
804+
.map_err(|e| Error::Generic(e.to_string()))?,
805+
#[cfg(feature = "esplora")]
806+
Esplora {
807+
client,
808+
parallel_requests: _,
809+
} => client
810+
.broadcast(&tx)
811+
.await
812+
.map(|()| tx.compute_txid())
813+
.map_err(|e| Error::Generic(e.to_string()))?,
814+
#[cfg(feature = "rpc")]
815+
RpcClient { client } => client
816+
.send_raw_transaction(&tx)
817+
.map_err(|e| Error::Generic(e.to_string()))?,
818+
819+
#[cfg(feature = "cbf")]
820+
KyotoClient { client } => {
821+
let LightClient {
822+
requester,
823+
mut info_subscriber,
824+
mut warning_subscriber,
825+
update_subscriber: _,
826+
node,
827+
} = *client;
828+
829+
let subscriber = tracing_subscriber::FmtSubscriber::new();
830+
tracing::subscriber::set_global_default(subscriber)
831+
.map_err(|e| Error::Generic(format!("SetGlobalDefault error: {e}")))?;
832+
833+
tokio::task::spawn(async move { node.run().await });
834+
tokio::task::spawn(async move {
835+
select! {
836+
info = info_subscriber.recv() => {
837+
if let Some(info) = info {
838+
tracing::info!("{info}");
839+
}
840+
},
841+
warn = warning_subscriber.recv() => {
842+
if let Some(warn) = warn {
843+
tracing::warn!("{warn}");
844+
}
845+
}
846+
}
847+
});
848+
let txid = tx.compute_txid();
849+
let wtxid = requester.broadcast_random(tx.clone()).await.map_err(|_| {
850+
tracing::warn!("Broadcast was unsuccessful");
851+
Error::Generic("Transaction broadcast timed out after 30 seconds".into())
852+
})?;
853+
tracing::info!("Successfully broadcast WTXID: {wtxid}");
854+
txid
855+
}
856+
};
857+
719858
Ok(serde_json::to_string_pretty(&json!({ "txid": txid }))?)
720859
}
721860
ReceivePayjoin {

src/utils.rs

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,21 @@
99
//! Utility Tools
1010
//!
1111
//! This module includes all the utility tools used by the App.
12-
use crate::config::WalletConfig;
13-
use crate::error::BDKCliError as Error;
14-
use std::{
15-
fmt::Display,
16-
path::{Path, PathBuf},
17-
str::FromStr,
18-
sync::Arc,
19-
};
2012
2113
use crate::commands::WalletOpts;
14+
use crate::error::BDKCliError as Error;
15+
use bdk_electrum::electrum_client::ConfigBuilder;
2216
#[cfg(feature = "cbf")]
2317
use bdk_kyoto::{
2418
BuilderExt, Info, LightClient, Receiver, ScanType::Sync, UnboundedReceiver, Warning,
2519
builder::Builder,
2620
};
27-
use bdk_wallet::{
28-
KeychainKind,
29-
bitcoin::bip32::{DerivationPath, Xpub},
30-
keys::DescriptorPublicKey,
31-
miniscript::{
32-
Descriptor, Miniscript, Terminal,
33-
descriptor::{DescriptorXKey, Wildcard},
34-
},
35-
template::DescriptorTemplate,
36-
};
37-
use cli_table::{Cell, CellStruct, Style, Table};
21+
22+
23+
use bdk_wallet::bitcoin::{Address, Network, OutPoint, ScriptBuf};
24+
use std::fmt::Display;
25+
use std::path::{Path, PathBuf};
26+
use std::str::FromStr;
3827

3928
#[cfg(any(
4029
feature = "electrum",
@@ -186,7 +175,8 @@ pub(crate) fn new_blockchain_client(
186175
let client = match wallet_opts.client_type {
187176
#[cfg(feature = "electrum")]
188177
ClientType::Electrum => {
189-
let client = bdk_electrum::electrum_client::Client::new(url)
178+
let config = ConfigBuilder::new().build();
179+
let client = bdk_electrum::electrum_client::Client::from_config(url, config)
190180
.map(bdk_electrum::BdkElectrumClient::new)?;
191181
BlockchainClient::Electrum {
192182
client: Box::new(client),

0 commit comments

Comments
 (0)