fix: algorithm, watch current shares from status command

This commit is contained in:
Cyrix126 2024-03-25 22:26:13 +01:00
parent 3233972cf7
commit aee777d160
2 changed files with 140 additions and 34 deletions

View file

@ -32,6 +32,7 @@ impl Helper {
output_pub: Arc<Mutex<String>>,
reader: Box<dyn std::io::Read + Send>,
gupax_p2pool_api: Arc<Mutex<GupaxP2poolApi>>,
pub_api: Arc<Mutex<PubP2poolApi>>,
) {
use std::io::BufRead;
let mut stdout = std::io::BufReader::new(reader).lines();
@ -40,6 +41,7 @@ impl Helper {
let mut i = 0;
while let Some(Ok(line)) = stdout.next() {
let line = strip_ansi_escapes::strip_str(line);
if let Err(e) = writeln!(lock!(output_parse), "{}", line) {
error!("P2Pool PTY Parse | Output error: {}", e);
}
@ -52,8 +54,26 @@ impl Helper {
i += 1;
}
}
let mut status_output = false;
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.
if P2POOL_REGEX.payout.is_match(&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_pub = Arc::clone(&lock!(process).output_pub);
let gupax_p2pool_api = Arc::clone(&gupax_p2pool_api);
let p2pool_api_c = Arc::clone(&pub_api);
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_pub = Arc::clone(&lock!(process).output_pub);
@ -434,6 +461,7 @@ impl Helper {
let now = Instant::now();
debug!("P2Pool Watchdog | ----------- Start of loop -----------");
lock!(gui_api).tick += 1;
lock!(gui_api).tick_status += 1;
// Check if the process is secretly died without us knowing :)
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)
let elapsed = now.elapsed().as_millis();
@ -733,6 +777,9 @@ pub struct PubP2poolApi {
// Tick. Every loop this gets incremented.
// At 60, it indicated we should read the below API files.
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
pub monero_difficulty: HumanNumber, // e.g: [15,000,000]
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 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.
// from status
pub sidechain_shares: u32,
}
impl Default for PubP2poolApi {
@ -780,6 +829,7 @@ impl PubP2poolApi {
current_effort: HumanNumber::unknown(),
connections: HumanNumber::unknown(),
tick: 0,
tick_status: 0,
user_p2pool_hashrate_u64: 0,
p2pool_difficulty_u64: 0,
monero_difficulty_u64: 0,
@ -799,6 +849,7 @@ impl PubP2poolApi {
p2pool_percent: HumanNumber::unknown(),
user_p2pool_percent: HumanNumber::unknown(),
user_monero_percent: HumanNumber::unknown(),
sidechain_shares: 0,
}
}
@ -816,6 +867,7 @@ impl PubP2poolApi {
*gui_api = Self {
output,
tick: std::mem::take(&mut gui_api.tick),
tick_status: std::mem::take(&mut gui_api.tick_status),
..pub_api.clone()
};
}

View file

@ -190,22 +190,8 @@ impl Helper {
.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 start = lock!(process).start;
let mut last_share = None;
let mut last_algorithm = tokio::time::Instant::now();
let mut last_request = tokio::time::Instant::now();
let mut first_loop = true;
@ -338,18 +324,7 @@ impl Helper {
}
}
});
// check if share is in pplns window
// 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);
}
let share = lock!(gui_api_p2pool).sidechain_shares;
// // verify in which round type we are
let round = XvbPrivStats::round_type(share, &pub_api);
@ -407,7 +382,7 @@ impl Helper {
});
// if share is in PW,
if share {
if share > 0 {
debug!("Xvb Process | Algorithm share is in current window");
// calcul minimum HR
@ -667,8 +642,8 @@ impl XvbPrivStats {
}
spared_time
}
fn round_type(share: bool, pub_api: &Arc<Mutex<PubXvbApi>>) -> Option<XvbRound> {
if share {
fn round_type(share: u32, pub_api: &Arc<Mutex<PubXvbApi>>) -> Option<XvbRound> {
if share > 0 {
let stats_priv = &lock!(pub_api).stats_priv;
match (
stats_priv.donor_1hr_avg as u32,
@ -987,15 +962,17 @@ mod test {
// };
use std::{
path::PathBuf,
sync::{Arc, Mutex},
thread,
time::Duration,
};
use crate::{
disk::state::{P2pool, Xvb},
helper::{p2pool::PubP2poolApi, xmrig::PubXmrigApi, xvb::XvbRound},
helper::{p2pool::PubP2poolApi, xmrig::PubXmrigApi, xvb::XvbRound, Process, ProcessState},
macros::lock,
XVB_TIME_ALGO,
TIME_PPLNS_WINDOW_MINI, XVB_TIME_ALGO,
};
use super::{PubXvbApi, XvbPrivStats, XvbPubStats};
@ -1021,7 +998,7 @@ mod test {
let state_p2pool = P2pool::default();
let mut state_xvb = Xvb::default();
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.
// 15mn average HR of xmrig is 5kH/s
lock!(gui_api_xmrig).hashrate_raw_15m = 5500.0;
@ -1234,6 +1211,83 @@ mod test {
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]
// async fn algo(share: bool, xvb_time_algo: u32) -> XvbPubStats {
// XvbPubStats::request_api(&client).await.unwrap()