diff --git a/src-tauri/src/cpu_miner.rs b/src-tauri/src/cpu_miner.rs index d9774d5d7..4ccd01f5e 100644 --- a/src-tauri/src/cpu_miner.rs +++ b/src-tauri/src/cpu_miner.rs @@ -1,5 +1,6 @@ use crate::app_config::MiningMode; use crate::mm_proxy_manager::MmProxyManager; +use crate::process_adapter::ProcessAdapter; use crate::xmrig::http_api::XmrigHttpApiClient; use crate::xmrig_adapter::{XmrigAdapter, XmrigNodeConnection}; use crate::{ @@ -77,15 +78,16 @@ impl CpuMiner { MiningMode::Eco => 30, MiningMode::Ludicrous => 100, }; - let xmrig = XmrigAdapter::new(xmrig_node_connection, "44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A".to_string() ); - let (mut _rx, mut xmrig_child, client) = xmrig.spawn( + let xmrig = XmrigAdapter::new( + xmrig_node_connection, + "44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A".to_string(), cache_dir, log_dir, - base_path, progress_tracker, cpu_max_percentage, - )?; - self.api_client = Some(client); + ); + let (mut xmrig_child, _xmrig_status_monitor) = xmrig.spawn_inner(base_path.clone())?; + self.api_client = Some(xmrig.client); self.watcher_task = Some(tauri::async_runtime::spawn(async move { println!("Starting process"); diff --git a/src-tauri/src/xmrig_adapter.rs b/src-tauri/src/xmrig_adapter.rs index 1eff61d67..1c785258a 100644 --- a/src-tauri/src/xmrig_adapter.rs +++ b/src-tauri/src/xmrig_adapter.rs @@ -39,83 +39,45 @@ pub struct XmrigAdapter { force_download: bool, node_connection: XmrigNodeConnection, monero_address: String, - // TODO: secure http_api_token: String, http_api_port: u16, + cache_dir: PathBuf, + logs_dir: PathBuf, + cpu_max_percentage: u16, + progress_tracker: ProgressTracker, + rx: Receiver, + pub client: XmrigHttpApiClient, + // TODO: secure } impl XmrigAdapter { - pub fn new(xmrig_node_connection: XmrigNodeConnection, monero_address: String) -> Self { - Self { - force_download: false, - node_connection: xmrig_node_connection, - monero_address, - http_api_token: "pass".to_string(), - http_api_port: 9090, - } - } - pub fn spawn( - &self, + pub fn new( + xmrig_node_connection: XmrigNodeConnection, + monero_address: String, cache_dir: PathBuf, logs_dir: PathBuf, - data_dir: PathBuf, progress_tracker: ProgressTracker, cpu_max_percentage: u16, - ) -> Result<(Receiver, ProcessInstance, XmrigHttpApiClient), anyhow::Error> { - let (instance, _) = self.spawn_inner(data_dir.clone())?; - let mut process_instance = instance; + ) -> Self { let (_tx, rx) = tokio::sync::mpsc::channel(100); - let force_download = self.force_download; - let xmrig_shutdown = Shutdown::new(); - let mut shutdown_signal = xmrig_shutdown.to_signal(); - let mut args = self.node_connection.generate_args(); - let xmrig_log_file = logs_dir.join("xmrig.log"); - std::fs::create_dir_all(xmrig_log_file.parent().unwrap())?; - args.push(format!("--log-file={}", &xmrig_log_file.to_str().unwrap())); - args.push(format!("--http-port={}", self.http_api_port)); - args.push(format!("--http-access-token={}", self.http_api_token)); - args.push(format!("--donate-level=1")); - args.push(format!("--user={}", self.monero_address)); - args.push(format!("--cpu-max-threads-hint={}", cpu_max_percentage)); - - let client = XmrigHttpApiClient::new( - format!("http://127.0.0.1:{}", self.http_api_port), - self.http_api_token.clone(), - ); - - process_instance.handle = Some(tokio::spawn(async move { - // TODO: Ensure version string is not malicious - let version = - Self::ensure_latest(cache_dir.clone(), force_download, progress_tracker).await?; - let xmrig_dir = cache_dir - .join("xmrig") - .join(&version) - .join(format!("xmrig-{}", version)); - let xmrig_bin = xmrig_dir.join("xmrig"); - let mut xmrig = tokio::process::Command::new(xmrig_bin) - .args(args) - .kill_on_drop(true) - .spawn()?; - - if let Some(id) = xmrig.id() { - std::fs::write(data_dir.join("xmrig_pid"), id.to_string())?; - } - shutdown_signal.wait().await; - println!("Stopping xmrig"); - - xmrig.kill().await?; - - match std::fs::remove_file(data_dir.join("xmrig_pid")) { - Ok(_) => {} - Err(e) => { - warn!(target: LOG_TARGET, "Could not clear xmrig's pid file {:?}", e); - } - } - - Ok(()) - })); - - Ok((rx, process_instance, client)) + let http_api_port = 9090; + let http_api_token = "pass".to_string(); + Self { + force_download: false, + node_connection: xmrig_node_connection, + monero_address, + http_api_token: http_api_token.clone(), + http_api_port: http_api_port.clone(), + cache_dir, + logs_dir, + cpu_max_percentage, + progress_tracker, + rx, + client: XmrigHttpApiClient::new( + format!("http://127.0.0.1:{}", http_api_port).clone(), + http_api_token.clone(), + ), + } } pub async fn ensure_latest( @@ -170,15 +132,70 @@ impl ProcessAdapter for XmrigAdapter { fn spawn_inner( &self, - base_folder: PathBuf, + data_dir: PathBuf, ) -> Result<(ProcessInstance, Self::StatusMonitor), anyhow::Error> { - self.kill_previous_instances(base_folder.clone())?; - let instance = ProcessInstance { - shutdown: Shutdown::new(), - handle: None, - }; + self.kill_previous_instances(data_dir.clone())?; + + let cache_dir = self.cache_dir.clone(); + let progress_tracker = self.progress_tracker.clone(); + let force_download = self.force_download; + let xmrig_shutdown = Shutdown::new(); + let mut shutdown_signal = xmrig_shutdown.to_signal(); + let mut args = self.node_connection.generate_args(); + let xmrig_log_file = self.logs_dir.join("xmrig.log"); + std::fs::create_dir_all(xmrig_log_file.parent().unwrap())?; + args.push(format!("--log-file={}", &xmrig_log_file.to_str().unwrap())); + args.push(format!("--http-port={}", self.http_api_port)); + args.push(format!("--http-access-token={}", self.http_api_token)); + args.push(format!("--donate-level=1")); + args.push(format!("--user={}", self.monero_address)); + args.push(format!( + "--cpu-max-threads-hint={}", + self.cpu_max_percentage + )); + + Ok(( + ProcessInstance { + shutdown: xmrig_shutdown, + handle: Some(tokio::spawn(async move { + // TODO: Ensure version string is not malicious + let version = Self::ensure_latest( + cache_dir.clone(), + force_download, + progress_tracker.clone(), + ) + .await?; + let xmrig_dir = cache_dir + .clone() + .join("xmrig") + .join(&version) + .join(format!("xmrig-{}", version)); + let xmrig_bin = xmrig_dir.join("xmrig"); + let mut xmrig = tokio::process::Command::new(xmrig_bin) + .args(args) + .kill_on_drop(true) + .spawn()?; + + if let Some(id) = xmrig.id() { + std::fs::write(data_dir.join("xmrig_pid"), id.to_string())?; + } + shutdown_signal.wait().await; + println!("Stopping xmrig"); + + xmrig.kill().await?; + + match std::fs::remove_file(data_dir.join("xmrig_pid")) { + Ok(_) => {} + Err(e) => { + warn!(target: LOG_TARGET, "Could not clear xmrig's pid file - {e}"); + } + } - Ok((instance, XmrigStatusMonitor {})) + Ok(()) + })), + }, + XmrigStatusMonitor {}, + )) } fn name(&self) -> &str {