Gui config: start_internal_bitcoind

Installer will install bitcoind in a directory
that will have always the same relative path to
the liana datadir.
GUI needs then only a flag "start_internal_bitcoind" set to true
to check the conventional path of the downloaded bitcoind exe
and start the internal bitcoind
This commit is contained in:
edouard 2023-08-31 11:50:43 +02:00
parent d700f8a3cf
commit bc87839e52
6 changed files with 63 additions and 100 deletions

View File

@ -3,15 +3,6 @@ use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use tracing_subscriber::filter; use tracing_subscriber::filter;
/// Config required to start internal bitcoind.
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct InternalBitcoindExeConfig {
/// Internal bitcoind executable path.
pub exe_path: PathBuf,
/// Internal bitcoind data dir.
pub data_dir: PathBuf,
}
#[derive(Debug, Clone, Deserialize, Serialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Config { pub struct Config {
/// Path to lianad configuration file. /// Path to lianad configuration file.
@ -25,24 +16,22 @@ pub struct Config {
/// hardware wallets config. /// hardware wallets config.
/// LEGACY: Use Settings module instead. /// LEGACY: Use Settings module instead.
pub hardware_wallets: Option<Vec<HardwareWalletConfig>>, pub hardware_wallets: Option<Vec<HardwareWalletConfig>>,
/// Internal bitcoind executable config. /// Start internal bitcoind executable.
pub internal_bitcoind_exe_config: Option<InternalBitcoindExeConfig>, #[serde(default)]
pub start_internal_bitcoind: bool,
} }
pub const DEFAULT_FILE_NAME: &str = "gui.toml"; pub const DEFAULT_FILE_NAME: &str = "gui.toml";
impl Config { impl Config {
pub fn new( pub fn new(daemon_config_path: PathBuf, start_internal_bitcoind: bool) -> Self {
daemon_config_path: PathBuf,
internal_bitcoind_exe_config: Option<InternalBitcoindExeConfig>,
) -> Self {
Self { Self {
daemon_config_path: Some(daemon_config_path), daemon_config_path: Some(daemon_config_path),
daemon_rpc_path: None, daemon_rpc_path: None,
log_level: None, log_level: None,
debug: None, debug: None,
hardware_wallets: None, hardware_wallets: None,
internal_bitcoind_exe_config, start_internal_bitcoind,
} }
} }

View File

@ -152,9 +152,10 @@ impl Bitcoind {
pub fn start( pub fn start(
network: &bitcoin::Network, network: &bitcoin::Network,
mut config: BitcoindConfig, mut config: BitcoindConfig,
bitcoind_datadir: &Path, liana_datadir: &PathBuf,
exe_path: &Path,
) -> Result<Self, StartInternalBitcoindError> { ) -> Result<Self, StartInternalBitcoindError> {
let bitcoind_datadir = internal_bitcoind_datadir(liana_datadir);
let bitcoind_exe_path = internal_bitcoind_exe_path(liana_datadir);
let datadir_path_str = bitcoind_datadir let datadir_path_str = bitcoind_datadir
.canonicalize() .canonicalize()
.map_err(|e| StartInternalBitcoindError::CouldNotCanonicalizeDataDir(e.to_string()))? .map_err(|e| StartInternalBitcoindError::CouldNotCanonicalizeDataDir(e.to_string()))?
@ -174,7 +175,7 @@ impl Bitcoind {
format!("-chain={}", network.to_core_arg()), format!("-chain={}", network.to_core_arg()),
format!("-datadir={}", datadir_path_str), format!("-datadir={}", datadir_path_str),
]; ];
let mut command = std::process::Command::new(exe_path); let mut command = std::process::Command::new(bitcoind_exe_path);
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let command = command.creation_flags(CREATE_NO_WINDOW); let command = command.creation_flags(CREATE_NO_WINDOW);

View File

@ -4,7 +4,6 @@ use std::time::Duration;
use crate::{ use crate::{
app::{ app::{
config::InternalBitcoindExeConfig,
settings::{KeySetting, Settings, WalletSetting}, settings::{KeySetting, Settings, WalletSetting},
wallet::DEFAULT_WALLET_NAME, wallet::DEFAULT_WALLET_NAME,
}, },
@ -36,7 +35,6 @@ pub struct Context {
pub recovered_signer: Option<Arc<Signer>>, pub recovered_signer: Option<Arc<Signer>>,
pub bitcoind_is_external: bool, pub bitcoind_is_external: bool,
pub internal_bitcoind_config: Option<InternalBitcoindConfig>, pub internal_bitcoind_config: Option<InternalBitcoindConfig>,
pub internal_bitcoind_exe_config: Option<InternalBitcoindExeConfig>,
pub internal_bitcoind: Option<Bitcoind>, pub internal_bitcoind: Option<Bitcoind>,
} }
@ -56,7 +54,6 @@ impl Context {
recovered_signer: None, recovered_signer: None,
bitcoind_is_external: true, bitcoind_is_external: true,
internal_bitcoind_config: None, internal_bitcoind_config: None,
internal_bitcoind_exe_config: None,
internal_bitcoind: None, internal_bitcoind: None,
} }
} }

View File

@ -16,7 +16,6 @@ use std::path::PathBuf;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use crate::{ use crate::{
app::config::InternalBitcoindExeConfig,
app::{config as gui_config, settings as gui_settings}, app::{config as gui_config, settings as gui_settings},
signer::Signer, signer::Signer,
}; };
@ -317,7 +316,8 @@ pub async fn install(ctx: Context, signer: Arc<Mutex<Signer>>) -> Result<PathBuf
daemon_config_path.canonicalize().map_err(|e| { daemon_config_path.canonicalize().map_err(|e| {
Error::Unexpected(format!("Failed to canonicalize daemon config path: {}", e)) Error::Unexpected(format!("Failed to canonicalize daemon config path: {}", e))
})?, })?,
ctx.internal_bitcoind_exe_config.clone(), // Installer started a bitcoind, it is expected that gui will start it on on startup
ctx.internal_bitcoind.is_some(),
)) ))
.map_err(|e| Error::Unexpected(format!("Failed to serialize gui config: {}", e)))? .map_err(|e| Error::Unexpected(format!("Failed to serialize gui config: {}", e)))?
.as_bytes(), .as_bytes(),

View File

@ -28,7 +28,7 @@ use crate::{
context::Context, context::Context,
message::{self, Message}, message::{self, Message},
step::Step, step::Step,
view, Error, InternalBitcoindExeConfig, view, Error,
}, },
}; };
@ -453,7 +453,6 @@ impl Step for SelectBitcoindTypeStep {
} }
} else { } else {
ctx.internal_bitcoind_config = None; ctx.internal_bitcoind_config = None;
ctx.internal_bitcoind_exe_config = None;
} }
ctx.bitcoind_is_external = self.use_external; ctx.bitcoind_is_external = self.use_external;
true true
@ -599,7 +598,6 @@ pub struct InternalBitcoindStep {
started: Option<Result<(), StartInternalBitcoindError>>, started: Option<Result<(), StartInternalBitcoindError>>,
exe_path: Option<PathBuf>, exe_path: Option<PathBuf>,
bitcoind_config: Option<BitcoindConfig>, bitcoind_config: Option<BitcoindConfig>,
exe_config: Option<InternalBitcoindExeConfig>,
internal_bitcoind_config: Option<InternalBitcoindConfig>, internal_bitcoind_config: Option<InternalBitcoindConfig>,
error: Option<String>, error: Option<String>,
exe_download: Option<Download>, exe_download: Option<Download>,
@ -622,7 +620,6 @@ impl InternalBitcoindStep {
started: None, started: None,
exe_path: None, exe_path: None,
bitcoind_config: None, bitcoind_config: None,
exe_config: None,
internal_bitcoind_config: None, internal_bitcoind_config: None,
error: None, error: None,
exe_download: None, exe_download: None,
@ -657,6 +654,7 @@ impl Step for InternalBitcoindStep {
bitcoind.stop(); bitcoind.stop();
self.started = None; self.started = None;
} }
self.internal_bitcoind = None;
return Command::perform(async {}, |_| Message::Previous); return Command::perform(async {}, |_| Message::Previous);
} }
message::InternalBitcoindMsg::Reload => { message::InternalBitcoindMsg::Reload => {
@ -768,70 +766,48 @@ impl Step for InternalBitcoindStep {
} }
} }
message::InternalBitcoindMsg::Start => { message::InternalBitcoindMsg::Start => {
if let Some(exe_path) = &self.exe_path { if let Err(e) = self.bitcoind_datadir.canonicalize() {
let exe_config = match ( self.started = Some(Err(
exe_path.canonicalize(), StartInternalBitcoindError::CouldNotCanonicalizeDataDir(e.to_string()),
self.bitcoind_datadir.canonicalize(), ));
) { return Command::none();
(Ok(exe_path), Ok(data_dir)) => {
InternalBitcoindExeConfig { exe_path, data_dir }
}
(Err(e), Ok(_)) | (Err(e), Err(_)) => {
self.started = Some(Err(
StartInternalBitcoindError::CouldNotCanonicalizeExePath(
e.to_string(),
),
));
return Command::none();
}
(Ok(_), Err(e)) => {
self.started = Some(Err(
StartInternalBitcoindError::CouldNotCanonicalizeDataDir(
e.to_string(),
),
));
return Command::none();
}
};
let cookie_path = bitcoind::internal_bitcoind_cookie_path(
&self.bitcoind_datadir,
&self.network,
);
let rpc_port = self
.internal_bitcoind_config
.as_ref()
.expect("Already added")
.clone()
.networks
.get(&self.network)
.expect("Already added")
.rpc_port;
match Bitcoind::start(
&self.network,
BitcoindConfig {
cookie_path,
addr: internal_bitcoind_address(rpc_port),
},
&exe_config.data_dir,
&exe_config.exe_path,
) {
Err(e) => {
self.started = Some(Err(StartInternalBitcoindError::CommandError(
e.to_string(),
)));
return Command::none();
}
Ok(bitcoind) => {
self.error = None;
self.bitcoind_config = Some(bitcoind.config.clone());
self.exe_config = Some(exe_config);
self.started = Some(Ok(()));
self.internal_bitcoind = Some(bitcoind);
}
};
} }
let cookie_path = bitcoind::internal_bitcoind_cookie_path(
&self.bitcoind_datadir,
&self.network,
);
let rpc_port = self
.internal_bitcoind_config
.as_ref()
.expect("Already added")
.clone()
.networks
.get(&self.network)
.expect("Already added")
.rpc_port;
match Bitcoind::start(
&self.network,
BitcoindConfig {
cookie_path,
addr: internal_bitcoind_address(rpc_port),
},
&self.liana_datadir,
) {
Err(e) => {
self.started =
Some(Err(StartInternalBitcoindError::CommandError(e.to_string())));
return Command::none();
}
Ok(bitcoind) => {
self.error = None;
self.bitcoind_config = Some(bitcoind.config.clone());
self.started = Some(Ok(()));
self.internal_bitcoind = Some(bitcoind);
}
};
} }
}; };
}; };
@ -871,7 +847,6 @@ impl Step for InternalBitcoindStep {
if let Some(Ok(_)) = self.started { if let Some(Ok(_)) = self.started {
ctx.bitcoind_config = self.bitcoind_config.clone(); ctx.bitcoind_config = self.bitcoind_config.clone();
ctx.internal_bitcoind_config = self.internal_bitcoind_config.clone(); ctx.internal_bitcoind_config = self.internal_bitcoind_config.clone();
ctx.internal_bitcoind_exe_config = self.exe_config.clone();
ctx.internal_bitcoind = self.internal_bitcoind.clone(); ctx.internal_bitcoind = self.internal_bitcoind.clone();
self.error = None; self.error = None;
return true; return true;

View File

@ -24,7 +24,7 @@ use liana_ui::{
use crate::{ use crate::{
app::{ app::{
cache::Cache, cache::Cache,
config::{Config as GUIConfig, InternalBitcoindExeConfig}, config::Config as GUIConfig,
wallet::{Wallet, WalletError}, wallet::{Wallet, WalletError},
}, },
bitcoind::{Bitcoind, StartInternalBitcoindError}, bitcoind::{Bitcoind, StartInternalBitcoindError},
@ -109,8 +109,8 @@ impl Loader {
progress: 0.0, progress: 0.0,
bitcoind_logs: String::new(), bitcoind_logs: String::new(),
}; };
if self.gui_config.internal_bitcoind_exe_config.is_some() { if self.gui_config.start_internal_bitcoind {
warn!("Ignoring internal bitcoind config because Liana daemon is external."); warn!("Lianad is external, gui will not start internal bitcoind");
} }
return Command::perform(sync(daemon, false), Message::Syncing); return Command::perform(sync(daemon, false), Message::Syncing);
} }
@ -127,7 +127,8 @@ impl Loader {
return Command::perform( return Command::perform(
start_bitcoind_and_daemon( start_bitcoind_and_daemon(
daemon_config_path, daemon_config_path,
self.gui_config.internal_bitcoind_exe_config.clone(), self.datadir_path.clone(),
self.gui_config.start_internal_bitcoind,
), ),
Message::Started, Message::Started,
); );
@ -411,11 +412,12 @@ async fn connect(socket_path: PathBuf) -> Result<Arc<dyn Daemon + Sync + Send>,
// Daemon can start only if a config path is given. // Daemon can start only if a config path is given.
pub async fn start_bitcoind_and_daemon( pub async fn start_bitcoind_and_daemon(
config_path: PathBuf, config_path: PathBuf,
bitcoind_exe_config: Option<InternalBitcoindExeConfig>, liana_datadir_path: PathBuf,
start_internal_bitcoind: bool,
) -> Result<(Arc<dyn Daemon + Sync + Send>, Option<Bitcoind>), Error> { ) -> Result<(Arc<dyn Daemon + Sync + Send>, Option<Bitcoind>), Error> {
let config = Config::from_file(Some(config_path)).map_err(Error::Config)?; let config = Config::from_file(Some(config_path)).map_err(Error::Config)?;
let mut bitcoind: Option<Bitcoind> = None; let mut bitcoind: Option<Bitcoind> = None;
if let Some(exe_config) = bitcoind_exe_config { if start_internal_bitcoind {
if let Some(bitcoind_config) = &config.bitcoind_config { if let Some(bitcoind_config) = &config.bitcoind_config {
// Check if bitcoind is already running before trying to start it. // Check if bitcoind is already running before trying to start it.
if liana::BitcoinD::new(bitcoind_config, "internal_bitcoind_start".to_string()).is_ok() if liana::BitcoinD::new(bitcoind_config, "internal_bitcoind_start".to_string()).is_ok()
@ -427,8 +429,7 @@ pub async fn start_bitcoind_and_daemon(
Bitcoind::start( Bitcoind::start(
&config.bitcoin_config.network, &config.bitcoin_config.network,
bitcoind_config.clone(), bitcoind_config.clone(),
&exe_config.data_dir, &liana_datadir_path,
&exe_config.exe_path,
) )
.map_err(Error::Bitcoind)?, .map_err(Error::Bitcoind)?,
); );