mirror of
https://github.com/Cyrix126/gupaxx.git
synced 2024-12-22 14:49:21 +00:00
fix: algorithm, watch current shares from status command
This commit is contained in:
parent
3233972cf7
commit
aee777d160
2 changed files with 140 additions and 34 deletions
|
@ -32,6 +32,7 @@ impl Helper {
|
||||||
output_pub: Arc<Mutex<String>>,
|
output_pub: Arc<Mutex<String>>,
|
||||||
reader: Box<dyn std::io::Read + Send>,
|
reader: Box<dyn std::io::Read + Send>,
|
||||||
gupax_p2pool_api: Arc<Mutex<GupaxP2poolApi>>,
|
gupax_p2pool_api: Arc<Mutex<GupaxP2poolApi>>,
|
||||||
|
pub_api: Arc<Mutex<PubP2poolApi>>,
|
||||||
) {
|
) {
|
||||||
use std::io::BufRead;
|
use std::io::BufRead;
|
||||||
let mut stdout = std::io::BufReader::new(reader).lines();
|
let mut stdout = std::io::BufReader::new(reader).lines();
|
||||||
|
@ -40,6 +41,7 @@ impl Helper {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while let Some(Ok(line)) = stdout.next() {
|
while let Some(Ok(line)) = stdout.next() {
|
||||||
let line = strip_ansi_escapes::strip_str(line);
|
let line = strip_ansi_escapes::strip_str(line);
|
||||||
|
|
||||||
if let Err(e) = writeln!(lock!(output_parse), "{}", line) {
|
if let Err(e) = writeln!(lock!(output_parse), "{}", line) {
|
||||||
error!("P2Pool PTY Parse | Output error: {}", e);
|
error!("P2Pool PTY Parse | Output error: {}", e);
|
||||||
}
|
}
|
||||||
|
@ -52,8 +54,26 @@ impl Helper {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let mut status_output = false;
|
||||||
while let Some(Ok(line)) = stdout.next() {
|
while let Some(Ok(line)) = stdout.next() {
|
||||||
|
// if command status is sent by gupaxx process and not the user, forward it only to update_from_status method.
|
||||||
|
// 25 lines after the command are the result of status, with last line finishing by update.
|
||||||
|
if line.contains("statusfromgupaxx") {
|
||||||
|
status_output = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if status_output {
|
||||||
|
if line.contains("Your shares") {
|
||||||
|
// update sidechain shares
|
||||||
|
let shares = line.split_once("=").expect("should be = at Your Share, maybe new version of p2pool has different output for status command ?").1.split_once("blocks").expect("should be a 'blocks' at Your Share, maybe new version of p2pool has different output for status command ?").0.trim().parse::<u32>().expect("this should be the number of share");
|
||||||
|
lock!(pub_api).sidechain_shares = shares;
|
||||||
|
}
|
||||||
|
if line.contains("Uptime") {
|
||||||
|
// end of status
|
||||||
|
status_output = false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// println!("{}", line); // For debugging.
|
// println!("{}", line); // For debugging.
|
||||||
if P2POOL_REGEX.payout.is_match(&line) {
|
if P2POOL_REGEX.payout.is_match(&line) {
|
||||||
debug!("P2Pool PTY | Found payout, attempting write: {}", line);
|
debug!("P2Pool PTY | Found payout, attempting write: {}", line);
|
||||||
|
@ -394,8 +414,15 @@ impl Helper {
|
||||||
let output_parse = Arc::clone(&lock!(process).output_parse);
|
let output_parse = Arc::clone(&lock!(process).output_parse);
|
||||||
let output_pub = Arc::clone(&lock!(process).output_pub);
|
let output_pub = Arc::clone(&lock!(process).output_pub);
|
||||||
let gupax_p2pool_api = Arc::clone(&gupax_p2pool_api);
|
let gupax_p2pool_api = Arc::clone(&gupax_p2pool_api);
|
||||||
|
let p2pool_api_c = Arc::clone(&pub_api);
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
Self::read_pty_p2pool(output_parse, output_pub, reader, gupax_p2pool_api);
|
Self::read_pty_p2pool(
|
||||||
|
output_parse,
|
||||||
|
output_pub,
|
||||||
|
reader,
|
||||||
|
gupax_p2pool_api,
|
||||||
|
p2pool_api_c,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
let output_parse = Arc::clone(&lock!(process).output_parse);
|
let output_parse = Arc::clone(&lock!(process).output_parse);
|
||||||
let output_pub = Arc::clone(&lock!(process).output_pub);
|
let output_pub = Arc::clone(&lock!(process).output_pub);
|
||||||
|
@ -434,6 +461,7 @@ impl Helper {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
debug!("P2Pool Watchdog | ----------- Start of loop -----------");
|
debug!("P2Pool Watchdog | ----------- Start of loop -----------");
|
||||||
lock!(gui_api).tick += 1;
|
lock!(gui_api).tick += 1;
|
||||||
|
lock!(gui_api).tick_status += 1;
|
||||||
|
|
||||||
// Check if the process is secretly died without us knowing :)
|
// Check if the process is secretly died without us knowing :)
|
||||||
if let Ok(Some(code)) = lock!(child_pty).try_wait() {
|
if let Ok(Some(code)) = lock!(child_pty).try_wait() {
|
||||||
|
@ -636,6 +664,22 @@ impl Helper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if lock!(gui_api).tick_status >= 10 && lock!(process).state == ProcessState::Alive {
|
||||||
|
debug!("reading status output of p2pool node");
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
if let Err(e) = write!(stdin, "statusfromgupaxx\r\n") {
|
||||||
|
error!("P2Pool Watchdog | STDIN error: {}", e);
|
||||||
|
}
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
if let Err(e) = writeln!(stdin, "statusfromgupaxx") {
|
||||||
|
error!("P2Pool Watchdog | STDIN error: {}", e);
|
||||||
|
}
|
||||||
|
// Flush.
|
||||||
|
if let Err(e) = stdin.flush() {
|
||||||
|
error!("P2Pool Watchdog | STDIN flush error: {}", e);
|
||||||
|
}
|
||||||
|
lock!(gui_api).tick_status = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Sleep (only if 900ms hasn't passed)
|
// Sleep (only if 900ms hasn't passed)
|
||||||
let elapsed = now.elapsed().as_millis();
|
let elapsed = now.elapsed().as_millis();
|
||||||
|
@ -733,6 +777,9 @@ pub struct PubP2poolApi {
|
||||||
// Tick. Every loop this gets incremented.
|
// Tick. Every loop this gets incremented.
|
||||||
// At 60, it indicated we should read the below API files.
|
// At 60, it indicated we should read the below API files.
|
||||||
pub tick: u8,
|
pub tick: u8,
|
||||||
|
// Tick. Every loop this gets incremented.
|
||||||
|
// At 10, it indicated we should fetch data from status
|
||||||
|
pub tick_status: u8,
|
||||||
// Network API
|
// Network API
|
||||||
pub monero_difficulty: HumanNumber, // e.g: [15,000,000]
|
pub monero_difficulty: HumanNumber, // e.g: [15,000,000]
|
||||||
pub monero_hashrate: HumanNumber, // e.g: [1.000 GH/s]
|
pub monero_hashrate: HumanNumber, // e.g: [1.000 GH/s]
|
||||||
|
@ -751,6 +798,8 @@ pub struct PubP2poolApi {
|
||||||
pub p2pool_percent: HumanNumber, // Percentage of P2Pool hashrate capture of overall Monero hashrate.
|
pub p2pool_percent: HumanNumber, // Percentage of P2Pool hashrate capture of overall Monero hashrate.
|
||||||
pub user_p2pool_percent: HumanNumber, // How much percent the user's hashrate accounts for in P2Pool.
|
pub user_p2pool_percent: HumanNumber, // How much percent the user's hashrate accounts for in P2Pool.
|
||||||
pub user_monero_percent: HumanNumber, // How much percent the user's hashrate accounts for in all of Monero hashrate.
|
pub user_monero_percent: HumanNumber, // How much percent the user's hashrate accounts for in all of Monero hashrate.
|
||||||
|
// from status
|
||||||
|
pub sidechain_shares: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PubP2poolApi {
|
impl Default for PubP2poolApi {
|
||||||
|
@ -780,6 +829,7 @@ impl PubP2poolApi {
|
||||||
current_effort: HumanNumber::unknown(),
|
current_effort: HumanNumber::unknown(),
|
||||||
connections: HumanNumber::unknown(),
|
connections: HumanNumber::unknown(),
|
||||||
tick: 0,
|
tick: 0,
|
||||||
|
tick_status: 0,
|
||||||
user_p2pool_hashrate_u64: 0,
|
user_p2pool_hashrate_u64: 0,
|
||||||
p2pool_difficulty_u64: 0,
|
p2pool_difficulty_u64: 0,
|
||||||
monero_difficulty_u64: 0,
|
monero_difficulty_u64: 0,
|
||||||
|
@ -799,6 +849,7 @@ impl PubP2poolApi {
|
||||||
p2pool_percent: HumanNumber::unknown(),
|
p2pool_percent: HumanNumber::unknown(),
|
||||||
user_p2pool_percent: HumanNumber::unknown(),
|
user_p2pool_percent: HumanNumber::unknown(),
|
||||||
user_monero_percent: HumanNumber::unknown(),
|
user_monero_percent: HumanNumber::unknown(),
|
||||||
|
sidechain_shares: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -816,6 +867,7 @@ impl PubP2poolApi {
|
||||||
*gui_api = Self {
|
*gui_api = Self {
|
||||||
output,
|
output,
|
||||||
tick: std::mem::take(&mut gui_api.tick),
|
tick: std::mem::take(&mut gui_api.tick),
|
||||||
|
tick_status: std::mem::take(&mut gui_api.tick_status),
|
||||||
..pub_api.clone()
|
..pub_api.clone()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,22 +190,8 @@ impl Helper {
|
||||||
.await;
|
.await;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// see how many shares are found at p2pool node only if XvB is started successfully. If it wasn't, maybe P2pool is node not running.
|
|
||||||
let mut old_shares = if lock!(process).state == ProcessState::Alive {
|
|
||||||
// a loop until the value is some to let p2pool work and get first value.
|
|
||||||
loop {
|
|
||||||
if let Some(s) = lock!(gui_api_p2pool).shares_found {
|
|
||||||
break s;
|
|
||||||
}
|
|
||||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// if Syncing state, this value is not needed
|
|
||||||
0
|
|
||||||
};
|
|
||||||
// let mut old_shares = 0;
|
// let mut old_shares = 0;
|
||||||
let start = lock!(process).start;
|
let start = lock!(process).start;
|
||||||
let mut last_share = None;
|
|
||||||
let mut last_algorithm = tokio::time::Instant::now();
|
let mut last_algorithm = tokio::time::Instant::now();
|
||||||
let mut last_request = tokio::time::Instant::now();
|
let mut last_request = tokio::time::Instant::now();
|
||||||
let mut first_loop = true;
|
let mut first_loop = true;
|
||||||
|
@ -338,18 +324,7 @@ impl Helper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// check if share is in pplns window
|
let share = lock!(gui_api_p2pool).sidechain_shares;
|
||||||
// p2pool local api show only found shares and not current shares. So we need to keep track of the time
|
|
||||||
// the height of p2pool would be nicer but the p2pool api doesn't show it.
|
|
||||||
let (share, new_time) = lock!(gui_api_p2pool)
|
|
||||||
.is_share_present_in_ppplns_window(
|
|
||||||
&mut old_shares,
|
|
||||||
last_share,
|
|
||||||
state_p2pool.mini,
|
|
||||||
);
|
|
||||||
if let Some(n) = new_time {
|
|
||||||
last_share = Some(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
// // verify in which round type we are
|
// // verify in which round type we are
|
||||||
let round = XvbPrivStats::round_type(share, &pub_api);
|
let round = XvbPrivStats::round_type(share, &pub_api);
|
||||||
|
@ -407,7 +382,7 @@ impl Helper {
|
||||||
});
|
});
|
||||||
|
|
||||||
// if share is in PW,
|
// if share is in PW,
|
||||||
if share {
|
if share > 0 {
|
||||||
debug!("Xvb Process | Algorithm share is in current window");
|
debug!("Xvb Process | Algorithm share is in current window");
|
||||||
// calcul minimum HR
|
// calcul minimum HR
|
||||||
|
|
||||||
|
@ -667,8 +642,8 @@ impl XvbPrivStats {
|
||||||
}
|
}
|
||||||
spared_time
|
spared_time
|
||||||
}
|
}
|
||||||
fn round_type(share: bool, pub_api: &Arc<Mutex<PubXvbApi>>) -> Option<XvbRound> {
|
fn round_type(share: u32, pub_api: &Arc<Mutex<PubXvbApi>>) -> Option<XvbRound> {
|
||||||
if share {
|
if share > 0 {
|
||||||
let stats_priv = &lock!(pub_api).stats_priv;
|
let stats_priv = &lock!(pub_api).stats_priv;
|
||||||
match (
|
match (
|
||||||
stats_priv.donor_1hr_avg as u32,
|
stats_priv.donor_1hr_avg as u32,
|
||||||
|
@ -987,15 +962,17 @@ mod test {
|
||||||
// };
|
// };
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
path::PathBuf,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
thread,
|
thread,
|
||||||
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
disk::state::{P2pool, Xvb},
|
disk::state::{P2pool, Xvb},
|
||||||
helper::{p2pool::PubP2poolApi, xmrig::PubXmrigApi, xvb::XvbRound},
|
helper::{p2pool::PubP2poolApi, xmrig::PubXmrigApi, xvb::XvbRound, Process, ProcessState},
|
||||||
macros::lock,
|
macros::lock,
|
||||||
XVB_TIME_ALGO,
|
TIME_PPLNS_WINDOW_MINI, XVB_TIME_ALGO,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{PubXvbApi, XvbPrivStats, XvbPubStats};
|
use super::{PubXvbApi, XvbPrivStats, XvbPubStats};
|
||||||
|
@ -1021,7 +998,7 @@ mod test {
|
||||||
let state_p2pool = P2pool::default();
|
let state_p2pool = P2pool::default();
|
||||||
let mut state_xvb = Xvb::default();
|
let mut state_xvb = Xvb::default();
|
||||||
lock!(gui_api_p2pool).p2pool_difficulty_u64 = 95000000;
|
lock!(gui_api_p2pool).p2pool_difficulty_u64 = 95000000;
|
||||||
let share = true;
|
let share = 1;
|
||||||
// verify that if one share found (enough for vip round) but not enough for donor round, no time will be given to xvb, except if in hero mode.
|
// verify that if one share found (enough for vip round) but not enough for donor round, no time will be given to xvb, except if in hero mode.
|
||||||
// 15mn average HR of xmrig is 5kH/s
|
// 15mn average HR of xmrig is 5kH/s
|
||||||
lock!(gui_api_xmrig).hashrate_raw_15m = 5500.0;
|
lock!(gui_api_xmrig).hashrate_raw_15m = 5500.0;
|
||||||
|
@ -1234,6 +1211,83 @@ mod test {
|
||||||
Some(XvbRound::DonorMega)
|
Some(XvbRound::DonorMega)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#[test]
|
||||||
|
fn detect_new_share() {
|
||||||
|
let gui_api_p2pool = Arc::new(Mutex::new(PubP2poolApi::new()));
|
||||||
|
|
||||||
|
let mut state_p2pool = P2pool::default();
|
||||||
|
state_p2pool.mini = true;
|
||||||
|
// verify that when no new share is found, share is false
|
||||||
|
let mut last_share = None;
|
||||||
|
let mut nb_old_share = 0;
|
||||||
|
lock!(gui_api_p2pool).shares_found = Some(0);
|
||||||
|
let (share, new_time) = lock!(gui_api_p2pool).is_share_present_in_ppplns_window(
|
||||||
|
&mut nb_old_share,
|
||||||
|
last_share,
|
||||||
|
state_p2pool.mini,
|
||||||
|
);
|
||||||
|
if let Some(n) = new_time {
|
||||||
|
last_share = Some(n);
|
||||||
|
}
|
||||||
|
dbg!(&last_share);
|
||||||
|
dbg!(&nb_old_share);
|
||||||
|
assert!(!share);
|
||||||
|
// verify that if a new share is found, it is detected.
|
||||||
|
lock!(gui_api_p2pool).shares_found = Some(1);
|
||||||
|
let (share, new_time) = lock!(gui_api_p2pool).is_share_present_in_ppplns_window(
|
||||||
|
&mut nb_old_share,
|
||||||
|
last_share,
|
||||||
|
state_p2pool.mini,
|
||||||
|
);
|
||||||
|
if let Some(n) = new_time {
|
||||||
|
last_share = Some(n);
|
||||||
|
}
|
||||||
|
dbg!(&last_share);
|
||||||
|
dbg!(&nb_old_share);
|
||||||
|
assert!(share);
|
||||||
|
// verify that if a new share is found after another one, it is detected.
|
||||||
|
last_share = Some(last_share.unwrap() + Duration::from_secs(1));
|
||||||
|
lock!(gui_api_p2pool).shares_found = Some(2);
|
||||||
|
let (share, new_time) = lock!(gui_api_p2pool).is_share_present_in_ppplns_window(
|
||||||
|
&mut nb_old_share,
|
||||||
|
last_share,
|
||||||
|
state_p2pool.mini,
|
||||||
|
);
|
||||||
|
if let Some(n) = new_time {
|
||||||
|
last_share = Some(n);
|
||||||
|
}
|
||||||
|
dbg!(&last_share);
|
||||||
|
dbg!(&nb_old_share);
|
||||||
|
assert!(share);
|
||||||
|
// verify that the last share is still valid because not enough time has passed.
|
||||||
|
last_share = Some(last_share.unwrap() + Duration::from_secs(1));
|
||||||
|
let (share, new_time) = lock!(gui_api_p2pool).is_share_present_in_ppplns_window(
|
||||||
|
&mut nb_old_share,
|
||||||
|
last_share,
|
||||||
|
state_p2pool.mini,
|
||||||
|
);
|
||||||
|
if let Some(n) = new_time {
|
||||||
|
last_share = Some(n);
|
||||||
|
}
|
||||||
|
dbg!(&last_share);
|
||||||
|
dbg!(&nb_old_share);
|
||||||
|
assert!(share);
|
||||||
|
// verify that share is no more valid after window time if no new share was found.
|
||||||
|
last_share = Some(last_share.unwrap() + TIME_PPLNS_WINDOW_MINI);
|
||||||
|
let (share, new_time) = lock!(gui_api_p2pool).is_share_present_in_ppplns_window(
|
||||||
|
&mut nb_old_share,
|
||||||
|
last_share,
|
||||||
|
state_p2pool.mini,
|
||||||
|
);
|
||||||
|
dbg!(&new_time);
|
||||||
|
|
||||||
|
if let Some(n) = new_time {
|
||||||
|
last_share = Some(n);
|
||||||
|
}
|
||||||
|
dbg!(&last_share);
|
||||||
|
dbg!(&nb_old_share);
|
||||||
|
assert!(!share);
|
||||||
|
}
|
||||||
// #[tokio::main]
|
// #[tokio::main]
|
||||||
// async fn algo(share: bool, xvb_time_algo: u32) -> XvbPubStats {
|
// async fn algo(share: bool, xvb_time_algo: u32) -> XvbPubStats {
|
||||||
// XvbPubStats::request_api(&client).await.unwrap()
|
// XvbPubStats::request_api(&client).await.unwrap()
|
||||||
|
|
Loading…
Reference in a new issue