mirror of
https://github.com/hinto-janai/gupax.git
synced 2024-12-23 11:29:38 +00:00
Status Submenu: add serde for p2pools [local/network/pool] API
This commit is contained in:
parent
acba71f157
commit
9245cc8a11
3 changed files with 177 additions and 52 deletions
|
@ -4,6 +4,7 @@
|
||||||
* [Bootstrap](#Bootstrap)
|
* [Bootstrap](#Bootstrap)
|
||||||
* [Scale](#Scale)
|
* [Scale](#Scale)
|
||||||
* [Naming Scheme](#naming-scheme)
|
* [Naming Scheme](#naming-scheme)
|
||||||
|
* [Mining Stat Reference](#mining-stat-reference)
|
||||||
* [Sudo](#Sudo)
|
* [Sudo](#Sudo)
|
||||||
* [Why does Gupax need to be Admin? (on Windows)](#why-does-gupax-need-to-be-admin-on-windows)
|
* [Why does Gupax need to be Admin? (on Windows)](#why-does-gupax-need-to-be-admin-on-windows)
|
||||||
- [The issue](#the-issue)
|
- [The issue](#the-issue)
|
||||||
|
@ -124,6 +125,31 @@ Exceptions (there are always exceptions...):
|
||||||
- XMRig separates the hash and signature
|
- XMRig separates the hash and signature
|
||||||
- P2Pool hashes are in UPPERCASE
|
- P2Pool hashes are in UPPERCASE
|
||||||
|
|
||||||
|
## Mining Stat Reference
|
||||||
|
Some pseudo JSON for constants/equations needed for generating mining stats. They're here for easy reference, I was never good at math :)
|
||||||
|
```
|
||||||
|
block_time_in_seconds: {
|
||||||
|
P2POOL_BLOCK_TIME: 10,
|
||||||
|
MONERO_BLOCK_TIME: 120,
|
||||||
|
}
|
||||||
|
|
||||||
|
difficulty: {
|
||||||
|
P2POOL_DIFFICULTY: (current_p2pool_hashrate * P2POOL_BLOCK_TIME),
|
||||||
|
MONERO_DIFFICULTY: (current_monero_hashrate * MONERO_BLOCK_TIME),
|
||||||
|
}
|
||||||
|
|
||||||
|
hashrate_per_second: {
|
||||||
|
P2POOL_HASHRATE: (P2POOL_DIFFICULTY / P2POOL_BLOCK_TIME),
|
||||||
|
MONERO_HASHRATE: (MONERO_DIFFICULTY / MONERO_BLOCK_TIME),
|
||||||
|
}
|
||||||
|
|
||||||
|
mean_in_seconds: {
|
||||||
|
P2POOL_BLOCK_MEAN: (MONERO_DIFF / P2POOL_HASHRATE),
|
||||||
|
MY_SOLO_BLOCK_MEAN: (MONERO_DIFF / my_hashrate),
|
||||||
|
MY_P2POOL_SHARE_MEAN: (P2POOL_DIFF / my_hashrate),
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Sudo
|
## Sudo
|
||||||
Unlike Windows, Unix (macOS/Linux) has a userland program that handles all the dirty details of privilege escalation: `sudo`.
|
Unlike Windows, Unix (macOS/Linux) has a userland program that handles all the dirty details of privilege escalation: `sudo`.
|
||||||
|
|
||||||
|
@ -208,7 +234,7 @@ This was the solution I would have gone with, but alas, the abstracted `Command`
|
||||||
---
|
---
|
||||||
|
|
||||||
### Windows vs Unix
|
### Windows vs Unix
|
||||||
Unix (macOS/Linux) has have a super nice, easy, friendly, not-completely-garbage userland program called: `sudo`. It is so extremely simple to use `sudo` as a sort of wrapper around XMRig since `sudo` isn't completely backwards and actually has valuable flags! No legacy `Administrator`, no UAC prompt, no shells within shells, no low-level system APIs, no messing with the user Registry.
|
Unix (macOS/Linux) has a super nice, easy, friendly, not-completely-garbage userland program called: `sudo`. It is so extremely simple to use `sudo` as a sort of wrapper around XMRig since `sudo` isn't completely backwards and actually has valuable flags! No legacy `Administrator`, no UAC prompt, no shells within shells, no low-level system APIs, no messing with the user Registry.
|
||||||
|
|
||||||
You get the user's password, you input it to `sudo` with `--stdin` and you execute XMRig with it. Simple, easy, nice. (Don't forget to zero the password memory, though).
|
You get the user's password, you input it to `sudo` with `--stdin` and you execute XMRig with it. Simple, easy, nice. (Don't forget to zero the password memory, though).
|
||||||
|
|
||||||
|
|
|
@ -70,9 +70,17 @@ r#"*---------------------------------------*
|
||||||
*---------------------------------------*"#;
|
*---------------------------------------*"#;
|
||||||
// P2Pool & XMRig default API stuff
|
// P2Pool & XMRig default API stuff
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub const P2POOL_API_PATH: &str = r"local\stats"; // The default relative FS path of P2Pool's local API
|
pub const P2POOL_API_PATH_LOCAL: &str = r"local\stats";
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
pub const P2POOL_API_PATH_NETWORK: &str = r"network\stats";
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
pub const P2POOL_API_PATH_POOL: &str = r"pool\stats";
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
pub const P2POOL_API_PATH: &str = "local/stats";
|
pub const P2POOL_API_PATH_LOCAL: &str = "local/stats";
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
pub const P2POOL_API_PATH_NETWORK: &str = "network/stats";
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
pub const P2POOL_API_PATH_POOL: &str = "pool/stats";
|
||||||
pub const XMRIG_API_URI: &str = "1/summary"; // The default relative URI of XMRig's API
|
pub const XMRIG_API_URI: &str = "1/summary"; // The default relative URI of XMRig's API
|
||||||
|
|
||||||
// Process state tooltips (online, offline, etc)
|
// Process state tooltips (online, offline, etc)
|
||||||
|
@ -148,8 +156,8 @@ pub const STATUS_GUPAX_SYSTEM_MEMORY: &str = "How much memory your entire system
|
||||||
pub const STATUS_GUPAX_SYSTEM_CPU_MODEL: &str = "The detected model of your system's CPU and its current frequency";
|
pub const STATUS_GUPAX_SYSTEM_CPU_MODEL: &str = "The detected model of your system's CPU and its current frequency";
|
||||||
//--
|
//--
|
||||||
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 and an extrapolated estimate of how many you will receive. Warning: these stats will be quite inaccurate if your P2Pool hasn't been running for a long time!";
|
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. Warning: 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 via P2Pool and an extrapolated estimate of how many you will mine in the future. Warning: 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. Warning: 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 = "The average amount of effort needed to find a share, and the current effort";
|
pub const STATUS_P2POOL_EFFORT: &str = "The average amount of effort needed to find a share, and the current effort";
|
||||||
|
|
185
src/helper.rs
185
src/helper.rs
|
@ -75,8 +75,10 @@ pub struct Helper {
|
||||||
pub img_xmrig: Arc<Mutex<ImgXmrig>>, // A static "image" of the data XMRig started with
|
pub img_xmrig: Arc<Mutex<ImgXmrig>>, // A static "image" of the data XMRig started with
|
||||||
pub_api_p2pool: Arc<Mutex<PubP2poolApi>>, // P2Pool API state (for Helper/P2Pool thread)
|
pub_api_p2pool: Arc<Mutex<PubP2poolApi>>, // P2Pool API state (for Helper/P2Pool thread)
|
||||||
pub_api_xmrig: Arc<Mutex<PubXmrigApi>>, // XMRig API state (for Helper/XMRig thread)
|
pub_api_xmrig: Arc<Mutex<PubXmrigApi>>, // XMRig API state (for Helper/XMRig thread)
|
||||||
priv_api_p2pool: Arc<Mutex<PrivP2poolApi>>, // For "watchdog" thread
|
priv_api_p2pool_local: Arc<Mutex<PrivP2poolLocalApi>>, // Serde struct(s) for P2Pool's API files
|
||||||
priv_api_xmrig: Arc<Mutex<PrivXmrigApi>>, // For "watchdog" thread
|
priv_api_p2pool_network: Arc<Mutex<PrivP2poolNetworkApi>>,
|
||||||
|
priv_api_p2pool_pool: Arc<Mutex<PrivP2poolPoolApi>>,
|
||||||
|
priv_api_xmrig: Arc<Mutex<PrivXmrigApi>>, // Serde struct for XMRig's HTTP API
|
||||||
}
|
}
|
||||||
|
|
||||||
// The communication between the data here and the GUI thread goes as follows:
|
// The communication between the data here and the GUI thread goes as follows:
|
||||||
|
@ -110,12 +112,7 @@ impl Sys {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Default for Sys { fn default() -> Self { Self::new() } }
|
||||||
impl Default for Sys {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- [Process] Struct
|
//---------------------------------------------------------------------------------------------------- [Process] Struct
|
||||||
// This holds all the state of a (child) process.
|
// This holds all the state of a (child) process.
|
||||||
|
@ -229,7 +226,9 @@ impl Helper {
|
||||||
instant,
|
instant,
|
||||||
pub_sys,
|
pub_sys,
|
||||||
uptime: HumanTime::into_human(instant.elapsed()),
|
uptime: HumanTime::into_human(instant.elapsed()),
|
||||||
priv_api_p2pool: Arc::new(Mutex::new(PrivP2poolApi::new())),
|
priv_api_p2pool_local: Arc::new(Mutex::new(PrivP2poolLocalApi::new())),
|
||||||
|
priv_api_p2pool_network: Arc::new(Mutex::new(PrivP2poolNetworkApi::new())),
|
||||||
|
priv_api_p2pool_pool: Arc::new(Mutex::new(PrivP2poolPoolApi::new())),
|
||||||
priv_api_xmrig: Arc::new(Mutex::new(PrivXmrigApi::new())),
|
priv_api_xmrig: Arc::new(Mutex::new(PrivXmrigApi::new())),
|
||||||
pub_api_p2pool: Arc::new(Mutex::new(PubP2poolApi::new())),
|
pub_api_p2pool: Arc::new(Mutex::new(PubP2poolApi::new())),
|
||||||
pub_api_xmrig: Arc::new(Mutex::new(PubXmrigApi::new())),
|
pub_api_xmrig: Arc::new(Mutex::new(PubXmrigApi::new())),
|
||||||
|
@ -278,6 +277,14 @@ impl Helper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read P2Pool/XMRig's API file to a [String].
|
||||||
|
fn path_to_string(path: &std::path::PathBuf, name: ProcessName) -> std::result::Result<String, std::io::Error> {
|
||||||
|
match std::fs::read_to_string(path) {
|
||||||
|
Ok(s) => Ok(s),
|
||||||
|
Err(e) => { warn!("{} API | [{}] read error: {}", name, path.display(), e); Err(e) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- P2Pool specific
|
//---------------------------------------------------------------------------------------------------- P2Pool specific
|
||||||
// Just sets some signals for the watchdog thread to pick up on.
|
// Just sets some signals for the watchdog thread to pick up on.
|
||||||
pub fn stop_p2pool(helper: &Arc<Mutex<Self>>) {
|
pub fn stop_p2pool(helper: &Arc<Mutex<Self>>) {
|
||||||
|
@ -313,19 +320,24 @@ impl Helper {
|
||||||
pub fn start_p2pool(helper: &Arc<Mutex<Self>>, state: &crate::disk::P2pool, path: &std::path::PathBuf) {
|
pub fn start_p2pool(helper: &Arc<Mutex<Self>>, state: &crate::disk::P2pool, path: &std::path::PathBuf) {
|
||||||
helper.lock().unwrap().p2pool.lock().unwrap().state = ProcessState::Middle;
|
helper.lock().unwrap().p2pool.lock().unwrap().state = ProcessState::Middle;
|
||||||
|
|
||||||
let (args, api_path) = Self::build_p2pool_args_and_mutate_img(helper, state, path);
|
let (args, api_path_local, api_path_network, api_path_pool) = Self::build_p2pool_args_and_mutate_img(helper, state, path);
|
||||||
|
|
||||||
// Print arguments & user settings to console
|
// Print arguments & user settings to console
|
||||||
crate::disk::print_dash(&format!("P2Pool | Launch arguments: {:#?} | API Path: {:#?}", args, api_path));
|
crate::disk::print_dash(&format!(
|
||||||
|
"P2Pool | Launch arguments: {:#?} | Local API Path: {:#?} | Network API Path: {:#?} | Pool API Path: {:#?}",
|
||||||
|
args,
|
||||||
|
api_path_local,
|
||||||
|
api_path_network,
|
||||||
|
api_path_pool,
|
||||||
|
));
|
||||||
|
|
||||||
// Spawn watchdog thread
|
// Spawn watchdog thread
|
||||||
let process = Arc::clone(&helper.lock().unwrap().p2pool);
|
let process = Arc::clone(&helper.lock().unwrap().p2pool);
|
||||||
let gui_api = Arc::clone(&helper.lock().unwrap().gui_api_p2pool);
|
let gui_api = Arc::clone(&helper.lock().unwrap().gui_api_p2pool);
|
||||||
let pub_api = Arc::clone(&helper.lock().unwrap().pub_api_p2pool);
|
let pub_api = Arc::clone(&helper.lock().unwrap().pub_api_p2pool);
|
||||||
let priv_api = Arc::clone(&helper.lock().unwrap().priv_api_p2pool);
|
|
||||||
let path = path.clone();
|
let path = path.clone();
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
Self::spawn_p2pool_watchdog(process, gui_api, pub_api, priv_api, args, path, api_path);
|
Self::spawn_p2pool_watchdog(process, gui_api, pub_api, args, path, api_path_local, api_path_network, api_path_pool);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,7 +353,7 @@ impl Helper {
|
||||||
// Takes in some [State/P2pool] and parses it to build the actual command arguments.
|
// Takes in some [State/P2pool] and parses it to build the actual command arguments.
|
||||||
// Returns the [Vec] of actual arguments, and mutates the [ImgP2pool] for the main GUI thread
|
// Returns the [Vec] of actual arguments, and mutates the [ImgP2pool] for the main GUI thread
|
||||||
// It returns a value... and mutates a deeply nested passed argument... this is some pretty bad code...
|
// It returns a value... and mutates a deeply nested passed argument... this is some pretty bad code...
|
||||||
pub fn build_p2pool_args_and_mutate_img(helper: &Arc<Mutex<Self>>, state: &crate::disk::P2pool, path: &std::path::PathBuf) -> (Vec<String>, PathBuf) {
|
pub fn build_p2pool_args_and_mutate_img(helper: &Arc<Mutex<Self>>, state: &crate::disk::P2pool, path: &std::path::PathBuf) -> (Vec<String>, PathBuf, PathBuf, PathBuf) {
|
||||||
let mut args = Vec::with_capacity(500);
|
let mut args = Vec::with_capacity(500);
|
||||||
let path = path.clone();
|
let path = path.clone();
|
||||||
let mut api_path = path;
|
let mut api_path = path;
|
||||||
|
@ -419,12 +431,17 @@ impl Helper {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
api_path.push(P2POOL_API_PATH);
|
let mut api_path_local = api_path.clone();
|
||||||
(args, api_path)
|
let mut api_path_network = api_path.clone();
|
||||||
|
let mut api_path_pool = api_path.clone();
|
||||||
|
api_path_local.push(P2POOL_API_PATH_LOCAL);
|
||||||
|
api_path_network.push(P2POOL_API_PATH_NETWORK);
|
||||||
|
api_path_pool.push(P2POOL_API_PATH_POOL);
|
||||||
|
(args, api_path_local, api_path_network, api_path_pool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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(process: Arc<Mutex<Process>>, gui_api: Arc<Mutex<PubP2poolApi>>, pub_api: Arc<Mutex<PubP2poolApi>>, _priv_api: Arc<Mutex<PrivP2poolApi>>, args: Vec<String>, path: std::path::PathBuf, api_path: std::path::PathBuf) {
|
fn spawn_p2pool_watchdog(process: Arc<Mutex<Process>>, gui_api: Arc<Mutex<PubP2poolApi>>, pub_api: Arc<Mutex<PubP2poolApi>>, args: Vec<String>, path: std::path::PathBuf, api_path_local: std::path::PathBuf, api_path_network: std::path::PathBuf, api_path_pool: std::path::PathBuf) {
|
||||||
// 1a. Create PTY
|
// 1a. Create PTY
|
||||||
debug!("P2Pool | Creating PTY...");
|
debug!("P2Pool | Creating PTY...");
|
||||||
let pty = portable_pty::native_pty_system();
|
let pty = portable_pty::native_pty_system();
|
||||||
|
@ -464,17 +481,17 @@ impl Helper {
|
||||||
let output_parse = Arc::clone(&process.lock().unwrap().output_parse);
|
let output_parse = Arc::clone(&process.lock().unwrap().output_parse);
|
||||||
let output_pub = Arc::clone(&process.lock().unwrap().output_pub);
|
let output_pub = Arc::clone(&process.lock().unwrap().output_pub);
|
||||||
|
|
||||||
debug!("P2Pool | Cleaning old API files...");
|
debug!("P2Pool | Cleaning old [local] API files...");
|
||||||
// Attempt to remove stale API file
|
// Attempt to remove stale API file
|
||||||
match std::fs::remove_file(&api_path) {
|
match std::fs::remove_file(&api_path_local) {
|
||||||
Ok(_) => info!("P2Pool | Attempting to remove stale API file ... OK"),
|
Ok(_) => info!("P2Pool | Attempting to remove stale API file ... OK"),
|
||||||
Err(e) => warn!("P2Pool | Attempting to remove stale API file ... FAIL ... {}", e),
|
Err(e) => warn!("P2Pool | Attempting to remove stale API file ... FAIL ... {}", e),
|
||||||
}
|
}
|
||||||
// Attempt to create a default empty one.
|
// Attempt to create a default empty one.
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
if std::fs::File::create(&api_path).is_ok() {
|
if std::fs::File::create(&api_path_local).is_ok() {
|
||||||
let text = r#"{"hashrate_15m":0,"hashrate_1h":0,"hashrate_24h":0,"shares_found":0,"average_effort":0.0,"current_effort":0.0,"connections":0}"#;
|
let text = r#"{"hashrate_15m":0,"hashrate_1h":0,"hashrate_24h":0,"shares_found":0,"average_effort":0.0,"current_effort":0.0,"connections":0}"#;
|
||||||
match std::fs::write(&api_path, text) {
|
match std::fs::write(&api_path_local, text) {
|
||||||
Ok(_) => info!("P2Pool | Creating default empty API file ... OK"),
|
Ok(_) => info!("P2Pool | Creating default empty API file ... OK"),
|
||||||
Err(e) => warn!("P2Pool | Creating default empty API file ... FAIL ... {}", e),
|
Err(e) => warn!("P2Pool | Creating default empty API file ... FAIL ... {}", e),
|
||||||
}
|
}
|
||||||
|
@ -600,13 +617,28 @@ impl Helper {
|
||||||
debug!("P2Pool Watchdog | Starting [update_from_output()]");
|
debug!("P2Pool Watchdog | Starting [update_from_output()]");
|
||||||
PubP2poolApi::update_from_output(&pub_api, &output_parse, &output_pub, start.elapsed(), ®ex);
|
PubP2poolApi::update_from_output(&pub_api, &output_parse, &output_pub, start.elapsed(), ®ex);
|
||||||
|
|
||||||
// Read API file into string
|
// Read [local] API
|
||||||
debug!("P2Pool Watchdog | Attempting API file read");
|
debug!("P2Pool Watchdog | Attempting [local] API file read");
|
||||||
if let Ok(string) = PrivP2poolApi::read_p2pool_api(&api_path) {
|
if let Ok(string) = Self::path_to_string(&api_path_local, ProcessName::P2pool) {
|
||||||
// Deserialize
|
// Deserialize
|
||||||
if let Ok(s) = PrivP2poolApi::str_to_priv_p2pool_api(&string) {
|
if let Ok(s) = PrivP2poolLocalApi::from_str(&string) {
|
||||||
// Update the structs.
|
// Update the structs.
|
||||||
PubP2poolApi::update_from_priv(&pub_api, s);
|
PubP2poolApi::update_from_local(&pub_api, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If more than 1 minute has passed, read the other API files.
|
||||||
|
if now.elapsed().as_secs() >= 60 {
|
||||||
|
debug!("P2Pool Watchdog | Attempting [network] API file read");
|
||||||
|
if let Ok(string) = Self::path_to_string(&api_path_network, ProcessName::P2pool) {
|
||||||
|
if let Ok(s) = PrivP2poolNetworkApi::from_str(&string) {
|
||||||
|
// PubP2poolApi::update_from_network(&pub_api, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug!("P2Pool Watchdog | Attempting [pool] API file read");
|
||||||
|
if let Ok(string) = Self::path_to_string(&api_path_pool, ProcessName::P2pool) {
|
||||||
|
if let Ok(s) = PrivP2poolPoolApi::from_str(&string) {
|
||||||
|
// PubP2poolApi::update_from_network(&pub_api, s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1388,7 +1420,7 @@ pub struct PubP2poolApi {
|
||||||
pub xmr_hour: f64,
|
pub xmr_hour: f64,
|
||||||
pub xmr_day: f64,
|
pub xmr_day: f64,
|
||||||
pub xmr_month: f64,
|
pub xmr_month: f64,
|
||||||
// The rest are serialized from the API, then turned into [HumanNumber]s
|
// Local API
|
||||||
pub hashrate_15m: HumanNumber,
|
pub hashrate_15m: HumanNumber,
|
||||||
pub hashrate_1h: HumanNumber,
|
pub hashrate_1h: HumanNumber,
|
||||||
pub hashrate_24h: HumanNumber,
|
pub hashrate_24h: HumanNumber,
|
||||||
|
@ -1396,6 +1428,8 @@ pub struct PubP2poolApi {
|
||||||
pub average_effort: HumanNumber,
|
pub average_effort: HumanNumber,
|
||||||
pub current_effort: HumanNumber,
|
pub current_effort: HumanNumber,
|
||||||
pub connections: HumanNumber,
|
pub connections: HumanNumber,
|
||||||
|
// Network API
|
||||||
|
// Pool API
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PubP2poolApi {
|
impl Default for PubP2poolApi {
|
||||||
|
@ -1498,8 +1532,8 @@ impl PubP2poolApi {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mutate [PubP2poolApi] with data from a [PrivP2poolApi] and the process output.
|
// Mutate [PubP2poolApi] with data from a [PrivP2poolLocalApi] and the process output.
|
||||||
fn update_from_priv(public: &Arc<Mutex<Self>>, private: PrivP2poolApi) {
|
fn update_from_local(public: &Arc<Mutex<Self>>, private: PrivP2poolLocalApi) {
|
||||||
// priv -> pub conversion
|
// priv -> pub conversion
|
||||||
let mut public = public.lock().unwrap();
|
let mut public = public.lock().unwrap();
|
||||||
*public = Self {
|
*public = Self {
|
||||||
|
@ -1530,12 +1564,11 @@ impl PubP2poolApi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Private P2Pool API
|
//---------------------------------------------------------------------------------------------------- Private P2Pool "Local" Api
|
||||||
// This is the data the "watchdog" threads mutate.
|
// This matches directly to P2Pool's [local/stats] JSON API file (excluding a few stats).
|
||||||
// It matches directly to P2Pool's [local/stats] JSON API file (excluding a few stats).
|
|
||||||
// P2Pool seems to initialize all stats at 0 (or 0.0), so no [Option] wrapper seems needed.
|
// P2Pool seems to initialize all stats at 0 (or 0.0), so no [Option] wrapper seems needed.
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
|
#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
|
||||||
struct PrivP2poolApi {
|
struct PrivP2poolLocalApi {
|
||||||
hashrate_15m: u128,
|
hashrate_15m: u128,
|
||||||
hashrate_1h: u128,
|
hashrate_1h: u128,
|
||||||
hashrate_24h: u128,
|
hashrate_24h: u128,
|
||||||
|
@ -1545,7 +1578,9 @@ struct PrivP2poolApi {
|
||||||
connections: u16, // No one will have more than 65535 connections... right?
|
connections: u16, // No one will have more than 65535 connections... right?
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrivP2poolApi {
|
impl Default for PrivP2poolLocalApi { fn default() -> Self { Self::new() } }
|
||||||
|
|
||||||
|
impl PrivP2poolLocalApi {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
hashrate_15m: 0,
|
hashrate_15m: 0,
|
||||||
|
@ -1558,23 +1593,79 @@ impl PrivP2poolApi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read P2Pool's API file to a [String].
|
|
||||||
fn read_p2pool_api(path: &std::path::PathBuf) -> std::result::Result<String, std::io::Error> {
|
|
||||||
match std::fs::read_to_string(path) {
|
|
||||||
Ok(s) => Ok(s),
|
|
||||||
Err(e) => { warn!("P2Pool API | [{}] read error: {}", path.display(), e); Err(e) },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the above [String] into a [PrivP2poolApi]
|
// Deserialize the above [String] into a [PrivP2poolApi]
|
||||||
fn str_to_priv_p2pool_api(string: &str) -> std::result::Result<Self, serde_json::Error> {
|
fn from_str(string: &str) -> std::result::Result<Self, serde_json::Error> {
|
||||||
match serde_json::from_str::<Self>(string) {
|
match serde_json::from_str::<Self>(string) {
|
||||||
Ok(a) => Ok(a),
|
Ok(a) => Ok(a),
|
||||||
Err(e) => { warn!("P2Pool API | Could not deserialize API data: {}", e); Err(e) },
|
Err(e) => { warn!("P2Pool Local API | Could not deserialize API data: {}", e); Err(e) },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------- Private P2Pool "Network" API
|
||||||
|
// This matches P2Pool's [network/stats] JSON API file.
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
struct PrivP2poolNetworkApi {
|
||||||
|
difficulty: u128,
|
||||||
|
hash: String,
|
||||||
|
height: u32,
|
||||||
|
reward: u128,
|
||||||
|
timestamp: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PrivP2poolNetworkApi { fn default() -> Self { Self::new() } }
|
||||||
|
|
||||||
|
impl PrivP2poolNetworkApi {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
difficulty: 0,
|
||||||
|
hash: String::from("???"),
|
||||||
|
height: 0,
|
||||||
|
reward: 0,
|
||||||
|
timestamp: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_str(string: &str) -> std::result::Result<Self, serde_json::Error> {
|
||||||
|
match serde_json::from_str::<Self>(string) {
|
||||||
|
Ok(a) => Ok(a),
|
||||||
|
Err(e) => { warn!("P2Pool Network API | Could not deserialize API data: {}", e); Err(e) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------- Private P2Pool "Pool" API
|
||||||
|
// This matches P2Pool's [pool/stats] JSON API file.
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
|
||||||
|
struct PrivP2poolPoolApi {
|
||||||
|
pool_statistics: PoolStatistics,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PrivP2poolPoolApi { fn default() -> Self { Self::new() } }
|
||||||
|
|
||||||
|
impl PrivP2poolPoolApi {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
pool_statistics: PoolStatistics::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_str(string: &str) -> std::result::Result<Self, serde_json::Error> {
|
||||||
|
match serde_json::from_str::<Self>(string) {
|
||||||
|
Ok(a) => Ok(a),
|
||||||
|
Err(e) => { warn!("P2Pool Pool API | Could not deserialize API data: {}", e); Err(e) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
|
||||||
|
struct PoolStatistics {
|
||||||
|
hashrate: u128,
|
||||||
|
miners: u32,
|
||||||
|
}
|
||||||
|
impl Default for PoolStatistics { fn default() -> Self { Self::new() } }
|
||||||
|
impl PoolStatistics { fn new() -> Self { Self { hashrate: 0, miners: 0 } } }
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- [ImgXmrig]
|
//---------------------------------------------------------------------------------------------------- [ImgXmrig]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ImgXmrig {
|
pub struct ImgXmrig {
|
||||||
|
@ -1928,7 +2019,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serde_priv_p2pool_api() {
|
fn serde_priv_p2pool_local_api() {
|
||||||
let data =
|
let data =
|
||||||
r#"{
|
r#"{
|
||||||
"hashrate_15m": 12,
|
"hashrate_15m": 12,
|
||||||
|
@ -1941,8 +2032,8 @@ mod test {
|
||||||
"connections": 123,
|
"connections": 123,
|
||||||
"incoming_connections": 96
|
"incoming_connections": 96
|
||||||
}"#;
|
}"#;
|
||||||
use crate::helper::PrivP2poolApi;
|
use crate::helper::PrivP2poolLocalApi;
|
||||||
let priv_api = PrivP2poolApi::str_to_priv_p2pool_api(data).unwrap();
|
let priv_api = PrivP2poolLocalApi::from_str(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 =
|
let data_after_ser =
|
||||||
|
|
Loading…
Reference in a new issue