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>>,
|
||||
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()
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in a new issue