feat: use API from p2pool to get state in case log verbosity is unsufficent.

This commit is contained in:
Cyrix126 2024-12-30 14:15:24 +01:00
parent 9092b5cd91
commit 22a9592c66
3 changed files with 116 additions and 9 deletions

View file

@ -207,13 +207,13 @@ impl Helper {
) { ) {
helper.lock().unwrap().p2pool.lock().unwrap().state = ProcessState::Middle; helper.lock().unwrap().p2pool.lock().unwrap().state = ProcessState::Middle;
let (args, api_path_local, api_path_network, api_path_pool) = let (args, api_path_local, api_path_network, api_path_pool, api_path_p2p) =
Self::build_p2pool_args_and_mutate_img(helper, state, path, backup_hosts); Self::build_p2pool_args_and_mutate_img(helper, state, path, backup_hosts);
// Print arguments & user settings to console // Print arguments & user settings to console
crate::disk::print_dash(&format!( crate::disk::print_dash(&format!(
"P2Pool | Launch arguments: {:#?} | Local API Path: {:#?} | Network API Path: {:#?} | Pool API Path: {:#?}", "P2Pool | Launch arguments: {:#?} | Local API Path: {:#?} | Network API Path: {:#?} | Pool API Path: {:#?} | P2P API Path {:#?}",
args, api_path_local, api_path_network, api_path_pool, args, api_path_local, api_path_network, api_path_pool, api_path_p2p
)); ));
// Spawn watchdog thread // Spawn watchdog thread
@ -232,6 +232,7 @@ impl Helper {
api_path_local, api_path_local,
api_path_network, api_path_network,
api_path_pool, api_path_pool,
api_path_p2p,
gupax_p2pool_api, gupax_p2pool_api,
); );
}); });
@ -257,7 +258,7 @@ impl Helper {
state: &P2pool, state: &P2pool,
path: &Path, path: &Path,
backup_hosts: Option<Vec<PoolNode>>, backup_hosts: Option<Vec<PoolNode>>,
) -> (Vec<String>, PathBuf, PathBuf, PathBuf) { ) -> (Vec<String>, PathBuf, PathBuf, PathBuf, PathBuf) {
let mut args = Vec::with_capacity(500); let mut args = Vec::with_capacity(500);
let path = path.to_path_buf(); let path = path.to_path_buf();
let mut api_path = path; let mut api_path = path;
@ -438,10 +439,18 @@ impl Helper {
let mut api_path_local = api_path.clone(); let mut api_path_local = api_path.clone();
let mut api_path_network = api_path.clone(); let mut api_path_network = api_path.clone();
let mut api_path_pool = api_path.clone(); let mut api_path_pool = api_path.clone();
let mut api_path_p2p = api_path.clone();
api_path_local.push(P2POOL_API_PATH_LOCAL); api_path_local.push(P2POOL_API_PATH_LOCAL);
api_path_network.push(P2POOL_API_PATH_NETWORK); api_path_network.push(P2POOL_API_PATH_NETWORK);
api_path_pool.push(P2POOL_API_PATH_POOL); api_path_pool.push(P2POOL_API_PATH_POOL);
(args, api_path_local, api_path_network, api_path_pool) api_path_p2p.push(P2POOL_API_PATH_P2P);
(
args,
api_path_local,
api_path_network,
api_path_pool,
api_path_p2p,
)
} }
#[cold] #[cold]
@ -460,6 +469,7 @@ impl Helper {
api_path_local: std::path::PathBuf, api_path_local: std::path::PathBuf,
api_path_network: std::path::PathBuf, api_path_network: std::path::PathBuf,
api_path_pool: std::path::PathBuf, api_path_pool: std::path::PathBuf,
api_path_p2p: std::path::PathBuf,
gupax_p2pool_api: Arc<Mutex<GupaxP2poolApi>>, gupax_p2pool_api: Arc<Mutex<GupaxP2poolApi>>,
) { ) {
// 1a. Create PTY // 1a. Create PTY
@ -533,6 +543,26 @@ impl Helper {
), ),
} }
} }
debug!("P2Pool | Cleaning old [p2p] API files...");
// Attempt to remove stale API file
match std::fs::remove_file(&api_path_p2p) {
Ok(_) => info!("P2Pool | Attempting to remove stale API file ... OK"),
Err(e) => warn!(
"P2Pool | Attempting to remove stale API file ... FAIL ... {}",
e
),
}
// Attempt to create a default empty one.
if std::fs::File::create(&api_path_p2p).is_ok() {
let text = r#"{"connections":0,"incoming_connections":0,"peer_list_size":0,"peers":[],"uptime":0}"#;
match std::fs::write(&api_path_p2p, text) {
Ok(_) => info!("P2Pool | Creating default empty API file ... OK"),
Err(e) => warn!(
"P2Pool | Creating default empty API file ... FAIL ... {}",
e
),
}
}
let start = process.lock().unwrap().start; let start = process.lock().unwrap().start;
// Reset stats before loop // Reset stats before loop
@ -599,6 +629,20 @@ impl Helper {
PubP2poolApi::update_from_local(&mut pub_api_lock, local_api); PubP2poolApi::update_from_local(&mut pub_api_lock, local_api);
} }
} }
// Read [p2p] API
// allows to know if p2p is synced and connected to a Node.
debug!("P2Pool Watchdog | Attempting [p2p] API file read");
if let Ok(string) = Self::path_to_string(&api_path_p2p, ProcessName::P2pool) {
// Deserialize
if let Ok(p2p_api) = PrivP2PoolP2PApi::from_str(&string) {
// Update the structs.
PubP2poolApi::update_from_p2p(&mut pub_api_lock, p2p_api);
}
}
// check if state must be changed based on local and p2p API
pub_api_lock.update_state(&process);
// If more than 1 minute has passed, read the other API files. // If more than 1 minute has passed, read the other API files.
let last_p2pool_request_expired = let last_p2pool_request_expired =
last_p2pool_request.elapsed() >= Duration::from_secs(60); last_p2pool_request.elapsed() >= Duration::from_secs(60);
@ -737,7 +781,7 @@ pub struct PubP2poolApi {
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]
pub hash: String, // Current block hash pub hash: String, // Current block hash
pub height: HumanNumber, pub height: u32,
pub reward: AtomicUnit, pub reward: AtomicUnit,
// Pool API // Pool API
pub p2pool_difficulty: HumanNumber, pub p2pool_difficulty: HumanNumber,
@ -754,6 +798,11 @@ pub struct PubP2poolApi {
// from status // from status
pub sidechain_shares: u32, pub sidechain_shares: u32,
pub sidechain_ehr: f32, pub sidechain_ehr: f32,
// from height
pub synchronised: bool,
// from local/p2p
pub p2p_connected: u32,
pub node_connected: bool,
} }
impl Default for PubP2poolApi { impl Default for PubP2poolApi {
@ -792,7 +841,7 @@ impl PubP2poolApi {
monero_difficulty: HumanNumber::unknown(), monero_difficulty: HumanNumber::unknown(),
monero_hashrate: HumanNumber::unknown(), monero_hashrate: HumanNumber::unknown(),
hash: String::from("???"), hash: String::from("???"),
height: HumanNumber::unknown(), height: 0,
reward: AtomicUnit::new(), reward: AtomicUnit::new(),
p2pool_difficulty: HumanNumber::unknown(), p2pool_difficulty: HumanNumber::unknown(),
p2pool_hashrate: HumanNumber::unknown(), p2pool_hashrate: HumanNumber::unknown(),
@ -805,6 +854,9 @@ impl PubP2poolApi {
user_monero_percent: HumanNumber::unknown(), user_monero_percent: HumanNumber::unknown(),
sidechain_shares: 0, sidechain_shares: 0,
sidechain_ehr: 0.0, sidechain_ehr: 0.0,
p2p_connected: 0,
synchronised: false,
node_connected: false,
} }
} }
@ -976,6 +1028,15 @@ impl PubP2poolApi {
..std::mem::take(&mut *public) ..std::mem::take(&mut *public)
}; };
} }
// Mutate [PubP2poolApi] with data from a [PrivP2PoolP2PApi] and the process output.
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 < 30,
..std::mem::take(&mut *public)
};
}
// Mutate [PubP2poolApi] with data from a [PrivP2pool(Network|Pool)Api]. // Mutate [PubP2poolApi] with data from a [PrivP2pool(Network|Pool)Api].
pub(super) fn update_from_network_pool( pub(super) fn update_from_network_pool(
@ -1033,7 +1094,7 @@ impl PubP2poolApi {
monero_difficulty: HumanNumber::from_u64(monero_difficulty), monero_difficulty: HumanNumber::from_u64(monero_difficulty),
monero_hashrate: HumanNumber::from_u64_to_gigahash_3_point(monero_hashrate), monero_hashrate: HumanNumber::from_u64_to_gigahash_3_point(monero_hashrate),
hash: net.hash, hash: net.hash,
height: HumanNumber::from_u32(net.height), height: net.height,
reward: AtomicUnit::from_u64(net.reward), reward: AtomicUnit::from_u64(net.reward),
p2pool_difficulty: HumanNumber::from_u64(p2pool_difficulty), p2pool_difficulty: HumanNumber::from_u64(p2pool_difficulty),
p2pool_hashrate: HumanNumber::from_u64_to_megahash_3_point(p2pool_hashrate), p2pool_hashrate: HumanNumber::from_u64_to_megahash_3_point(p2pool_hashrate),
@ -1047,6 +1108,15 @@ impl PubP2poolApi {
..std::mem::take(&mut *public) ..std::mem::take(&mut *public)
}; };
} }
/// Check if all conditions are met to be alive or if something is wrong
fn update_state(&self, process: &Arc<Mutex<Process>>) {
let mut process = process.lock().unwrap();
if self.synchronised && self.node_connected && self.p2p_connected > 1 && self.height > 10 {
process.state = ProcessState::Alive;
} else {
process.state = ProcessState::Syncing;
}
}
#[inline] #[inline]
pub fn calculate_share_or_block_time(hashrate: u64, difficulty: u64) -> HumanTime { pub fn calculate_share_or_block_time(hashrate: u64, difficulty: u64) -> HumanTime {
@ -1273,3 +1343,35 @@ impl PoolStatistics {
} }
} }
} }
//---------------------------------------------------------------------------------------------------- Private P2Pool "Network" API
// This matches P2Pool's [local/p2p] JSON API file.
#[derive(Debug, Serialize, Deserialize, Clone)]
pub(super) struct PrivP2PoolP2PApi {
pub connections: u32,
pub zmq_last_active: u32,
}
impl Default for PrivP2PoolP2PApi {
fn default() -> Self {
Self::new()
}
}
impl PrivP2PoolP2PApi {
fn new() -> Self {
Self {
connections: 0,
zmq_last_active: 0,
}
}
pub(super) 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)
}
}
}
}

View file

@ -8,6 +8,7 @@ mod test {
p2pool::{PrivP2poolLocalApi, PrivP2poolNetworkApi}, p2pool::{PrivP2poolLocalApi, PrivP2poolNetworkApi},
xvb::{priv_stats::RuntimeDonationLevel, priv_stats::RuntimeMode}, xvb::{priv_stats::RuntimeDonationLevel, priv_stats::RuntimeMode},
}; };
use crate::human::HumanNumber;
use crate::miscs::client; use crate::miscs::client;
#[test] #[test]
@ -291,7 +292,7 @@ Uptime = 0h 2m 4s
assert_eq!(p.monero_difficulty.to_string(), "300,000,000,000"); assert_eq!(p.monero_difficulty.to_string(), "300,000,000,000");
assert_eq!(p.monero_hashrate.to_string(), "2.500 GH/s"); assert_eq!(p.monero_hashrate.to_string(), "2.500 GH/s");
assert_eq!(p.hash.to_string(), "asdf"); assert_eq!(p.hash.to_string(), "asdf");
assert_eq!(p.height.to_string(), "1,234"); assert_eq!(HumanNumber::from_u32(p.height).to_string(), "1,234");
assert_eq!(p.reward.to_u64(), 2345); assert_eq!(p.reward.to_u64(), 2345);
assert_eq!(p.p2pool_difficulty.to_string(), "10,000,000"); assert_eq!(p.p2pool_difficulty.to_string(), "10,000,000");
assert_eq!(p.p2pool_hashrate.to_string(), "1.000 MH/s"); assert_eq!(p.p2pool_hashrate.to_string(), "1.000 MH/s");

View file

@ -81,12 +81,16 @@ pub const P2POOL_API_PATH_LOCAL: &str = r"local\stratum";
pub const P2POOL_API_PATH_NETWORK: &str = r"network\stats"; pub const P2POOL_API_PATH_NETWORK: &str = r"network\stats";
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub const P2POOL_API_PATH_POOL: &str = r"pool\stats"; pub const P2POOL_API_PATH_POOL: &str = r"pool\stats";
#[cfg(target_family = "windows")]
pub const P2POOL_API_PATH_P2P: &str = r"local\p2p";
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
pub const P2POOL_API_PATH_LOCAL: &str = "local/stratum"; pub const P2POOL_API_PATH_LOCAL: &str = "local/stratum";
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
pub const P2POOL_API_PATH_NETWORK: &str = "network/stats"; pub const P2POOL_API_PATH_NETWORK: &str = "network/stats";
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
pub const P2POOL_API_PATH_POOL: &str = "pool/stats"; pub const P2POOL_API_PATH_POOL: &str = "pool/stats";
#[cfg(target_family = "unix")]
pub const P2POOL_API_PATH_P2P: &str = "local/p2p";
pub const XMRIG_API_SUMMARY_URI: &str = "1/summary"; // The default relative URI of XMRig's API summary pub const XMRIG_API_SUMMARY_URI: &str = "1/summary"; // The default relative URI of XMRig's API summary
// pub const XMRIG_API_CONFIG_URI: &str = "1/config"; // The default relative URI of XMRig's API config // pub const XMRIG_API_CONFIG_URI: &str = "1/config"; // The default relative URI of XMRig's API config
// todo allow user to change the port of the http api for xmrig and xmrig-proxy // todo allow user to change the port of the http api for xmrig and xmrig-proxy