Merge #1665: Remove the link between gui config and lianad config

19f5132ee8439ef3d4d27dd7254104d60c8540af Remove the link between gui config and lianad config (edouardparis)

Pull request description:

  This commit is part of preparatory work to support multiple wallets.

  This commit introduces two breaking change:

  The fields daemon_config_path and daemon_rpc_path are removed. The GUI will deduce these values from their expected location in the root data directory.

  Because this link is removed, the gui flag --conf is not useful anymore as it cannot then find the location of the root data directory.

ACKs for top commit:
  jp1ac4:
    ACK 19f5132ee8439ef3d4d27dd7254104d60c8540af.

Tree-SHA512: f883781e935e2253ebc2d4b71331c12efbaa142d45c418d17411c3de0b2288127832de8ff34eb24d07abfdb8e3045b48c3e5c3773857518c3a28df2a7c46263c
This commit is contained in:
edouardparis 2025-04-23 13:50:08 +02:00
commit 1213858489
No known key found for this signature in database
GPG Key ID: E65F7A089C20DC8F
6 changed files with 49 additions and 125 deletions

View File

@ -6,10 +6,6 @@ use tracing_subscriber::filter;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Config {
/// Path to lianad configuration file.
pub daemon_config_path: Option<PathBuf>,
/// Path to lianad_rpc socket file.
pub daemon_rpc_path: Option<PathBuf>,
/// log level, can be "info", "debug", "trace".
pub log_level: Option<String>,
/// Use iced debug feature if true.
@ -22,10 +18,8 @@ pub struct Config {
pub const DEFAULT_FILE_NAME: &str = "gui.toml";
impl Config {
pub fn new(daemon_config_path: PathBuf, start_internal_bitcoind: bool) -> Self {
pub fn new(start_internal_bitcoind: bool) -> Self {
Self {
daemon_config_path: Some(daemon_config_path),
daemon_rpc_path: None,
log_level: None,
debug: None,
start_internal_bitcoind,

View File

@ -142,7 +142,6 @@ impl Panels {
pub struct App {
cache: Cache,
config: Arc<Config>,
wallet: Arc<Wallet>,
daemon: Arc<dyn Daemon + Sync + Send>,
internal_bitcoind: Option<Bitcoind>,
@ -175,7 +174,6 @@ impl App {
Self {
panels,
cache,
config,
daemon,
wallet,
internal_bitcoind,
@ -365,10 +363,7 @@ impl App {
Task::none()
}
Message::LoadDaemonConfig(cfg) => {
let path = self.config.daemon_config_path.clone().expect(
"Application config must have a daemon configuration file path at this point.",
);
let res = self.load_daemon_config(&path, *cfg);
let res = self.load_daemon_config(self.cache.datadir_path.clone(), *cfg);
self.update(Message::DaemonConfigLoaded(res))
}
Message::WalletUpdated(Ok(wallet)) => {
@ -390,12 +385,16 @@ impl App {
pub fn load_daemon_config(
&mut self,
daemon_config_path: &PathBuf,
datadir_path: PathBuf,
cfg: DaemonConfig,
) -> Result<(), Error> {
Handle::current().block_on(async { self.daemon.stop().await })?;
let network = cfg.bitcoin_config.network;
let daemon = EmbeddedDaemon::start(cfg)?;
self.daemon = Arc::new(daemon);
let mut daemon_config_path = datadir_path;
daemon_config_path.push(network.to_string());
daemon_config_path.push("daemon.toml");
let content =
toml::to_string(&self.daemon.config()).map_err(|e| Error::Config(e.to_string()))?;

View File

@ -380,7 +380,7 @@ pub async fn install_local_wallet(
.map_err(|e| Error::Unexpected(format!("Failed to serialize daemon config: {}", e)))?;
// create lianad configuration file
let daemon_config_path = create_and_write_file(
let _daemon_config_path = create_and_write_file(
network_datadir_path.clone(),
"daemon.toml",
daemon_config.to_string().as_bytes(),
@ -421,9 +421,6 @@ pub async fn install_local_wallet(
network_datadir_path.clone(),
gui_config::DEFAULT_FILE_NAME,
toml::to_string(&gui_config::Config::new(
daemon_config_path.canonicalize().map_err(|e| {
Error::Unexpected(format!("Failed to canonicalize daemon config path: {}", e))
})?,
// Installer started a bitcoind, it is expected that gui will start it on startup
ctx.internal_bitcoind.is_some(),
))
@ -497,8 +494,6 @@ pub async fn create_remote_wallet(
network_datadir_path.clone(),
gui_config::DEFAULT_FILE_NAME,
toml::to_string(&gui_config::Config {
daemon_config_path: None,
daemon_rpc_path: None,
log_level: Some("info".to_string()),
debug: Some(false),
start_internal_bitcoind: false,
@ -613,8 +608,6 @@ pub async fn import_remote_wallet(
network_datadir_path.clone(),
gui_config::DEFAULT_FILE_NAME,
toml::to_string(&gui_config::Config {
daemon_config_path: None,
daemon_rpc_path: None,
log_level: Some("info".to_string()),
debug: Some(false),
start_internal_bitcoind: false,

View File

@ -464,21 +464,22 @@ async fn check_network_datadir(path: PathBuf, network: Network) -> Result<State,
config_path.push(network.to_string());
config_path.push(app::config::DEFAULT_FILE_NAME);
let cfg = match app::Config::from_file(&config_path) {
Ok(cfg) => cfg,
Err(e) => {
if e == app::config::ConfigError::NotFound {
return Ok(State::NoWallet);
} else {
return Err(format!(
"Failed to read GUI configuration file in the directory: {}",
path.to_string_lossy()
));
}
if let Err(e) = app::Config::from_file(&config_path) {
if e == app::config::ConfigError::NotFound {
return Ok(State::NoWallet);
} else {
return Err(format!(
"Failed to read GUI configuration file in the directory: {}",
path.to_string_lossy()
));
}
};
if let Some(daemon_config_path) = cfg.daemon_config_path {
let mut daemon_config_path = path.clone();
daemon_config_path.push(network.to_string());
daemon_config_path.push("daemon.toml");
if daemon_config_path.exists() {
lianad::config::Config::from_file(Some(daemon_config_path.clone())).map_err(|e| match e {
ConfigError::FileNotFound
| ConfigError::DatadirNotFound => {

View File

@ -119,10 +119,7 @@ impl Loader {
internal_bitcoind: Option<Bitcoind>,
backup: Option<Backup>,
) -> (Self, Task<Message>) {
let path = gui_config
.daemon_rpc_path
.clone()
.unwrap_or_else(|| socket_path(&datadir_path, network));
let path = socket_path(&datadir_path, network);
(
Loader {
network,
@ -185,22 +182,18 @@ impl Loader {
Error::Daemon(DaemonError::ClientNotSupported)
| Error::Daemon(DaemonError::RpcSocket(Some(ErrorKind::ConnectionRefused), _))
| Error::Daemon(DaemonError::RpcSocket(Some(ErrorKind::NotFound), _)) => {
if let Some(daemon_config_path) = self.gui_config.daemon_config_path.clone() {
self.step = Step::StartingDaemon;
self.daemon_started = true;
self.waiting_daemon_bitcoind = true;
return Task::perform(
start_bitcoind_and_daemon(
daemon_config_path,
self.datadir_path.clone(),
self.gui_config.start_internal_bitcoind
&& self.internal_bitcoind.is_none(),
),
Message::Started,
);
} else {
self.step = Step::Error(Box::new(e));
}
self.step = Step::StartingDaemon;
self.daemon_started = true;
self.waiting_daemon_bitcoind = true;
return Task::perform(
start_bitcoind_and_daemon(
self.datadir_path.clone(),
self.gui_config.start_internal_bitcoind
&& self.internal_bitcoind.is_none(),
self.network,
),
Message::Started,
);
}
_ => {
self.step = Step::Error(Box::new(e));
@ -291,7 +284,10 @@ impl Loader {
bitcoind.stop();
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()) {
let mut daemon_config_path = self.datadir_path.clone();
daemon_config_path.push(self.network.to_string());
daemon_config_path.push("daemon.toml");
if let Ok(config) = Config::from_file(Some(daemon_config_path)) {
if let Some(BitcoinBackend::Bitcoind(bitcoind_config)) = &config.bitcoin_backend {
let mut retry = 0;
while !stop_bitcoind(bitcoind_config) && retry < 10 {
@ -551,10 +547,13 @@ async fn connect(
// Daemon can start only if a config path is given.
pub async fn start_bitcoind_and_daemon(
config_path: PathBuf,
liana_datadir_path: PathBuf,
start_internal_bitcoind: bool,
network: bitcoin::Network,
) -> StartedResult {
let mut config_path = liana_datadir_path.clone();
config_path.push(network.to_string());
config_path.push("daemon.toml");
let config = Config::from_file(Some(config_path)).map_err(Error::Config)?;
let mut bitcoind: Option<Bitcoind> = None;
if start_internal_bitcoind {

View File

@ -19,7 +19,7 @@ extern crate serde_json;
use liana::miniscript::bitcoin;
use liana_ui::{component::text, font, image, theme, widget::Element};
use lianad::{commands::ListCoinsResult, config::Config as DaemonConfig};
use lianad::commands::ListCoinsResult;
use liana_gui::{
app::{self, cache::Cache, config::default_datadir, wallet::Wallet, App},
@ -39,7 +39,6 @@ use liana_gui::{
#[derive(Debug, PartialEq)]
enum Arg {
ConfigPath(PathBuf),
DatadirPath(PathBuf),
Network(bitcoin::Network),
}
@ -58,7 +57,6 @@ fn parse_args(args: Vec<String>) -> Result<Vec<Arg>, Box<dyn Error>> {
Usage: liana-gui [OPTIONS]
Options:
--conf <PATH> Path of configuration file (gui.toml)
--datadir <PATH> Path of liana datadir
-v, --version Display liana-gui version
-h, --help Print help
@ -72,13 +70,7 @@ Options:
}
for (i, arg) in args.iter().enumerate() {
if arg == "--conf" {
if let Some(a) = args.get(i + 1) {
res.push(Arg::ConfigPath(PathBuf::from(a)));
} else {
return Err("missing arg to --conf".into());
}
} else if arg == "--datadir" {
if arg == "--datadir" {
if let Some(a) = args.get(i + 1) {
res.push(Arg::DatadirPath(PathBuf::from(a)));
} else {
@ -315,27 +307,20 @@ impl GUI {
command.map(|msg| Message::Login(Box::new(msg)))
} else {
let cfg = app::Config::from_file(&path).expect("A config file was created");
let daemon_cfg =
DaemonConfig::from_file(cfg.daemon_config_path.clone()).unwrap();
let datadir_path = daemon_cfg
.data_dir
.as_ref()
.expect("Installer must have set it")
.clone();
self.logger.set_running_mode(
datadir_path.clone(),
daemon_cfg.bitcoin_config.network,
i.datadir.clone(),
i.network,
self.log_level
.unwrap_or_else(|| cfg.log_level().unwrap_or(LevelFilter::INFO)),
);
if remove_log {
self.logger.remove_install_log_file(datadir_path.clone());
self.logger.remove_install_log_file(i.datadir.clone());
}
let (loader, command) = Loader::new(
datadir_path,
i.datadir.clone(),
cfg,
daemon_cfg.bitcoin_config.network,
i.network,
internal_bitcoind,
i.context.backup.take(),
);
@ -561,39 +546,6 @@ fn main() -> Result<(), Box<dyn Error>> {
let datadir_path = default_datadir().unwrap();
Config::new(datadir_path, Some(*network))
}
[Arg::ConfigPath(path)] => {
let cfg = app::Config::from_file(path)?;
if let Some(daemon_config_path) = cfg.daemon_config_path.clone() {
let daemon_cfg = DaemonConfig::from_file(Some(daemon_config_path))?;
let datadir_path = daemon_cfg
.data_dir
.unwrap_or_else(|| default_datadir().unwrap());
Ok(Config::Run(
datadir_path,
cfg,
daemon_cfg.bitcoin_config.network,
))
} else {
Err("Application cannot guess network".into())
}
}
[Arg::ConfigPath(path), Arg::Network(network)]
| [Arg::Network(network), Arg::ConfigPath(path)] => {
let cfg = app::Config::from_file(path)?;
if let Some(daemon_config_path) = cfg.daemon_config_path.clone() {
let daemon_cfg = DaemonConfig::from_file(Some(daemon_config_path))?;
let datadir_path = daemon_cfg
.data_dir
.unwrap_or_else(|| default_datadir().unwrap());
Ok(Config::Run(
datadir_path,
cfg,
daemon_cfg.bitcoin_config.network,
))
} else {
Ok(Config::Run(default_datadir().unwrap(), cfg, *network))
}
}
[Arg::DatadirPath(datadir_path)] => Config::new(datadir_path.clone(), None),
[Arg::DatadirPath(datadir_path), Arg::Network(network)]
| [Arg::Network(network), Arg::DatadirPath(datadir_path)] => {
@ -692,20 +644,6 @@ mod tests {
fn test_parse_args() {
assert!(parse_args(vec!["--meth".into()]).is_err());
assert!(parse_args(vec!["--datadir".into()]).is_err());
assert!(parse_args(vec!["--conf".into()]).is_err());
assert_eq!(
Some(vec![
Arg::DatadirPath(PathBuf::from(".")),
Arg::ConfigPath(PathBuf::from("hello.toml")),
]),
parse_args(
"--datadir . --conf hello.toml"
.split(' ')
.map(|a| a.to_string())
.collect()
)
.ok()
);
assert_eq!(
Some(vec![Arg::Network(bitcoin::Network::Regtest)]),
parse_args(vec!["--regtest".into()]).ok()