Skip to content

Commit

Permalink
Use BitcoinD to check connection
Browse files Browse the repository at this point in the history
  • Loading branch information
jp1ac4 committed Aug 10, 2023
1 parent a7ff519 commit 7ced747
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 36 deletions.
2 changes: 1 addition & 1 deletion gui/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion gui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ path = "src/main.rs"

[dependencies]
async-hwi = "0.0.9"
liana = { git = "https://github.com/wizardsardine/liana", branch = "master", default-features = false }
liana = { git = "https://github.com/jp1ac4/liana", branch = "make-bitcoind-public", default-features = false }
liana_ui = { path = "ui" }
backtrace = "0.3"
base64 = "0.13"
Expand Down
128 changes: 97 additions & 31 deletions gui/src/installer/step/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub use mnemonic::{BackupMnemonic, RecoverMnemonic};

use std::collections::HashMap;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener};
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::str::FromStr;

use iced::Command;
Expand Down Expand Up @@ -71,8 +71,35 @@ pub struct DefineBitcoind {
pub struct StartInternalBitcoindStep {
bitcoind_datadir: PathBuf,
network: Network,
started: Option<Result<std::process::Child, std::io::Error>>,
started: Option<Result<(), StartInternalBitcoindError>>,
exe_path: Option<PathBuf>,
rpc_port: Option<u16>,
bitcoind_config: Option<BitcoindConfig>,
}

#[derive(PartialEq, Eq, Debug, Clone)]
pub enum StartInternalBitcoindError {
CommandError(String),
CouldNotCanonicalizeDataDir(String),
CouldNotCanonicalizeCookiePath(String),
BitcoinDError(String),
}

impl std::fmt::Display for StartInternalBitcoindError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::CommandError(e) => {
write!(f, "Command to start bitcoind returned an error: {}", e)
}
Self::CouldNotCanonicalizeDataDir(e) => {
write!(f, "Failed to canonicalize datadir: {}", e)
}
Self::CouldNotCanonicalizeCookiePath(e) => {
write!(f, "Failed to canonicalize cookie path: {}", e)
}
Self::BitcoinDError(e) => write!(f, "bitcoind connection check failed: {}", e),
}
}
}

pub struct SelectBitcoindTypeStep {
Expand Down Expand Up @@ -226,8 +253,8 @@ fn internal_bitcoind_config_path(liana_datadir: &PathBuf) -> PathBuf {
config_path
}

fn internal_bitcoind_cookie_path(liana_datadir: &PathBuf, network: &Network) -> PathBuf {
let mut cookie_path = internal_bitcoind_datadir(liana_datadir);
fn internal_bitcoind_cookie_path(bitcoind_datadir: &Path, network: &Network) -> PathBuf {
let mut cookie_path = bitcoind_datadir.to_path_buf();
if let Some(dir) = bitcoind_network_dir(network) {
cookie_path.push(dir);
}
Expand Down Expand Up @@ -540,6 +567,8 @@ impl StartInternalBitcoindStep {
network: Network::Bitcoin,
started: None,
exe_path: None,
rpc_port: None,
bitcoind_config: None,
}
}
}
Expand All @@ -550,25 +579,79 @@ impl Step for StartInternalBitcoindStep {
self.exe_path = bitcoind_exe_path();
}
self.network = ctx.bitcoin_config.network;
self.rpc_port = Some(
ctx.internal_bitcoind_config
.as_ref()
.expect("Already added")
.clone()
.networks
.get(&self.network)
.expect("Already added")
.rpc_port,
);
}
fn update(&mut self, message: Message) -> Command<Message> {
if let Message::StartInternalBitcoind(msg) = message {
match msg {
message::StartInternalBitcoindMsg::Start => {
if let Some(path) = &self.exe_path {
let datadir = self
.bitcoind_datadir
.canonicalize()
.expect("Failed to canonicalize bitcoind datadir path");
let datadir = match self.bitcoind_datadir.canonicalize() {
Ok(datadir) => datadir,
Err(e) => {
self.started = Some(Err(
StartInternalBitcoindError::CouldNotCanonicalizeDataDir(
e.to_string(),
),
));
return Command::none();
}
};

let args = vec![
format!("-chain={}", &self.network.to_core_arg()),
format!("-datadir={}", &datadir.to_string_lossy()),
];
let res = std::process::Command::new(path)
if let Err(e) = std::process::Command::new(path)
.args(&args)
.stdout(std::process::Stdio::null())
.spawn();
self.started = Some(res);
.spawn()
{
self.started =
Some(Err(StartInternalBitcoindError::CommandError(e.to_string())));
return Command::none();
}
// Need to wait for cookie file to appear.
std::thread::sleep(std::time::Duration::from_secs(1));
let cookie_path = match internal_bitcoind_cookie_path(
&self.bitcoind_datadir,
&self.network,
)
.canonicalize()
{
Ok(cookie_path) => cookie_path,
Err(e) => {
self.started = Some(Err(
StartInternalBitcoindError::CouldNotCanonicalizeCookiePath(
e.to_string(),
),
));
return Command::none();
}
};

let bitcoind_config = BitcoindConfig {
cookie_path,
addr: internal_bitcoind_address(self.rpc_port.expect("Already added")),
};
self.started = Some(
liana::BitcoinD::new(
&bitcoind_config,
"internal_bitcoind_connection_check".to_string(),
)
.map_err(|e| StartInternalBitcoindError::BitcoinDError(e.to_string()))
.map(|_| ()),
);
self.bitcoind_config = Some(bitcoind_config);
}
}
};
Expand All @@ -586,26 +669,9 @@ impl Step for StartInternalBitcoindStep {
}

fn apply(&mut self, ctx: &mut Context) -> bool {
if let Some(Ok(_child)) = self.started.as_ref() {
// The command was executed successfully, but we have not yet checked connection.
let rpc_port = ctx
.internal_bitcoind_config
.as_ref()
.expect("Already added")
.networks
.get(&ctx.bitcoin_config.network)
.expect("Already added")
.rpc_port;
if let Ok(cookie_path) =
internal_bitcoind_cookie_path(&ctx.data_dir, &ctx.bitcoin_config.network)
.canonicalize()
{
ctx.bitcoind_config = Some(BitcoindConfig {
cookie_path,
addr: internal_bitcoind_address(rpc_port),
});
return true;
}
if let Some(Ok(_)) = self.started {
ctx.bitcoind_config = self.bitcoind_config.clone();
return true;
}
false
}
Expand Down
7 changes: 4 additions & 3 deletions gui/src/installer/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ use crate::{
},
};

use super::step::StartInternalBitcoindError;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Network {
Mainnet,
Expand Down Expand Up @@ -938,13 +940,12 @@ pub fn select_bitcoind_type<'a>(progress: (usize, usize)) -> Element<'a, Message
pub fn start_internal_bitcoind<'a>(
progress: (usize, usize),
exe_path: Option<&PathBuf>,
started: Option<&Result<std::process::Child, std::io::Error>>,
started: Option<&Result<(), StartInternalBitcoindError>>,
) -> Element<'a, Message> {
let start_button = button::primary(None, "Start bitcoind").width(Length::Fixed(200.0));

let mut next_button = button::primary(None, "Next").width(Length::Fixed(200.0));
if let Some(Ok(_child)) = started {
// Next button is pressable even if stderr, e.g. in case bitcoind already running.
if let Some(Ok(_)) = started {
next_button = next_button.on_press(Message::Next);
};
layout(
Expand Down

0 comments on commit 7ced747

Please sign in to comment.