From e8751842cec5060aeedcf71421b341be13b3ed3d Mon Sep 17 00:00:00 2001 From: hinto-janaiyo Date: Fri, 30 Dec 2022 19:22:43 -0500 Subject: [PATCH] Status Submenu: Add [Status/P2Pool] UI and data --- README.md | 2 +- src/constants.rs | 19 ++++++++++++ src/disk.rs | 18 ++++++++++- src/helper.rs | 39 ++++++++++++++++-------- src/human.rs | 7 +++++ src/main.rs | 21 ++++++++----- src/status.rs | 77 ++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 161 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index c202117..16235fd 100644 --- a/README.md +++ b/README.md @@ -482,7 +482,7 @@ You need [`cargo`](https://www.rust-lang.org/learn/get-started), Rust's build to The `--release` profile in Gupax is set to prefer code performance & small binary sizes over compilation speed (see [`Cargo.toml`](https://github.com/hinto-janaiyo/gupax/blob/main/Cargo.toml)). Gupax itself (with all dependencies already built) takes around 1m30s to build (vs 10s on a normal `--release`) with a Ryzen 5950x. -There are `37` unit tests throughout the codebase files, you should probably run: +There are `38` unit tests throughout the codebase files, you should probably run: ``` cargo test ``` diff --git a/src/constants.rs b/src/constants.rs index 9ac72fa..e3cb85e 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -176,11 +176,30 @@ pub const STATUS_SUBMENU_PROCESSES: &str = "View the status of process related d pub const STATUS_SUBMENU_P2POOL: &str = "View P2Pool specific data"; pub const STATUS_SUBMENU_MONERO: &str = "View general Monero blockchain data"; pub const STATUS_SUBMENU_PAYOUT: &str = "The total amount of payouts received via P2Pool across all time"; +//-- P2Pool pub const STATUS_SUBMENU_XMR: &str = "The total of XMR mined via P2Pool across all time"; pub const STATUS_SUBMENU_LATEST: &str = "Sort the logs latest to oldest"; pub const STATUS_SUBMENU_OLDEST: &str = "Sort the logs oldest to latest"; pub const STATUS_SUBMENU_BIGGEST: &str = "Sort the logs by the biggest payouts first"; pub const STATUS_SUBMENU_SMALLEST: &str = "Sort the logs by the smallest payouts first"; +pub const STATUS_SUBMENU_AUTOMATIC: &str = "Automatically calculate share/block time with your current P2Pool 1 hour average hashrate"; +pub const STATUS_SUBMENU_MANUAL: &str = "Manually input a hashrate to calculate share/block time with current P2Pool/Monero network stats"; +pub const STATUS_SUBMENU_HASH: &str = "Use [Hash] as the hashrate metric"; +pub const STATUS_SUBMENU_KILO: &str = "Use [Kilo] as the hashrate metric (1,000x hash)"; +pub const STATUS_SUBMENU_MEGA: &str = "Use [Mega] as the hashrate metric (1,000,000x hash)"; +pub const STATUS_SUBMENU_GIGA: &str = "Use [Giga] as the hashrate metric (1,000,000,000x hash)"; +pub const STATUS_SUBMENU_P2POOL_BLOCK_MEAN: &str = "The average time it takes for P2Pool to find a block"; +pub const STATUS_SUBMENU_YOUR_P2POOL_HASHRATE: &str = "Your 1 hour average hashrate on P2Pool"; +pub const STATUS_SUBMENU_P2POOL_SHARE_MEAN: &str = "The average time it takes for your hashrate to find a share on P2Pool"; +pub const STATUS_SUBMENU_SOLO_BLOCK_MEAN: &str = "The average time it would take for your hashrate to find a block solo mining Monero"; +pub const STATUS_SUBMENU_MONERO_DIFFICULTY: &str = "The current Monero network's difficulty (how many hashes it will take on average to find a block)"; +pub const STATUS_SUBMENU_MONERO_HASHRATE: &str = "The current Monero network's hashrate"; +pub const STATUS_SUBMENU_P2POOL_DIFFICULTY: &str = "The current P2Pool network's difficulty (how many hashes it will take on average to find a share)"; +pub const STATUS_SUBMENU_P2POOL_HASHRATE: &str = "The current P2Pool network's hashrate"; +pub const STATUS_SUBMENU_P2POOL_MINERS: &str = "The current amount of miners on P2Pool"; +pub const STATUS_SUBMENU_P2POOL_DOMINANCE: &str = "The percent of hashrate P2Pool accounts for in the entire Monero network"; +pub const STATUS_SUBMENU_YOUR_P2POOL_DOMINANCE: &str = "The percent of hashrate you account for in P2Pool"; +pub const STATUS_SUBMENU_YOUR_MONERO_DOMINANCE: &str = "The percent of hashrate you account for in the entire Monero network"; // Gupax pub const GUPAX_UPDATE: &str = "Check for updates on Gupax, P2Pool, and XMRig via GitHub's API and upgrade automatically"; diff --git a/src/disk.rs b/src/disk.rs index 4a6eadd..4613b1f 100644 --- a/src/disk.rs +++ b/src/disk.rs @@ -239,6 +239,12 @@ impl State { } } + pub fn update_absolute_path(&mut self) -> Result<(), TomlError> { + self.gupax.absolute_p2pool_path = into_absolute_path(self.gupax.p2pool_path.clone())?; + self.gupax.absolute_xmrig_path = into_absolute_path(self.gupax.xmrig_path.clone())?; + Ok(()) + } + // Convert [&str] to [State] pub fn from_str(string: &str) -> Result { match toml::de::from_str(string) { @@ -869,6 +875,15 @@ impl Default for Hash { } impl Hash { + pub fn convert_to_hash(f: f64, from: Self) -> f64 { + match from { + Self::Hash => f, + Self::Kilo => f * 1_000.0, + Self::Mega => f * 1_000_000.0, + Self::Giga => f * 1_000_000_000.0, + } + } + pub fn convert(f: f64, og: Self, new: Self) -> f64 { match og { Self::Hash => { @@ -1034,7 +1049,7 @@ impl Default for Status { payout_view: PayoutView::default(), monero_enabled: false, manual_hash: false, - hashrate: 0.0, + hashrate: 1.0, hash_metric: Hash::default(), } } @@ -1064,6 +1079,7 @@ impl Default for Gupax { } } } + impl Default for P2pool { fn default() -> Self { Self { diff --git a/src/helper.rs b/src/helper.rs index 6d3249b..c5c79d6 100644 --- a/src/helper.rs +++ b/src/helper.rs @@ -1239,17 +1239,18 @@ pub struct PubP2poolApi { pub average_effort: HumanNumber, pub current_effort: HumanNumber, pub connections: HumanNumber, - // The API below needs a raw int [hashrate] to go off of and + // The API needs a raw ints to go off of and // there's not a good way to access it without doing weird - // [Arc] shenanigans, so the raw [hashrate_1h] is - // copied here instead. - pub hashrate: u64, + // [Arc] shenanigans, so some raw ints are stored here. + pub user_p2pool_hashrate_u64: u64, + pub p2pool_difficulty_u64: u64, + pub monero_difficulty_u64: u64, // Network API pub monero_difficulty: HumanNumber, // e.g: [15,000,000] pub monero_hashrate: HumanNumber, // e.g: [1.000 GH/s] - pub hash: String, + pub hash: String, // Current block hash pub height: HumanNumber, - pub reward: u64, // Atomic units + pub reward: AtomicUnit, // Pool API pub p2pool_difficulty: HumanNumber, pub p2pool_hashrate: HumanNumber, @@ -1290,12 +1291,14 @@ impl PubP2poolApi { average_effort: HumanNumber::unknown(), current_effort: HumanNumber::unknown(), connections: HumanNumber::unknown(), - hashrate: 0, + user_p2pool_hashrate_u64: 0, + p2pool_difficulty_u64: 0, + monero_difficulty_u64: 0, monero_difficulty: HumanNumber::unknown(), monero_hashrate: HumanNumber::unknown(), hash: String::from("???"), height: HumanNumber::unknown(), - reward: 0, + reward: AtomicUnit::new(), p2pool_difficulty: HumanNumber::unknown(), p2pool_hashrate: HumanNumber::unknown(), miners: HumanNumber::unknown(), @@ -1407,14 +1410,14 @@ impl PubP2poolApi { average_effort: HumanNumber::to_percent(local.average_effort), current_effort: HumanNumber::to_percent(local.current_effort), connections: HumanNumber::from_u16(local.connections), - hashrate: local.hashrate_1h, + user_p2pool_hashrate_u64: local.hashrate_1h, ..std::mem::take(&mut *public) }; } // Mutate [PubP2poolApi] with data from a [PrivP2pool(Network|Pool)Api]. fn update_from_network_pool(public: &Arc>, net: PrivP2poolNetworkApi, pool: PrivP2poolPoolApi) { - let user_hashrate = lock!(public).hashrate; // The user's total P2Pool hashrate + let user_hashrate = lock!(public).user_p2pool_hashrate_u64; // The user's total P2Pool hashrate let monero_difficulty = net.difficulty; let monero_hashrate = monero_difficulty / MONERO_BLOCK_TIME_IN_SECONDS; let p2pool_hashrate = pool.pool_statistics.hashRate; @@ -1452,11 +1455,13 @@ impl PubP2poolApi { } let mut public = lock!(public); *public = Self { + p2pool_difficulty_u64: p2pool_difficulty, + monero_difficulty_u64: monero_difficulty, monero_difficulty: HumanNumber::from_u64(monero_difficulty), monero_hashrate: HumanNumber::from_u64_to_gigahash_3_point(monero_hashrate), hash: net.hash, height: HumanNumber::from_u32(net.height), - reward: net.reward, + reward: AtomicUnit::from_u64(net.reward), p2pool_difficulty: HumanNumber::from_u64(p2pool_difficulty), p2pool_hashrate: HumanNumber::from_u64_to_megahash_3_point(p2pool_hashrate), miners: HumanNumber::from_u32(pool.pool_statistics.miners), @@ -1469,6 +1474,14 @@ impl PubP2poolApi { ..std::mem::take(&mut *public) }; } + + pub fn calculate_share_or_block_time(hashrate: u64, difficulty: u64) -> HumanTime { + if hashrate == 0 { + HumanTime::new() + } else { + HumanTime::from_u64(difficulty / hashrate) + } + } } //---------------------------------------------------------------------------------------------------- Private P2Pool "Local" Api @@ -1889,7 +1902,7 @@ mod test { assert_eq!(p.average_effort.to_string(), "100.00%"); assert_eq!(p.current_effort.to_string(), "200.00%"); assert_eq!(p.connections.to_string(), "1,234"); - assert_eq!(p.hashrate, 20000); + assert_eq!(p.user_p2pool_hashrate_u64, 20000); drop(p); // Update Network + Pool PubP2poolApi::update_from_network_pool(&public, network, pool); @@ -1899,7 +1912,7 @@ mod test { assert_eq!(p.monero_hashrate.to_string(), "2.500 GH/s"); assert_eq!(p.hash.to_string(), "asdf"); assert_eq!(p.height.to_string(), "1,234"); - assert_eq!(p.reward, 2345); + assert_eq!(p.reward.to_u64(), 2345); assert_eq!(p.p2pool_difficulty.to_string(), "10,000,000"); assert_eq!(p.p2pool_hashrate.to_string(), "1.000 MH/s"); assert_eq!(p.miners.to_string(), "1,000"); diff --git a/src/human.rs b/src/human.rs index e5034ce..e62356d 100644 --- a/src/human.rs +++ b/src/human.rs @@ -44,6 +44,10 @@ impl HumanTime { HumanTime(d) } + pub const fn from_u64(u: u64) -> HumanTime { + HumanTime(Duration::from_secs(u)) + } + fn plural(f: &mut std::fmt::Formatter, started: &mut bool, name: &str, value: u64) -> std::fmt::Result { if value > 0 { if *started { @@ -216,6 +220,9 @@ impl HumanNumber { let f = format!("{}", f); Self(f) } + pub fn as_str(&self) -> &str { + self.0.as_str() + } } //---------------------------------------------------------------------------------------------------- TESTS diff --git a/src/main.rs b/src/main.rs index 13d3fd5..d31a543 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1520,6 +1520,8 @@ impl eframe::App for App { }); } else if p2pool_is_alive { if key.is_up() && !wants_input || ui.add_sized([width, height], Button::new("⟲")).on_hover_text("Restart P2Pool").clicked() { + lock!(self.og).update_absolute_path(); + self.state.update_absolute_path(); Helper::restart_p2pool(&self.helper, &self.state.p2pool, &self.state.gupax.absolute_p2pool_path); } if key.is_down() && !wants_input || ui.add_sized([width, height], Button::new("⏹")).on_hover_text("Stop P2Pool").clicked() { @@ -1549,6 +1551,8 @@ impl eframe::App for App { ui.set_enabled(ui_enabled); let color = if ui_enabled { GREEN } else { RED }; if (ui_enabled && key.is_up() && !wants_input) || ui.add_sized([width, height], Button::new(RichText::new("▶").color(color))).on_hover_text("Start P2Pool").on_disabled_hover_text(text).clicked() { + lock!(self.og).update_absolute_path(); + self.state.update_absolute_path(); Helper::start_p2pool(&self.helper, &self.state.p2pool, &self.state.gupax.absolute_p2pool_path); } } @@ -1575,6 +1579,8 @@ impl eframe::App for App { }); } else if xmrig_is_alive { if key.is_up() && !wants_input || ui.add_sized([width, height], Button::new("⟲")).on_hover_text("Restart XMRig").clicked() { + lock!(self.og).update_absolute_path(); + self.state.update_absolute_path(); if cfg!(windows) { Helper::restart_xmrig(&self.helper, &self.state.xmrig, &self.state.gupax.absolute_xmrig_path, Arc::clone(&self.sudo)); } else { @@ -1609,14 +1615,15 @@ impl eframe::App for App { } ui.set_enabled(ui_enabled); let color = if ui_enabled { GREEN } else { RED }; - #[cfg(target_os = "windows")] if (ui_enabled && key.is_up() && !wants_input) || ui.add_sized([width, height], Button::new(RichText::new("▶").color(color))).on_hover_text("Start XMRig").on_disabled_hover_text(text).clicked() { - Helper::start_xmrig(&self.helper, &self.state.xmrig, &self.state.gupax.absolute_xmrig_path, Arc::clone(&self.sudo)); - } - #[cfg(target_family = "unix")] - if (ui_enabled && key.is_up() && !wants_input) || ui.add_sized([width, height], Button::new(RichText::new("▶").color(color))).on_hover_text("Start XMRig").on_disabled_hover_text(text).clicked() { - lock!(self.sudo).signal = ProcessSignal::Start; - self.error_state.ask_sudo(&self.sudo); + lock!(self.og).update_absolute_path(); + self.state.update_absolute_path(); + if cfg!(windows) { + Helper::start_xmrig(&self.helper, &self.state.xmrig, &self.state.gupax.absolute_xmrig_path, Arc::clone(&self.sudo)); + } else if cfg!(unix) { + lock!(self.sudo).signal = ProcessSignal::Start; + self.error_state.ask_sudo(&self.sudo); + } } } }); diff --git a/src/status.rs b/src/status.rs index e238ab9..150792c 100644 --- a/src/status.rs +++ b/src/status.rs @@ -27,6 +27,7 @@ use crate::{ macros::*, GupaxP2poolApi, PayoutView, + human::HumanNumber, }; use std::sync::{Arc,Mutex}; use log::*; @@ -36,6 +37,7 @@ use egui::{ TextStyle::Name, TextEdit, SelectableLabel, + Slider, }; impl crate::disk::Status { @@ -172,6 +174,81 @@ pub fn show(&mut self, sys: &Arc>, p2pool_api: &Arc