diff --git a/public/locales/af/settings.json b/public/locales/af/settings.json index 38a0d53e1..f36ee2ccb 100644 --- a/public/locales/af/settings.json +++ b/public/locales/af/settings.json @@ -16,6 +16,7 @@ }, "last-block-added-time": "Tyd toe laaste blok by ketting gevoeg was", "visual-mode": "Visuele modus", + "randomX-miner": "RandomX mynwerker", "gpu-unavailable": "⚠️ GPU gedeaktiveer omdat jou hardeware dit nie ondersteun nie", "reset-settings": "Reset Settings", "reset-permanently": "Are you sure you want to reset all settings permanently?", diff --git a/public/locales/af/setup-view.json b/public/locales/af/setup-view.json index 2a4ae6c65..e352442d0 100644 --- a/public/locales/af/setup-view.json +++ b/public/locales/af/setup-view.json @@ -10,6 +10,7 @@ "checking-latest-version-wallet": "Bepaal nuutste weergawe van beursie", "checking-latest-version-xmrig": "Bepaal nuutste weergawe van xmrig", "checking-latest-version-sha-p2pool": "Bepaal nuutste weergawe van sha-p2pool", + "checking-latest-version-clythor": "Bepaal nuutste weergawe van clythor", "waiting-for-wallet": "Wag vir beursie", "waiting-for-node": "Wag vir node om te sinkroniseer", "preparing-for-initial-sync": "Gekoppel aan netwerk nodes {{initial_connected_peers}}/{{required_peers}}", diff --git a/public/locales/cn/settings.json b/public/locales/cn/settings.json index 5e295f635..d274b0157 100644 --- a/public/locales/cn/settings.json +++ b/public/locales/cn/settings.json @@ -44,6 +44,7 @@ "reset-wallet": "Reset wallet", "experimental-title": "实验性功能", "experimental-warning": "⚠️ 警告:这些功能正在积极开发中,可能会表现得不可预测。请谨慎操作。", + "randomX-miner": "RandomX 挖矿", "connected-to-tari": "Connected to the Tari Network", "not-connected-to-tari": "Not connected to the Tari Network", "connected-peers": "Connected Peers", diff --git a/public/locales/cn/setup-view.json b/public/locales/cn/setup-view.json index aa1aa5ff1..53b0ff6d1 100644 --- a/public/locales/cn/setup-view.json +++ b/public/locales/cn/setup-view.json @@ -10,6 +10,7 @@ "checking-latest-version-wallet": "正在检查钱包的最新版本", "checking-latest-version-xmrig": "正在检查 xmrig 的最新版本", "checking-latest-version-sha-p2pool": "正在检查 sha-p2pool 的最新版本", + "checking-latest-version-clythor": "正在检查clythor的最新版本", "waiting-for-wallet": "等待钱包", "waiting-for-node": "等待节点同步", "preparing-for-initial-sync": "连接到网络节点 {{initial_connected_peers}}/{{required_peers}}", @@ -25,4 +26,4 @@ "would-you-like-to-install": "您想现在安装 Tari Universe {{version}} 吗?", "yes": "是", "no": "否" -} \ No newline at end of file +} diff --git a/public/locales/en/settings.json b/public/locales/en/settings.json index 0b46cc99c..f15908757 100644 --- a/public/locales/en/settings.json +++ b/public/locales/en/settings.json @@ -50,6 +50,7 @@ "reset-permanently": "Are you sure you want to reset all settings permanently?", "reset-wallet": "Reset wallet", "experimental-title": "Experimental Features", + "randomX-miner": "RandomX miner", "experimental-warning": "⚠️ Warning: These features are under active development and could behave unpredictably. Please proceed carefully.", "connected-to-tari": "Connected to the Tari Network", "not-connected-to-tari": "Not connected to the Tari Network", diff --git a/public/locales/en/setup-view.json b/public/locales/en/setup-view.json index dc376abf0..0383afb7f 100644 --- a/public/locales/en/setup-view.json +++ b/public/locales/en/setup-view.json @@ -10,6 +10,7 @@ "checking-latest-version-wallet": "Checking for latest version of wallet", "checking-latest-version-xmrig": "Checking for latest version of xmrig", "checking-latest-version-sha-p2pool": "Checking for latest version of sha-p2pool", + "checking-latest-version-clythor": "Checking for latest version of clythor", "waiting-for-wallet": "Waiting for wallet", "waiting-for-node": "Waiting for node to sync", "preparing-for-initial-sync": "Connecting to network peers {{initial_connected_peers}}/{{required_peers}}", @@ -25,4 +26,4 @@ "would-you-like-to-install": "Would you like to install Tari Universe {{version}} now?", "yes": "Yes", "no": "No" -} \ No newline at end of file +} diff --git a/public/locales/pl/settings.json b/public/locales/pl/settings.json index 96605f7bb..bdbc6498e 100644 --- a/public/locales/pl/settings.json +++ b/public/locales/pl/settings.json @@ -28,6 +28,7 @@ "reset-permanently": "Czy na pewno chcesz trwale zresetować ustawienia?", "gpu-unavailable": "⚠️ Kopanie GPU niedostępne ponieważ Twój sprzęt go nie obsługuje", "reset-wallet": "Resetuj porfel", + "randomX-miner": "Miner RandomX", "connected-to-tari-network": "Połączono z siecią Tari", "not-connected-to-tari-network": "Brak połączenia z siecią Tari", "connected-peers": "Połączone węzły", diff --git a/public/locales/pl/setup-view.json b/public/locales/pl/setup-view.json index 39060c0dd..a6aaf36c0 100644 --- a/public/locales/pl/setup-view.json +++ b/public/locales/pl/setup-view.json @@ -10,6 +10,7 @@ "checking-latest-version-wallet": "Sprawdzanie najnowszej wersji portfela", "checking-latest-version-xmrig": "Sprawdzanie najnowszej wersji xmrig", "checking-latest-version-sha-p2pool": "Sprawdzanie najnowszej wersji sha-p2pool", + "checking-latest-version-clythor": "Sprawdzanie najnowszej wersji clythor", "waiting-for-wallet": "Oczekiwanie na portfel", "waiting-for-node": "Oczekiwanie na synchronizację węzła", "preparing-for-initial-sync": "Łączenie się z urządzeniami równorzędnymi w sieci {{initial_connected_peers}}/{{required_peers}}", diff --git a/public/locales/tr/settings.json b/public/locales/tr/settings.json index 9ced4fab4..7a3a768d1 100644 --- a/public/locales/tr/settings.json +++ b/public/locales/tr/settings.json @@ -44,9 +44,10 @@ "reset-permanently": "Tüm ayarları kalıcı olarak sıfırlamak istediğinizden emin misiniz?", "reset-wallet": "Reset wallet", "experimental-title": "Deneysel Özellikler", + "randomX-miner": "RandomX madencisi", "experimental-warning": "⚠️ Uyarı: Bu özellikler aktif geliştirme aşamasındadır ve öngörülemeyen şekilde davranabilir. Lütfen dikkatlice ilerleyin.", "connected-to-tari": "Connected to the Tari Network", "not-connected-to-tari": "Not connected to the Tari Network", "connected-peers": "Connected Peers", "should-use-system-language": "Use system language" -} \ No newline at end of file +} diff --git a/public/locales/tr/setup-view.json b/public/locales/tr/setup-view.json index a46d356b4..99ca5a29f 100644 --- a/public/locales/tr/setup-view.json +++ b/public/locales/tr/setup-view.json @@ -10,6 +10,7 @@ "checking-latest-version-wallet": "Cüzdanın en son sürümü kontrol ediliyor", "checking-latest-version-xmrig": "xmrig'in en son sürümü kontrol ediliyor", "checking-latest-version-sha-p2pool": "sha-p2pool'un en son sürümü kontrol ediliyor", + "checking-latest-version-clythor": "clythor'un en son sürümü kontrol ediliyor", "waiting-for-wallet": "Cüzdan bekleniyor", "waiting-for-node": "Düğümün senkronize edilmesi bekleniyor", "preparing-for-initial-sync": "İlk senkronizasyon için hazırlanıyor {{initial_connected_peers}}/{{required_peers}}", @@ -25,4 +26,4 @@ "would-you-like-to-install": "Tari Universe'ü şimdi yüklemek ister misiniz {{version}} ?", "yes": "Evet", "no": "Hayır" -} \ No newline at end of file +} diff --git a/src-tauri/src/app_config.rs b/src-tauri/src/app_config.rs index 7db585ddb..e9d976f3c 100644 --- a/src-tauri/src/app_config.rs +++ b/src-tauri/src/app_config.rs @@ -6,7 +6,9 @@ use log::{debug, info, warn}; use serde::{Deserialize, Serialize}; use tokio::fs; -use crate::{consts::DEFAULT_MONERO_ADDRESS, internal_wallet::generate_password}; +use crate::{ + consts::DEFAULT_MONERO_ADDRESS, cpu_miner::RandomXMiner, internal_wallet::generate_password, +}; const LOG_TARGET: &str = "tari::universe::app_config"; @@ -33,6 +35,8 @@ pub struct AppConfigFromFile { gpu_mining_enabled: bool, #[serde(default = "default_true")] cpu_mining_enabled: bool, + #[serde(default = "default_randomx_miner")] + randomx_miner: RandomXMiner, #[serde(default = "default_false")] has_system_language_been_proposed: bool, #[serde(default = "default_false")] @@ -54,6 +58,7 @@ impl Default for AppConfigFromFile { monero_address: default_monero_address(), gpu_mining_enabled: true, cpu_mining_enabled: true, + randomx_miner: default_randomx_miner(), has_system_language_been_proposed: false, should_always_use_system_language: false, application_language: default_application_language(), @@ -98,6 +103,7 @@ pub(crate) struct AppConfig { monero_address: String, gpu_mining_enabled: bool, cpu_mining_enabled: bool, + randomx_miner: RandomXMiner, has_system_language_been_proposed: bool, should_always_use_system_language: bool, application_language: String, @@ -117,6 +123,7 @@ impl AppConfig { monero_address: DEFAULT_MONERO_ADDRESS.to_string(), gpu_mining_enabled: true, cpu_mining_enabled: true, + randomx_miner: RandomXMiner::Clythor, has_system_language_been_proposed: false, should_always_use_system_language: false, application_language: default_application_language(), @@ -152,6 +159,7 @@ impl AppConfig { self.monero_address = config.monero_address; self.gpu_mining_enabled = config.gpu_mining_enabled; self.cpu_mining_enabled = config.cpu_mining_enabled; + self.randomx_miner = config.randomx_miner; self.has_system_language_been_proposed = config.has_system_language_been_proposed; self.should_always_use_system_language = config.should_always_use_system_language; self.application_language = config.application_language; @@ -257,6 +265,15 @@ impl AppConfig { Ok(()) } + pub fn randomx_miner(&self) -> RandomXMiner { + self.randomx_miner + } + + pub async fn set_randomx_miner(&mut self, miner: RandomXMiner) -> Result<(), anyhow::Error> { + self.randomx_miner = miner; + self.update_config_file().await?; + Ok(()) + } pub fn application_language(&self) -> &str { &self.application_language } @@ -310,6 +327,7 @@ impl AppConfig { monero_address: self.monero_address.clone(), gpu_mining_enabled: self.gpu_mining_enabled, cpu_mining_enabled: self.cpu_mining_enabled, + randomx_miner: self.randomx_miner, has_system_language_been_proposed: self.has_system_language_been_proposed, should_always_use_system_language: self.should_always_use_system_language, application_language: self.application_language.clone(), @@ -351,6 +369,10 @@ fn default_monero_address() -> String { DEFAULT_MONERO_ADDRESS.to_string() } +fn default_randomx_miner() -> RandomXMiner { + RandomXMiner::Clythor +} + fn default_application_language() -> String { "en".to_string() } diff --git a/src-tauri/src/binaries/binaries_list.rs b/src-tauri/src/binaries/binaries_list.rs index 18bb3ab34..95315b60e 100644 --- a/src-tauri/src/binaries/binaries_list.rs +++ b/src-tauri/src/binaries/binaries_list.rs @@ -10,6 +10,7 @@ pub enum Binaries { Wallet, ShaP2pool, GpuMiner, + Clythor, } impl Binaries { @@ -21,6 +22,7 @@ impl Binaries { Binaries::Wallet => "wallet", Binaries::ShaP2pool => "sha-p2pool", Binaries::GpuMiner => "xtrgpuminer", + Binaries::Clythor => "clythor", } } @@ -32,6 +34,7 @@ impl Binaries { "wallet" => Some(Binaries::Wallet), "sha-p2pool" => Some(Binaries::ShaP2pool), "xtrgpuminer" => Some(Binaries::GpuMiner), + "clythor" => Some(Binaries::Clythor), _ => None, } } @@ -62,6 +65,10 @@ impl Binaries { let file_name = "xtrgpuminer"; PathBuf::from(file_name) } + Binaries::Clythor => { + let file_name = "clythor"; + PathBuf::from(file_name) + } } } @@ -73,6 +80,7 @@ impl Binaries { Binaries::Wallet, Binaries::ShaP2pool, Binaries::GpuMiner, + Binaries::Clythor, ] .iter() .copied() diff --git a/src-tauri/src/binaries/binaries_resolver.rs b/src-tauri/src/binaries/binaries_resolver.rs index 4e8fe78cb..3ef828514 100644 --- a/src-tauri/src/binaries/binaries_resolver.rs +++ b/src-tauri/src/binaries/binaries_resolver.rs @@ -63,6 +63,19 @@ impl BinaryResolver { _ => panic!("Unsupported network"), }; + binary_manager.insert( + Binaries::Clythor, + BinaryManager::new( + Binaries::Clythor.name().to_string(), + Box::new(GithubReleasesAdapter { + repo: "clythor".to_string(), + owner: "tari-project".to_string(), + specific_name: None, + }), + None, + true, + ), + ); binary_manager.insert( Binaries::Xmrig, BinaryManager::new( diff --git a/src-tauri/src/clythor_adapter.rs b/src-tauri/src/clythor_adapter.rs new file mode 100644 index 000000000..fe12ba52d --- /dev/null +++ b/src-tauri/src/clythor_adapter.rs @@ -0,0 +1,139 @@ +use std::path::PathBuf; + +use anyhow::Error; +use async_trait::async_trait; +use log::warn; +use tari_shutdown::Shutdown; + +use crate::binaries::{Binaries, BinaryResolver}; +use crate::process_adapter::{ProcessAdapter, ProcessInstance, StatusMonitor}; +use crate::process_utils; +use crate::xmrig::http_api::XmrigHttpApiClient; + +const LOG_TARGET: &str = "tari::universe::clythor_adapter"; + +pub struct LocalMmproxy { + pub host_name: String, + pub port: u16, +} + +pub struct ClythorAdapter { + node_connection: LocalMmproxy, + monero_address: String, + http_api_token: String, + http_api_port: u16, + mining_threads: usize, + pub client: XmrigHttpApiClient, + // TODO: secure +} + +impl ClythorAdapter { + pub fn new( + node_connection: LocalMmproxy, + monero_address: String, + mining_threads: usize, + ) -> Self { + let http_api_port = 18000; + let http_api_token = "pass".to_string(); + Self { + node_connection, + monero_address, + http_api_token: http_api_token.clone(), + http_api_port, + mining_threads, + client: XmrigHttpApiClient::new( + format!("http://127.0.0.1:{}", http_api_port).clone(), + http_api_token.clone(), + ), + } + } +} + +impl ProcessAdapter for ClythorAdapter { + type StatusMonitor = ClythorStatusMonitor; + + fn spawn_inner( + &self, + data_dir: PathBuf, + _config_dir: PathBuf, + log_dir: PathBuf, + ) -> Result<(ProcessInstance, Self::StatusMonitor), anyhow::Error> { + self.kill_previous_instances(data_dir.clone())?; + + let clythor_shutdown = Shutdown::new(); + let mut shutdown_signal = clythor_shutdown.to_signal(); + let clythor_log_file = log_dir.join("clythor.log"); + std::fs::create_dir_all(clythor_log_file.parent().unwrap())?; + let clythor_data_dir = data_dir.join("clythor"); + std::fs::create_dir_all(&clythor_data_dir)?; + let args = vec![ + format!("-b {}", clythor_data_dir.to_str().unwrap()), + format!( + "--log-path={}", + &clythor_log_file.parent().unwrap().to_str().unwrap() + ), + format!("--http-port={}", self.http_api_port), + format!("--access-token={}", self.http_api_token), + format!("--user={}", self.monero_address), + format!("--threads={}", self.mining_threads), + format!( + "--monero-base-node-address={}:{}", + self.node_connection.host_name, self.node_connection.port + ), + ]; + let pid_file_path = data_dir.join(self.pid_file_name()); + + Ok(( + ProcessInstance { + shutdown: clythor_shutdown, + handle: Some(tokio::spawn(async move { + let clythor_bin = BinaryResolver::current() + .read() + .await + .resolve_path_to_binary_files(Binaries::Clythor) + .await?; + + crate::download_utils::set_permissions(&clythor_bin).await?; + let mut child = process_utils::launch_child_process(&clythor_bin, None, &args)?; + + if let Some(id) = child.id() { + let pid_file_path = data_dir.join(&pid_file_path); + std::fs::write(pid_file_path, id.to_string())?; + } + shutdown_signal.wait().await; + + child.kill().await?; + + match std::fs::remove_file(data_dir.join(&pid_file_path)) { + Ok(_) => {} + Err(e) => { + warn!(target: LOG_TARGET, "Could not clear clythor's pid file - {e}"); + } + } + + Ok(0) + })), + }, + ClythorStatusMonitor {}, + )) + } + + fn name(&self) -> &str { + "clythor" + } + + fn pid_file_name(&self) -> &str { + "clythor_pid" + } +} + +pub struct ClythorStatusMonitor {} + +#[async_trait] +impl StatusMonitor for ClythorStatusMonitor { + type Status = (); + + async fn status(&self) -> Result { + todo!() + } +} diff --git a/src-tauri/src/cpu_miner.rs b/src-tauri/src/cpu_miner.rs index 52ff99069..460c26f94 100644 --- a/src-tauri/src/cpu_miner.rs +++ b/src-tauri/src/cpu_miner.rs @@ -1,9 +1,11 @@ use crate::app_config::MiningMode; +use crate::clythor_adapter::{ClythorAdapter, LocalMmproxy}; use crate::process_adapter::ProcessAdapter; use crate::xmrig::http_api::XmrigHttpApiClient; use crate::xmrig_adapter::{XmrigAdapter, XmrigNodeConnection}; use crate::{CpuMinerConfig, CpuMinerConnection, CpuMinerConnectionStatus, CpuMinerStatus}; use log::{debug, error, info, warn}; +use serde::{Deserialize, Serialize}; use std::path::PathBuf; use std::thread; use tari_core::transactions::tari_amount::MicroMinotari; @@ -15,6 +17,12 @@ use tokio::time::MissedTickBehavior; const RANDOMX_BLOCKS_PER_DAY: u64 = 360; const LOG_TARGET: &str = "tari::universe::cpu_miner"; +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)] +pub enum RandomXMiner { + Xmrig, + Clythor, +} + pub(crate) struct CpuMiner { watcher_task: Option>>, miner_shutdown: Shutdown, @@ -33,7 +41,7 @@ impl CpuMiner { } #[allow(clippy::too_many_arguments)] - pub async fn start( + pub async fn start_xmrig( &mut self, mut app_shutdown: ShutdownSignal, cpu_miner_config: &CpuMinerConfig, @@ -138,6 +146,88 @@ impl CpuMiner { Ok(()) } + #[allow(clippy::too_many_arguments)] + pub async fn start_clythor( + &mut self, + mut app_shutdown: ShutdownSignal, + cpu_miner_config: &CpuMinerConfig, + monero_address: String, + monero_port: u16, + base_path: PathBuf, + config_path: PathBuf, + log_dir: PathBuf, + mode: MiningMode, + ) -> Result<(), anyhow::Error> { + if self.watcher_task.is_some() { + warn!(target: LOG_TARGET, "Tried to start mining twice"); + return Ok(()); + } + self.miner_shutdown = Shutdown::new(); + let mut inner_shutdown = self.miner_shutdown.to_signal(); + + let node_connection = match cpu_miner_config.node_connection { + CpuMinerConnection::BuiltInProxy => LocalMmproxy { + host_name: "http://127.0.0.1".to_string(), + port: monero_port, + }, + }; + let max_cpu_available = thread::available_parallelism(); + let max_cpu_available = match max_cpu_available { + Ok(available_cpus) => { + debug!(target:LOG_TARGET, "Available CPUs: {}", available_cpus); + available_cpus.get() + } + Err(err) => { + error!("Available CPUs: Unknown, error: {}", err); + 1 + } + }; + let mining_threads = match mode { + MiningMode::Eco => (30 * max_cpu_available) / 100, + MiningMode::Ludicrous => max_cpu_available, + }; + let clythor = ClythorAdapter::new(node_connection, monero_address.clone(), mining_threads); + let (mut clythor_child, _clythor_status_monitor) = + clythor.spawn_inner(base_path.clone(), config_path.clone(), log_dir.clone())?; + self.api_client = Some(clythor.client); + + self.watcher_task = Some(tauri::async_runtime::spawn(async move { + let mut watch_timer = tokio::time::interval(tokio::time::Duration::from_secs(1)); + watch_timer.set_missed_tick_behavior(MissedTickBehavior::Skip); + // read events such as stdout + loop { + select! { + _ = watch_timer.tick() => { + if !clythor_child.ping() + { + warn!(target: LOG_TARGET, "clythor is not running"); + match clythor_child.stop().await { + Ok(_) => { + info!(target: LOG_TARGET, "clythor exited successfully"); + } + Err(e) => { + error!(target: LOG_TARGET, "clythor exited with error: {}", e); + return Err(e) + } + } + break; + } + }, + _ = inner_shutdown.wait() => { + clythor_child.stop().await?; + break; + }, + _ = app_shutdown.wait() => { + clythor_child.stop().await?; + break; + } + } + } + Ok(()) + })); + Ok(()) + } + pub async fn status( &mut self, network_hash_rate: u64, diff --git a/src-tauri/src/hardware_monitor.rs b/src-tauri/src/hardware_monitor.rs index 2c40e24e4..038999058 100644 --- a/src-tauri/src/hardware_monitor.rs +++ b/src-tauri/src/hardware_monitor.rs @@ -316,7 +316,6 @@ impl HardwareMonitorImpl for LinuxHardwareMonitor { let nvml: &Nvml = match &self.nvml { Some(nvml) => nvml, None => { - println!("Failed to get NVML"); return HardwareParameters { label: "N/A".to_string(), usage_percentage: 0.0, diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index a539f7745..8c54c944d 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,6 +1,7 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] +use cpu_miner::RandomXMiner; use log::trace; use log::{debug, error, info, warn}; use serde::Serialize; @@ -44,6 +45,7 @@ use crate::wallet_manager::WalletManager; mod app_config; mod app_in_memory_config; mod binaries; +mod clythor_adapter; mod consts; mod cpu_miner; mod download_utils; @@ -442,6 +444,15 @@ async fn setup_inner( sleep(Duration::from_secs(1)); progress.set_max(30).await; + progress + .update("checking-latest-version-clythor".to_string(), None, 0) + .await; + binary_resolver + .initalize_binary(Binaries::Clythor, progress.clone(), should_check_for_update) + .await?; + sleep(Duration::from_secs(1)); + + progress.set_max(35).await; progress .update("checking-latest-version-xmrig".to_string(), None, 0) .await; @@ -449,7 +460,7 @@ async fn setup_inner( .initalize_binary(Binaries::Xmrig, progress.clone(), should_check_for_update) .await?; sleep(Duration::from_secs(1)); - progress.set_max(35).await; + progress.set_max(40).await; progress .update("checking-latest-version-sha-p2pool".to_string(), None, 0) .await; @@ -511,7 +522,7 @@ async fn setup_inner( info!(target: LOG_TARGET, "Node has started and is ready"); - progress.set_max(40).await; + progress.set_max(45).await; progress .update("waiting-for-wallet".to_string(), None, 0) .await; @@ -719,9 +730,11 @@ async fn get_seed_words( } #[tauri::command] +#[allow(clippy::too_many_lines)] async fn start_mining<'r>( state: tauri::State<'_, UniverseAppState>, app: tauri::AppHandle, + miner: RandomXMiner, ) -> Result<(), String> { let timer = Instant::now(); let config = state.config.read().await; @@ -738,21 +751,36 @@ async fn start_mining<'r>( .await .map_err(|e| e.to_string())?; - let res = state - .cpu_miner - .write() - .await - .start( - state.shutdown.to_signal(), - &cpu_miner_config, - monero_address.to_string(), - mm_proxy_port, - app.path_resolver().app_local_data_dir().unwrap(), - app.path_resolver().app_config_dir().unwrap(), - app.path_resolver().app_log_dir().unwrap(), - mode, - ) - .await; + let mut res = state.cpu_miner.write().await; + + let res = match miner { + cpu_miner::RandomXMiner::Clythor => { + res.start_clythor( + state.shutdown.to_signal(), + &cpu_miner_config, + monero_address, + mm_proxy_port, + app.path_resolver().app_local_data_dir().unwrap(), + app.path_resolver().app_config_dir().unwrap(), + app.path_resolver().app_log_dir().unwrap(), + mode, + ) + .await + } + cpu_miner::RandomXMiner::Xmrig => { + res.start_xmrig( + state.shutdown.to_signal(), + &cpu_miner_config, + monero_address, + mm_proxy_port, + app.path_resolver().app_local_data_dir().unwrap(), + app.path_resolver().app_config_dir().unwrap(), + app.path_resolver().app_log_dir().unwrap(), + mode, + ) + .await + } + }; if let Err(e) = res { error!(target: LOG_TARGET, "Could not start mining: {:?}", e); @@ -867,6 +895,9 @@ async fn get_applications_versions(app: tauri::AppHandle) -> Result Result( Ok(()) } +#[tauri::command] +async fn set_randomx_miner<'r>( + state: tauri::State<'_, UniverseAppState>, + miner: RandomXMiner, +) -> Result<(), String> { + let mut app_config = state.config.write().await; + app_config + .set_randomx_miner(miner) + .await + .inspect_err(|e| error!("error at set_randomx_miner {:?}", e)) + .map_err(|e| e.to_string())?; + + Ok(()) +} + +#[tauri::command] +async fn get_randomx_miner<'r>( + state: tauri::State<'_, UniverseAppState>, +) -> Result { + let randomx_miner = state.config.read().await.randomx_miner(); + Ok(randomx_miner) +} + +#[allow(clippy::struct_excessive_bools)] #[derive(Debug, Serialize)] pub struct CpuMinerMetrics { hardware: Option, @@ -1236,6 +1297,7 @@ pub struct TariWalletDetails { #[derive(Debug, Serialize)] pub struct ApplicationsVersions { tari_universe: String, + clythor: String, xmrig: String, minotari_node: String, mm_proxy: String, @@ -1484,6 +1546,8 @@ fn main() { set_gpu_mining_enabled, set_cpu_mining_enabled, restart_application, + get_randomx_miner, + set_randomx_miner, resolve_application_language, set_application_language, get_miner_metrics, diff --git a/src-tauri/src/mm_proxy_adapter.rs b/src-tauri/src/mm_proxy_adapter.rs index f783fc583..df028a9fd 100644 --- a/src-tauri/src/mm_proxy_adapter.rs +++ b/src-tauri/src/mm_proxy_adapter.rs @@ -93,6 +93,8 @@ impl ProcessAdapter for MergeMiningProxyAdapter { ), "-p".to_string(), "merge_mining_proxy.wait_for_initial_sync_at_startup=false".to_string(), + "-p".to_string(), + "merge_mining_proxy.use_dynamic_fail_data=false".to_string(), ]; // TODO: uncomment if p2pool is needed in CPU mining diff --git a/src/containers/Settings/MiningSettings.tsx b/src/containers/Settings/MiningSettings.tsx index b6f215927..ecf003121 100644 --- a/src/containers/Settings/MiningSettings.tsx +++ b/src/containers/Settings/MiningSettings.tsx @@ -3,11 +3,13 @@ import GpuMiningMarkup from './sections/mining/GpuMiningMarkup.tsx'; import SeedWordsMarkup from './sections/mining/SeedWordsMarkup'; import MoneroAddressMarkup from './sections/mining/MoneroAddressMarkup'; import WalletAddressMarkup from './sections/mining/WalletAddressMarkup.tsx'; +import RandomXCpuMiner from './sections/experimental/RandomXCpuMiner.tsx'; export const MiningSettings = () => { return ( <> + diff --git a/src/containers/Settings/sections/experimental/RandomXCpuMiner.tsx b/src/containers/Settings/sections/experimental/RandomXCpuMiner.tsx new file mode 100644 index 000000000..fa5016709 --- /dev/null +++ b/src/containers/Settings/sections/experimental/RandomXCpuMiner.tsx @@ -0,0 +1,43 @@ +import { Select } from '@app/components/elements/inputs/Select'; +import { useMiningStore } from '@app/store/useMiningStore'; +import { CpuMiner } from '@app/types/mining'; +import { TileItem } from '@app/containers/SideBar/Miner/styles'; +import { Typography } from '@app/components/elements/Typography'; +import { useTranslation } from 'react-i18next'; +import { useShallow } from 'zustand/react/shallow'; +import { useAppStateStore } from '@app/store/appStateStore'; + +const options = [ + { label: 'Clythor', value: 'Clythor' }, + { label: 'Xmrig', value: 'Xmrig' }, +]; + +export const RandomXCpuMiner: React.FC = () => { + const { cpuMiner, setCpuMiner } = useMiningStore((s) => ({ cpuMiner: s.cpuMiner, setCpuMiner: s.setCpuMiner })); + const { t } = useTranslation('settings', { useSuspense: false }); + const isSettingUp = useAppStateStore(useShallow((s) => s.isSettingUp)); + + const isMiningControlsEnabled = useMiningStore(useShallow((s) => s.miningControlsEnabled)); + const isChangingMode = useMiningStore((s) => s.isChangingMode); + + const isCPUMining = useMiningStore((s) => s.cpu.mining.is_mining); + const isGPUMining = useMiningStore((s) => s.gpu.mining.is_mining); + const isMiningInitiated = useMiningStore((s) => s.miningInitiated); + const isMining = isCPUMining || isGPUMining; + const isMiningLoading = (isMining && !isMiningInitiated) || (isMiningInitiated && !isMining); + + return ( + + {t('randomX-miner')} +