From 1eb92f7372201552889c86e860a395892027312c Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Tue, 3 Jul 2018 10:09:16 +0300 Subject: [PATCH] Allow specifying custom bitcoind data directory --- src/bin/electrs.rs | 2 +- src/config.rs | 19 ++++++++++++++++++- src/daemon.rs | 27 ++++++++++----------------- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/bin/electrs.rs b/src/bin/electrs.rs index 7b5c1c8..6146052 100644 --- a/src/bin/electrs.rs +++ b/src/bin/electrs.rs @@ -43,7 +43,7 @@ fn run_server(config: &Config) -> Result<()> { let metrics = Metrics::new(config.monitoring_addr); metrics.start(); - let daemon = Daemon::new(config.network_type, &metrics)?; + let daemon = Daemon::new(&config.daemon_dir, config.network_type, &metrics)?; bulk_load( DBStore::open(&config.db_path, StoreOptions { bulk_import: true }), &daemon, diff --git a/src/config.rs b/src/config.rs index 4f31ce1..0fa0f2a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,5 +1,7 @@ use clap::{App, Arg}; +use std::env::home_dir; use std::net::SocketAddr; +use std::path::PathBuf; use stderrlog; use daemon::Network; @@ -9,6 +11,7 @@ pub struct Config { pub log: stderrlog::StdErrLog, pub network_type: Network, // bitcoind JSONRPC endpoint pub db_path: String, // RocksDB directory path + pub daemon_dir: PathBuf, // Bitcoind data directory pub rpc_addr: SocketAddr, // for serving Electrum clients pub monitoring_addr: SocketAddr, // for Prometheus monitoring } @@ -32,7 +35,13 @@ impl Config { Arg::with_name("db_dir") .short("d") .long("db-dir") - .help("Directory to store index database") + .help("Directory to store index database (deafult: ./db/)") + .takes_value(true), + ) + .arg( + Arg::with_name("daemon_dir") + .long("daemon-dir") + .help("Data directory of Bitcoind (default: ~/.bitcoin/)") .takes_value(true), ) .arg( @@ -46,6 +55,13 @@ impl Config { true => Network::Testnet, }; let db_dir = m.value_of("db_dir").unwrap_or("./db"); + let mut daemon_dir = m.value_of("daemon_dir") + .map(|p| PathBuf::from(p)) + .unwrap_or(home_dir().expect("no homedir")); + if let Network::Testnet = network_type { + daemon_dir.push("testnet3"); + } + let mut log = stderrlog::new(); log.verbosity(m.occurrences_of("verbosity") as usize); log.timestamp(if m.is_present("timestamp") { @@ -61,6 +77,7 @@ impl Config { Network::Mainnet => format!("{}/mainnet", db_dir), Network::Testnet => format!("{}/testnet", db_dir), }, + daemon_dir, rpc_addr: match network_type { Network::Mainnet => "127.0.0.1:50001", Network::Testnet => "127.0.0.1:60001", diff --git a/src/daemon.rs b/src/daemon.rs index 436ae7e..6bafe8a 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -8,7 +8,6 @@ use glob; use hex; use serde_json::{from_str, from_value, Value}; use std::collections::HashSet; -use std::env::home_dir; use std::fs; use std::io::{BufRead, BufReader, Lines, Write}; use std::net::{SocketAddr, TcpStream}; @@ -27,17 +26,8 @@ pub enum Network { Testnet, } -fn data_dir(network: Network) -> Result { - let mut path = home_dir().chain_err(|| "could not find home directory")?; - path.push(".bitcoin"); - if let Network::Testnet = network { - path.push("testnet3"); - } - Ok(path) -} - -fn read_cookie(network: Network) -> Result> { - let mut path = data_dir(network)?; +fn read_cookie(daemon_dir: PathBuf) -> Result> { + let mut path = daemon_dir; path.push(".cookie"); fs::read(&path).chain_err(|| format!("failed to read cookie from {:?}", path)) } @@ -122,14 +112,14 @@ struct Connection { } impl Connection { - fn new(addr: SocketAddr, cookie_b64: String) -> Result { + fn new(addr: SocketAddr, daemon_dir: &PathBuf) -> Result { let conn = TcpStream::connect(addr).chain_err(|| format!("failed to connect to {}", addr))?; let reader = BufReader::new(conn.try_clone() .chain_err(|| format!("failed to clone {:?}", conn))?); Ok(Connection { tx: conn, rx: reader.lines(), - cookie_b64, + cookie_b64: base64::encode(&read_cookie(daemon_dir.clone())?), addr, }) } @@ -176,6 +166,7 @@ impl Connection { } pub struct Daemon { + daemon_dir: PathBuf, network: Network, conn: Mutex, @@ -185,16 +176,17 @@ pub struct Daemon { } impl Daemon { - pub fn new(network: Network, metrics: &Metrics) -> Result { + pub fn new(daemon_dir: &PathBuf, network: Network, metrics: &Metrics) -> Result { let addr = match network { Network::Mainnet => "127.0.0.1:8332", Network::Testnet => "127.0.0.1:18332", }; let daemon = Daemon { + daemon_dir: daemon_dir.clone(), network, conn: Mutex::new(Connection::new( SocketAddr::from_str(addr).unwrap(), - base64::encode(&read_cookie(network)?), + &daemon_dir, )?), latency: metrics.histogram_vec( HistogramOpts::new("daemon_rpc", "Bitcoind RPC latency (in seconds)"), @@ -211,6 +203,7 @@ impl Daemon { pub fn reconnect(&self) -> Result { Ok(Daemon { + daemon_dir: self.daemon_dir.clone(), network: self.network, conn: Mutex::new(self.conn.lock().unwrap().reconnect()?), latency: self.latency.clone(), @@ -219,7 +212,7 @@ impl Daemon { } pub fn list_blk_files(&self) -> Result> { - let mut path = data_dir(self.network)?; + let mut path = self.daemon_dir.clone(); path.push("blocks"); path.push("blk*.dat"); Ok(glob::glob(path.to_str().unwrap())