v1.3.10
Some checks failed
Cache `gupax.io` / build (push) Has been cancelled
CI / ci (macos-14) (push) Has been cancelled
CI / ci (ubuntu-20.04) (push) Has been cancelled
CI / ci (windows-2019) (push) Has been cancelled
gupax.io / build (push) Has been cancelled
Remote Node Ping / build (push) Has been cancelled
Typo / typo (push) Has been cancelled

This commit is contained in:
hinto.janai 2024-11-21 20:16:32 -05:00
parent ab9912fccc
commit f3d29c99de
No known key found for this signature in database
GPG key ID: D47CE05FA175A499
32 changed files with 7797 additions and 6615 deletions

View file

@ -1,14 +0,0 @@
---
name: Feature request
about: Request a feature
title: ''
labels: feature
assignees: ''
---
**Feature request**
Describe the feature you're requesting.
**Additional context**
Add any other context or screenshots about the feature request.

View file

@ -1,4 +1,4 @@
# Forces `gupax.io` to cache stuff every day. # Forces `gupax.io` to cache.
name: Cache `gupax.io` name: Cache `gupax.io`
on: on:

View file

@ -16,7 +16,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [windows-2019, macos-12, ubuntu-20.04] os: [windows-2019, macos-14, ubuntu-20.04]
steps: steps:
- name: Checkout - name: Checkout
@ -39,6 +39,7 @@ jobs:
sudo apt install -y libgtk-3-dev sudo apt install -y libgtk-3-dev
elif [ "$RUNNER_OS" == "macOS" ]; then elif [ "$RUNNER_OS" == "macOS" ]; then
cargo install cargo-bundle cargo install cargo-bundle
rustup target install x86_64-apple-darwin
rustup target install aarch64-apple-darwin rustup target install aarch64-apple-darwin
fi fi
shell: bash shell: bash
@ -49,9 +50,9 @@ jobs:
- name: Build - name: Build
run: | run: |
if [ "$RUNNER_OS" == "macOS" ]; then if [ "$RUNNER_OS" == "macOS" ]; then
cargo bundle --release cargo bundle --release --target x86_64-apple-darwin
cargo bundle --release --target aarch64-apple-darwin cargo bundle --release --target aarch64-apple-darwin
mv target/release/bundle/osx/Gupax.app Gupax-macos-x64.app mv target/x86_64-apple-darwin/release/bundle/osx/Gupax.app Gupax-macos-x64.app
mv target/aarch64-apple-darwin/release/bundle/osx/Gupax.app Gupax-macos-arm64.app mv target/aarch64-apple-darwin/release/bundle/osx/Gupax.app Gupax-macos-arm64.app
tar -cf macos.tar Gupax-macos-arm64.app Gupax-macos-x64.app tar -cf macos.tar Gupax-macos-arm64.app Gupax-macos-x64.app
elif [ "$RUNNER_OS" == "Linux" ]; then elif [ "$RUNNER_OS" == "Linux" ]; then

View file

@ -3,8 +3,6 @@
name: Remote Node Ping name: Remote Node Ping
on: on:
schedule:
- cron: "0 4 * * *"
push: push:
branches: [ "main" ] branches: [ "main" ]
pull_request: pull_request:

View file

@ -1,3 +1,22 @@
# v1.3.10
## Changes
* [Remote Node](https://github.com/hinto-janai/gupax#remote-monero-nodes) changes:
- Removed `monero1.heitechsoft.com`
- Removed `node.cryptocano.de`
- Removed `fbx.tranbert.com`
- Removed `home.allantaylor.kiwi`
- Removed `sf.xmr.support`
* Text/visual changes
## Bundled Versions
* [`P2Pool v4.2`](https://github.com/SChernykh/p2pool/releases/tag/v4.2)
* [`XMRig v6.22.2`](https://github.com/xmrig/xmrig/releases/tag/v6.22.2)
---
# v1.3.9 # v1.3.9
## Changes ## Changes
* [Remote Node](https://github.com/hinto-janai/gupax#remote-monero-nodes) changes: * [Remote Node](https://github.com/hinto-janai/gupax#remote-monero-nodes) changes:

2071
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
[package] [package]
name = "gupax" name = "gupax"
version = "1.3.9" version = "1.3.10"
authors = ["hinto-janai <hinto.janai@protonmail.com>"] authors = ["hinto-janai <hinto.janai@protonmail.com>"]
description = "GUI for P2Pool+XMRig" description = "GUI for P2Pool+XMRig"
documentation = "https://github.com/hinto-janai/gupax" documentation = "https://github.com/hinto-janai/gupax"
@ -106,7 +106,7 @@ tls-api-native-tls = "0.9.0"
# Windows dependencies # Windows dependencies
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
zip = "1.2.2" zip = "1"
is_elevated = "0.1.2" is_elevated = "0.1.2"
wgpu = { version = "0.19.4", features = ["angle"] } wgpu = { version = "0.19.4", features = ["angle"] }
@ -121,3 +121,213 @@ name = "Gupax"
identifier = "com.github.hinto-janai.gupax" identifier = "com.github.hinto-janai.gupax"
icon = ["images/icons/icon@2x.png"] icon = ["images/icons/icon@2x.png"]
category = "public.app-category.utilities" category = "public.app-category.utilities"
[workspace.lints.clippy]
borrow_as_ptr = "deny"
case_sensitive_file_extension_comparisons = "deny"
cast_lossless = "deny"
cast_ptr_alignment = "deny"
checked_conversions = "deny"
cloned_instead_of_copied = "deny"
const_is_empty = "deny"
doc_lazy_continuation = "deny"
doc_link_with_quotes = "deny"
duplicated_attributes = "deny"
empty_enum = "deny"
enum_glob_use = "deny"
expl_impl_clone_on_copy = "deny"
explicit_into_iter_loop = "deny"
filter_map_next = "deny"
flat_map_option = "deny"
from_iter_instead_of_collect = "deny"
if_not_else = "deny"
ignored_unit_patterns = "deny"
inconsistent_struct_constructor = "deny"
index_refutable_slice = "deny"
inefficient_to_string = "deny"
invalid_upcast_comparisons = "deny"
iter_filter_is_ok = "deny"
iter_filter_is_some = "deny"
implicit_clone = "deny"
legacy_numeric_constants = "deny"
manual_c_str_literals = "deny"
manual_pattern_char_comparison = "deny"
manual_instant_elapsed = "deny"
manual_inspect = "deny"
manual_is_variant_and = "deny"
manual_let_else = "deny"
manual_ok_or = "deny"
manual_string_new = "deny"
manual_unwrap_or_default = "deny"
map_unwrap_or = "deny"
match_bool = "deny"
match_same_arms = "deny"
match_wildcard_for_single_variants = "deny"
mismatching_type_param_order = "deny"
missing_transmute_annotations = "deny"
mut_mut = "deny"
needless_bitwise_bool = "deny"
needless_character_iteration = "deny"
needless_continue = "deny"
needless_for_each = "deny"
needless_maybe_sized = "deny"
needless_raw_string_hashes = "deny"
no_effect_underscore_binding = "deny"
no_mangle_with_rust_abi = "deny"
option_as_ref_cloned = "deny"
option_option = "deny"
ptr_as_ptr = "deny"
ptr_cast_constness = "deny"
pub_underscore_fields = "deny"
redundant_closure_for_method_calls = "deny"
ref_as_ptr = "deny"
ref_option_ref = "deny"
same_functions_in_if_condition = "deny"
semicolon_if_nothing_returned = "deny"
trivially_copy_pass_by_ref = "deny"
uninlined_format_args = "deny"
unnecessary_join = "deny"
unnested_or_patterns = "deny"
unused_async = "deny"
unused_self = "deny"
used_underscore_binding = "deny"
zero_sized_map_values = "deny"
as_ptr_cast_mut = "deny"
clear_with_drain = "deny"
collection_is_never_read = "deny"
debug_assert_with_mut_call = "deny"
derive_partial_eq_without_eq = "deny"
empty_line_after_doc_comments = "deny"
empty_line_after_outer_attr = "deny"
equatable_if_let = "deny"
iter_on_empty_collections = "deny"
iter_on_single_items = "deny"
iter_with_drain = "deny"
needless_collect = "deny"
needless_pass_by_ref_mut = "deny"
negative_feature_names = "deny"
non_send_fields_in_send_ty = "deny"
nonstandard_macro_braces = "deny"
path_buf_push_overwrite = "deny"
read_zero_byte_vec = "deny"
redundant_clone = "deny"
redundant_feature_names = "deny"
trailing_empty_array = "deny"
trait_duplication_in_bounds = "deny"
type_repetition_in_bounds = "deny"
uninhabited_references = "deny"
unnecessary_struct_initialization = "deny"
unused_peekable = "deny"
unused_rounding = "deny"
use_self = "deny"
useless_let_if_seq = "deny"
wildcard_dependencies = "deny"
unseparated_literal_suffix = "deny"
unnecessary_safety_doc = "deny"
unnecessary_safety_comment = "deny"
unnecessary_self_imports = "deny"
string_to_string = "deny"
rest_pat_in_fully_bound_structs = "deny"
redundant_type_annotations = "deny"
infinite_loop = "deny"
zero_repeat_side_effects = "deny"
cast_possible_truncation = "deny"
cast_possible_wrap = "deny"
cast_precision_loss = "deny"
cast_sign_loss = "deny"
copy_iterator = "deny"
doc_markdown = "deny"
explicit_deref_methods = "deny"
explicit_iter_loop = "deny"
float_cmp = "deny"
fn_params_excessive_bools = "deny"
into_iter_without_iter = "deny"
iter_without_into_iter = "deny"
iter_not_returning_iterator = "deny"
large_digit_groups = "deny"
large_types_passed_by_value = "deny"
manual_assert = "deny"
maybe_infinite_iter = "deny"
missing_fields_in_debug = "deny"
needless_pass_by_value = "deny"
range_minus_one = "deny"
range_plus_one = "deny"
redundant_else = "deny"
ref_binding_to_reference = "deny"
return_self_not_must_use = "deny"
single_match_else = "deny"
string_add_assign = "deny"
transmute_ptr_to_ptr = "deny"
unchecked_duration_subtraction = "deny"
unnecessary_box_returns = "deny"
unnecessary_wraps = "deny"
branches_sharing_code = "deny"
fallible_impl_from = "deny"
missing_const_for_fn = "deny"
significant_drop_in_scrutinee = "deny"
significant_drop_tightening = "deny"
try_err = "deny"
lossy_float_literal = "deny"
let_underscore_must_use = "deny"
iter_over_hash_type = "deny"
get_unwrap = "deny"
error_impl_error = "deny"
empty_structs_with_brackets = "deny"
empty_enum_variants_with_brackets = "deny"
empty_drop = "deny"
clone_on_ref_ptr = "deny"
upper_case_acronyms = "deny"
allow_attributes = "deny"
# inline_always = "deny"
# large_futures = "deny"
# large_stack_arrays = "deny"
# linkedlist = "deny"
# missing_errors_doc = "deny"
# missing_panics_doc = "deny"
# should_panic_without_expect = "deny"
# similar_names = "deny"
# too_many_lines = "deny"
# unreadable_literal = "deny"
# wildcard_imports = "deny"
# allow_attributes_without_reason = "deny"
# missing_assert_message = "deny"
# missing_docs_in_private_items = "deny"
undocumented_unsafe_blocks = "deny"
# multiple_unsafe_ops_per_block = "deny"
# single_char_lifetime_names = "deny"
# wildcard_enum_match_arm = "deny"
[workspace.lints.rust]
future_incompatible = { level = "deny", priority = -1 }
nonstandard_style = { level = "deny", priority = -1 }
absolute_paths_not_starting_with_crate = "deny"
explicit_outlives_requirements = "deny"
keyword_idents_2018 = "deny"
keyword_idents_2024 = "deny"
missing_abi = "deny"
non_ascii_idents = "deny"
non_local_definitions = "deny"
redundant_lifetimes = "deny"
single_use_lifetimes = "deny"
trivial_casts = "deny"
trivial_numeric_casts = "deny"
unsafe_op_in_unsafe_fn = "deny"
unused_crate_dependencies = "deny"
unused_import_braces = "deny"
unused_lifetimes = "deny"
unused_macro_rules = "deny"
ambiguous_glob_imports = "deny"
unused_unsafe = "deny"
let_underscore = { level = "deny", priority = -1 }
unreachable_pub = "deny"
unused_qualifications = "deny"
variant_size_differences = "deny"
non_camel_case_types = "deny"
# unused_results = "deny"
# non_exhaustive_omitted_patterns = "deny"
# missing_docs = "deny"
# missing_copy_implementations = "deny"

130
README.md
View file

@ -3,9 +3,9 @@
Gupax is a GUI for mining [**Monero**](https://github.com/monero-project/monero) on [**P2Pool**](https://github.com/SChernykh/p2pool), using [**XMRig**](https://github.com/xmrig/xmrig). Gupax is a GUI for mining [**Monero**](https://github.com/monero-project/monero) on [**P2Pool**](https://github.com/SChernykh/p2pool), using [**XMRig**](https://github.com/xmrig/xmrig).
**To see a 3-minute video guide on how to set-up Gupax: [click here.](#Guide)** To see a 3-minute video guide on how to set-up Gupax: [click here.](#Guide)
[![CI](https://github.com/hinto-janai/gupax/actions/workflows/ci.yml/badge.svg)](https://github.com/hinto-janai/gupax/actions/workflows/ci.yml) [![gupax.io](https://github.com/hinto-janai/gupax/actions/workflows/download.yml/badge.svg)](https://github.com/hinto-janai/gupax/actions/workflows/download.yml) [![Remote Node Ping](https://github.com/hinto-janai/gupax/actions/workflows/ping.yml/badge.svg)](https://github.com/hinto-janai/gupax/actions/workflows/ping.yml) [![CI](https://github.com/hinto-janai/gupax/actions/workflows/ci.yml/badge.svg)](https://github.com/hinto-janai/gupax/actions/workflows/ci.yml) [![gupax.io](https://github.com/hinto-janai/gupax/actions/workflows/download.yml/badge.svg)](https://github.com/hinto-janai/gupax/actions/workflows/download.yml)
</div> </div>
@ -19,11 +19,10 @@ Gupax is a GUI for mining [**Monero**](https://github.com/monero-project/monero)
- [XMRig](#XMRig) - [XMRig](#XMRig)
* [Advanced](#Advanced) * [Advanced](#Advanced)
- [Verifying](#Verifying) - [Verifying](#Verifying)
- [Running a Local Monero Node](#running-a-local-monero-node) - [Running a Local Monero node](#running-a-local-monero-node)
- [Command Line](#Command-Line) - [Command Line](#Command-Line)
- [Key Shortcuts](#Key-Shortcuts) - [Key Shortcuts](#Key-Shortcuts)
- [Resolution](#Resolution) - [Tor](#Tor)
- [Tor/Arti](#TorArti)
- [Logs](#Logs) - [Logs](#Logs)
- [Disk](#Disk) - [Disk](#Disk)
- [Swapping P2Pool/XMRig](#Swapping-P2PoolXMRig) - [Swapping P2Pool/XMRig](#Swapping-P2PoolXMRig)
@ -32,7 +31,7 @@ Gupax is a GUI for mining [**Monero**](https://github.com/monero-project/monero)
- [P2Pool](#P2Pool-1) - [P2Pool](#P2Pool-1)
- [XMRig](#XMRig-1) - [XMRig](#XMRig-1)
* [Connections](#Connections) * [Connections](#Connections)
* [Remote Monero Nodes](#remote-monero-nodes) * [Remote Monero nodes](#remote-monero-nodes)
* [Build](#Build) * [Build](#Build)
- [General Info](#General-Info) - [General Info](#General-Info)
- [Linux](#Linux) - [Linux](#Linux)
@ -54,7 +53,7 @@ Gupax is a GUI for mining [**Monero**](https://github.com/monero-project/monero)
## What is Monero/P2Pool/XMRig/Gupax? ## What is Monero/P2Pool/XMRig/Gupax?
[**`Monero`**](https://getmonero.org) is a secure, private, and untraceable cryptocurrency. [**`Monero`**](https://getmonero.org) is a secure, private, and untraceable cryptocurrency.
[Monero GUI](https://github.com/monero-project/monero-gui) allows you to run a Monero node (among other things). [Monero GUI](https://github.com/monero-project/monero-gui) allows you to run a Monero node, among other things.
--- ---
@ -69,17 +68,17 @@ P2Pool combines the best of solo mining and traditional pool mining:
* **It's decentralized:** There's no central server that can be shutdown or pool admin that controls your hashrate * **It's decentralized:** There's no central server that can be shutdown or pool admin that controls your hashrate
* **It's permissionless:** It's peer-to-peer so there's no one to decide who can and cannot mine on the pool * **It's permissionless:** It's peer-to-peer so there's no one to decide who can and cannot mine on the pool
* **It's trustless:** Funds are never in custody, all pool blocks pay out to miners directly and immediately * **It's trustless:** Funds are never in custody, all pool blocks pay out to miners directly and immediately
* **0% transaction fee, 0 payout fee, immediate ~0.0003 XMR minimum payout** * **0% transaction fee, 0 payout fee, immediate ~0.00027 XMR minimum payout**
--- ---
[**`XMRig`**](https://github.com/xmrig/xmrig) is an optimized miner that can mine Monero. [**`XMRig`**](https://github.com/xmrig/xmrig) is an optimized miner that can mine Monero.
Both Monero and P2Pool have built in miners but XMRig is quite faster than both of them. Due to issues like [anti-virus flagging](https://github.com/monero-project/monero-gui/pull/3829#issuecomment-1018191461), it is not feasible to integrate XMRig directly into Monero. Both Monero and P2Pool have built in miners but XMRig is faster than both of them. Due to issues like [anti-virus flagging](https://github.com/monero-project/monero-gui/pull/3829#issuecomment-1018191461), it is not feasible to integrate XMRig directly into Monero.
--- ---
[**`Gupax`**](https://github.com/hinto-janai/gupax) is a GUI that helps manage P2Pool & XMRig (both originally CLI-only). [**`Gupax`**](https://github.com/hinto-janai/gupax) is a GUI that helps manage P2Pool & XMRig which are both CLI-only.
<img src="images/local.png" align="left" width="50%"/> <img src="images/local.png" align="left" width="50%"/>
@ -97,7 +96,7 @@ Both Monero and P2Pool have built in miners but XMRig is quite faster than both
<img src="images/remote.png" align="left" width="50%"/> <img src="images/remote.png" align="left" width="50%"/>
By default, Gupax will use a [Remote Monero Node](#remote-monero-nodes) so you don't have to run [your own Monero node](#running-a-local-monero-node) to start mining on P2Pool. By default, Gupax will use a [Remote Monero node](#remote-monero-nodes) so you don't have to run [your own Monero node](#running-a-local-monero-node) to start mining on P2Pool.
<br clear="left"/> <br clear="left"/>
@ -110,7 +109,7 @@ https://user-images.githubusercontent.com/101352116/207978455-6ffdc0cc-204c-4594
2. Extract 2. Extract
3. Launch Gupax 3. Launch Gupax
4. Input your Monero address in the `P2Pool` tab 4. Input your Monero address in the `P2Pool` tab
5. Select a [`Remote Monero Node`](#remote-monero-nodes) (or run your own local [Monero Node](#running-a-local-monero-node)) 5. Select a [`Remote Monero node`](#remote-monero-nodes) (or run your own local [Monero node](#running-a-local-monero-node))
6. Start P2Pool 6. Start P2Pool
7. Start XMRig 7. Start XMRig
@ -167,8 +166,8 @@ This tab has the updater and general Gupax settings.
If `Check for updates` is pressed, Gupax will update your `Gupax/P2Pool/XMRig` (if needed) using the [GitHub API](#where-are-updates-downloaded-from). If `Check for updates` is pressed, Gupax will update your `Gupax/P2Pool/XMRig` (if needed) using the [GitHub API](#where-are-updates-downloaded-from).
Below that, there are some general Gupax settings: Below that, there are some general Gupax settings:
| Setting | What does it do? | | Setting | What it does |
|--------------------|-------------------| |--------------------|--------------|
| `Update via Tor` | Causes updates to be fetched via the Tor network. Tor is embedded within Gupax; a Tor system proxy is not required | `Update via Tor` | Causes updates to be fetched via the Tor network. Tor is embedded within Gupax; a Tor system proxy is not required
| `Auto-Update` | Gupax will automatically check for updates at startup | `Auto-Update` | Gupax will automatically check for updates at startup
| `Auto-P2Pool` | Gupax will automatically start P2Pool at startup | `Auto-P2Pool` | Gupax will automatically start P2Pool at startup
@ -179,7 +178,7 @@ Below that, there are some general Gupax settings:
--- ---
### P2Pool ### P2Pool
P2Pool Simple allows you to ping & connect to a [Remote Monero Node](#remote-monero-nodes) and start your own local P2Pool instance on the `Mini` sidechain. P2Pool Simple allows you to ping & connect to a [Remote Monero node](#remote-monero-nodes) and start your own local P2Pool instance on the `Mini` sidechain.
To start P2Pool, first input the Monero address you'd like to receive payouts from. You must use a primary Monero address to mine on P2Pool (starts with a 4). It is highly recommended to create a new wallet since addresses are public on P2Pool! To start P2Pool, first input the Monero address you'd like to receive payouts from. You must use a primary Monero address to mine on P2Pool (starts with a 4). It is highly recommended to create a new wallet since addresses are public on P2Pool!
@ -204,30 +203,27 @@ XMRig Simple will always mine to your own local P2Pool (`127.0.0.1:3333`), if yo
### Verifying ### Verifying
It is recommended to verify the hash and PGP signature of the download before using Gupax. It is recommended to verify the hash and PGP signature of the download before using Gupax.
Download the [`SHA256SUMS`](https://github.com/hinto-janai/gupax/releases/latest) file, download and import my [`PGP key`](https://github.com/hinto-janai/gupax/blob/main/pgp/hinto-janai.asc), and verify: Download the [`SHA256SUMS`](https://github.com/hinto-janai/gupax/releases/latest) file, download and import this [`PGP key`](https://github.com/hinto-janai/gupax/blob/main/pgp/hinto-janai.asc), and verify:
```bash ```bash
sha256sum -c SHA256SUMS sha256sum -c SHA256SUMS
gpg --import hinto-janai.asc gpg --import hinto-janai.asc
gpg --verify SHA256SUMS gpg --verify SHA256SUMS
``` ```
Q: How can I be sure the P2Pool/XMRig bundled with Gupax hasn't been tampered with? You can compare the hash of the `P2Pool/XMRig` binaries bundled with Gupax with the hashes of the binaries found here:
A: Verify the hash.
You can always compare the hash of the `P2Pool/XMRig` binaries bundled with Gupax with the hashes of the binaries found here:
- https://github.com/SChernykh/p2pool/releases - https://github.com/SChernykh/p2pool/releases
- https://github.com/xmrig/xmrig/releases - https://github.com/xmrig/xmrig/releases
Make sure the _version_ you are comparing against is correct, and make sure you are comparing the _binary_ to the _binary_, not the `tar/zip`. If they match, you can be sure they are the exact same. Verifying the PGP signature is also recommended: Make sure the _version_ you are comparing against is correct, and make sure you are comparing the _binary_ to the _binary_, not the `tar/zip`. If they match, they are the exact same. Verifying the PGP signature is also recommended:
- P2Pool - [`SChernykh.asc`](https://github.com/monero-project/gitian.sigs/blob/master/gitian-pubkeys/SChernykh.asc) - P2Pool - [`SChernykh.asc`](https://github.com/monero-project/gitian.sigs/blob/master/gitian-pubkeys/SChernykh.asc)
- XMRig - [`xmrig.asc`](https://github.com/xmrig/xmrig/blob/master/doc/gpg_keys/xmrig.asc) - XMRig - [`xmrig.asc`](https://github.com/xmrig/xmrig/blob/master/doc/gpg_keys/xmrig.asc)
--- ---
### Running a Local Monero Node ### Running a Local Monero node
Running and using your own local Monero node improves privacy and security. It also means you won't be depending on one of the [Remote Monero Nodes](#remote-monero-nodes) provided by Gupax. This comes at the cost of downloading and syncing Monero's blockchain yourself (currently `155GB`). Running and using your own local Monero node improves privacy and security. It also means you won't be depending on one of the [Remote Monero nodes](#remote-monero-nodes) provided by Gupax. This comes at the cost of downloading and syncing Monero's blockchain yourself.
If you'd like to run and use your own local Monero node for P2Pool, follow these steps: To run and use your own local Monero node for P2Pool, follow these steps:
<div align="center"> <div align="center">
<img src="images/local_node.png" width="66%"/> <img src="images/local_node.png" width="66%"/>
@ -237,11 +233,10 @@ If you'd like to run and use your own local Monero node for P2Pool, follow these
3. Enable `Local node` 3. Enable `Local node`
4. Enter `--zmq-pub=tcp://127.0.0.1:18083` into `Daemon startup flags` 4. Enter `--zmq-pub=tcp://127.0.0.1:18083` into `Daemon startup flags`
5. [(Optionally)](https://github.com/SChernykh/p2pool#windows) enter `--disable-dns-checkpoints --enable-dns-blocklist` into `Daemon startup flags` 5. [(Optionally)](https://github.com/SChernykh/p2pool#windows) enter `--disable-dns-checkpoints --enable-dns-blocklist` into `Daemon startup flags`
6. Start and fully sync node
</div> </div>
After syncing the blockchain, you will now have your own Monero node.
The 4th step enables `ZMQ`, which is extra Monero node functionality that is needed for P2Pool to work correctly. The 4th step enables `ZMQ`, which is extra Monero node functionality that is needed for P2Pool to work correctly.
The 5th step: The 5th step:
@ -249,14 +244,10 @@ The 5th step:
- `--disable-dns-checkpoints` avoids periodical lag when DNS is updated (it's not needed when mining) - `--disable-dns-checkpoints` avoids periodical lag when DNS is updated (it's not needed when mining)
- `--enable-dns-blocklist` bans known bad nodes - `--enable-dns-blocklist` bans known bad nodes
[For more detailed information on configuring a Monero node, click here.](https://monerodocs.org)
--- ---
### Command Line ### Command Line
By default, Gupax has `auto-update` & `auto-ping` enabled. This can only be turned off in the GUI which causes a chicken-and-egg problem. By default, Gupax has `auto-update` & `auto-ping` enabled. This can only be turned off in the GUI. To get around this, start Gupax with `--no-startup`. This will disable all `auto` features for that instance.
To get around this, start Gupax with `--no-startup`. This will disable all `auto` features for that instance.
``` ```
USAGE: ./gupax [--flag] USAGE: ./gupax [--flag]
@ -276,9 +267,6 @@ USAGE: ./gupax [--flag]
--- ---
### Key Shortcuts ### Key Shortcuts
The letter keys (Z/X/C/V/S/R) will only work if nothing is in focus, i.e, you _are not_ editing a text box.
An ALT+F4 will also trigger the exit confirm screen (if enabled).
``` ```
*---------------------------------------* *---------------------------------------*
| Key shortcuts | | Key shortcuts |
@ -298,23 +286,10 @@ An ALT+F4 will also trigger the exit confirm screen (if enabled).
--- ---
### Resolution ### Tor
The default resolution of Gupax is `1280x960` which is a `4:3` aspect ratio.
This can be changed by dragging the corner of the window itself or by using the resolution sliders in the `Gupax Advanced` tab. After a resolution change, Gupax will fade-in/out of black and will take a second to resize all the UI elements to scale correctly to the new resolution.
If you have changed your OS's pixel scaling, you may need to resize Gupax to see all UI correctly.
The minimum window size is: `640x480`
The maximum window size is: `3840x2160`
Fullscreen mode can also be entered by pressing `F11`.
---
### Tor/Arti
By default, Gupax updates via Tor. In particular, it uses [`Arti`](https://gitlab.torproject.org/tpo/core/arti), the official Rust implementation of Tor. By default, Gupax updates via Tor. In particular, it uses [`Arti`](https://gitlab.torproject.org/tpo/core/arti), the official Rust implementation of Tor.
Instead of bootstrapping onto the Tor network every time, Arti saves state/cache about the Tor network (circuits, guards, etc) for later reuse onto the disk: Arti saves state/cache about the Tor network (circuits, guards, etc) for later reuse onto the disk:
State: State:
| OS | Data Folder | | OS | Data Folder |
@ -354,10 +329,8 @@ The current files saved to disk:
--- ---
### Logs ### Logs
Gupax has console logs that show with increasing detail, what exactly it is is doing.
There are multiple log filter levels but by default, `INFO` and above are enabled. There are multiple log filter levels but by default, `INFO` and above are enabled.
To view more detailed console debug information, start Gupax with the environment variable `RUST_LOG` set to a log level like so: To view more detailed console debug information, start Gupax with the environment variable `RUST_LOG` set to a log level:
```bash ```bash
RUST_LOG=(trace|debug|info|warn|error) ./gupax RUST_LOG=(trace|debug|info|warn|error) ./gupax
``` ```
@ -366,12 +339,11 @@ For example:
RUST_LOG=debug ./gupax RUST_LOG=debug ./gupax
``` ```
In general: - `ERROR`: has gone wrong and that something will probably break
- `ERROR` means something has gone wrong and that something will probably break - `WARN`: something has gone wrong, but things will be fine
- `WARN` means something has gone wrong, but things will be fine - `INFO`: general info about what Gupax (the GUI thread) is currently doing
- `INFO` logs are general info about what Gupax (the GUI thread) is currently doing - `DEBUG`: much more verbose and include what EVERY thread is doing (not just the main GUI thread)
- `DEBUG` logs are much more verbose and include what EVERY thread is doing (not just the main GUI thread) - `TRACE`: insanely verbose and shows very low-level logs
- `TRACE` logs are insanely verbose and shows very low-level logs
--- ---
@ -463,13 +435,13 @@ Along with the updater and settings mentioned in [Simple](#simple), `Gupax Advan
- The selected tab on startup - The selected tab on startup
- Gupax's resolution - Gupax's resolution
**Warning:** Gupax will use your custom PATH/binary and will replace them if you use `Check for updates` in the `[Gupax]` tab. There are sanity checks in place, however. Your PATH MUST end in a value that _appears_ correct or else the updater will refuse to start: **Warning:** Gupax will use your custom PATH/binary and will replace them if you use `Check for updates` in the `[Gupax]` tab. Your PATH must end in a value that appears correct or else the updater will refuse to start:
| Binary | Accepted values | Good PATH | Bad PATH | | Binary | Accepted values | Good PATH | Bad PATH |
|----------|----------------------------------|-----------------|----------| |----------|----------------------------------|-----------------|----------|
| `P2Pool` | `P2POOL, P2Pool, P2pool, p2pool` | `P2pool/p2pool` | `Documents/my_really_important_file` | `P2Pool` | `P2POOL, P2Pool, P2pool, p2pool` | `P2pool/p2pool` | `Documents/important_file`
| `XMRig` | `XMRIG, XMRig, Xmrig, xmrig` | `XMRig/XMRig` | `Desktop/` | `XMRig` | `XMRIG, XMRig, Xmrig, xmrig` | `XMRig/XMRig` | `Desktop/`
If using Windows, the PATH _must_ end with `.exe`. If using Windows, the PATH must end with `.exe`.
--- ---
@ -488,9 +460,9 @@ The manual node list allows you save and connect up-to 1000 custom Monero nodes:
| Data Field | Purpose | Limits | Max Length | | Data Field | Purpose | Limits | Max Length |
|------------|---------------------------------------------------------------|--------------------------------------------------------|----------------| |------------|---------------------------------------------------------------|--------------------------------------------------------|----------------|
| `Name` | A unique name to identify this node (only for Gupax purposes) | Only `[A-Za-z0-9-_.]` and spaces allowed | 30 characters | | `Name` | A unique name to identify this node (only for Gupax purposes) | Only `[A-Za-z0-9-_.]` and spaces allowed | 30 characters |
| `IP` | The Monero Node IP to connect to with P2Pool | It must be a valid IPv4 address or a valid domain name | 255 characters | | `IP` | The Monero node IP to connect to with P2Pool | It must be a valid IPv4 address or a valid domain name | 255 characters |
| `RPC` | The RPC port of the Monero node | `[1-65535]` | 5 characters | | `RPC` | The RPC port of the Monero node | `[1-65535]` | 5 characters |
| `ZMQ` | The ZMQ port of the Monero node | `[1-65535]` | 5 characters | | `ZMQ` | The ZMQ port of the Monero node | `[1-65535]` | 5 characters |
The `Main/Mini` selector allows you to change which P2Pool sidechain you mine on: The `Main/Mini` selector allows you to change which P2Pool sidechain you mine on:
| P2Pool Sidechain | Description | Use-case | | P2Pool Sidechain | Description | Use-case |
@ -514,7 +486,6 @@ The remaining sliders control miscellaneous settings:
| `In peers` | How many in-bound peers P2Pool will allow to connect to you | `10` | `10..450` | | `In peers` | How many in-bound peers P2Pool will allow to connect to you | `10` | `10..450` |
| `Log level` | Verbosity of the P2Pool console log | `3` | `0..6` | | `Log level` | Verbosity of the P2Pool console log | `3` | `0..6` |
--- ---
### XMRig ### XMRig
@ -537,7 +508,7 @@ The manual pool list allows you save and connect up-to 1000 custom Pools (regard
|------------|---------------------------------------------------------------|--------------------------------------------------------|----------------| |------------|---------------------------------------------------------------|--------------------------------------------------------|----------------|
| `Name` | A unique name to identify this pool (only for Gupax purposes) | Only `[A-Za-z0-9-_.]` and spaces allowed | 30 characters | | `Name` | A unique name to identify this pool (only for Gupax purposes) | Only `[A-Za-z0-9-_.]` and spaces allowed | 30 characters |
| `IP` | The pool IP to connect to with XMRig | It must be a valid IPv4 address or a valid domain name | 255 characters | | `IP` | The pool IP to connect to with XMRig | It must be a valid IPv4 address or a valid domain name | 255 characters |
| `Port` | The port of the pool | `[1-65535]` | 5 characters | | `Port` | The port of the pool | `[1-65535]` | 5 characters |
| `Rig` | An optional rig ID; This will be the name shown on the pool | Only `[A-Za-z0-9-_]` and spaces allowed | 30 characters | | `Rig` | An optional rig ID; This will be the name shown on the pool | Only `[A-Za-z0-9-_]` and spaces allowed | 30 characters |
The HTTP API textboxes allow you to change to IP/Port XMRig's HTTP API opens up on: The HTTP API textboxes allow you to change to IP/Port XMRig's HTTP API opens up on:
@ -558,25 +529,20 @@ For transparency, here's all the connections Gupax makes:
| Domain | Why | When | Where | | Domain | Why | When | Where |
|--------------------|-------------------------------------------------------|------|-------| |--------------------|-------------------------------------------------------|------|-------|
| https://github.com | Fetching metadata information on packages + download | `[Gupax]` tab -> `Check for updates` | [`update.rs`](https://github.com/hinto-janai/gupax/blob/main/src/update.rs) | | https://github.com | Fetching metadata information on packages + download | `[Gupax]` tab -> `Check for updates` | [`update.rs`](https://github.com/hinto-janai/gupax/blob/main/src/update.rs) |
| Remote Monero Nodes | Connecting to with P2Pool, measuring ping latency | `[P2Pool Simple]` tab | [`node.rs`](https://github.com/hinto-janai/gupax/blob/main/src/node.rs) | | Remote Monero nodes | Connecting to with P2Pool, measuring ping latency | `[P2Pool Simple]` tab | [`node.rs`](https://github.com/hinto-janai/gupax/blob/main/src/node.rs) |
| DNS | DNS connections will usually be handled by your OS (or whatever custom DNS setup you have). If using Tor, DNS requests for updates [*should*](https://tpo.pages.torproject.net/core/doc/rust/arti/) be routed through the Tor network automatically | All of the above | All of the above | | DNS | DNS connections will usually be handled by your OS (or whatever custom DNS setup you have). If using Tor, DNS requests for updates [*should*](https://tpo.pages.torproject.net/core/doc/rust/arti/) be routed through the Tor network automatically | All of the above | All of the above |
## Remote Monero Nodes ## Remote Monero nodes
These are the remote nodes used by Gupax in the `[P2Pool Simple]` tab. These are the remote nodes used by Gupax in the `[P2Pool Simple]` tab.
| IP/Domain | Location | RPC Port | ZMQ Port | | IP/Domain | Location | RPC Port | ZMQ Port |
|-------------------------|-------------------|----------|----------| |-------------------------|-------------------|----------|----------|
| monero.10z.com.ar | 🇦🇷 Argentina | 18089 | 18084 | | monero.10z.com.ar | 🇦🇷 Argentina | 18089 | 18084 |
| monero1.heitechsoft.com | 🇨🇦 Canada | 18081 | 18084 |
| node.monerodevs.org | 🇨🇦 Canada | 18089 | 18084 | | node.monerodevs.org | 🇨🇦 Canada | 18089 | 18084 |
| node.cryptocano.de | 🇩🇪 Germany | 18089 | 18083 |
| p2pmd.xmrvsbeast.com | 🇩🇪 Germany | 18081 | 18083 | | p2pmd.xmrvsbeast.com | 🇩🇪 Germany | 18081 | 18083 |
| fbx.tranbert.com | 🇫🇷 France | 18089 | 18084 |
| node2.monerodevs.org | 🇫🇷 France | 18089 | 18084 | | node2.monerodevs.org | 🇫🇷 France | 18089 | 18084 |
| home.allantaylor.kiwi | 🇳🇿 New Zealand | 18089 | 18083 |
| p2pool.uk | 🇬🇧 United Kingdom | 18089 | 18084 | | p2pool.uk | 🇬🇧 United Kingdom | 18089 | 18084 |
| xmr.support | 🇺🇸 United States | 18081 | 18083 | | xmr.support | 🇺🇸 United States | 18081 | 18083 |
| sf.xmr.support | 🇺🇸 United States | 18081 | 18083 |
| xmrbandwagon.hopto.org | 🇺🇸 United States | 18081 | 18084 | | xmrbandwagon.hopto.org | 🇺🇸 United States | 18081 | 18084 |
| xmr.spotlightsound.com | 🇺🇸 United States | 18081 | 18084 | | xmr.spotlightsound.com | 🇺🇸 United States | 18081 | 18084 |
| node.richfowler.net | 🇺🇸 United States | 18089 | 18084 | | node.richfowler.net | 🇺🇸 United States | 18089 | 18084 |
@ -585,16 +551,10 @@ These are the remote nodes used by Gupax in the `[P2Pool Simple]` tab.
### General Info ### General Info
You need [`cargo`](https://www.rust-lang.org/learn/get-started), Rust's build tool and package manager. You need [`cargo`](https://www.rust-lang.org/learn/get-started), Rust's build tool and package manager.
There are `41` unit tests, you should probably run:
```
cargo test
```
before attempting a full build.
--- ---
### Linux ### Linux
The pre-compiled Linux binaries are built on Debian 11, you'll need these packages to build: The pre-compiled Linux binaries are built on Ubuntu 20.04, you'll need these packages to build:
``` ```
sudo apt install build-essential cmake libgtk-3-dev sudo apt install build-essential cmake libgtk-3-dev
``` ```
@ -706,17 +666,17 @@ GitHub's API blocks request that do not have an HTTP `User-Agent` header.
[Gupax uses a random recent version of a `Wget/Curl` user-agent.](https://github.com/hinto-janai/gupax/blob/2c5bd0d7f6a39415353769427d60c0ca57f29710/src/update.rs#L178) [Gupax uses a random recent version of a `Wget/Curl` user-agent.](https://github.com/hinto-janai/gupax/blob/2c5bd0d7f6a39415353769427d60c0ca57f29710/src/update.rs#L178)
### P2Pool connection errors ### P2Pool connection errors
**TL;DR: Run & use your own Monero Node.** **TL;DR: Run & use your own Monero node.**
If you are using the [default P2Pool settings](#P2Pool) then you are using a [Remote Monero Node](#remote-monero-nodes). Using a remote node is convenient but comes at the cost of privacy and reliability. You may encounter connections issues with these nodes that look like this: If you are using the [default P2Pool settings](#P2Pool) then you are using a [Remote Monero node](#remote-monero-nodes). Using a remote node is convenient but comes at the cost of privacy and reliability. You may encounter connections issues with these nodes that look like this:
``` ```
2023-01-05 12:27:37.7962 P2PServer peer 23.233.96.72:37888 is ahead on mainchain (height 2792939, your height 2792936). Is your monerod stuck or lagging? 2023-01-05 12:27:37.7962 P2PServer peer 23.233.96.72:37888 is ahead on mainchain (height 2792939, your height 2792936). Is your monerod stuck or lagging?
``` ```
To fix this you can select a different remote node, or better yet: [Run your own local Monero Node](#running-a-local-monero-node). To fix this you can select a different remote node, or better yet: [Run your own local Monero node](#running-a-local-monero-node).
Running and using your own local Monero node improves privacy and ensures your connection is as stable as your own internet connection. This comes at the cost of downloading and syncing Monero's blockchain yourself (currently 155GB). If you have the disk space, consider using the [P2Pool Advanced](#p2pool-1) tab and connecting to your own Monero node. Running and using your own local Monero node improves privacy and ensures your connection is as stable as your own internet connection. This comes at the cost of downloading and syncing Monero's blockchain yourself (currently 155GB). If you have the disk space, consider using the [P2Pool Advanced](#p2pool-1) tab and connecting to your own Monero node.
For a simple guide, see the [Running a Local Monero Node](#running-a-local-monero-node) section. For a simple guide, see the [Running a Local Monero node](#running-a-local-monero-node) section.
### Can I quit mid-update? ### Can I quit mid-update?
If you started an update, you should let it finish. If the update has been stuck for a *long* time, quitting Gupax is probably okay. 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. If you started an update, you should let it finish. If the update has been stuck for a *long* time, quitting Gupax is probably okay. 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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 KiB

View file

@ -21,7 +21,6 @@
| cpu.json | [XMRig benchmark data in JSON](https://github.com/hinto-janai/xmrig-benchmarks) | cpu.json | [XMRig benchmark data in JSON](https://github.com/hinto-janai/xmrig-benchmarks)
| constants.rs | General constants used in Gupax | constants.rs | General constants used in Gupax
| disk.rs | Code for writing to disk: `state.toml/node.toml/pool.toml`; This holds the structs for the [State] struct | disk.rs | Code for writing to disk: `state.toml/node.toml/pool.toml`; This holds the structs for the [State] struct
| ferris.rs | Cute crab bytes
| gupax.rs | `Gupax` tab | gupax.rs | `Gupax` tab
| helper.rs | The "helper" thread that runs for the entire duration Gupax is alive. All the processing that needs to be done without blocking the main GUI thread runs here, including everything related to handling P2Pool/XMRig | helper.rs | The "helper" thread that runs for the entire duration Gupax is alive. All the processing that needs to be done without blocking the main GUI thread runs here, including everything related to handling P2Pool/XMRig
| human.rs | Code for displaying human readable numbers & time | human.rs | Code for displaying human readable numbers & time

View file

@ -16,8 +16,8 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
pub const GUPAX_VERSION: &str = concat!("v", env!("CARGO_PKG_VERSION")); // e.g: v1.0.0 pub const GUPAX_VERSION: &str = concat!("v", env!("CARGO_PKG_VERSION")); // e.g: v1.0.0
pub const P2POOL_VERSION: &str = "v3.10"; pub const P2POOL_VERSION: &str = "v4.2";
pub const XMRIG_VERSION: &str = "v6.21.3"; pub const XMRIG_VERSION: &str = "v6.22.2";
pub const COMMIT: &str = env!("COMMIT"); // set in build.rs pub const COMMIT: &str = env!("COMMIT"); // set in build.rs
// e.g: Gupax_v1_0_0 // e.g: Gupax_v1_0_0
// Would have been [Gupax_v1.0.0] but P2Pool truncates everything after [.] // Would have been [Gupax_v1.0.0] but P2Pool truncates everything after [.]
@ -164,10 +164,10 @@ pub const STATUS_GUPAX_SYSTEM_CPU_MODEL: &str =
pub const STATUS_P2POOL_UPTIME: &str = "How long P2Pool has been online"; pub const STATUS_P2POOL_UPTIME: &str = "How long P2Pool has been online";
pub const STATUS_P2POOL_PAYOUTS: &str = "The total amount of payouts received in this instance of P2Pool and an extrapolated estimate of how many you will receive. pub const STATUS_P2POOL_PAYOUTS: &str = "The total amount of payouts received in this instance of P2Pool and an extrapolated estimate of how many you will receive.
Note: these stats will be quite inaccurate if your P2Pool hasn't been running for a long time!"; Note: these stats will be quite inaccurate if your P2Pool hasn't been running for a long time.";
pub const STATUS_P2POOL_XMR: &str = "The total amount of XMR mined in this instance of P2Pool and an extrapolated estimate of how many you will mine in the future. pub const STATUS_P2POOL_XMR: &str = "The total amount of XMR mined in this instance of P2Pool and an extrapolated estimate of how many you will mine in the future.
Note: these stats will be quite inaccurate if your P2Pool hasn't been running for a long time!"; Note: these stats will be quite inaccurate if your P2Pool hasn't been running for a long time.";
pub const STATUS_P2POOL_HASHRATE: &str = "The total amount of hashrate your P2Pool has pointed at it in 15 minute, 1 hour, and 24 hour averages"; pub const STATUS_P2POOL_HASHRATE: &str = "The total amount of hashrate your P2Pool has pointed at it in 15 minute, 1 hour, and 24 hour averages";
pub const STATUS_P2POOL_SHARES: &str = "The total amount of shares found on P2Pool"; pub const STATUS_P2POOL_SHARES: &str = "The total amount of shares found on P2Pool";
pub const STATUS_P2POOL_EFFORT: &str = pub const STATUS_P2POOL_EFFORT: &str =
@ -259,8 +259,8 @@ pub const GUPAX_UPDATE_VIA_TOR: &str = "Update through the Tor network. Tor is
Note: This option is unstable on macOS."; Note: This option is unstable on macOS.";
pub const GUPAX_ASK_BEFORE_QUIT: &str = "Ask before quitting Gupax"; pub const GUPAX_ASK_BEFORE_QUIT: &str = "Ask before quitting Gupax";
pub const GUPAX_SAVE_BEFORE_QUIT: &str = "Automatically save any changed settings before quitting"; pub const GUPAX_SAVE_BEFORE_QUIT: &str = "Automatically save any changed settings before quitting";
pub const GUPAX_AUTO_P2POOL: &str = "Automatically start P2Pool on Gupax startup. If you are using [P2Pool Simple], this will NOT wait for your [Auto-Ping] to finish, it will start P2Pool on the pool you already have selected. This option will fail if your P2Pool settings aren't valid!"; pub const GUPAX_AUTO_P2POOL: &str = "Automatically start P2Pool on Gupax startup. If you are using [P2Pool Simple], this will NOT wait for your [Auto-Ping] to finish, it will start P2Pool on the pool you already have selected. This option will fail if your P2Pool settings aren't valid.";
pub const GUPAX_AUTO_XMRIG: &str = "Automatically start XMRig on Gupax startup. This option will fail if your XMRig settings aren't valid!"; pub const GUPAX_AUTO_XMRIG: &str = "Automatically start XMRig on Gupax startup. This option will fail if your XMRig settings aren't valid.";
pub const GUPAX_ADJUST: &str = "Adjust and set the width/height of the Gupax window"; pub const GUPAX_ADJUST: &str = "Adjust and set the width/height of the Gupax window";
pub const GUPAX_WIDTH: &str = "Set the width of the Gupax window"; pub const GUPAX_WIDTH: &str = "Set the width of the Gupax window";
pub const GUPAX_HEIGHT: &str = "Set the height of the Gupax window"; pub const GUPAX_HEIGHT: &str = "Set the height of the Gupax window";
@ -312,16 +312,16 @@ pub const P2POOL_SELECT_RANDOM: &str = "Select a random remote Monero node";
pub const P2POOL_SELECT_LAST: &str = "Select the previous remote Monero node"; pub const P2POOL_SELECT_LAST: &str = "Select the previous remote Monero node";
pub const P2POOL_SELECT_NEXT: &str = "Select the next remote Monero node"; pub const P2POOL_SELECT_NEXT: &str = "Select the next remote Monero node";
pub const P2POOL_PING: &str = "Ping the built-in remote Monero nodes"; pub const P2POOL_PING: &str = "Ping the built-in remote Monero nodes";
pub const P2POOL_ADDRESS: &str = "You must use a primary Monero address to mine on P2Pool (starts with a 4). It is highly recommended to create a new wallet since addresses are public on P2Pool!"; pub const P2POOL_ADDRESS: &str = "You must use a primary Monero address to mine on P2Pool (starts with a 4). It is highly recommended to create a new wallet since addresses are public on P2Pool.";
pub const P2POOL_COMMUNITY_NODE_WARNING: &str = r#"--- Run and use your own Monero node --- pub const P2POOL_COMMUNITY_NODE_WARNING: &str = r#"--- Run and use your own Monero node ---
Using a remote Monero node is convenient but comes at the cost of privacy and reliability. Using a remote Monero node is convenient but comes at the cost of privacy and reliability.
You may encounter connection issues with remote nodes which may cause mining performance loss! Late info from laggy nodes will cause your mining jobs to start later than they should. You may encounter connection issues with remote nodes which may cause mining performance loss. Late info from remote nodes may cause mining jobs to start later than they should.
Running and using your own local Monero node improves privacy and ensures your connection is as stable as your own internet connection. This comes at the cost of downloading and syncing Monero's blockchain yourself (currently ~170GB). If you have the disk space, consider using the [Advanced] tab and connecting to your own Monero node. Running and using your own local Monero node improves privacy and ensures your connection is as stable as your own internet connection. This comes at the cost of downloading and syncing Monero's blockchain. If you have the disk space, consider using the [Advanced] tab and connecting to your own Monero node.
For a simple guide, see the [Running a Local Monero Node] section on Gupax's GitHub by clicking this message."#; For a simple guide, see the [Running a Local Monero Node] documentation by clicking this message."#;
pub const P2POOL_INPUT: &str = "Send a command to P2Pool"; pub const P2POOL_INPUT: &str = "Send a command to P2Pool";
pub const P2POOL_ARGUMENTS: &str = r#"Note: [--no-color] & [--data-api <PATH>] & [--local-api] must be set so that the [Status] tab can work! pub const P2POOL_ARGUMENTS: &str = r#"Note: [--no-color] & [--data-api <PATH>] & [--local-api] must be set so that the [Status] tab can work!
@ -415,9 +415,9 @@ For more information, see link below:
<https://github.com/hinto-janai/gupax>"#; <https://github.com/hinto-janai/gupax>"#;
//---------------------------------------------------------------------------------------------------- Visuals //---------------------------------------------------------------------------------------------------- Visuals
use egui::epaint::{Rounding, Shadow, Stroke}; use egui::epaint::{Rounding, Stroke};
use egui::{style::Spacing, Color32, Visuals}; use egui::{Color32, Visuals};
use egui::style::{Selection, WidgetVisuals, Widgets}; use egui::style::{Selection, WidgetVisuals, Widgets};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
@ -499,7 +499,9 @@ pub static VISUALS: Lazy<Visuals> = Lazy::new(|| {
mod test { mod test {
#[test] #[test]
fn gupax_version_is_semver() { fn gupax_version_is_semver() {
assert_eq!(crate::GUPAX_VERSION.len(), 6); let len = crate::GUPAX_VERSION.len();
println!("{len}");
assert!(len == 6 || len == 7);
} }
#[test] #[test]

11685
src/cpu.json

File diff suppressed because it is too large Load diff

View file

@ -817,13 +817,13 @@ impl GupaxP2poolApi {
"GupaxP2poolApi | Deleting old folder at [{}]...", "GupaxP2poolApi | Deleting old folder at [{}]...",
path.display() path.display()
); );
std::fs::remove_dir_all(&path)?; std::fs::remove_dir_all(path)?;
info!( info!(
"GupaxP2poolApi | Creating new default folder at [{}]...", "GupaxP2poolApi | Creating new default folder at [{}]...",
path.display() path.display()
); );
create_gupax_p2pool_dir(&path)?; create_gupax_p2pool_dir(path)?;
Self::create_all_files(&path)?; Self::create_all_files(path)?;
Ok(()) Ok(())
} }

File diff suppressed because one or more lines are too long

View file

@ -19,7 +19,7 @@ use crate::State;
use crate::{constants::*, macros::*, update::*, ErrorState, Restart, Tab}; use crate::{constants::*, macros::*, update::*, ErrorState, Restart, Tab};
use egui::{ use egui::{
Button, Checkbox, Label, ProgressBar, RichText, SelectableLabel, Slider, Spinner, TextEdit, Button, Checkbox, Label, ProgressBar, RichText, SelectableLabel, Slider, Spinner, TextEdit,
TextStyle, TextStyle::Monospace, Vec2, Vec2,
}; };
use log::*; use log::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -70,7 +70,7 @@ pub enum Ratio {
//---------------------------------------------------------------------------------------------------- Gupax //---------------------------------------------------------------------------------------------------- Gupax
impl crate::disk::Gupax { impl crate::disk::Gupax {
#[inline(always)] // called once #[expect(clippy::too_many_arguments)]
pub fn show( pub fn show(
&mut self, &mut self,
og: &Arc<Mutex<State>>, og: &Arc<Mutex<State>>,
@ -81,7 +81,7 @@ impl crate::disk::Gupax {
restart: &Arc<Mutex<Restart>>, restart: &Arc<Mutex<Restart>>,
width: f32, width: f32,
height: f32, height: f32,
frame: &mut eframe::Frame, _frame: &mut eframe::Frame,
_ctx: &egui::Context, _ctx: &egui::Context,
ui: &mut egui::Ui, ui: &mut egui::Ui,
) { ) {
@ -512,7 +512,7 @@ impl crate::disk::Gupax {
lock!(file_window).thread = true; lock!(file_window).thread = true;
thread::spawn(move || { thread::spawn(move || {
match rfd::FileDialog::new() match rfd::FileDialog::new()
.set_title(&format!("Select {} Binary for Gupax", name)) .set_title(format!("Select {} Binary for Gupax", name))
.pick_file() .pick_file()
{ {
Some(path) => { Some(path) => {

View file

@ -264,6 +264,7 @@ impl std::fmt::Display for ProcessName {
//---------------------------------------------------------------------------------------------------- [Helper] //---------------------------------------------------------------------------------------------------- [Helper]
impl Helper { impl Helper {
//---------------------------------------------------------------------------------------------------- General Functions //---------------------------------------------------------------------------------------------------- General Functions
#[expect(clippy::too_many_arguments)]
pub fn new( pub fn new(
instant: std::time::Instant, instant: std::time::Instant,
pub_sys: Arc<Mutex<Sys>>, pub_sys: Arc<Mutex<Sys>>,
@ -318,7 +319,6 @@ impl Helper {
i += 1; i += 1;
} }
} }
drop(i);
while let Some(Ok(line)) = stdout.next() { while let Some(Ok(line)) = stdout.next() {
// println!("{}", line); // For debugging. // println!("{}", line); // For debugging.
@ -358,7 +358,6 @@ impl Helper {
i += 1; i += 1;
} }
} }
drop(i);
while let Some(Ok(line)) = stdout.next() { while let Some(Ok(line)) = stdout.next() {
// println!("{}", line); // For debugging. // println!("{}", line); // For debugging.
@ -398,7 +397,7 @@ impl Helper {
"{} Watchdog | Output is nearing {} bytes, resetting!", "{} Watchdog | Output is nearing {} bytes, resetting!",
name, MAX_GUI_OUTPUT_BYTES 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", HORI_CONSOLE, name, MAX_GUI_OUTPUT_BYTES, HORI_CONSOLE); let text = format!("{}\n{} GUI log is exceeding the maximum: {} bytes!\nResetting the logs...\n{}\n\n\n\n", HORI_CONSOLE, name, MAX_GUI_OUTPUT_BYTES, HORI_CONSOLE);
output.clear(); output.clear();
output.push_str(&text); output.push_str(&text);
debug!("{} Watchdog | Resetting GUI output ... OK", name); debug!("{} Watchdog | Resetting GUI output ... OK", name);
@ -687,6 +686,7 @@ impl Helper {
#[cold] #[cold]
#[inline(never)] #[inline(never)]
#[expect(clippy::too_many_arguments)]
// The P2Pool watchdog. Spawns 1 OS thread for reading a PTY (STDOUT+STDERR), and combines the [Child] with a PTY so STDIN actually works. // The P2Pool watchdog. Spawns 1 OS thread for reading a PTY (STDOUT+STDERR), and combines the [Child] with a PTY so STDIN actually works.
fn spawn_p2pool_watchdog( fn spawn_p2pool_watchdog(
process: Arc<Mutex<Process>>, process: Arc<Mutex<Process>>,
@ -1109,7 +1109,7 @@ impl Helper {
// The actual binary we're executing is [sudo], technically // The actual binary we're executing is [sudo], technically
// the XMRig path is just an argument to sudo, so add it. // the XMRig path is just an argument to sudo, so add it.
// Before that though, add the ["--prompt"] flag and set it // Before that though, add the ["--prompt"] flag and set it
// to emptyness so that it doesn't show up in the output. // to emptiness so that it doesn't show up in the output.
if cfg!(unix) { if cfg!(unix) {
args.push(r#"--prompt="#.to_string()); args.push(r#"--prompt="#.to_string());
args.push("--".to_string()); args.push("--".to_string());
@ -1262,7 +1262,7 @@ impl Helper {
// 1a. Create PTY // 1a. Create PTY
debug!("XMRig | Creating PTY..."); debug!("XMRig | Creating PTY...");
let pty = portable_pty::native_pty_system(); let pty = portable_pty::native_pty_system();
let mut pair = pty let pair = pty
.openpty(portable_pty::PtySize { .openpty(portable_pty::PtySize {
rows: 100, rows: 100,
cols: 1000, cols: 1000,
@ -2395,7 +2395,7 @@ impl PubXmrigApi {
// Formats raw private data into ready-to-print human readable version. // Formats raw private data into ready-to-print human readable version.
fn update_from_priv(public: &Arc<Mutex<Self>>, private: PrivXmrigApi) { fn update_from_priv(public: &Arc<Mutex<Self>>, private: PrivXmrigApi) {
let mut public = lock!(public); let mut public = lock!(public);
let hashrate_raw = match private.hashrate.total.get(0) { let hashrate_raw = match private.hashrate.total.first() {
Some(Some(h)) => *h, Some(Some(h)) => *h,
_ => 0.0, _ => 0.0,
}; };
@ -2911,7 +2911,7 @@ mod test {
"hugepages": true "hugepages": true
}"#; }"#;
use crate::helper::PrivXmrigApi; use crate::helper::PrivXmrigApi;
let priv_api = serde_json::from_str::<PrivXmrigApi>(&data).unwrap(); let priv_api = serde_json::from_str::<PrivXmrigApi>(data).unwrap();
let json = serde_json::ser::to_string_pretty(&priv_api).unwrap(); let json = serde_json::ser::to_string_pretty(&priv_api).unwrap();
println!("{}", json); println!("{}", json);
let data_after_ser = r#"{ let data_after_ser = r#"{

View file

@ -281,14 +281,14 @@ mod test {
fn human_number() { fn human_number() {
use crate::human::HumanNumber; use crate::human::HumanNumber;
assert!(HumanNumber::to_percent(0.001).to_string() == "0%"); assert!(HumanNumber::to_percent(0.001).to_string() == "0%");
assert!(HumanNumber::to_percent(12.123123123123).to_string() == "12.12%"); assert!(HumanNumber::to_percent(12.123_123).to_string() == "12.12%");
assert!(HumanNumber::to_percent_3_point(0.001).to_string() == "0.001%"); assert!(HumanNumber::to_percent_3_point(0.001).to_string() == "0.001%");
assert!( assert!(
HumanNumber::from_hashrate([Some(123.1), Some(11111.1), None]).to_string() HumanNumber::from_hashrate([Some(123.1), Some(11111.1), None]).to_string()
== "[123 H/s, 11,111 H/s, ??? H/s]" == "[123 H/s, 11,111 H/s, ??? H/s]"
); );
assert!( assert!(
HumanNumber::from_hashrate([None, Some(1.123), Some(123123.312)]).to_string() HumanNumber::from_hashrate([None, Some(1.123), Some(123_123.31)]).to_string()
== "[??? H/s, 1 H/s, 123,123 H/s]" == "[??? H/s, 1 H/s, 123,123 H/s]"
); );
assert!( assert!(
@ -299,8 +299,8 @@ mod test {
HumanNumber::from_load([None, Some(4321.43), Some(1234.1)]).to_string() HumanNumber::from_load([None, Some(4321.43), Some(1234.1)]).to_string()
== "[???, 4321.43, 1234.10]" == "[???, 4321.43, 1234.10]"
); );
assert!(HumanNumber::from_f32(123_123.123123123).to_string() == "123,123"); assert!(HumanNumber::from_f32(123_123.125).to_string() == "123,123");
assert!(HumanNumber::from_f64(123_123_123.123123123123123).to_string() == "123,123,123"); assert!(HumanNumber::from_f64(123_123_123.123_123_12).to_string() == "123,123,123");
assert!(HumanNumber::from_u16(1_000).to_string() == "1,000"); assert!(HumanNumber::from_u16(1_000).to_string() == "1,000");
assert!(HumanNumber::from_u16(65_535).to_string() == "65,535"); assert!(HumanNumber::from_u16(65_535).to_string() == "65,535");
assert!(HumanNumber::from_u32(65_536).to_string() == "65,536"); assert!(HumanNumber::from_u32(65_536).to_string() == "65,536");

View file

@ -88,7 +88,7 @@ mod test {
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
let arc_mutex = Arc::new(Mutex::new(false)); let arc_mutex = Arc::new(Mutex::new(false));
*lock!(arc_mutex) = true; *lock!(arc_mutex) = true;
assert!(*lock!(arc_mutex) == true); assert!(*lock!(arc_mutex));
} }
#[test] #[test]
@ -101,19 +101,19 @@ mod test {
a: Arc::new(Mutex::new(false)), a: Arc::new(Mutex::new(false)),
})); }));
*lock2!(arc_mutex, a) = true; *lock2!(arc_mutex, a) = true;
assert!(*lock2!(arc_mutex, a) == true); assert!(*lock2!(arc_mutex, a));
} }
#[test] #[test]
fn arc_mut() { fn arc_mut() {
let a = arc_mut!(false); let a = arc_mut!(false);
assert!(*lock!(a) == false); assert!(!(*lock!(a)));
} }
#[test] #[test]
fn flip() { fn flip() {
let mut b = true; let mut b = true;
flip!(b); flip!(b);
assert!(b == false); assert!(!b);
} }
} }

View file

@ -29,9 +29,8 @@ compile_error!("gupax is only built for windows/macos/linux");
// egui/eframe // egui/eframe
use eframe::{egui, NativeOptions}; use eframe::{egui, NativeOptions};
use egui::{ use egui::{
Align, Button, CentralPanel, Color32, FontFamily::Proportional, FontId, Hyperlink, Key, Label, Align, Button, CentralPanel, Color32, FontId, Hyperlink, Key, Label, Layout, Modifiers,
Layout, Modifiers, RichText, SelectableLabel, Spinner, Stroke, TextEdit, TextStyle, RichText, SelectableLabel, Spinner, TextEdit, TextStyle, TextStyle::*, TopBottomPanel, Vec2,
TextStyle::*, TopBottomPanel, Vec2,
}; };
use egui_extras::RetainedImage; use egui_extras::RetainedImage;
// Logging // Logging
@ -57,7 +56,6 @@ use sysinfo::SystemExt;
//mod benchmark; //mod benchmark;
mod constants; mod constants;
mod disk; mod disk;
mod ferris;
mod free; mod free;
mod gupax; mod gupax;
mod helper; mod helper;
@ -71,10 +69,7 @@ mod status;
mod update; mod update;
mod xmr; mod xmr;
mod xmrig; mod xmrig;
use { use {crate::regex::*, constants::*, disk::*, gupax::*, helper::*, macros::*, node::*, update::*};
crate::regex::*, constants::*, disk::*, ferris::*, gupax::*, helper::*, macros::*, node::*,
update::*,
};
// Sudo (dummy values for Windows) // Sudo (dummy values for Windows)
mod sudo; mod sudo;
@ -153,7 +148,6 @@ pub struct App {
now: Instant, // Internal timer now: Instant, // Internal timer
exe: String, // Path for [Gupax] binary exe: String, // Path for [Gupax] binary
dir: String, // Directory [Gupax] binary is in dir: String, // Directory [Gupax] binary is in
resolution: Vec2, // Frame resolution
os: &'static str, // OS os: &'static str, // OS
admin: bool, // Are we admin? (for Windows) admin: bool, // Are we admin? (for Windows)
os_data_path: PathBuf, // OS data path (e.g: ~/.local/share/gupax/) os_data_path: PathBuf, // OS data path (e.g: ~/.local/share/gupax/)
@ -161,7 +155,6 @@ pub struct App {
state_path: PathBuf, // State file path state_path: PathBuf, // State file path
node_path: PathBuf, // Node file path node_path: PathBuf, // Node file path
pool_path: PathBuf, // Pool file path pool_path: PathBuf, // Pool file path
version: &'static str, // Gupax version
name_version: String, // [Gupax vX.X.X] name_version: String, // [Gupax vX.X.X]
img: Images, // Custom Struct holding pre-compiled bytes of [Images] img: Images, // Custom Struct holding pre-compiled bytes of [Images]
} }
@ -176,7 +169,7 @@ impl App {
crate::free::clamp_scale(app.state.gupax.selected_scale), crate::free::clamp_scale(app.state.gupax.selected_scale),
); );
cc.egui_ctx.set_visuals(VISUALS.clone()); cc.egui_ctx.set_visuals(VISUALS.clone());
Self { resolution, ..app } Self { ..app }
} }
#[cold] #[cold]
@ -237,7 +230,7 @@ impl App {
let cpu = sysinfo.cpus()[0].brand(); let cpu = sysinfo.cpus()[0].brand();
let mut json: Vec<Benchmark> = let mut json: Vec<Benchmark> =
serde_json::from_slice(include_bytes!("cpu.json")).unwrap(); serde_json::from_slice(include_bytes!("cpu.json")).unwrap();
json.sort_by(|a, b| cmp_f64(strsim::jaro(&b.cpu, &cpu), strsim::jaro(&a.cpu, &cpu))); json.sort_by(|a, b| cmp_f64(strsim::jaro(&b.cpu, cpu), strsim::jaro(&a.cpu, cpu)));
json json
}; };
info!("App Init | Assuming user's CPU is: {}", benchmarks[0].cpu); info!("App Init | Assuming user's CPU is: {}", benchmarks[0].cpu);
@ -297,14 +290,12 @@ impl App {
admin: false, admin: false,
exe: String::new(), exe: String::new(),
dir: String::new(), dir: String::new(),
resolution: Vec2::new(APP_DEFAULT_HEIGHT, APP_DEFAULT_WIDTH),
os: OS, os: OS,
os_data_path: PathBuf::new(), os_data_path: PathBuf::new(),
gupax_p2pool_api_path: PathBuf::new(), gupax_p2pool_api_path: PathBuf::new(),
state_path: PathBuf::new(), state_path: PathBuf::new(),
node_path: PathBuf::new(), node_path: PathBuf::new(),
pool_path: PathBuf::new(), pool_path: PathBuf::new(),
version: GUPAX_VERSION,
name_version: format!("Gupax {}", GUPAX_VERSION), name_version: format!("Gupax {}", GUPAX_VERSION),
img: Images::new(), img: Images::new(),
}; };
@ -494,7 +485,7 @@ impl App {
og.p2pool.selected_index, og.p2pool.selected_index,
app.og_node_vec.len() app.og_node_vec.len()
); );
let (name, node) = match app.og_node_vec.get(0) { let (name, node) = match app.og_node_vec.first() {
Some(zero) => zero.clone(), Some(zero) => zero.clone(),
None => Node::new_tuple(), None => Node::new_tuple(),
}; };
@ -517,7 +508,7 @@ impl App {
og.xmrig.selected_index, og.xmrig.selected_index,
app.og_pool_vec.len() app.og_pool_vec.len()
); );
let (name, pool) = match app.og_pool_vec.get(0) { let (name, pool) = match app.og_pool_vec.first() {
Some(zero) => zero.clone(), Some(zero) => zero.clone(),
None => Pool::new_tuple(), None => Pool::new_tuple(),
}; };
@ -627,7 +618,7 @@ impl App {
continue; continue;
} }
let (ip, rpc, zmq) = RemoteNode::get_ip_rpc_zmq(&pinged_node.ip); let (ip, rpc, zmq) = RemoteNode::get_ip_rpc_zmq(pinged_node.ip);
let node = Node { let node = Node {
ip: ip.into(), ip: ip.into(),
@ -779,12 +770,6 @@ impl ErrorState {
//---------------------------------------------------------------------------------------------------- [Images] struct //---------------------------------------------------------------------------------------------------- [Images] struct
struct Images { struct Images {
banner: RetainedImage, banner: RetainedImage,
happy: RetainedImage,
cute: RetainedImage,
oops: RetainedImage,
error: RetainedImage,
panic: RetainedImage,
sudo: RetainedImage,
} }
impl Images { impl Images {
@ -793,12 +778,6 @@ impl Images {
fn new() -> Self { fn new() -> Self {
Self { Self {
banner: RetainedImage::from_image_bytes("banner.png", BYTES_BANNER).unwrap(), banner: RetainedImage::from_image_bytes("banner.png", BYTES_BANNER).unwrap(),
happy: RetainedImage::from_image_bytes("happy.png", FERRIS_HAPPY).unwrap(),
cute: RetainedImage::from_image_bytes("cute.png", FERRIS_CUTE).unwrap(),
oops: RetainedImage::from_image_bytes("oops.png", FERRIS_OOPS).unwrap(),
error: RetainedImage::from_image_bytes("error.png", FERRIS_ERROR).unwrap(),
panic: RetainedImage::from_image_bytes("panic.png", FERRIS_PANIC).unwrap(),
sudo: RetainedImage::from_image_bytes("panic.png", FERRIS_SUDO).unwrap(),
} }
} }
} }
@ -872,10 +851,6 @@ impl KeyPressed {
fn is_v(&self) -> bool { fn is_v(&self) -> bool {
*self == Self::V *self == Self::V
} }
#[inline]
fn is_none(&self) -> bool {
*self == Self::None
}
} }
//---------------------------------------------------------------------------------------------------- Init functions //---------------------------------------------------------------------------------------------------- Init functions
@ -1227,10 +1202,6 @@ fn parse_args<S: Into<String>>(mut app: App, panic: S) -> App {
println!("Gupax {} [OS: {}, Commit: {}]\nThis Gupax was originally bundled with:\n - P2Pool {}\n - XMRig {}\n\n{}", GUPAX_VERSION, OS_NAME, &COMMIT[..40], P2POOL_VERSION, XMRIG_VERSION, ARG_COPYRIGHT); println!("Gupax {} [OS: {}, Commit: {}]\nThis Gupax was originally bundled with:\n - P2Pool {}\n - XMRig {}\n\n{}", GUPAX_VERSION, OS_NAME, &COMMIT[..40], P2POOL_VERSION, XMRIG_VERSION, ARG_COPYRIGHT);
exit(0); exit(0);
} }
"--ferris" => {
println!("{}", FERRIS_ANSI);
exit(0);
}
_ => (), _ => (),
} }
} }
@ -1479,7 +1450,8 @@ fn main() {
&app.name_version.clone(), &app.name_version.clone(),
options, options,
Box::new(move |cc| Box::new(App::cc(cc, resolution, app))), Box::new(move |cc| Box::new(App::cc(cc, resolution, app))),
); )
.unwrap();
} }
impl eframe::App for App { impl eframe::App for App {
@ -1723,18 +1695,9 @@ impl eframe::App for App {
// Display ferris // Display ferris
use ErrorFerris::*; use ErrorFerris::*;
use ErrorButtons::*; use ErrorButtons::*;
let ferris = match self.error_state.ferris { if self.error_state.buttons == Debug {
Happy => &self.img.happy, ui.add_sized([width, height/4.0], Label::new("--- Debug Info ---\n\nPress [ESC] to quit"));
Cute => &self.img.cute, }
Oops => &self.img.oops,
Error => &self.img.error,
Panic => &self.img.panic,
ErrorFerris::Sudo => &self.img.sudo,
};
match self.error_state.buttons {
Debug => ui.add_sized([width, height/4.0], Label::new("--- Debug Info ---\n\nPress [ESC] to quit")),
_ => ferris.show_max_size(ui, Vec2::new(width, height)),
};
// Error/Quit screen // Error/Quit screen
match self.error_state.buttons { match self.error_state.buttons {
@ -1895,17 +1858,12 @@ impl eframe::App for App {
// They don't need to be compared anyway. // They don't need to be compared anyway.
debug!("App | Checking diff between [og] & [state]"); debug!("App | Checking diff between [og] & [state]");
let og = lock!(self.og); let og = lock!(self.og);
if og.status != self.state.status self.diff = og.status != self.state.status
|| og.gupax != self.state.gupax || og.gupax != self.state.gupax
|| og.p2pool != self.state.p2pool || og.p2pool != self.state.p2pool
|| og.xmrig != self.state.xmrig || og.xmrig != self.state.xmrig
|| self.og_node_vec != self.node_vec || self.og_node_vec != self.node_vec
|| self.og_pool_vec != self.pool_vec || self.og_pool_vec != self.pool_vec;
{
self.diff = true;
} else {
self.diff = false;
}
drop(og); drop(og);
// Top: Tabs // Top: Tabs
@ -2253,8 +2211,8 @@ impl eframe::App for App {
.on_hover_text("Restart P2Pool") .on_hover_text("Restart P2Pool")
.clicked() .clicked()
{ {
lock!(self.og).update_absolute_path(); let _ = lock!(self.og).update_absolute_path();
self.state.update_absolute_path(); let _ = self.state.update_absolute_path();
Helper::restart_p2pool( Helper::restart_p2pool(
&self.helper, &self.helper,
&self.state.p2pool, &self.state.p2pool,
@ -2308,8 +2266,8 @@ impl eframe::App for App {
.on_disabled_hover_text(text) .on_disabled_hover_text(text)
.clicked() .clicked()
{ {
lock!(self.og).update_absolute_path(); let _ = lock!(self.og).update_absolute_path();
self.state.update_absolute_path(); let _ = self.state.update_absolute_path();
Helper::start_p2pool( Helper::start_p2pool(
&self.helper, &self.helper,
&self.state.p2pool, &self.state.p2pool,
@ -2363,8 +2321,8 @@ impl eframe::App for App {
.on_hover_text("Restart XMRig") .on_hover_text("Restart XMRig")
.clicked() .clicked()
{ {
lock!(self.og).update_absolute_path(); let _ = lock!(self.og).update_absolute_path();
self.state.update_absolute_path(); let _ = self.state.update_absolute_path();
if cfg!(windows) { if cfg!(windows) {
Helper::restart_xmrig( Helper::restart_xmrig(
&self.helper, &self.helper,
@ -2424,8 +2382,8 @@ impl eframe::App for App {
.on_disabled_hover_text(text) .on_disabled_hover_text(text)
.clicked() .clicked()
{ {
lock!(self.og).update_absolute_path(); let _ = lock!(self.og).update_absolute_path();
self.state.update_absolute_path(); let _ = self.state.update_absolute_path();
if cfg!(windows) { if cfg!(windows) {
Helper::start_xmrig( Helper::start_xmrig(
&self.helper, &self.helper,
@ -2601,7 +2559,7 @@ mod test {
let benchmarks: Vec<Benchmark> = { let benchmarks: Vec<Benchmark> = {
let mut json: Vec<Benchmark> = let mut json: Vec<Benchmark> =
serde_json::from_slice(include_bytes!("cpu.json")).unwrap(); serde_json::from_slice(include_bytes!("cpu.json")).unwrap();
json.sort_by(|a, b| cmp_f64(strsim::jaro(&b.cpu, &cpu), strsim::jaro(&a.cpu, &cpu))); json.sort_by(|a, b| cmp_f64(strsim::jaro(&b.cpu, cpu), strsim::jaro(&a.cpu, cpu)));
json json
}; };

View file

@ -20,7 +20,6 @@ use egui::Color32;
use hyper::{client::HttpConnector, Body, Client, Request}; use hyper::{client::HttpConnector, Body, Client, Request};
use log::*; use log::*;
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};
use serde::{Deserialize, Serialize};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
@ -28,18 +27,13 @@ use std::time::{Duration, Instant};
// Remote Monero Nodes with ZMQ enabled. // Remote Monero Nodes with ZMQ enabled.
// The format is an array of tuples consisting of: (IP, LOCATION, RPC_PORT, ZMQ_PORT) // The format is an array of tuples consisting of: (IP, LOCATION, RPC_PORT, ZMQ_PORT)
pub const REMOTE_NODES: [(&str, &str, &str, &str); 14] = [ pub const REMOTE_NODES: [(&str, &str, &str, &str); 9] = [
("monero.10z.com.ar", "Argentina", "18089", "18084"), ("monero.10z.com.ar", "Argentina", "18089", "18084"),
("monero1.heitechsoft.com", "Canada", "18081", "18084"),
("node.monerodevs.org", "Canada", "18089", "18084"), ("node.monerodevs.org", "Canada", "18089", "18084"),
("node.cryptocano.de", "Germany", "18089", "18083"),
("p2pmd.xmrvsbeast.com", "Germany", "18081", "18083"), ("p2pmd.xmrvsbeast.com", "Germany", "18081", "18083"),
("fbx.tranbert.com", "France", "18089", "18084"),
("node2.monerodevs.org", "France", "18089", "18084"), ("node2.monerodevs.org", "France", "18089", "18084"),
("home.allantaylor.kiwi", "New Zealand", "18089", "18083"),
("p2pool.uk", "United Kingdom", "18089", "18084"), ("p2pool.uk", "United Kingdom", "18089", "18084"),
("xmr.support", "United States", "18081", "18083"), ("xmr.support", "United States", "18081", "18083"),
("sf.xmr.support", "United States", "18081", "18083"),
("xmrbandwagon.hopto.org", "United States", "18081", "18084"), ("xmrbandwagon.hopto.org", "United States", "18081", "18084"),
("xmr.spotlightsound.com", "United States", "18081", "18084"), ("xmr.spotlightsound.com", "United States", "18081", "18084"),
("node.richfowler.net", "United States", "18089", "18084"), ("node.richfowler.net", "United States", "18089", "18084"),
@ -260,10 +254,10 @@ pub fn format_ip_location(og_ip: &str, extra_space: bool) -> String {
} }
pub fn format_ip(ip: &str) -> String { pub fn format_ip(ip: &str) -> String {
const _: () = if 23 != REMOTE_NODE_MAX_CHARS { const _: () = if 22 != REMOTE_NODE_MAX_CHARS {
panic!(); panic!();
}; };
format!("{ip: >23}") format!("{ip: >22}")
} }
//---------------------------------------------------------------------------------------------------- Node data //---------------------------------------------------------------------------------------------------- Node data
@ -409,7 +403,7 @@ impl Ping {
let mut handles = Vec::with_capacity(REMOTE_NODE_LENGTH); let mut handles = Vec::with_capacity(REMOTE_NODE_LENGTH);
let node_vec = arc_mut!(Vec::with_capacity(REMOTE_NODE_LENGTH)); let node_vec = arc_mut!(Vec::with_capacity(REMOTE_NODE_LENGTH));
for (ip, _, rpc, zmq) in REMOTE_NODES { for (ip, _country, rpc, _zmq) in REMOTE_NODES {
let client = client.clone(); let client = client.clone();
let ping = Arc::clone(&ping); let ping = Arc::clone(&ping);
let node_vec = Arc::clone(&node_vec); let node_vec = Arc::clone(&node_vec);
@ -531,7 +525,7 @@ mod test {
#[ignore] #[ignore]
async fn full_ping() { async fn full_ping() {
use crate::{REMOTE_NODES, REMOTE_NODE_LENGTH}; use crate::{REMOTE_NODES, REMOTE_NODE_LENGTH};
use hyper::{client::HttpConnector, Body, Client, Request}; use hyper::{client::HttpConnector, Client, Request};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]

View file

@ -22,11 +22,10 @@ use egui::{
Slider, Spinner, TextEdit, TextStyle::*, Slider, Spinner, TextEdit, TextStyle::*,
}; };
use log::*; use log::*;
use regex::Regex;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
impl crate::disk::P2pool { impl crate::disk::P2pool {
#[inline(always)] // called once #[expect(clippy::too_many_arguments)]
pub fn show( pub fn show(
&mut self, &mut self,
node_vec: &mut Vec<(String, Node)>, node_vec: &mut Vec<(String, Node)>,
@ -323,7 +322,7 @@ impl crate::disk::P2pool {
ui.add_sized( ui.add_sized(
[width, height / 2.0], [width, height / 2.0],
Hyperlink::from_label_and_url( Hyperlink::from_label_and_url(
"WARNING: It is recommended to use your own Monero Node (hover for details)", "Warning: It is recommended to use your own Monero node.",
"https://github.com/hinto-janai/gupax#running-a-local-monero-node", "https://github.com/hinto-janai/gupax#running-a-local-monero-node",
), ),
) )
@ -431,11 +430,10 @@ impl crate::disk::P2pool {
debug!("P2Pool Tab | Rendering [Node List]"); debug!("P2Pool Tab | Rendering [Node List]");
let text = RichText::new(format!("{}. {}", self.selected_index+1, self.selected_name)); let text = RichText::new(format!("{}. {}", self.selected_index+1, self.selected_name));
ComboBox::from_id_source("manual_nodes").selected_text(text).width(width).show_ui(ui, |ui| { ComboBox::from_id_source("manual_nodes").selected_text(text).width(width).show_ui(ui, |ui| {
let mut n = 0; for (i, (name, node)) in node_vec.iter().enumerate() {
for (name, node) in node_vec.iter() { let text = RichText::new(format!("{}. {}\n IP: {}\n RPC: {}\n ZMQ: {}", i+1, name, node.ip, node.rpc, node.zmq));
let text = RichText::new(format!("{}. {}\n IP: {}\n RPC: {}\n ZMQ: {}", n+1, name, node.ip, node.rpc, node.zmq));
if ui.add(SelectableLabel::new(self.selected_name == *name, text)).clicked() { if ui.add(SelectableLabel::new(self.selected_name == *name, text)).clicked() {
self.selected_index = n; self.selected_index = i;
let node = node.clone(); let node = node.clone();
self.selected_name = name.clone(); self.selected_name = name.clone();
self.selected_ip = node.ip.clone(); self.selected_ip = node.ip.clone();
@ -446,7 +444,6 @@ impl crate::disk::P2pool {
self.rpc = node.rpc; self.rpc = node.rpc;
self.zmq = node.zmq; self.zmq = node.zmq;
} }
n += 1;
} }
}); });
// [Add/Save] // [Add/Save]

View file

@ -21,9 +21,9 @@ use once_cell::sync::Lazy;
use regex::Regex; use regex::Regex;
//---------------------------------------------------------------------------------------------------- Lazy //---------------------------------------------------------------------------------------------------- Lazy
pub static REGEXES: Lazy<Regexes> = Lazy::new(|| Regexes::new()); pub static REGEXES: Lazy<Regexes> = Lazy::new(Regexes::new);
pub static P2POOL_REGEX: Lazy<P2poolRegex> = Lazy::new(|| P2poolRegex::new()); pub static P2POOL_REGEX: Lazy<P2poolRegex> = Lazy::new(P2poolRegex::new);
pub static XMRIG_REGEX: Lazy<XmrigRegex> = Lazy::new(|| XmrigRegex::new()); pub static XMRIG_REGEX: Lazy<XmrigRegex> = Lazy::new(XmrigRegex::new);
//---------------------------------------------------------------------------------------------------- [Regexes] struct //---------------------------------------------------------------------------------------------------- [Regexes] struct
// General purpose Regexes, mostly used in the GUI. // General purpose Regexes, mostly used in the GUI.

View file

@ -21,13 +21,13 @@ use crate::{
}; };
use egui::{ use egui::{
Hyperlink, Label, ProgressBar, RichText, SelectableLabel, Slider, Spinner, TextEdit, TextStyle, Hyperlink, Label, ProgressBar, RichText, SelectableLabel, Slider, Spinner, TextEdit, TextStyle,
TextStyle::Monospace, TextStyle::Name, TextStyle::Name,
}; };
use log::*; use log::*;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
impl crate::disk::Status { impl crate::disk::Status {
#[inline(always)] // called once #[expect(clippy::too_many_arguments)]
pub fn show( pub fn show(
&mut self, &mut self,
sys: &Arc<Mutex<Sys>>, sys: &Arc<Mutex<Sys>>,

View file

@ -40,6 +40,12 @@ use log::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AtomicUnit(u64); pub struct AtomicUnit(u64);
impl Default for AtomicUnit {
fn default() -> Self {
Self::new()
}
}
impl AtomicUnit { impl AtomicUnit {
pub const fn new() -> Self { pub const fn new() -> Self {
Self(0) Self(0)
@ -136,18 +142,16 @@ impl PayoutOrd {
if a.0.len() != b.0.len() { if a.0.len() != b.0.len() {
return false; return false;
} }
let mut n = 0; for (i, (date, atomic_unit, block)) in a.0.iter().enumerate() {
for (date, atomic_unit, block) in &a.0 { if *date != b.0[i].0 {
if *date != b.0[n].0 {
return false; return false;
} }
if *atomic_unit != b.0[n].1 { if *atomic_unit != b.0[i].1 {
return false; return false;
} }
if *block != b.0[n].2 { if *block != b.0[i].2 {
return false; return false;
} }
n += 1;
} }
true true
} }
@ -340,8 +344,6 @@ mod test {
#[test] #[test]
fn push_to_payout_ord() { fn push_to_payout_ord() {
use crate::human::HumanNumber;
use crate::xmr::AtomicUnit;
use crate::xmr::PayoutOrd; use crate::xmr::PayoutOrd;
let mut payout_ord = PayoutOrd::from_vec(vec![]); let mut payout_ord = PayoutOrd::from_vec(vec![]);
let should_be = "2022-09-08 18:42:55.4636 | 0.000000000001 XMR | Block 2,654,321\n"; let should_be = "2022-09-08 18:42:55.4636 | 0.000000000001 XMR | Block 2,654,321\n";
@ -357,7 +359,7 @@ mod test {
use crate::human::HumanNumber; use crate::human::HumanNumber;
use crate::xmr::AtomicUnit; use crate::xmr::AtomicUnit;
use crate::xmr::PayoutOrd; use crate::xmr::PayoutOrd;
let mut payout_ord = PayoutOrd::from_vec(vec![ let payout_ord = PayoutOrd::from_vec(vec![
( (
"2022-09-08 18:42:55.4636".to_string(), "2022-09-08 18:42:55.4636".to_string(),
AtomicUnit::from_u64(1), AtomicUnit::from_u64(1),
@ -453,11 +455,11 @@ mod test {
println!("1: {:#?}", payout_ord); println!("1: {:#?}", payout_ord);
println!("2: {:#?}", payout_ord); println!("2: {:#?}", payout_ord);
assert!(PayoutOrd::is_same(&payout_ord, &payout_ord_2) == true); assert!(PayoutOrd::is_same(&payout_ord, &payout_ord_2));
payout_ord.push_raw("2022-09-08 18:42:55.4636", 1000000000, 2654321); payout_ord.push_raw("2022-09-08 18:42:55.4636", 1000000000, 2654321);
println!("1: {:#?}", payout_ord); println!("1: {:#?}", payout_ord);
println!("2: {:#?}", payout_ord); println!("2: {:#?}", payout_ord);
assert!(PayoutOrd::is_same(&payout_ord, &payout_ord_2) == false); assert!(!PayoutOrd::is_same(&payout_ord, &payout_ord_2));
} }
#[test] #[test]
@ -465,7 +467,7 @@ mod test {
use crate::human::HumanNumber; use crate::human::HumanNumber;
use crate::xmr::AtomicUnit; use crate::xmr::AtomicUnit;
use crate::xmr::PayoutOrd; use crate::xmr::PayoutOrd;
let mut payout_ord = PayoutOrd::from_vec(vec![ let payout_ord = PayoutOrd::from_vec(vec![
( (
"2022-09-08 18:42:55.4636".to_string(), "2022-09-08 18:42:55.4636".to_string(),
AtomicUnit::from_u64(1000000000), AtomicUnit::from_u64(1000000000),

View file

@ -21,11 +21,10 @@ use egui::{
Button, Checkbox, ComboBox, Label, RichText, SelectableLabel, Slider, TextEdit, TextStyle::*, Button, Checkbox, ComboBox, Label, RichText, SelectableLabel, Slider, TextEdit, TextStyle::*,
}; };
use log::*; use log::*;
use regex::Regex;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
impl crate::disk::Xmrig { impl crate::disk::Xmrig {
#[inline(always)] // called once #[expect(clippy::too_many_arguments)]
pub fn show( pub fn show(
&mut self, &mut self,
pool_vec: &mut Vec<(String, Pool)>, pool_vec: &mut Vec<(String, Pool)>,
@ -282,8 +281,7 @@ impl crate::disk::Xmrig {
debug!("XMRig Tab | Rendering [Node List] ComboBox"); debug!("XMRig Tab | Rendering [Node List] ComboBox");
let text = RichText::new(format!("{}. {}", self.selected_index+1, self.selected_name)); let text = RichText::new(format!("{}. {}", self.selected_index+1, self.selected_name));
ComboBox::from_id_source("manual_pool").selected_text(text).width(width).show_ui(ui, |ui| { ComboBox::from_id_source("manual_pool").selected_text(text).width(width).show_ui(ui, |ui| {
let mut n = 0; for (n, (name, pool)) in pool_vec.iter().enumerate() {
for (name, pool) in pool_vec.iter() {
let text = format!("{}. {}\n IP: {}\n Port: {}\n Rig: {}", n+1, name, pool.ip, pool.port, pool.rig); let text = format!("{}. {}\n IP: {}\n Port: {}\n Rig: {}", n+1, name, pool.ip, pool.port, pool.rig);
if ui.add(SelectableLabel::new(self.selected_name == *name, text)).clicked() { if ui.add(SelectableLabel::new(self.selected_name == *name, text)).clicked() {
self.selected_index = n; self.selected_index = n;
@ -297,7 +295,6 @@ impl crate::disk::Xmrig {
self.ip = pool.ip; self.ip = pool.ip;
self.port = pool.port; self.port = pool.port;
} }
n += 1;
} }
}); });
// [Add/Save] // [Add/Save]

View file

@ -2,4 +2,5 @@
extend-exclude = [ extend-exclude = [
"src/cpu.json", "src/cpu.json",
"pgp/", "pgp/",
"external",
] ]