Add parent directory to bitcoind exe and datadir

.liana/bitcoind
├── bitcoin-25.0
│   └── bin
└── datadir
    ├── anchors.dat
    ├── banlist.json
    ├── bitcoin.conf
    ├── blocks
    ├── chainstate
    ├── debug.log
    ├── fee_estimates.dat
    ├── mempool.dat
    ├── peers.dat
    └── settings.json
This commit is contained in:
edouard 2023-08-31 11:06:05 +02:00
parent 1bdc6e9fb4
commit d700f8a3cf
3 changed files with 122 additions and 106 deletions

View File

@ -1,5 +1,8 @@
use liana::{config::BitcoindConfig, miniscript::bitcoin}; use liana::{
use std::path::Path; config::BitcoindConfig,
miniscript::bitcoin::{self, Network},
};
use std::path::{Path, PathBuf};
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::Mutex; use tokio::sync::Mutex;
@ -11,6 +14,95 @@ use std::os::windows::process::CommandExt;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
const CREATE_NO_WINDOW: u32 = 0x08000000; const CREATE_NO_WINDOW: u32 = 0x08000000;
pub const VERSION: &str = "25.0";
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
pub const SHA256SUM: &str = "5708fc639cdfc27347cccfd50db9b73b53647b36fb5f3a4a93537cbe8828c27f";
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub const SHA256SUM: &str = "33930d432593e49d58a9bff4c30078823e9af5d98594d2935862788ce8a20aec";
#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
pub const SHA256SUM: &str = "7154b35ecc8247589070ae739b7c73c4dee4794bea49eb18dc66faed65b819e7";
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
pub fn download_filename() -> String {
format!("bitcoin-{}-x86_64-apple-darwin.tar.gz", &VERSION)
}
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn download_filename() -> String {
format!("bitcoin-{}-x86_64-linux-gnu.tar.gz", &VERSION)
}
#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
fn download_filename() -> String {
format!("bitcoin-{}-win64.zip", &VERSION)
}
pub fn download_url() -> String {
format!(
"https://bitcoincore.org/bin/bitcoin-core-{}/{}",
&VERSION,
download_filename()
)
}
pub fn internal_bitcoind_directory(liana_datadir: &PathBuf) -> PathBuf {
let mut datadir = PathBuf::from(liana_datadir);
datadir.push("bitcoind");
datadir
}
/// Data directory used by internal bitcoind.
pub fn internal_bitcoind_datadir(liana_datadir: &PathBuf) -> PathBuf {
let mut datadir = internal_bitcoind_directory(liana_datadir);
datadir.push("datadir");
datadir
}
/// Internal bitcoind executable path.
pub fn internal_bitcoind_exe_path(liana_datadir: &PathBuf) -> PathBuf {
internal_bitcoind_directory(liana_datadir)
.join(format!("bitcoin-{}", &VERSION))
.join("bin")
.join(if cfg!(target_os = "windows") {
"bitcoind.exe"
} else {
"bitcoind"
})
}
/// Path of the `bitcoin.conf` file used by internal bitcoind.
pub fn internal_bitcoind_config_path(bitcoind_datadir: &PathBuf) -> PathBuf {
let mut config_path = PathBuf::from(bitcoind_datadir);
config_path.push("bitcoin.conf");
config_path
}
/// Path of the cookie file used by internal bitcoind on a given network.
pub 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);
}
cookie_path.push(".cookie");
cookie_path
}
pub fn bitcoind_network_dir(network: &Network) -> Option<String> {
let dir = match network {
Network::Bitcoin => {
return None;
}
Network::Testnet => "testnet3",
Network::Regtest => "regtest",
Network::Signet => "signet",
_ => panic!("Directory required for this network is unknown."),
};
Some(dir.to_string())
}
/// Possible errors when starting bitcoind. /// Possible errors when starting bitcoind.
#[derive(PartialEq, Eq, Debug, Clone)] #[derive(PartialEq, Eq, Debug, Clone)]
pub enum StartInternalBitcoindError { pub enum StartInternalBitcoindError {
@ -89,7 +181,7 @@ impl Bitcoind {
let mut process = command let mut process = command
.args(&args) .args(&args)
.stdout(std::process::Stdio::piped()) // We still get bitcoind's logs in debug.log. .stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped()) .stderr(std::process::Stdio::piped())
.spawn() .spawn()
.map_err(|e| StartInternalBitcoindError::CommandError(e.to_string()))?; .map_err(|e| StartInternalBitcoindError::CommandError(e.to_string()))?;

View File

@ -252,13 +252,6 @@ pub fn daemon_check(cfg: liana::config::Config) -> Result<(), Error> {
} }
} }
/// Data directory used by internal bitcoind.
pub fn internal_bitcoind_datadir(liana_datadir: &PathBuf) -> PathBuf {
let mut datadir = PathBuf::from(liana_datadir);
datadir.push("bitcoind_datadir");
datadir
}
pub async fn install(ctx: Context, signer: Arc<Mutex<Signer>>) -> Result<PathBuf, Error> { pub async fn install(ctx: Context, signer: Arc<Mutex<Signer>>) -> Result<PathBuf, Error> {
let mut cfg: liana::config::Config = ctx.extract_daemon_config(); let mut cfg: liana::config::Config = ctx.extract_daemon_config();
let data_dir = cfg.data_dir.unwrap(); let data_dir = cfg.data_dir.unwrap();

View File

@ -2,7 +2,7 @@ use std::collections::BTreeMap;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
use std::io::{self, Cursor}; use std::io::{self, Cursor};
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener}; use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener};
use std::path::{Path, PathBuf}; use std::path::PathBuf;
use std::str::FromStr; use std::str::FromStr;
use bitcoin_hashes::{sha256, Hash}; use bitcoin_hashes::{sha256, Hash};
@ -19,11 +19,13 @@ use jsonrpc::{client::Client, simple_http::SimpleHttpTransport};
use liana_ui::{component::form, widget::*}; use liana_ui::{component::form, widget::*};
use crate::{ use crate::{
bitcoind::{Bitcoind, StartInternalBitcoindError}, bitcoind::{
self, bitcoind_network_dir, internal_bitcoind_datadir, internal_bitcoind_directory,
Bitcoind, StartInternalBitcoindError,
},
download, download,
installer::{ installer::{
context::Context, context::Context,
internal_bitcoind_datadir,
message::{self, Message}, message::{self, Message},
step::Step, step::Step,
view, Error, InternalBitcoindExeConfig, view, Error, InternalBitcoindExeConfig,
@ -86,52 +88,17 @@ impl Download {
pub fn subscription(&self) -> Subscription<Message> { pub fn subscription(&self) -> Subscription<Message> {
match self.state { match self.state {
DownloadState::Downloading { .. } => { DownloadState::Downloading { .. } => download::file(self.id, bitcoind::download_url())
download::file(self.id, download_url()).map(|(_, progress)| { .map(|(_, progress)| {
Message::InternalBitcoind(message::InternalBitcoindMsg::DownloadProgressed( Message::InternalBitcoind(message::InternalBitcoindMsg::DownloadProgressed(
progress, progress,
)) ))
}) }),
}
_ => Subscription::none(), _ => Subscription::none(),
} }
} }
} }
const VERSION: &str = "25.0";
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
const SHA256SUM: &str = "5708fc639cdfc27347cccfd50db9b73b53647b36fb5f3a4a93537cbe8828c27f";
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
const SHA256SUM: &str = "33930d432593e49d58a9bff4c30078823e9af5d98594d2935862788ce8a20aec";
#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
const SHA256SUM: &str = "7154b35ecc8247589070ae739b7c73c4dee4794bea49eb18dc66faed65b819e7";
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
fn download_filename() -> String {
format!("bitcoin-{}-x86_64-apple-darwin.tar.gz", &VERSION)
}
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn download_filename() -> String {
format!("bitcoin-{}-x86_64-linux-gnu.tar.gz", &VERSION)
}
#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
fn download_filename() -> String {
format!("bitcoin-{}-win64.zip", &VERSION)
}
fn download_url() -> String {
format!(
"https://bitcoincore.org/bin/bitcoin-core-{}/{}",
&VERSION,
download_filename()
)
}
/// Default prune value used by internal bitcoind. /// Default prune value used by internal bitcoind.
pub const PRUNE_DEFAULT: u32 = 15_000; pub const PRUNE_DEFAULT: u32 = 15_000;
/// Default ports used by bitcoind across all networks. /// Default ports used by bitcoind across all networks.
@ -361,7 +328,7 @@ fn unpack_bitcoind(install_dir: &PathBuf, bytes: &[u8]) -> Result<(), InstallBit
fn verify_hash(bytes: &[u8]) -> bool { fn verify_hash(bytes: &[u8]) -> bool {
let bytes_hash = sha256::Hash::hash(bytes); let bytes_hash = sha256::Hash::hash(bytes);
info!("Download hash: '{}'.", bytes_hash); info!("Download hash: '{}'.", bytes_hash);
let expected_hash = sha256::Hash::from_str(SHA256SUM).expect("This cannot fail."); let expected_hash = sha256::Hash::from_str(bitcoind::SHA256SUM).expect("This cannot fail.");
expected_hash == bytes_hash expected_hash == bytes_hash
} }
@ -373,35 +340,6 @@ fn install_bitcoind(install_dir: &PathBuf, bytes: &[u8]) -> Result<(), InstallBi
unpack_bitcoind(install_dir, bytes) unpack_bitcoind(install_dir, bytes)
} }
/// Internal bitcoind executable path.
fn internal_bitcoind_exe_path(liana_datadir: &PathBuf) -> PathBuf {
PathBuf::from(liana_datadir)
.join(format!("bitcoin-{}", &VERSION))
.join("bin")
.join(if cfg!(target_os = "windows") {
"bitcoind.exe"
} else {
"bitcoind"
})
}
/// Path of the `bitcoin.conf` file used by internal bitcoind.
fn internal_bitcoind_config_path(bitcoind_datadir: &PathBuf) -> PathBuf {
let mut config_path = PathBuf::from(bitcoind_datadir);
config_path.push("bitcoin.conf");
config_path
}
/// Path of the cookie file used by internal bitcoind on a given network.
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);
}
cookie_path.push(".cookie");
cookie_path
}
/// RPC address for internal bitcoind. /// RPC address for internal bitcoind.
fn internal_bitcoind_address(rpc_port: u16) -> SocketAddr { fn internal_bitcoind_address(rpc_port: u16) -> SocketAddr {
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), rpc_port) SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), rpc_port)
@ -426,19 +364,6 @@ fn bitcoind_default_datadir() -> Option<PathBuf> {
None None
} }
fn bitcoind_network_dir(network: &Network) -> Option<String> {
let dir = match network {
Network::Bitcoin => {
return None;
}
Network::Testnet => "testnet3",
Network::Regtest => "regtest",
Network::Signet => "signet",
_ => panic!("Directory required for this network is unknown."),
};
Some(dir.to_string())
}
fn bitcoind_default_cookie_path(network: &Network) -> Option<String> { fn bitcoind_default_cookie_path(network: &Network) -> Option<String> {
if let Some(mut path) = bitcoind_default_datadir() { if let Some(mut path) = bitcoind_default_datadir() {
if let Some(dir) = bitcoind_network_dir(network) { if let Some(dir) = bitcoind_network_dir(network) {
@ -710,8 +635,8 @@ impl InternalBitcoindStep {
impl Step for InternalBitcoindStep { impl Step for InternalBitcoindStep {
fn load_context(&mut self, ctx: &Context) { fn load_context(&mut self, ctx: &Context) {
if self.exe_path.is_none() { if self.exe_path.is_none() {
if internal_bitcoind_exe_path(&ctx.data_dir).exists() { if bitcoind::internal_bitcoind_exe_path(&ctx.data_dir).exists() {
self.exe_path = Some(internal_bitcoind_exe_path(&ctx.data_dir)) self.exe_path = Some(bitcoind::internal_bitcoind_exe_path(&ctx.data_dir))
} else if self.exe_download.is_none() { } else if self.exe_download.is_none() {
self.exe_download = Some(Download::new(0)); self.exe_download = Some(Download::new(0));
}; };
@ -739,7 +664,7 @@ impl Step for InternalBitcoindStep {
} }
message::InternalBitcoindMsg::DefineConfig => { message::InternalBitcoindMsg::DefineConfig => {
let mut conf = match InternalBitcoindConfig::from_file( let mut conf = match InternalBitcoindConfig::from_file(
&internal_bitcoind_config_path(&self.bitcoind_datadir), &bitcoind::internal_bitcoind_config_path(&self.bitcoind_datadir),
) { ) {
Ok(conf) => conf, Ok(conf) => conf,
Err(InternalBitcoindConfigError::FileNotFound) => { Err(InternalBitcoindConfigError::FileNotFound) => {
@ -780,9 +705,9 @@ impl Step for InternalBitcoindStep {
}; };
conf.networks.insert(self.network, network_conf); conf.networks.insert(self.network, network_conf);
} }
if let Err(e) = if let Err(e) = conf.to_file(&bitcoind::internal_bitcoind_config_path(
conf.to_file(&internal_bitcoind_config_path(&self.bitcoind_datadir)) &self.bitcoind_datadir,
{ )) {
self.error = Some(e.to_string()); self.error = Some(e.to_string());
return Command::none(); return Command::none();
}; };
@ -795,7 +720,7 @@ impl Step for InternalBitcoindStep {
message::InternalBitcoindMsg::Download => { message::InternalBitcoindMsg::Download => {
if let Some(download) = &mut self.exe_download { if let Some(download) = &mut self.exe_download {
if let DownloadState::Idle = download.state { if let DownloadState::Idle = download.state {
info!("Downloading bitcoind version {}...", &VERSION); info!("Downloading bitcoind version {}...", &bitcoind::VERSION);
download.start(); download.start();
} }
} }
@ -816,12 +741,16 @@ impl Step for InternalBitcoindStep {
if let DownloadState::Finished(bytes) = &download.state { if let DownloadState::Finished(bytes) = &download.state {
info!("Installing bitcoind..."); info!("Installing bitcoind...");
self.install_state = Some(InstallState::InProgress); self.install_state = Some(InstallState::InProgress);
match install_bitcoind(&self.liana_datadir, bytes) { match install_bitcoind(
&internal_bitcoind_directory(&self.liana_datadir),
bytes,
) {
Ok(_) => { Ok(_) => {
info!("Installation of bitcoind complete."); info!("Installation of bitcoind complete.");
self.install_state = Some(InstallState::Finished); self.install_state = Some(InstallState::Finished);
self.exe_path = self.exe_path = Some(bitcoind::internal_bitcoind_exe_path(
Some(internal_bitcoind_exe_path(&self.liana_datadir)); &self.liana_datadir,
));
return Command::perform(async {}, |_| { return Command::perform(async {}, |_| {
Message::InternalBitcoind( Message::InternalBitcoind(
message::InternalBitcoindMsg::Start, message::InternalBitcoindMsg::Start,
@ -864,8 +793,10 @@ impl Step for InternalBitcoindStep {
return Command::none(); return Command::none();
} }
}; };
let cookie_path = let cookie_path = bitcoind::internal_bitcoind_cookie_path(
internal_bitcoind_cookie_path(&self.bitcoind_datadir, &self.network); &self.bitcoind_datadir,
&self.network,
);
let rpc_port = self let rpc_port = self
.internal_bitcoind_config .internal_bitcoind_config