diff --git a/.gitignore b/.gitignore index 08666063a4..241c3a428f 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ target .vscode/ *.code-workspace tags +null # Ignore OS files .DS_Store diff --git a/Cargo.lock b/Cargo.lock index 735a43318c..f0a1537756 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7303,7 +7303,6 @@ dependencies = [ "rand", "tari_common", "tari_p2p", - "tempfile", "tor-hash-passwd", ] diff --git a/applications/minotari_console_wallet/src/cli.rs b/applications/minotari_console_wallet/src/cli.rs index fd81288c88..45be632dcf 100644 --- a/applications/minotari_console_wallet/src/cli.rs +++ b/applications/minotari_console_wallet/src/cli.rs @@ -94,6 +94,9 @@ pub struct Cli { pub view_private_key: Option, #[clap(long)] pub spend_key: Option, + /// Path to the libtor data directory + #[clap(short, long, parse(from_os_str))] + pub libtor_data_dir: Option, } impl ConfigOverrideProvider for Cli { diff --git a/applications/minotari_console_wallet/src/lib.rs b/applications/minotari_console_wallet/src/lib.rs index ce4aa9722e..4eaca951cf 100644 --- a/applications/minotari_console_wallet/src/lib.rs +++ b/applications/minotari_console_wallet/src/lib.rs @@ -33,7 +33,6 @@ mod recovery; mod ui; mod utils; mod wallet_modes; - pub use cli::{ BurnMinotariArgs, Cli, @@ -108,6 +107,7 @@ pub fn run_wallet(shutdown: &mut Shutdown, runtime: Runtime, config: &mut Applic profile_with_tokio_console: false, view_private_key: None, spend_key: None, + libtor_data_dir: None, }; run_wallet_with_cli(shutdown, runtime, config, cli) @@ -165,7 +165,12 @@ pub fn run_wallet_with_cli( // This is currently only possible on linux/macos #[cfg(all(unix, feature = "libtor"))] if config.wallet.use_libtor && config.wallet.p2p.transport.is_tor() { - let tor = Tor::initialize()?; + let data_dir = if let Some(dir) = cli.libtor_data_dir.clone() { + dir.join("libtor").join("wallet") + } else { + cli.common.get_base_path().join("libtor").join("wallet") + }; + let tor = Tor::initialize(data_dir)?; tor.update_comms_transport(&mut config.wallet.p2p.transport)?; tor.run_background(); debug!( @@ -265,6 +270,7 @@ pub fn run_wallet_with_cli( print!("\nShutting down wallet... "); shutdown.trigger(); runtime.block_on(wallet.wait_until_shutdown()); + println!("Done."); result diff --git a/applications/minotari_node/src/cli.rs b/applications/minotari_node/src/cli.rs index 091f621f86..3c805948d6 100644 --- a/applications/minotari_node/src/cli.rs +++ b/applications/minotari_node/src/cli.rs @@ -20,6 +20,8 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +use std::path::PathBuf; + use clap::Parser; use minotari_app_utilities::common_cli_args::CommonCliArgs; use tari_common::configuration::{ConfigOverrideProvider, Network}; @@ -58,6 +60,9 @@ pub struct Cli { /// Disable the splash screen #[clap(long)] pub disable_splash_screen: bool, + /// Path to the libtor data directory + #[clap(short, long, parse(from_os_str))] + pub libtor_data_dir: Option, } impl ConfigOverrideProvider for Cli { diff --git a/applications/minotari_node/src/commands/command/test_peer_liveness.rs b/applications/minotari_node/src/commands/command/test_peer_liveness.rs index bda5c3a30a..b933cf8916 100644 --- a/applications/minotari_node/src/commands/command/test_peer_liveness.rs +++ b/applications/minotari_node/src/commands/command/test_peer_liveness.rs @@ -119,6 +119,7 @@ impl HandleCommand for CommandContext { } // Wait for the liveness test to complete + let mut count = 0; loop { tokio::select! { _ = rx.changed() => { @@ -153,7 +154,20 @@ impl HandleCommand for CommandContext { break; }, - _ = tokio::time::sleep(Duration::from_secs(1)) => {}, + _ = tokio::time::sleep(Duration::from_secs(1)) => { + count += 1; + if count >= 180 { + if let Some(true) = args.exit { + println!(" >> The liveness test failed to complete and base node will now exit\n"); + self.shutdown.trigger(); + tokio::time::sleep(Duration::from_secs(1)).await; + process::exit(1) + } else { + println!(" >> The liveness test failed to complete\n"); + break; + } + } + }, } } diff --git a/applications/minotari_node/src/lib.rs b/applications/minotari_node/src/lib.rs index 726ae11a57..9b2d11f844 100644 --- a/applications/minotari_node/src/lib.rs +++ b/applications/minotari_node/src/lib.rs @@ -92,6 +92,7 @@ pub async fn run_base_node( mining_enabled: false, second_layer_grpc_enabled: false, disable_splash_screen: false, + libtor_data_dir: None, }; run_base_node_with_cli(node_identity, config, cli, shutdown).await @@ -169,7 +170,6 @@ pub async fn run_base_node_with_cli( info!(target: LOG_TARGET, "Minotari base node has STARTED"); main_loop.cli_loop(cli.disable_splash_screen).await; - ctx.wait_for_shutdown().await; println!("Goodbye!"); diff --git a/applications/minotari_node/src/main.rs b/applications/minotari_node/src/main.rs index 3f76c71abd..272ad865bc 100644 --- a/applications/minotari_node/src/main.rs +++ b/applications/minotari_node/src/main.rs @@ -152,7 +152,12 @@ fn main_inner() -> Result<(), ExitError> { // This is currently only possible on linux/macos #[cfg(all(unix, feature = "libtor"))] if config.base_node.use_libtor && config.base_node.p2p.transport.is_tor() { - let tor = Tor::initialize()?; + let data_dir = if let Some(dir) = cli.libtor_data_dir.clone() { + dir.join("libtor").join("base_node") + } else { + cli.common.get_base_path().join("libtor").join("base_node") + }; + let tor = Tor::initialize(data_dir)?; tor.update_comms_transport(&mut config.base_node.p2p.transport)?; tor.run_background(); debug!( diff --git a/infrastructure/libtor/Cargo.toml b/infrastructure/libtor/Cargo.toml index 8c9fe89781..795dcdb78f 100644 --- a/infrastructure/libtor/Cargo.toml +++ b/infrastructure/libtor/Cargo.toml @@ -11,7 +11,6 @@ tari_p2p = { path = "../../base_layer/p2p" } derivative = "2.2.0" log = "0.4.8" rand = "0.8" -tempfile = "3.1.0" tor-hash-passwd = "1.0.1" [target.'cfg(unix)'.dependencies] diff --git a/infrastructure/libtor/src/tor.rs b/infrastructure/libtor/src/tor.rs index 218e6f1928..f427cd33fe 100644 --- a/infrastructure/libtor/src/tor.rs +++ b/infrastructure/libtor/src/tor.rs @@ -20,7 +20,7 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use std::{fmt, io, net::TcpListener, path::PathBuf, thread}; +use std::{fmt, fs, io, net::TcpListener, path::PathBuf, thread}; use derivative::Derivative; use libtor::{LogDestination, LogLevel, TorFlag}; @@ -28,7 +28,6 @@ use log::*; use rand::{distributions::Alphanumeric, thread_rng, Rng}; use tari_common::exit_codes::{ExitCode, ExitError}; use tari_p2p::{TorControlAuthentication, TransportConfig, TransportType}; -use tempfile::{tempdir, NamedTempFile, TempDir, TempPath}; use tor_hash_passwd::EncryptedKey; const LOG_TARGET: &str = "tari_libtor"; @@ -46,13 +45,11 @@ impl fmt::Debug for TorPassword { pub struct Tor { control_port: u16, data_dir: PathBuf, - log_destination: String, + log_destination: PathBuf, log_level: LogLevel, #[derivative(Debug = "ignore")] passphrase: TorPassword, socks_port: u16, - temp_dir: Option, - temp_file: Option, } impl Default for Tor { @@ -64,8 +61,6 @@ impl Default for Tor { log_level: LogLevel::Err, passphrase: TorPassword(None), socks_port: 0, - temp_dir: None, - temp_file: None, } } } @@ -76,7 +71,7 @@ impl Tor { /// Two TCP ports will be provided by the operating system. /// These ports are used for the control and socks ports, the onion address and port info are still loaded from the /// node identity file. - pub fn initialize() -> Result { + pub fn initialize(data_dir: PathBuf) -> Result { debug!(target: LOG_TARGET, "Initializing libtor"); let mut instance = Tor::default(); @@ -95,15 +90,33 @@ impl Tor { instance.passphrase = TorPassword(Some(passphrase)); // data dir - let temp = tempdir()?; - instance.data_dir = temp.path().to_path_buf(); - instance.temp_dir = Some(temp); + instance.data_dir = data_dir.join("data"); + + let exists = fs::exists(instance.data_dir.clone()).map_err(|e| { + ExitError::new( + ExitCode::InputError, + format!( + "Could not verify libtor data directory: {} ({})", + instance.data_dir.display(), + e + ), + ) + })?; + if !exists { + fs::create_dir_all(&instance.data_dir).map_err(|e| { + ExitError::new( + ExitCode::InputError, + format!( + "Could not create libtor data directory: {} ({})", + instance.data_dir.display(), + e + ), + ) + })?; + } // log destination - let temp = NamedTempFile::new()?.into_temp_path(); - let file = temp.to_string_lossy().to_string(); - instance.temp_file = Some(temp); - instance.log_destination = file; + instance.log_destination = data_dir.join("tor.log"); debug!(target: LOG_TARGET, "tor instance: {:?}", instance); Ok(instance) @@ -152,7 +165,7 @@ impl Tor { // Write the final control port to a file. This could be used to configure the node to use this port when auto is set. .flag(TorFlag::ControlPortWriteToFile(data_dir.join("control_port").to_string_lossy().to_string())) .flag(TorFlag::Hush()) - .flag(TorFlag::LogTo(log_level, LogDestination::File(log_destination))); + .flag(TorFlag::LogTo(log_level, LogDestination::File(log_destination.to_string_lossy().to_string()))); if socks_port == 0 { tor.flag(TorFlag::SocksPortAuto); diff --git a/integration_tests/src/wallet_process.rs b/integration_tests/src/wallet_process.rs index 2e3fcea656..464508a9f3 100644 --- a/integration_tests/src/wallet_process.rs +++ b/integration_tests/src/wallet_process.rs @@ -235,6 +235,7 @@ pub fn get_default_cli() -> Cli { profile_with_tokio_console: false, view_private_key: None, spend_key: None, + libtor_data_dir: None, } }