mirror of
https://github.com/Cyrix126/gupaxx.git
synced 2025-01-06 22:19:22 +00:00
feat: p2pool sync detection reworked using only API
This commit is contained in:
parent
ddd8f404af
commit
341002b047
6 changed files with 33 additions and 218 deletions
|
@ -19,7 +19,7 @@ use crate::{
|
|||
app::{Benchmark, eframe_impl::ProcessStatesGui},
|
||||
disk::{gupax_p2pool_api::GupaxP2poolApi, state::Status, status::*},
|
||||
helper::{
|
||||
ProcessName, Sys,
|
||||
ProcessName, ProcessState, Sys,
|
||||
node::PubNodeApi,
|
||||
p2pool::{ImgP2pool, PubP2poolApi},
|
||||
xrig::{
|
||||
|
@ -75,7 +75,7 @@ impl Status {
|
|||
self.p2pool(
|
||||
ui,
|
||||
gupax_p2pool_api,
|
||||
states.is_alive(ProcessName::P2pool),
|
||||
states.find(ProcessName::P2pool).state == ProcessState::Alive,
|
||||
p2pool_api,
|
||||
);
|
||||
//---------------------------------------------------------------------------------------------------- [Benchmarks]
|
||||
|
|
|
@ -366,11 +366,6 @@ impl Status {
|
|||
});
|
||||
});
|
||||
});
|
||||
// Tick bar
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(api.calculate_tick_bar())
|
||||
.on_hover_text(STATUS_SUBMENU_PROGRESS_BAR);
|
||||
});
|
||||
drop(api);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -30,7 +30,6 @@ use crate::helper::signal_end;
|
|||
use crate::helper::sleep_end_loop;
|
||||
use crate::regex::P2POOL_REGEX;
|
||||
use crate::regex::contains_end_status;
|
||||
use crate::regex::contains_newchain_tip;
|
||||
use crate::regex::contains_statuscommand;
|
||||
use crate::regex::contains_yourhashrate;
|
||||
use crate::regex::contains_yourshare;
|
||||
|
@ -691,30 +690,21 @@ impl Helper {
|
|||
// check if state must be changed based on local and p2p API
|
||||
pub_api_lock.update_state(&mut process_lock);
|
||||
|
||||
// If more than 1 minute has passed, read the other API files.
|
||||
let last_p2pool_request_expired =
|
||||
last_p2pool_request.elapsed() >= Duration::from_secs(60);
|
||||
// need to reload fast to get the first right values after syncing.
|
||||
// check if value is 100k or under and request immediately if that's the case. fixed in release of p2pool including commit https://github.com/SChernykh/p2pool/commit/64a199be6dec7924b41f857a401086f25e1ec9be
|
||||
if (last_p2pool_request_expired || pub_api_lock.p2pool_difficulty_u64 <= 100000)
|
||||
&& process_lock.state == ProcessState::Alive
|
||||
{
|
||||
debug!("P2Pool Watchdog | Attempting [network] & [pool] API file read");
|
||||
debug!("P2Pool Watchdog | Attempting [network] & [pool] API file read");
|
||||
if let (Ok(network_api), Ok(pool_api)) = (
|
||||
Self::path_to_string(&api_path_network, ProcessName::P2pool),
|
||||
Self::path_to_string(&api_path_pool, ProcessName::P2pool),
|
||||
) {
|
||||
if let (Ok(network_api), Ok(pool_api)) = (
|
||||
Self::path_to_string(&api_path_network, ProcessName::P2pool),
|
||||
Self::path_to_string(&api_path_pool, ProcessName::P2pool),
|
||||
PrivP2poolNetworkApi::from_str(&network_api),
|
||||
PrivP2poolPoolApi::from_str(&pool_api),
|
||||
) {
|
||||
if let (Ok(network_api), Ok(pool_api)) = (
|
||||
PrivP2poolNetworkApi::from_str(&network_api),
|
||||
PrivP2poolPoolApi::from_str(&pool_api),
|
||||
) {
|
||||
PubP2poolApi::update_from_network_pool(
|
||||
&mut pub_api_lock,
|
||||
network_api,
|
||||
pool_api,
|
||||
);
|
||||
last_p2pool_request = tokio::time::Instant::now();
|
||||
}
|
||||
PubP2poolApi::update_from_network_pool(
|
||||
&mut pub_api_lock,
|
||||
network_api,
|
||||
pool_api,
|
||||
);
|
||||
last_p2pool_request = tokio::time::Instant::now();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -883,8 +873,7 @@ pub struct PubP2poolApi {
|
|||
// from status
|
||||
pub sidechain_shares: u32,
|
||||
pub sidechain_ehr: f32,
|
||||
// from height
|
||||
pub synchronised: bool,
|
||||
pub sidechain_height: u32,
|
||||
// from local/p2p
|
||||
pub p2p_connected: u32,
|
||||
pub node_connected: bool,
|
||||
|
@ -940,8 +929,8 @@ impl PubP2poolApi {
|
|||
user_monero_percent: HumanNumber::unknown(),
|
||||
sidechain_shares: 0,
|
||||
sidechain_ehr: 0.0,
|
||||
sidechain_height: 0,
|
||||
p2p_connected: 0,
|
||||
synchronised: false,
|
||||
node_connected: false,
|
||||
prefer_local_node: true,
|
||||
}
|
||||
|
@ -1007,33 +996,6 @@ impl PubP2poolApi {
|
|||
// 2. Parse the full STDOUT
|
||||
let mut output_parse = output_parse.lock().unwrap();
|
||||
let (payouts_new, xmr_new) = Self::calc_payouts_and_xmr(&output_parse);
|
||||
// Check for "SYNCHRONIZED" only if we aren't already. Works at level 0 and above.
|
||||
if process.state == ProcessState::Syncing {
|
||||
// How many times the word was captured.
|
||||
let synchronized_captures = P2POOL_REGEX.synchronized.find_iter(&output_parse).count();
|
||||
|
||||
// If P2Pool receives shares before syncing, it will start mining on its own sidechain.
|
||||
// In this instance, we technically are "synced" on block 1 and P2Pool will print "SYNCHRONIZED"
|
||||
// although, that doesn't necessarily mean we're synced on main/mini-chain.
|
||||
//
|
||||
// So, if we find a `next block = 1`, that means we
|
||||
// must look for at least 2 instances of "SYNCHRONIZED",
|
||||
// one for the sidechain, one for main/mini.
|
||||
if P2POOL_REGEX.next_height_1.is_match(&output_parse) {
|
||||
if synchronized_captures > 1 {
|
||||
process.state = ProcessState::Alive;
|
||||
}
|
||||
} else if synchronized_captures > 0 {
|
||||
// if there is no `next block = 1`, fallback to
|
||||
// just finding 1 instance of "SYNCHRONIZED".
|
||||
process.state = ProcessState::Alive;
|
||||
}
|
||||
// if the p2pool node was synced but is not anymore due to faulty monero node and is synced again, the status must be alive again
|
||||
// required log level 2 minimum
|
||||
if contains_newchain_tip(&output_parse) {
|
||||
process.state = ProcessState::Alive;
|
||||
}
|
||||
}
|
||||
// if the node is offline, p2pool can not function properly. Requires at least p2pool log level 1
|
||||
if process.state == ProcessState::Alive && contains_zmq_failure(&output_parse) {
|
||||
process.state = ProcessState::Syncing;
|
||||
|
@ -1120,8 +1082,8 @@ impl PubP2poolApi {
|
|||
pub(super) fn update_from_p2p(public: &mut Self, p2p: PrivP2PoolP2PApi) {
|
||||
*public = Self {
|
||||
p2p_connected: p2p.connections,
|
||||
// 30 seconds before concluding the monero node connection is lost
|
||||
node_connected: p2p.zmq_last_active.is_some_and(|x| x < 30),
|
||||
// 10 seconds before concluding the monero node connection is lost
|
||||
node_connected: p2p.zmq_last_active.is_some_and(|x| x < 10),
|
||||
..std::mem::take(&mut *public)
|
||||
};
|
||||
}
|
||||
|
@ -1187,6 +1149,7 @@ impl PubP2poolApi {
|
|||
p2pool_difficulty: HumanNumber::from_u64(p2pool_difficulty),
|
||||
p2pool_hashrate: HumanNumber::from_u64_to_megahash_3_point(p2pool_hashrate),
|
||||
miners: HumanNumber::from_u32(pool.pool_statistics.miners),
|
||||
sidechain_height: pool.pool_statistics.sidechainHeight,
|
||||
solo_block_mean,
|
||||
p2pool_block_mean,
|
||||
p2pool_share_mean,
|
||||
|
@ -1196,16 +1159,19 @@ impl PubP2poolApi {
|
|||
..std::mem::take(&mut *public)
|
||||
};
|
||||
}
|
||||
/// Check if all conditions are met to be alive or if something is wrong
|
||||
fn update_state(&self, process: &mut Process) {
|
||||
if process.state == ProcessState::Syncing
|
||||
&& self.synchronised
|
||||
&& self.node_connected
|
||||
&& self.p2p_connected > 1
|
||||
&& self.height > 10
|
||||
&& self.sidechain_height > 1000
|
||||
{
|
||||
process.state = ProcessState::Alive;
|
||||
}
|
||||
if process.state == ProcessState::Alive
|
||||
&& (self.sidechain_height < 1000 || !self.node_connected || self.p2p_connected == 0)
|
||||
{
|
||||
process.state = ProcessState::Syncing;
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -1226,77 +1192,6 @@ impl PubP2poolApi {
|
|||
HumanNumber::from_f64_to_percent_6_point(f)
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn calculate_tick_bar(&self) -> &'static str {
|
||||
// The stars are reduced by one because it takes a frame to render the stats.
|
||||
// We want 0 stars at the same time stats are rendered, so it looks a little off here.
|
||||
// let stars = "*".repeat(self.tick - 1);
|
||||
// let blanks = " ".repeat(60 - (self.tick - 1));
|
||||
// [use crate::PubP2poolApi;use crate::PubP2poolApi;"[", &stars, &blanks, "]"].concat().as_str()
|
||||
match self.tick {
|
||||
0 => "[ ]",
|
||||
1 => "[* ]",
|
||||
2 => "[** ]",
|
||||
3 => "[*** ]",
|
||||
4 => "[**** ]",
|
||||
5 => "[***** ]",
|
||||
6 => "[****** ]",
|
||||
7 => "[******* ]",
|
||||
8 => "[******** ]",
|
||||
9 => "[********* ]",
|
||||
10 => "[********** ]",
|
||||
11 => "[*********** ]",
|
||||
12 => "[************ ]",
|
||||
13 => "[************* ]",
|
||||
14 => "[************** ]",
|
||||
15 => "[*************** ]",
|
||||
16 => "[**************** ]",
|
||||
17 => "[***************** ]",
|
||||
18 => "[****************** ]",
|
||||
19 => "[******************* ]",
|
||||
20 => "[******************** ]",
|
||||
21 => "[********************* ]",
|
||||
22 => "[********************** ]",
|
||||
23 => "[*********************** ]",
|
||||
24 => "[************************ ]",
|
||||
25 => "[************************* ]",
|
||||
26 => "[************************** ]",
|
||||
27 => "[*************************** ]",
|
||||
28 => "[**************************** ]",
|
||||
29 => "[***************************** ]",
|
||||
30 => "[****************************** ]",
|
||||
31 => "[******************************* ]",
|
||||
32 => "[******************************** ]",
|
||||
33 => "[********************************* ]",
|
||||
34 => "[********************************** ]",
|
||||
35 => "[*********************************** ]",
|
||||
36 => "[************************************ ]",
|
||||
37 => "[************************************* ]",
|
||||
38 => "[************************************** ]",
|
||||
39 => "[*************************************** ]",
|
||||
40 => "[**************************************** ]",
|
||||
41 => "[***************************************** ]",
|
||||
42 => "[****************************************** ]",
|
||||
43 => "[******************************************* ]",
|
||||
44 => "[******************************************** ]",
|
||||
45 => "[********************************************* ]",
|
||||
46 => "[********************************************** ]",
|
||||
47 => "[*********************************************** ]",
|
||||
48 => "[************************************************ ]",
|
||||
49 => "[************************************************* ]",
|
||||
50 => "[************************************************** ]",
|
||||
51 => "[*************************************************** ]",
|
||||
52 => "[**************************************************** ]",
|
||||
53 => "[***************************************************** ]",
|
||||
54 => "[****************************************************** ]",
|
||||
55 => "[******************************************************* ]",
|
||||
56 => "[******************************************************** ]",
|
||||
57 => "[********************************************************* ]",
|
||||
58 => "[********************************************************** ]",
|
||||
59 => "[*********************************************************** ]",
|
||||
_ => "[************************************************************]",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Private P2Pool "Local" Api
|
||||
|
@ -1419,6 +1314,7 @@ impl PrivP2poolPoolApi {
|
|||
pub(super) struct PoolStatistics {
|
||||
pub hashRate: u64,
|
||||
pub miners: u32,
|
||||
pub sidechainHeight: u32,
|
||||
}
|
||||
impl Default for PoolStatistics {
|
||||
fn default() -> Self {
|
||||
|
@ -1430,6 +1326,7 @@ impl PoolStatistics {
|
|||
Self {
|
||||
hashRate: 0,
|
||||
miners: 0,
|
||||
sidechainHeight: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,37 +155,6 @@ Uptime = 0h 2m 4s
|
|||
assert_eq!(public.xmr_month, 648000.0000001296);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_p2pool_synchronized() {
|
||||
use crate::helper::PubP2poolApi;
|
||||
use std::sync::{Arc, Mutex};
|
||||
let public = Arc::new(Mutex::new(PubP2poolApi::new()));
|
||||
let output_parse = Arc::new(Mutex::new(String::from(
|
||||
r#"payout of 5.000000000001 XMR in block 1111
|
||||
NOTICE 2021-12-27 21:42:17.2008 SideChain SYNCHRONIZED
|
||||
payout of 5.000000000001 XMR in block 1113"#,
|
||||
)));
|
||||
let output_pub = Arc::new(Mutex::new(String::new()));
|
||||
let elapsed = std::time::Duration::from_secs(60);
|
||||
let process = Arc::new(Mutex::new(Process::new(
|
||||
ProcessName::P2pool,
|
||||
"".to_string(),
|
||||
PathBuf::new(),
|
||||
)));
|
||||
|
||||
// It only gets checked if we're `Syncing`.
|
||||
process.lock().unwrap().state = ProcessState::Syncing;
|
||||
PubP2poolApi::update_from_output(
|
||||
&mut public.lock().unwrap(),
|
||||
&output_parse,
|
||||
&output_pub,
|
||||
elapsed,
|
||||
&mut process.lock().unwrap(),
|
||||
);
|
||||
println!("{:#?}", process);
|
||||
assert!(process.lock().unwrap().state == ProcessState::Alive);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn p2pool_synchronized_false_positive() {
|
||||
use crate::helper::PubP2poolApi;
|
||||
|
@ -221,43 +190,6 @@ Uptime = 0h 2m 4s
|
|||
assert!(process.lock().unwrap().state == ProcessState::Syncing); // still syncing
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn p2pool_synchronized_double_synchronized() {
|
||||
use crate::helper::PubP2poolApi;
|
||||
use std::sync::{Arc, Mutex};
|
||||
let public = Arc::new(Mutex::new(PubP2poolApi::new()));
|
||||
|
||||
// The 1st SideChain that is "SYNCHRONIZED" in this output is
|
||||
// the sidechain started on height 1, but there is another one
|
||||
// which means the real main/mini is probably synced,
|
||||
// so this _should_ trigger alive state.
|
||||
let output_parse = Arc::new(Mutex::new(String::from(
|
||||
r#"2024-11-02 17:39:02.6241 SideChain SYNCHRONIZED
|
||||
2024-11-02 17:39:02.6242 StratumServer SHARE FOUND: mainchain height 3272685, sidechain height 0, diff 100000, client 127.0.0.1:40874, effort 100.001%
|
||||
2024-11-02 17:39:02.6559 StratumServer SHARE FOUND: mainchain height 3272685, sidechain height 0, diff 100000, client 127.0.0.1:40874, effort 200.002%
|
||||
2024-11-02 17:40:06.8562 SideChain SYNCHRONIZED"#,
|
||||
)));
|
||||
let output_pub = Arc::new(Mutex::new(String::new()));
|
||||
let elapsed = std::time::Duration::from_secs(60);
|
||||
let process = Arc::new(Mutex::new(Process::new(
|
||||
ProcessName::P2pool,
|
||||
"".to_string(),
|
||||
PathBuf::new(),
|
||||
)));
|
||||
|
||||
// It only gets checked if we're `Syncing`.
|
||||
process.lock().unwrap().state = ProcessState::Syncing;
|
||||
PubP2poolApi::update_from_output(
|
||||
&mut public.lock().unwrap(),
|
||||
&output_parse,
|
||||
&output_pub,
|
||||
elapsed,
|
||||
&mut process.lock().unwrap(),
|
||||
);
|
||||
println!("{:#?}", process);
|
||||
assert!(process.lock().unwrap().state == ProcessState::Alive);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_pub_p2pool_from_local_network_pool() {
|
||||
use crate::helper::PubP2poolApi;
|
||||
|
@ -287,6 +219,7 @@ Uptime = 0h 2m 4s
|
|||
pool_statistics: PoolStatistics {
|
||||
hashRate: 1_000_000, // 1 MH/s
|
||||
miners: 1_000,
|
||||
sidechainHeight: 10_000_000,
|
||||
},
|
||||
};
|
||||
// Update Local
|
||||
|
@ -430,7 +363,8 @@ Uptime = 0h 2m 4s
|
|||
"totalHashes": 487463929193948,
|
||||
"lastBlockFoundTime": 1670453228,
|
||||
"lastBlockFound": 2756570,
|
||||
"totalBlocksFound": 4
|
||||
"totalBlocksFound": 4,
|
||||
"sidechainHeight": 9000000
|
||||
}
|
||||
}"#;
|
||||
let priv_api = crate::helper::p2pool::PrivP2poolPoolApi::from_str(data).unwrap();
|
||||
|
@ -439,7 +373,8 @@ Uptime = 0h 2m 4s
|
|||
let data_after_ser = r#"{
|
||||
"pool_statistics": {
|
||||
"hashRate": 10225772,
|
||||
"miners": 713
|
||||
"miners": 713,
|
||||
"sidechainHeight": 9000000
|
||||
}
|
||||
}"#;
|
||||
assert_eq!(data_after_ser, json)
|
||||
|
|
|
@ -308,7 +308,6 @@ pub const STATUS_SUBMENU_YOUR_P2POOL_DOMINANCE: &str =
|
|||
"The percent of hashrate you account for in P2Pool";
|
||||
pub const STATUS_SUBMENU_YOUR_MONERO_DOMINANCE: &str =
|
||||
"The percent of hashrate you account for in the entire Monero network";
|
||||
pub const STATUS_SUBMENU_PROGRESS_BAR: &str = "The next time Gupaxx will update P2Pool stats.";
|
||||
//-- Benchmarks
|
||||
pub const STATUS_SUBMENU_YOUR_CPU: &str = "The CPU detected by Gupaxx";
|
||||
pub const STATUS_SUBMENU_YOUR_BENCHMARKS: &str =
|
||||
|
|
|
@ -90,8 +90,6 @@ pub struct P2poolRegex {
|
|||
pub block: Regex,
|
||||
pub block_int: Regex,
|
||||
pub block_comma: Regex,
|
||||
pub synchronized: Regex,
|
||||
pub next_height_1: Regex,
|
||||
}
|
||||
|
||||
impl P2poolRegex {
|
||||
|
@ -105,8 +103,6 @@ impl P2poolRegex {
|
|||
block: Regex::new("block [0-9]{7}").unwrap(), // Monero blocks will be 7 digits for... the next 10,379 years
|
||||
block_int: Regex::new("[0-9]{7}").unwrap(),
|
||||
block_comma: Regex::new("[0-9],[0-9]{3},[0-9]{3}").unwrap(),
|
||||
synchronized: Regex::new("SYNCHRONIZED").unwrap(),
|
||||
next_height_1: Regex::new("sidechain height 0").unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -286,11 +282,6 @@ pub fn contains_zmq_failure(l: &str) -> bool {
|
|||
});
|
||||
LINE_SHARE.is_match(l)
|
||||
}
|
||||
/// a way to detect that p2pool is alive
|
||||
pub fn contains_newchain_tip(l: &str) -> bool {
|
||||
static LINE_SHARE: Lazy<Regex> = Lazy::new(|| Regex::new(r"new chain tip").unwrap());
|
||||
LINE_SHARE.is_match(l)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- TEST
|
||||
#[cfg(test)]
|
||||
|
@ -329,7 +320,6 @@ mod test {
|
|||
let r = P2poolRegex::new();
|
||||
let text = "NOTICE 2022-11-11 11:11:11.1111 P2Pool You received a payout of 0.111111111111 XMR in block 1111111";
|
||||
let text2 = "2022-11-11 11:11:11.1111 | 0.111111111111 XMR | Block 1,111,111";
|
||||
let text3 = "NOTICE 2020-12-11 12:35:41.3150 SideChain SYNCHRONIZED";
|
||||
assert_eq!(
|
||||
r.payout.find(text).unwrap().as_str(),
|
||||
"payout of 0.111111111111 XMR"
|
||||
|
@ -345,7 +335,6 @@ mod test {
|
|||
assert_eq!(r.block.find(text).unwrap().as_str(), "block 1111111");
|
||||
assert_eq!(r.block_int.find(text).unwrap().as_str(), "1111111");
|
||||
assert_eq!(r.block_comma.find(text2).unwrap().as_str(), "1,111,111");
|
||||
assert_eq!(r.synchronized.find(text3).unwrap().as_str(), "SYNCHRONIZED");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in a new issue