helper: add functions for p2pool/xmrig UI -> command arguments

This commit is contained in:
hinto-janaiyo 2022-12-03 13:37:57 -05:00
parent f33207b503
commit 0a8deee359
No known key found for this signature in database
GPG key ID: B1C5A64B80691E45
8 changed files with 151 additions and 32 deletions

22
Cargo.lock generated
View file

@ -491,7 +491,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bcf530afb40e45e14440701e5e996d7fd139e84a912a4d83a8d6a0fb3e58663"
dependencies = [
"log",
"nix 0.25.0",
"nix 0.25.1",
"slotmap",
"thiserror",
"vec_map",
@ -2143,9 +2143,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
[[package]]
name = "libc"
version = "0.2.137"
version = "0.2.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
[[package]]
name = "libloading"
@ -2431,9 +2431,9 @@ dependencies = [
[[package]]
name = "nix"
version = "0.24.2"
version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc"
checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069"
dependencies = [
"bitflags",
"cfg-if",
@ -2443,9 +2443,9 @@ dependencies = [
[[package]]
name = "nix"
version = "0.25.0"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb"
checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4"
dependencies = [
"autocfg",
"bitflags",
@ -3584,7 +3584,7 @@ dependencies = [
"lazy_static",
"log",
"memmap2",
"nix 0.24.2",
"nix 0.24.3",
"pkg-config",
"wayland-client",
"wayland-cursor",
@ -4781,7 +4781,7 @@ dependencies = [
"bitflags",
"downcast-rs",
"libc",
"nix 0.24.2",
"nix 0.24.3",
"scoped-tls",
"wayland-commons",
"wayland-scanner",
@ -4794,7 +4794,7 @@ version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902"
dependencies = [
"nix 0.24.2",
"nix 0.24.3",
"once_cell",
"smallvec",
"wayland-sys",
@ -4806,7 +4806,7 @@ version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661"
dependencies = [
"nix 0.24.2",
"nix 0.24.3",
"wayland-client",
"xcursor",
]

View file

@ -113,6 +113,7 @@ https://user-images.githubusercontent.com/101352116/194763334-d8e936c9-a71e-474e
* A Monero node/wallet
## Build
Windows/Linux:
```
cargo build --release
```
@ -120,5 +121,8 @@ On macOS, if you want the binary to have an icon in `Finder`, you must install [
```
cargo bundle --release
```
This bundles Gupax into a `Gupax.app`, the way it comes in the pre-built tars for macOS.
The `build.rs` file in the repo root sets the icon in `File Explorer` for Windows. The taskbar icon & App frame icon (for all OS's) get set at runtime using pre-compiled bytes in [`src/constants.rs`](https://github.com/hinto-janaiyo/gupax/blob/main/src/constants.rs) from [`images`](https://github.com/hinto-janaiyo/gupax/blob/main/images).
The `--release` profile is set to prefer code performance & small binary sizes over compilation speed (see [`Cargo.toml`](https://github.com/hinto-janaiyo/gupax/blob/main/Cargo.toml)). Gupax itself (with all dependencies already built) takes around 1m30s to build (vs 10s on a normal `--release`) with a Ryzen 5950x.

View file

@ -113,7 +113,7 @@ pub const P2POOL_AUTO_SELECT: &str = "Automatically select the fastest community
pub const P2POOL_SELECT_FASTEST: &str = "Select the fastest community Monero node";
pub const P2POOL_PING: &str = "Ping the built-in community 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 for P2Pool mining; wallet addresses are public on P2Pool!";
pub const P2POOL_COMMAND: &str = "Start P2Pool with these arguments and override all below settings; If the [--data-api] flag is not given, Gupax will append it to the arguments automatically so that the [Status] tab can work";
pub const P2POOL_ARGUMENTS: &str = "Start P2Pool with these arguments and override all below settings; If the [--data-api] & [--local-api] flag is not given, Gupax will append it to the arguments automatically so that the [Status] tab can work";
pub const P2POOL_SIMPLE: &str =
r#"Use simple P2Pool settings:
- Remote community Monero node
@ -151,7 +151,7 @@ r#"Use advanced XMRig settings:
- TLS setting
- Keepalive setting
- Custom HTTP API IP/Port"#;
pub const XMRIG_CONFIG: &str = "Start XMRig with this config file and override all below settings; If the [http-api] options are not set, the [Status] tab will not properly show XMRig stats. If they are set, Gupax will detect which automatically IP/Port you are using";
pub const XMRIG_ARGUMENTS: &str = "Start XMRig with these arguments and override all below settings; If the [http-api] options are not set, Gupax will append it to the arguments automatically so that the [Status] tab can work";
pub const XMRIG_ADDRESS: &str = "Specify which Monero address to send payouts to; Must be a valid primary address (starts with 4)";
pub const XMRIG_NAME: &str = "Add a unique name to identify this pool; Only [A-Za-z0-9-_] and spaces allowed; Max length = 30 characters";
pub const XMRIG_IP: &str = "Specify the pool IP to connect to with XMRig; It must be a valid IPv4 address or a valid domain name; Max length = 255 characters";

View file

@ -112,7 +112,7 @@ pub fn read_to_string(file: File, path: &PathBuf) -> Result<String, TomlError> {
}
// Write str to console with [info!] surrounded by "---"
pub fn print_toml(toml: &str) {
pub fn print_dash(toml: &str) {
info!("{}", HORIZONTAL);
for i in toml.lines() { info!("{}", i); }
info!("{}", HORIZONTAL);
@ -165,7 +165,7 @@ impl State {
log_level: 3,
node: crate::NodeEnum::C3pool,
arguments: String::new(),
address: String::with_capacity(95),
address: String::with_capacity(96),
name: "Local Monero Node".to_string(),
ip: "localhost".to_string(),
rpc: "18081".to_string(),
@ -179,8 +179,9 @@ impl State {
xmrig: Xmrig {
simple: true,
pause: 0,
config: String::with_capacity(100),
address: String::with_capacity(95),
simple_rig: String::with_capacity(30),
arguments: String::with_capacity(300),
address: String::with_capacity(96),
name: "Local P2Pool".to_string(),
rig: "Gupax".to_string(),
ip: "localhost".to_string(),
@ -210,7 +211,7 @@ impl State {
match toml::de::from_str(string) {
Ok(state) => {
info!("State | Parse ... OK");
print_toml(string);
print_dash(string);
Ok(state)
}
Err(err) => {
@ -272,7 +273,7 @@ impl State {
let string = match toml::ser::to_string(&self) {
Ok(string) => {
info!("State | Parse ... OK");
print_toml(&string);
print_dash(&string);
string
},
Err(err) => { error!("State | Couldn't parse TOML into string ... FAIL"); return Err(TomlError::Serialize(err)) },
@ -615,7 +616,8 @@ pub struct P2pool {
pub struct Xmrig {
pub simple: bool,
pub pause: u8,
pub config: String,
pub simple_rig: String,
pub arguments: String,
pub tls: bool,
pub keepalive: bool,
pub max_threads: usize,

View file

@ -323,6 +323,7 @@ impl Hashrate {
use tokio::io::{BufReader,AsyncBufReadExt};
impl Helper {
//---------------------------------------------------------------------------------------------------- General Functions
pub fn new(instant: std::time::Instant) -> Self {
Self {
instant,
@ -336,12 +337,6 @@ impl Helper {
}
}
// Intermediate function that spawns the helper thread.
pub fn spawn_helper(helper: &Arc<Mutex<Self>>) {
let helper = Arc::clone(helper);
thread::spawn(move || { Self::helper(helper); });
}
// The tokio runtime that blocks while async reading both STDOUT/STDERR
// Cheaper than spawning 2 OS threads just to read 2 pipes (...right? :D)
#[tokio::main]
@ -364,7 +359,113 @@ impl Helper {
tokio::join![stdout_job, stderr_job];
}
// The "helper" loop
//---------------------------------------------------------------------------------------------------- P2Pool specific
// Intermediate function that parses the arguments, and spawns the P2Pool watchdog thread.
pub fn spawn_p2pool(state: &crate::disk::P2pool, api_path: &std::path::Path) {
let mut args = Vec::with_capacity(500);
// [Simple]
if state.simple {
// Build the p2pool argument
let (ip, rpc, zmq) = crate::node::enum_to_ip_rpc_zmq_tuple(state.node); // Get: (IP, RPC, ZMQ)
args.push(format!("--wallet {}", state.address)); // Wallet Address
args.push(format!("--host {}", ip)); // IP Address
args.push(format!("--rpc-port {}", rpc)); // RPC Port
args.push(format!("--zmq-port {}", zmq)); // ZMQ Port
args.push(format!("--data-api {}", api_path.display())); // API Path
args.push("--local-api".to_string()); // Enable API
args.push("--no-color".to_string()); // Remove color escape sequences, Gupax terminal can't parse it :(
args.push("--mini".to_string()); // P2Pool Mini
// [Advanced]
} else {
// Overriding command arguments
if !state.arguments.is_empty() {
for arg in state.arguments.split_whitespace() {
args.push(arg.to_string());
}
// Else, build the argument
} else {
args.push(state.address.clone()); // Wallet
args.push(state.selected_ip.clone()); // IP
args.push(state.selected_rpc.clone()); // RPC
args.push(state.selected_zmq.clone()); // ZMQ
args.push("--local-api".to_string()); // Enable API
args.push("--no-color".to_string()); // Remove color escape sequences
if state.mini { args.push("--mini".to_string()); }; // Mini
args.push(format!("--loglevel {}", state.log_level)); // Log Level
args.push(format!("--out-peers {}", state.out_peers)); // Out Peers
args.push(format!("--in-peers {}", state.in_peers)); // In Peers
args.push(format!("--data-api {}", api_path.display())); // API Path
}
}
// Print arguments to console
crate::disk::print_dash(&format!("P2Pool | Launch arguments ... {:#?}", args));
// Spawn watchdog thread
thread::spawn(move || {
Self::spawn_p2pool_watchdog(args);
});
}
// The actual P2Pool watchdog tokio runtime.
#[tokio::main]
pub async fn spawn_p2pool_watchdog(args: Vec<String>) {
// 1. Create command
// 2. Spawn STDOUT/STDERR thread
// 3. Loop forever as watchdog until process dies
}
//---------------------------------------------------------------------------------------------------- XMRig specific
// Intermediate function that parses the arguments, and spawns the XMRig watchdog thread.
pub fn spawn_xmrig(state: &crate::disk::Xmrig, api_path: &std::path::Path) {
let mut args = Vec::with_capacity(500);
if state.simple {
let rig_name = if state.simple_rig.is_empty() { GUPAX_VERSION.to_string() } else { state.simple_rig.clone() }; // Rig name
args.push(format!("--threads {}", state.current_threads)); // Threads
args.push(format!("--user {}", state.simple_rig)); // Rig name
args.push(format!("--url 127.0.0.1:3333")); // Local P2Pool (the default)
args.push("--no-color".to_string()); // No color escape codes
if state.pause != 0 { args.push(format!("--pause-on-active {}", state.pause)); } // Pause on active
} else {
if !state.arguments.is_empty() {
for arg in state.arguments.split_whitespace() {
args.push(arg.to_string());
}
} else {
args.push(format!("--user {}", state.address.clone())); // Wallet
args.push(format!("--threads {}", state.current_threads)); // Threads
args.push(format!("--rig-id {}", state.selected_rig)); // Rig ID
args.push(format!("--url {}:{}", state.selected_ip.clone(), state.selected_port.clone())); // IP/Port
args.push(format!("--http-host {}", state.api_ip).to_string()); // HTTP API IP
args.push(format!("--http-port {}", state.api_port).to_string()); // HTTP API Port
args.push("--no-color".to_string()); // No color escape codes
if state.tls { args.push("--tls".to_string()); } // TLS
if state.keepalive { args.push("--keepalive".to_string()); } // Keepalive
if state.pause != 0 { args.push(format!("--pause-on-active {}", state.pause)); } // Pause on active
}
}
// Print arguments to console
crate::disk::print_dash(&format!("XMRig | Launch arguments ... {:#?}", args));
// Spawn watchdog thread
thread::spawn(move || {
Self::spawn_xmrig_watchdog(args);
});
}
// The actual XMRig watchdog tokio runtime.
#[tokio::main]
pub async fn spawn_xmrig_watchdog(args: Vec<String>) {
}
//---------------------------------------------------------------------------------------------------- The "helper"
// Intermediate function that spawns the helper thread.
pub fn spawn_helper(helper: &Arc<Mutex<Self>>) {
let helper = Arc::clone(helper);
thread::spawn(move || { Self::helper(helper); });
}
// [helper] = Actual Arc
// [h] = Temporary lock that gets dropped
// [jobs] = Vector of async jobs ready to go

View file

@ -143,6 +143,18 @@ pub fn enum_to_ip(node: NodeEnum) -> &'static str {
}
}
// Returns a tuple of (IP, RPC_PORT, ZMQ_PORT)
pub fn enum_to_ip_rpc_zmq_tuple(node: NodeEnum) -> (&'static str, &'static str, &'static str) {
// [.unwrap()] should be safe, IP:PORTs are constants after all.
let (ip, rpc) = enum_to_ip(node).rsplit_once(':').unwrap();
// Get ZMQ, grr... plowsof is the only 18084 zmq person.
let zmq = match node {
Plowsof1|Plowsof2 => "18084",
_ => "18083",
};
(ip, rpc, zmq)
}
// 5000 = 4 max length
pub fn format_ms(ms: u128) -> String {
match ms.to_string().len() {

View file

@ -66,7 +66,7 @@ egui::Frame::none()
let width = (width/10.0) - SPACE;
ui.style_mut().override_text_style = Some(Monospace);
ui.add_sized([width, text_edit], Label::new("Command arguments:"));
ui.add_sized([ui.available_width(), text_edit], TextEdit::hint_text(TextEdit::singleline(&mut self.arguments), r#"--wallet <...> --host <...>"#)).on_hover_text(P2POOL_COMMAND);
ui.add_sized([ui.available_width(), text_edit], TextEdit::hint_text(TextEdit::singleline(&mut self.arguments), r#"--wallet <...> --host <...>"#)).on_hover_text(P2POOL_ARGUMENTS);
self.arguments.truncate(1024);
})});
ui.set_enabled(self.arguments.is_empty());

View file

@ -45,11 +45,11 @@ impl Xmrig {
ui.group(|ui| { ui.horizontal(|ui| {
let width = (width/10.0) - SPACE;
ui.style_mut().override_text_style = Some(Monospace);
ui.add_sized([width, text_edit], Label::new("Config file:"));
ui.add_sized([ui.available_width(), text_edit], TextEdit::hint_text(TextEdit::singleline(&mut self.config), r#"...config.json"#)).on_hover_text(XMRIG_CONFIG);
self.config.truncate(1024);
ui.add_sized([width, text_edit], Label::new("Command arguments:"));
ui.add_sized([ui.available_width(), text_edit], TextEdit::hint_text(TextEdit::singleline(&mut self.arguments), r#"--url <...> --user <...> --config <...>"#)).on_hover_text(XMRIG_ARGUMENTS);
self.arguments.truncate(1024);
})});
ui.set_enabled(self.config.is_empty());
ui.set_enabled(self.arguments.is_empty());
//---------------------------------------------------------------------------------------------------- Address
ui.group(|ui| {
let width = width - SPACE;