diff --git a/Cargo.lock b/Cargo.lock index 66020d3..434b12d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,9 +63,9 @@ checksum = "330223a1aecc308757b9926e9391c9b47f8ef2dbd8aea9df88312aea18c5e8d6" [[package]] name = "addr2line" -version = "0.17.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" dependencies = [ "gimli", ] @@ -343,15 +343,15 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" dependencies = [ "addr2line", "cc", "cfg-if", "libc", - "miniz_oxide 0.5.4", + "miniz_oxide", "object", "rustc-demangle", ] @@ -1322,7 +1322,7 @@ dependencies = [ "flume", "half", "lebe", - "miniz_oxide 0.6.2", + "miniz_oxide", "smallvec", "threadpool", ] @@ -1391,7 +1391,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", - "miniz_oxide 0.6.2", + "miniz_oxide", ] [[package]] @@ -1695,9 +1695,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.2" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" [[package]] name = "gio-sys" @@ -2299,15 +2299,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.6.2" @@ -2656,9 +2647,9 @@ dependencies = [ [[package]] name = "object" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb" dependencies = [ "memchr", ] @@ -2957,7 +2948,7 @@ dependencies = [ "bitflags", "crc32fast", "flate2", - "miniz_oxide 0.6.2", + "miniz_oxide", ] [[package]] @@ -4130,9 +4121,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" dependencies = [ "indexmap", "serde", diff --git a/README.md b/README.md index b34db61..af412a6 100644 --- a/README.md +++ b/README.md @@ -9,13 +9,14 @@ Gupax is a (Windows|macOS|Linux) GUI for mining [**Monero**](https://github.com/ * [How-To](#How-To) - [Video](#Video) - [Text](#Text) -- [Simple](#Simple) +* [Simple](#Simple) - [Gupax](#Gupax) - [P2Pool](#P2Pool) - [XMRig](#XMRig) -- [Advanced](#Advanced) +* [Advanced](#Advanced) - [Verifying](#Verifying) - [Command Line](#Command-Line) + - [Resolution](#Resolution) - [Tor/Arti](#TorArti) - [Logs](#Logs) - [Disk](#Disk) @@ -23,7 +24,7 @@ Gupax is a (Windows|macOS|Linux) GUI for mining [**Monero**](https://github.com/ - [Gupax](#Gupax) - [P2Pool](#P2Pool) - [XMRig](#XMRig) -- [Connections](#Connections) +* [Connections](#Connections) * [Community Monero Nodes](#community-monero-nodes) * [Build](#Build) - [General Info](#General-Info) @@ -31,6 +32,11 @@ Gupax is a (Windows|macOS|Linux) GUI for mining [**Monero**](https://github.com/ - [macOS](#macOS) - [Windows](#Windows) * [FAQ](#FAQ) + - [Where are updates downloaded from?](#where-are-updates-downloaded-from) + - [Can I quit mid-update?](#can-i-quit-mid-update) + - [How much memory does Gupax use?](#how-much-memory-does-gupax-use) + - [How is sudo handled? (on macOS/Linux)](#how-is-sudo-handled-on-macos-linux) + - [Why does Gupax need to be Admin? (on Windows)](#why-does-gupax-need-to-be-admin-on-windows) ## What is Monero/P2Pool/XMRig/Gupax? **Monero** is a secure, private, and untraceable cryptocurrency. @@ -133,28 +139,25 @@ For transparency, here's all the connections Gupax makes: | Community Monero Nodes | Connecting to with P2Pool, measuring ping latency | `[P2Pool Simple]` tab | [`node.rs`](https://github.com/hinto-janaiyo/gupax/blob/main/src/node.rs) | ## Community Monero Nodes -| Name | IP/Domain | RPC Port | -|----------------|----------------------------------|----------| -| C3pool | node.c3pool.com | 18081 | -| Cake | xmr-node.cakewallet.com | 18081 | -| CakeEu | xmr-node-eu.cakewallet.com | 18081 | -| CakeUk | xmr-node-uk.cakewallet.com | 18081 | -| CakeUs | xmr-node-usa-east.cakewallet.com | 18081 | -| Feather1 | selsta1.featherwallet.net | 18081 | -| Feather2 | selsta2.featherwallet.net | 18081 | -| MajesticBankIs | node.majesticbank.is | 18089 | -| MajesticBankSu | node.majesticbank.su | 18089 | -| Monerujo | nodex.monerujo.io | 18081 | -| Plowsof1 | node.monerodevs.org | 18089 | -| Plowsof2 | node2.monerodevs.org | 18089 | -| Rino | node.community.rino.io | 18081 | -| Seth | node.sethforprivacy.com | 18089 | -| Singapore | singapore.node.xmr | 18081 | -| SupportXmr | node.supportxmr.com | 18081 | -| SupportXmrIr | node.supportxmr.ir | 18089 | -| XmrVsBeast | p2pmd.xmrvsbeast.com | 18081 | - -*Note: Plowsof1 & Plowsof2 have ZMQ port on 18084, the rest are 18083* +| Name | IP/Domain | RPC Port | ZMQ Port | +|-------------------------------------------------------|----------------------------------|----------|----------| +| [C3pool](https://www.c3pool.com) | node.c3pool.com | 18081 | 18083 | +| [Cake](https://cakewallet.com) | xmr-node.cakewallet.com | 18081 | 18083 | +| [CakeEu](https://cakewallet.com) | xmr-node-eu.cakewallet.com | 18081 | 18083 | +| [CakeUk](https://cakewallet.com) | xmr-node-uk.cakewallet.com | 18081 | 18083 | +| [CakeUs](https://cakewallet.com) | xmr-node-usa-east.cakewallet.com | 18081 | 18083 | +| [Feather1](https://github.com/feather-wallet/feather) | selsta1.featherwallet.net | 18081 | 18083 | +| [Feather2](https://github.com/feather-wallet/feather) | selsta2.featherwallet.net | 18081 | 18083 | +| [MajesticBankIs](https://www.majesticbank.sc) | node.majesticbank.is | 18089 | 18083 | +| [MajesticBankSu](https://www.majesticbank.sc) | node.majesticbank.su | 18089 | 18083 | +| [Monerujo](https://www.monerujo.io) | nodex.monerujo.io | 18081 | 18083 | +| [Plowsof1](https://github.com/plowsof) | node.monerodevs.org | 18089 | 18084 | +| [Plowsof2](https://github.com/plowsof) | node2.monerodevs.org | 18089 | 18084 | +| [Rino](https://cakewallet.com) | node.community.rino.io | 18081 | 18083 | +| [Seth](https://github.com/sethforprivacy) | node.sethforprivacy.com | 18089 | 18083 | +| [SupportXmr](https://www.supportxmr.com) | node.supportxmr.com | 18081 | 18083 | +| [SupportXmrIr](https://www.supportxmr.com) | node.supportxmr.ir | 18089 | 18083 | +| [XmrVsBeast](https://xmrvsbeast.com) | p2pmd.xmrvsbeast.com | 18081 | 18083 | ## Build ### General Info @@ -200,3 +203,36 @@ cargo build --release This will build Gupax with the MSVC toolchain (`x86_64-pc-windows-msvc`). This is the recommended method and is how the pre-compiled release binaries are built. ## FAQ +### Where are updates downloaded from? +The latest versions are downloaded using the GitHub API. +* Gupax [`https://github.com/hinto-janaiyo/gupax`](https://github.com/hinto-janaiyo/gupax) +* P2Pool [`https://github.com/SChernykh/p2pool`](https://github.com/SChernykh/p2pool) +* XMRig [`https://github.com/xmrig/xmrig`](https://github.com/xmrig/xmrig) + +GitHub's API blocks request that do not have an HTTP `User-Agent` header. [For privacy, Gupax randomly uses a recent version of a `Wget/Curl` user-agent.](https://github.com/hinto-janaiyo/gupax/blob/2b80aa027728ddd193bac2e77caa5ddb4323f8fd/src/update.rs#L134) + +--- + +### Can I quit mid-update? +Although Gupax uses a temporary folder (`gupax_update_[A-Za-z0-9]`) to store temporary downloaded files, there aren't measures in place to revert an upgrade once the file swapping has actually started. If you quit Gupax anytime before the `Upgrading packages` phase (after metadata, download, extraction), you will technically be safe but this is not recommended as it is risky, especially since these updates can be very fast. + +If you started an update, you should let it finish. If the update has been stuck for a *long* time, it may be worth quitting Gupax. The worst that can happen is that your `Gupax/P2Pool/XMRig` binaries may be moved/deleted. Those can be easily redownloaded. Your actual `Gupax` user data (settings, custom nodes, pools, etc) is never touched. + +--- + +### How much memory does Gupax use? +Gupax itself uses around 100-300 megabytes of memory. + +Gupax also holds up to [500,000 bytes](https://github.com/hinto-janaiyo/gupax/blob/2b80aa027728ddd193bac2e77caa5ddb4323f8fd/src/helper.rs#L63) of log data from `P2Pool/XMRig` to display in the GUI terminals. These logs are reset once over capacity which takes around 1-2 hours. + +Memory usage should *never* be above 400~ megabytes. If you see Gupax using more than this, please send a bug report. + +--- + +### How is sudo handled? (on macOS/Linux) +[See here for more info.](https://github.com/hinto-janaiyo/gupax/tree/main/src#sudo) + +--- + +### Why does Gupax need to be Admin? (on Windows) +[See here for more info.](https://github.com/hinto-janaiyo/gupax/tree/main/src#why-does-gupax-need-to-be-admin-on-windows) diff --git a/src/README.md b/src/README.md index cf3dde6..944e153 100644 --- a/src/README.md +++ b/src/README.md @@ -5,6 +5,7 @@ * [Disk](#Disk) * [Scale](#Scale) * [Naming Scheme](#naming-scheme) +* [Sudo](#Sudo) * [Why does Gupax need to be Admin? (on Windows)](#why-does-gupax-need-to-be-admin-on-windows) - [The issue](#the-issue) - [The requirements](#the-requirements) @@ -120,6 +121,13 @@ Exceptions (there are always exceptions...): - XMRig separates the hash and signature - P2Pool hashes are in UPPERCASE +## Sudo +Unlike Windows, Unix (macOS/Linux) have a userland program that handles all the dirty details of privilege escalation: `sudo`. + +`sudo` is used in Gupax to execute XMRig, to enable MSR mods and hugepages. After every use of `sudo`, the memory holding the `String` buffer containing the password is wiped with 0's using [`zeroize`](https://docs.rs/zeroize/) to make sure the compiler doesn't optimize away the wipe. Although memory *should* be safe, this prevents passive accidents (core-dumps revealing plain-text password) and active attacks (attackers accessing live process memory) from happening. + +In general, secrets should be ephemeral or encrypted if not in use. I considered using [`secrets`](https://docs.rs/secrets/) to keep the password encrypted so that the user would only have to enter their password once, but simply wiping the memory was easier to implement and caused less worries of handling things incorrectly. + ## Why does Gupax need to be Admin? (on Windows) **TL;DR:** Because Windows. diff --git a/src/helper.rs b/src/helper.rs index d69dc48..cd4bd71 100644 --- a/src/helper.rs +++ b/src/helper.rs @@ -265,27 +265,16 @@ impl Helper { // Reset output if larger than max bytes. // This will also append a message showing it was reset. - fn check_reset_gui_p2pool_output(gui_api: &Arc>) { - debug!("P2Pool Watchdog | Checking if GUI output needs reset..."); - let mut gui_api = gui_api.lock().unwrap(); - if gui_api.output.len() > GUI_OUTPUT_LEEWAY { - info!("P2Pool | Output is nearing {} bytes, resetting!", MAX_GUI_OUTPUT_BYTES); - let text = format!("{}\nP2Pool GUI log is exceeding the maximum: {} bytes!\nI've reset the logs for you!\n{}\n\n\n\n", HORI_CONSOLE, MAX_GUI_OUTPUT_BYTES, HORI_CONSOLE); - gui_api.output.clear(); - gui_api.output.push_str(&text); - debug!("P2Pool Watchdog | Resetting GUI output ... OK"); - } - } - - fn check_reset_gui_xmrig_output(gui_api: &Arc>) { - debug!("XMRig Watchdog | Checking if GUI output needs reset..."); - let mut gui_api = gui_api.lock().unwrap(); - if gui_api.output.len() > GUI_OUTPUT_LEEWAY { - info!("XMRig | Output is nearing {} bytes, resetting!", MAX_GUI_OUTPUT_BYTES); - let text = format!("{}\nXMRig GUI log is exceeding the maximum: {} bytes!\nI've reset the logs for you!\n{}\n\n\n\n", HORI_CONSOLE, MAX_GUI_OUTPUT_BYTES, HORI_CONSOLE); - gui_api.output.clear(); - gui_api.output.push_str(&text); - debug!("XMRig Watchdog | Resetting GUI output ... OK"); + fn check_reset_gui_output(output: &mut String, name: ProcessName) { + let len = output.len(); + if len > GUI_OUTPUT_LEEWAY { + info!("{} Watchdog | Output is nearing {} bytes, resetting!", name, MAX_GUI_OUTPUT_BYTES); + let text = format!("{}\n{} GUI log is exceeding the maximum: {} bytes!\nI've reset the logs for you!\n{}\n\n\n\n", name, HORI_CONSOLE, MAX_GUI_OUTPUT_BYTES, HORI_CONSOLE); + output.clear(); + output.push_str(&text); + debug!("{} Watchdog | Resetting GUI output ... OK", name); + } else { + debug!("{} Watchdog | GUI output reset not needed! Current byte length ... {}", name, len); } } @@ -478,7 +467,7 @@ impl Helper { use std::io::Write; if std::fs::File::create(&api_path).is_ok() { let text = r#"{"hashrate_15m":0,"hashrate_1h":0,"hashrate_24h":0,"shares_found":0,"average_effort":0.0,"current_effort":0.0,"connections":0}"#; - match std::fs::write(&path, text) { + match std::fs::write(&api_path, text) { Ok(_) => info!("P2Pool | Creating default empty API file ... OK"), Err(e) => warn!("P2Pool | Creating default empty API file ... FAIL ... {}", e), } @@ -565,7 +554,9 @@ impl Helper { // Check if logs need resetting debug!("P2Pool Watchdog | Attempting GUI log reset check"); - Self::check_reset_gui_p2pool_output(&gui_api); + let mut lock = gui_api.lock().unwrap(); + Self::check_reset_gui_output(&mut lock.output, ProcessName::P2pool); + drop(lock); // Always update from output debug!("P2Pool Watchdog | Starting [update_from_output()]"); @@ -905,7 +896,9 @@ impl Helper { // Check if logs need resetting debug!("XMRig Watchdog | Attempting GUI log reset check"); - Self::check_reset_gui_xmrig_output(&gui_api); + let mut lock = gui_api.lock().unwrap(); + Self::check_reset_gui_output(&mut lock.output, ProcessName::Xmrig); + drop(lock); // Always update from output debug!("XMRig Watchdog | Starting [update_from_output()]"); diff --git a/src/node.rs b/src/node.rs index bd89900..6713e92 100644 --- a/src/node.rs +++ b/src/node.rs @@ -49,18 +49,17 @@ pub const RINO: &str = "node.community.rino.io:18081"; pub const SETH: &str = "node.sethforprivacy.com:18089"; pub const SUPPORTXMR: &str = "node.supportxmr.com:18081"; pub const SUPPORTXMR_IR: &str = "node.supportxmr.ir:18081"; -pub const SINGAPORE: &str = "singapore.node.xmr.pm:18089"; pub const XMRVSBEAST: &str = "p2pmd.xmrvsbeast.com:18081"; -pub const NODE_IPS: [&str; 18] = [ +pub const NODE_IPS: [&str; 17] = [ C3POOL,CAKE,CAKE_EU,CAKE_UK,CAKE_US,FEATHER_1,FEATHER_2,MAJESTICBANK_IS,MAJESTICBANK_SU, - MONERUJO,PLOWSOF_1,PLOWSOF_2,RINO,SETH,SUPPORTXMR,SUPPORTXMR_IR,SINGAPORE,XMRVSBEAST, + MONERUJO,PLOWSOF_1,PLOWSOF_2,RINO,SETH,SUPPORTXMR,SUPPORTXMR_IR,XMRVSBEAST, ]; #[derive(Copy,Clone,Eq,PartialEq,Debug,Deserialize,Serialize)] pub enum NodeEnum { C3pool,Cake,CakeEu,CakeUk,CakeUs,MajesticBankIs,MajesticBankSu,Monerujo,Plowsof1, - Plowsof2,Rino,Feather1,Feather2,Seth,SupportXmr,SupportXmrIr,Singapore,XmrVsBeast, + Plowsof2,Rino,Feather1,Feather2,Seth,SupportXmr,SupportXmrIr,XmrVsBeast, } impl std::fmt::Display for NodeEnum { @@ -112,7 +111,6 @@ pub fn ip_to_enum(ip: &'static str) -> NodeEnum { PLOWSOF_2 => Plowsof2, RINO => Rino, SETH => Seth, - SINGAPORE => Singapore, SUPPORTXMR => SupportXmr, SUPPORTXMR_IR => SupportXmrIr, _ => XmrVsBeast, @@ -135,7 +133,6 @@ pub fn enum_to_ip(node: NodeEnum) -> &'static str { Plowsof2 => PLOWSOF_2, Rino => RINO, Seth => SETH, - Singapore => SINGAPORE, SupportXmr => SUPPORTXMR, SupportXmrIr => SUPPORTXMR_IR, _ => XMRVSBEAST