diff --git a/gui/Cargo.lock b/gui/Cargo.lock index 3e5014f6..46c16861 100644 --- a/gui/Cargo.lock +++ b/gui/Cargo.lock @@ -308,12 +308,32 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bdk_chain" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c601c4dc7e6c3efa538a0afbb43b964cefab9a9b5e8f352fa0ca38145448a5e7" +dependencies = [ + "bitcoin", + "miniscript", +] + [[package]] name = "bdk_coin_select" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c084bf76f0f67546fc814ffa82044144be1bb4618183a15016c162f8b087ad4" +[[package]] +name = "bdk_electrum" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28906275aeb1f71dc32045670f06c8a26fb17cc62151a99f7425d258f4bda589" +dependencies = [ + "bdk_chain", + "electrum-client", +] + [[package]] name = "bech32" version = "0.10.0-beta" @@ -1143,11 +1163,11 @@ dependencies = [ [[package]] name = "dirs" -version = "5.0.0" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dece029acd3353e3a58ac2e3eb3c8d6c35827a892edc6cc4138ef9c33df46ecd" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "dirs-sys 0.4.0", + "dirs-sys 0.4.1", ] [[package]] @@ -1163,13 +1183,14 @@ dependencies = [ [[package]] name = "dirs-sys" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04414300db88f70d74c5ff54e50f9e1d1737d9a5b90f53fcf2e95ca2a9ab554b" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", + "option-ext", "redox_users", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -1267,6 +1288,23 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +[[package]] +name = "electrum-client" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89008f106be6f303695522f2f4c1f28b40c3e8367ed8b3bb227f1f882cb52cc2" +dependencies = [ + "bitcoin", + "byteorder", + "libc", + "log", + "rustls", + "serde", + "serde_json", + "webpki-roots", + "winapi", +] + [[package]] name = "elliptic-curve" version = "0.13.8" @@ -2589,12 +2627,13 @@ dependencies = [ [[package]] name = "liana" version = "6.0.0" -source = "git+https://github.com/wizardsardine/liana?branch=master#585bb5b763127f4e0686ce8201fb846fa84137b9" +source = "git+https://github.com/wizardsardine/liana?branch=master#6f7334738360a554d17875b364ccdf2120250315" dependencies = [ "backtrace", "bdk_coin_select", + "bdk_electrum", "bip39", - "dirs 5.0.0", + "dirs 5.0.1", "fern", "getrandom", "jsonrpc 0.17.0", @@ -2936,9 +2975,9 @@ dependencies = [ [[package]] name = "minreq" -version = "2.8.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3de406eeb24aba36ed3829532fa01649129677186b44a49debec0ec574ca7da7" +checksum = "763d142cdff44aaadd9268bebddb156ef6c65a0e13486bb81673cf2d8739f9b0" dependencies = [ "log", "serde", @@ -3260,6 +3299,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "orbclient" version = "0.3.47" @@ -3818,9 +3863,9 @@ checksum = "3b42e27ef78c35d3998403c1d26f3efd9e135d3e5121b0a4845cc5cc27547f4f" [[package]] name = "rdrand" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e233b642160555c1aa1ff7a78443c6139342f411b6fa6602af2ebbfee9e166bb" +checksum = "d92195228612ac8eed47adbc2ed0f04e513a4ccb98175b6f2bd04d963b533655" dependencies = [ "rand_core", ] diff --git a/gui/src/app/state/settings/bitcoind.rs b/gui/src/app/state/settings/bitcoind.rs index 430b1fe5..5d8fc07e 100644 --- a/gui/src/app/state/settings/bitcoind.rs +++ b/gui/src/app/state/settings/bitcoind.rs @@ -9,7 +9,7 @@ use iced::Command; use tracing::info; use liana::{ - config::{BitcoinConfig, BitcoindConfig, BitcoindRpcAuth, Config}, + config::{BitcoinBackend, BitcoinConfig, BitcoindConfig, BitcoindRpcAuth, Config}, miniscript::bitcoin::Network, }; @@ -37,13 +37,22 @@ impl BitcoindSettingsState { daemon_is_external: bool, bitcoind_is_internal: bool, ) -> Self { + let bitcoind_config = if let Some(BitcoinBackend::Bitcoind(bitcoind_config)) = + config.clone().and_then(|c| c.bitcoin_backend) + { + Some(bitcoind_config) + } else { + None + }; BitcoindSettingsState { warning: None, config_updated: false, - node_settings: config.map(|config| { + node_settings: bitcoind_config.map(|bitcoind_config| { BitcoindSettings::new( - config.bitcoin_config.clone(), - config.bitcoind_config.unwrap(), + config + .expect("config must exist if bitcoind_config exists") + .bitcoin_config, + bitcoind_config, daemon_is_external, bitcoind_is_internal, ) @@ -110,9 +119,10 @@ impl State for BitcoindSettingsState { } fn view<'a>(&'a self, cache: &'a Cache) -> Element<'a, view::Message> { - let can_edit_bitcoind_settings = !self.rescan_settings.processing; + let can_edit_bitcoind_settings = + self.node_settings.is_some() && !self.rescan_settings.processing; let can_do_rescan = !self.rescan_settings.processing - && self.node_settings.as_ref().map(|settings| settings.edit) != Some(true); + && self.node_settings.as_ref().map(|settings| settings.edit) == Some(false); view::settings::bitcoind_settings( cache, self.warning.as_ref(), @@ -274,10 +284,11 @@ impl BitcoindSettings { if let (true, Some(rpc_auth)) = (self.addr.valid, rpc_auth) { let mut daemon_config = daemon.config().cloned().unwrap(); - daemon_config.bitcoind_config = Some(liana::config::BitcoindConfig { - rpc_auth, - addr: new_addr.unwrap(), - }); + daemon_config.bitcoin_backend = + Some(liana::config::BitcoinBackend::Bitcoind(BitcoindConfig { + rpc_auth, + addr: new_addr.unwrap(), + })); self.processing = true; return Command::perform(async move { daemon_config }, |cfg| { Message::LoadDaemonConfig(Box::new(cfg)) diff --git a/gui/src/daemon/embedded.rs b/gui/src/daemon/embedded.rs index 9ee78d80..06f6203c 100644 --- a/gui/src/daemon/embedded.rs +++ b/gui/src/daemon/embedded.rs @@ -27,9 +27,9 @@ impl EmbeddedDaemon { pub async fn command(&self, method: F) -> Result where - F: FnOnce(&DaemonControl) -> Result, + F: FnOnce(&mut DaemonControl) -> Result, { - match self.handle.lock().await.as_ref() { + match self.handle.lock().await.as_mut() { Some(DaemonHandle::Controller { control, .. }) => method(control), None => Err(DaemonError::DaemonStopped), } diff --git a/gui/src/installer/context.rs b/gui/src/installer/context.rs index 38215b64..740c55c0 100644 --- a/gui/src/installer/context.rs +++ b/gui/src/installer/context.rs @@ -10,7 +10,7 @@ use crate::{ }; use async_hwi::DeviceKind; use liana::{ - config::{BitcoinConfig, BitcoindConfig}, + config::{BitcoinBackend, BitcoinConfig}, descriptors::LianaDescriptor, miniscript::bitcoin, }; @@ -48,7 +48,7 @@ impl RemoteBackend { #[derive(Clone)] pub struct Context { pub bitcoin_config: BitcoinConfig, - pub bitcoind_config: Option, + pub bitcoin_backend: Option, pub descriptor: Option, pub keys: Vec, pub hws: Vec<(DeviceKind, bitcoin::bip32::Fingerprint, Option<[u8; 32]>)>, @@ -77,7 +77,7 @@ impl Context { }, hws: Vec::new(), keys: Vec::new(), - bitcoind_config: None, + bitcoin_backend: None, descriptor: None, data_dir, network, diff --git a/gui/src/installer/mod.rs b/gui/src/installer/mod.rs index f9cdb339..a05f4e0a 100644 --- a/gui/src/installer/mod.rs +++ b/gui/src/installer/mod.rs @@ -689,7 +689,7 @@ pub fn extract_daemon_config(ctx: &Context) -> Config { .expect("Context must have a descriptor at this point"), data_dir: Some(ctx.data_dir.clone()), bitcoin_config: ctx.bitcoin_config.clone(), - bitcoind_config: ctx.bitcoind_config.clone(), + bitcoin_backend: ctx.bitcoin_backend.clone(), } } diff --git a/gui/src/installer/step/bitcoind.rs b/gui/src/installer/step/bitcoind.rs index e48637b9..a76d8408 100644 --- a/gui/src/installer/step/bitcoind.rs +++ b/gui/src/installer/step/bitcoind.rs @@ -9,7 +9,7 @@ use bitcoin_hashes::{sha256, Hash}; use flate2::read::GzDecoder; use iced::{Command, Subscription}; use liana::{ - config::{BitcoindConfig, BitcoindRpcAuth}, + config::{BitcoinBackend, BitcoindConfig, BitcoindRpcAuth}, miniscript::bitcoin::Network, }; #[cfg(any(target_os = "macos", target_os = "linux"))] @@ -320,7 +320,7 @@ impl Step for SelectBitcoindTypeStep { fn apply(&mut self, ctx: &mut Context) -> bool { if !self.use_external { if ctx.internal_bitcoind_config.is_none() { - ctx.bitcoind_config = None; // Ensures internal bitcoind can be restarted in case user has switched selection. + ctx.bitcoin_backend = None; // Ensures internal bitcoind can be restarted in case user has switched selection. } } else { ctx.internal_bitcoind_config = None; @@ -481,7 +481,11 @@ impl Step for DefineBitcoind { false } (Some(rpc_auth), Ok(addr)) => { - ctx.bitcoind_config = Some(BitcoindConfig { rpc_auth, addr }); + ctx.bitcoin_backend = + Some(liana::config::BitcoinBackend::Bitcoind(BitcoindConfig { + rpc_auth, + addr, + })); true } } @@ -579,7 +583,7 @@ impl Step for InternalBitcoindStep { } if let Some(Ok(_)) = self.started { // This case can arise if a user switches from internal bitcoind to external and back to internal. - if ctx.bitcoind_config.is_none() { + if ctx.bitcoin_backend.is_none() { self.started = None; // So that internal bitcoind will be restarted. } } @@ -790,7 +794,10 @@ impl Step for InternalBitcoindStep { fn apply(&mut self, ctx: &mut Context) -> bool { // Any errors have been handled as part of `message::InternalBitcoindMsg::Start` if let Some(Ok(_)) = self.started { - ctx.bitcoind_config.clone_from(&self.bitcoind_config); + ctx.bitcoin_backend = self + .bitcoind_config + .as_ref() + .map(|bitcoind_config| BitcoinBackend::Bitcoind(bitcoind_config.clone())); ctx.internal_bitcoind_config .clone_from(&self.internal_bitcoind_config); ctx.internal_bitcoind.clone_from(&self.internal_bitcoind); diff --git a/gui/src/loader.rs b/gui/src/loader.rs index 47e22ac3..d5f25d19 100644 --- a/gui/src/loader.rs +++ b/gui/src/loader.rs @@ -11,7 +11,7 @@ use tracing::{debug, info, warn}; use liana::{ commands::CoinStatus, - config::{Config, ConfigError}, + config::{BitcoinBackend, Config, ConfigError}, miniscript::bitcoin, StartupError, }; @@ -245,7 +245,7 @@ impl Loader { log::info!("Managed bitcoind stopped."); } else if self.waiting_daemon_bitcoind && self.gui_config.start_internal_bitcoind { if let Ok(config) = Config::from_file(self.gui_config.daemon_config_path.clone()) { - if let Some(bitcoind_config) = &config.bitcoind_config { + if let Some(BitcoinBackend::Bitcoind(bitcoind_config)) = &config.bitcoin_backend { let mut retry = 0; while !stop_bitcoind(bitcoind_config) && retry < 10 { std::thread::sleep(std::time::Duration::from_millis(500)); @@ -500,7 +500,7 @@ pub async fn start_bitcoind_and_daemon( let config = Config::from_file(Some(config_path)).map_err(Error::Config)?; let mut bitcoind: Option = None; if start_internal_bitcoind { - if let Some(bitcoind_config) = &config.bitcoind_config { + if let Some(BitcoinBackend::Bitcoind(bitcoind_config)) = &config.bitcoin_backend { // Check if bitcoind is already running before trying to start it. if liana::BitcoinD::new(bitcoind_config, "internal_bitcoind_start".to_string()).is_ok() {