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 std::path::Path;
use liana::{
config::BitcoindConfig,
miniscript::bitcoin::{self, Network},
};
use std::path::{Path, PathBuf};
use std::sync::Arc;
use tokio::sync::Mutex;
@ -11,6 +14,95 @@ use std::os::windows::process::CommandExt;
#[cfg(target_os = "windows")]
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.
#[derive(PartialEq, Eq, Debug, Clone)]
pub enum StartInternalBitcoindError {
@ -89,7 +181,7 @@ impl Bitcoind {
let mut process = command
.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())
.spawn()
.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> {
let mut cfg: liana::config::Config = ctx.extract_daemon_config();
let data_dir = cfg.data_dir.unwrap();

View File

@ -2,7 +2,7 @@ use std::collections::BTreeMap;
#[cfg(target_os = "windows")]
use std::io::{self, Cursor};
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener};
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use std::str::FromStr;
use bitcoin_hashes::{sha256, Hash};
@ -19,11 +19,13 @@ use jsonrpc::{client::Client, simple_http::SimpleHttpTransport};
use liana_ui::{component::form, widget::*};
use crate::{
bitcoind::{Bitcoind, StartInternalBitcoindError},
bitcoind::{
self, bitcoind_network_dir, internal_bitcoind_datadir, internal_bitcoind_directory,
Bitcoind, StartInternalBitcoindError,
},
download,
installer::{
context::Context,
internal_bitcoind_datadir,
message::{self, Message},
step::Step,
view, Error, InternalBitcoindExeConfig,
@ -86,52 +88,17 @@ impl Download {
pub fn subscription(&self) -> Subscription<Message> {
match self.state {
DownloadState::Downloading { .. } => {
download::file(self.id, download_url()).map(|(_, progress)| {
DownloadState::Downloading { .. } => download::file(self.id, bitcoind::download_url())
.map(|(_, progress)| {
Message::InternalBitcoind(message::InternalBitcoindMsg::DownloadProgressed(
progress,
))
})
}
}),
_ => 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.
pub const PRUNE_DEFAULT: u32 = 15_000;
/// 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 {
let bytes_hash = sha256::Hash::hash(bytes);
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
}
@ -373,35 +340,6 @@ fn install_bitcoind(install_dir: &PathBuf, bytes: &[u8]) -> Result<(), InstallBi
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.
fn internal_bitcoind_address(rpc_port: u16) -> SocketAddr {
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), rpc_port)
@ -426,19 +364,6 @@ fn bitcoind_default_datadir() -> Option<PathBuf> {
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> {
if let Some(mut path) = bitcoind_default_datadir() {
if let Some(dir) = bitcoind_network_dir(network) {
@ -710,8 +635,8 @@ impl InternalBitcoindStep {
impl Step for InternalBitcoindStep {
fn load_context(&mut self, ctx: &Context) {
if self.exe_path.is_none() {
if internal_bitcoind_exe_path(&ctx.data_dir).exists() {
self.exe_path = Some(internal_bitcoind_exe_path(&ctx.data_dir))
if bitcoind::internal_bitcoind_exe_path(&ctx.data_dir).exists() {
self.exe_path = Some(bitcoind::internal_bitcoind_exe_path(&ctx.data_dir))
} else if self.exe_download.is_none() {
self.exe_download = Some(Download::new(0));
};
@ -739,7 +664,7 @@ impl Step for InternalBitcoindStep {
}
message::InternalBitcoindMsg::DefineConfig => {
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,
Err(InternalBitcoindConfigError::FileNotFound) => {
@ -780,9 +705,9 @@ impl Step for InternalBitcoindStep {
};
conf.networks.insert(self.network, network_conf);
}
if let Err(e) =
conf.to_file(&internal_bitcoind_config_path(&self.bitcoind_datadir))
{
if let Err(e) = conf.to_file(&bitcoind::internal_bitcoind_config_path(
&self.bitcoind_datadir,
)) {
self.error = Some(e.to_string());
return Command::none();
};
@ -795,7 +720,7 @@ impl Step for InternalBitcoindStep {
message::InternalBitcoindMsg::Download => {
if let Some(download) = &mut self.exe_download {
if let DownloadState::Idle = download.state {
info!("Downloading bitcoind version {}...", &VERSION);
info!("Downloading bitcoind version {}...", &bitcoind::VERSION);
download.start();
}
}
@ -816,12 +741,16 @@ impl Step for InternalBitcoindStep {
if let DownloadState::Finished(bytes) = &download.state {
info!("Installing bitcoind...");
self.install_state = Some(InstallState::InProgress);
match install_bitcoind(&self.liana_datadir, bytes) {
match install_bitcoind(
&internal_bitcoind_directory(&self.liana_datadir),
bytes,
) {
Ok(_) => {
info!("Installation of bitcoind complete.");
self.install_state = Some(InstallState::Finished);
self.exe_path =
Some(internal_bitcoind_exe_path(&self.liana_datadir));
self.exe_path = Some(bitcoind::internal_bitcoind_exe_path(
&self.liana_datadir,
));
return Command::perform(async {}, |_| {
Message::InternalBitcoind(
message::InternalBitcoindMsg::Start,
@ -864,8 +793,10 @@ impl Step for InternalBitcoindStep {
return Command::none();
}
};
let cookie_path =
internal_bitcoind_cookie_path(&self.bitcoind_datadir, &self.network);
let cookie_path = bitcoind::internal_bitcoind_cookie_path(
&self.bitcoind_datadir,
&self.network,
);
let rpc_port = self
.internal_bitcoind_config