225 lines
8.6 KiB
Rust
225 lines
8.6 KiB
Rust
|
//! This module contains endpoints that are non-standard and only available on Lighthouse servers.
|
||
|
|
||
|
use crate::{
|
||
|
types::{Epoch, EthSpec, GenericResponse, ValidatorId},
|
||
|
BeaconNodeHttpClient, Error,
|
||
|
};
|
||
|
use proto_array::core::ProtoArray;
|
||
|
use serde::{Deserialize, Serialize};
|
||
|
|
||
|
pub use eth2_libp2p::{types::SyncState, PeerInfo};
|
||
|
|
||
|
/// Information returned by `peers` and `connected_peers`.
|
||
|
// TODO: this should be deserializable..
|
||
|
#[derive(Debug, Clone, Serialize)]
|
||
|
#[serde(bound = "T: EthSpec")]
|
||
|
pub struct Peer<T: EthSpec> {
|
||
|
/// The Peer's ID
|
||
|
pub peer_id: String,
|
||
|
/// The PeerInfo associated with the peer.
|
||
|
pub peer_info: PeerInfo<T>,
|
||
|
}
|
||
|
|
||
|
/// The results of validators voting during an epoch.
|
||
|
///
|
||
|
/// Provides information about the current and previous epochs.
|
||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||
|
pub struct GlobalValidatorInclusionData {
|
||
|
/// The total effective balance of all active validators during the _current_ epoch.
|
||
|
pub current_epoch_active_gwei: u64,
|
||
|
/// The total effective balance of all active validators during the _previous_ epoch.
|
||
|
pub previous_epoch_active_gwei: u64,
|
||
|
/// The total effective balance of all validators who attested during the _current_ epoch.
|
||
|
pub current_epoch_attesting_gwei: u64,
|
||
|
/// The total effective balance of all validators who attested during the _current_ epoch and
|
||
|
/// agreed with the state about the beacon block at the first slot of the _current_ epoch.
|
||
|
pub current_epoch_target_attesting_gwei: u64,
|
||
|
/// The total effective balance of all validators who attested during the _previous_ epoch.
|
||
|
pub previous_epoch_attesting_gwei: u64,
|
||
|
/// The total effective balance of all validators who attested during the _previous_ epoch and
|
||
|
/// agreed with the state about the beacon block at the first slot of the _previous_ epoch.
|
||
|
pub previous_epoch_target_attesting_gwei: u64,
|
||
|
/// The total effective balance of all validators who attested during the _previous_ epoch and
|
||
|
/// agreed with the state about the beacon block at the time of attestation.
|
||
|
pub previous_epoch_head_attesting_gwei: u64,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||
|
pub struct ValidatorInclusionData {
|
||
|
/// True if the validator has been slashed, ever.
|
||
|
pub is_slashed: bool,
|
||
|
/// True if the validator can withdraw in the current epoch.
|
||
|
pub is_withdrawable_in_current_epoch: bool,
|
||
|
/// True if the validator was active in the state's _current_ epoch.
|
||
|
pub is_active_in_current_epoch: bool,
|
||
|
/// True if the validator was active in the state's _previous_ epoch.
|
||
|
pub is_active_in_previous_epoch: bool,
|
||
|
/// The validator's effective balance in the _current_ epoch.
|
||
|
pub current_epoch_effective_balance_gwei: u64,
|
||
|
/// True if the validator had an attestation included in the _current_ epoch.
|
||
|
pub is_current_epoch_attester: bool,
|
||
|
/// True if the validator's beacon block root attestation for the first slot of the _current_
|
||
|
/// epoch matches the block root known to the state.
|
||
|
pub is_current_epoch_target_attester: bool,
|
||
|
/// True if the validator had an attestation included in the _previous_ epoch.
|
||
|
pub is_previous_epoch_attester: bool,
|
||
|
/// True if the validator's beacon block root attestation for the first slot of the _previous_
|
||
|
/// epoch matches the block root known to the state.
|
||
|
pub is_previous_epoch_target_attester: bool,
|
||
|
/// True if the validator's beacon block root attestation in the _previous_ epoch at the
|
||
|
/// attestation's slot (`attestation_data.slot`) matches the block root known to the state.
|
||
|
pub is_previous_epoch_head_attester: bool,
|
||
|
}
|
||
|
|
||
|
#[cfg(target_os = "linux")]
|
||
|
use {procinfo::pid, psutil::process::Process};
|
||
|
|
||
|
/// Reports on the health of the Lighthouse instance.
|
||
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||
|
pub struct Health {
|
||
|
/// The pid of this process.
|
||
|
pub pid: u32,
|
||
|
/// The number of threads used by this pid.
|
||
|
pub pid_num_threads: i32,
|
||
|
/// The total resident memory used by this pid.
|
||
|
pub pid_mem_resident_set_size: u64,
|
||
|
/// The total virtual memory used by this pid.
|
||
|
pub pid_mem_virtual_memory_size: u64,
|
||
|
/// Total virtual memory on the system
|
||
|
pub sys_virt_mem_total: u64,
|
||
|
/// Total virtual memory available for new processes.
|
||
|
pub sys_virt_mem_available: u64,
|
||
|
/// Total virtual memory used on the system
|
||
|
pub sys_virt_mem_used: u64,
|
||
|
/// Total virtual memory not used on the system
|
||
|
pub sys_virt_mem_free: u64,
|
||
|
/// Percentage of virtual memory used on the system
|
||
|
pub sys_virt_mem_percent: f32,
|
||
|
/// System load average over 1 minute.
|
||
|
pub sys_loadavg_1: f64,
|
||
|
/// System load average over 5 minutes.
|
||
|
pub sys_loadavg_5: f64,
|
||
|
/// System load average over 15 minutes.
|
||
|
pub sys_loadavg_15: f64,
|
||
|
}
|
||
|
|
||
|
impl Health {
|
||
|
#[cfg(not(target_os = "linux"))]
|
||
|
pub fn observe() -> Result<Self, String> {
|
||
|
Err("Health is only available on Linux".into())
|
||
|
}
|
||
|
|
||
|
#[cfg(target_os = "linux")]
|
||
|
pub fn observe() -> Result<Self, String> {
|
||
|
let process =
|
||
|
Process::current().map_err(|e| format!("Unable to get current process: {:?}", e))?;
|
||
|
|
||
|
let process_mem = process
|
||
|
.memory_info()
|
||
|
.map_err(|e| format!("Unable to get process memory info: {:?}", e))?;
|
||
|
|
||
|
let stat = pid::stat_self().map_err(|e| format!("Unable to get stat: {:?}", e))?;
|
||
|
|
||
|
let vm = psutil::memory::virtual_memory()
|
||
|
.map_err(|e| format!("Unable to get virtual memory: {:?}", e))?;
|
||
|
let loadavg =
|
||
|
psutil::host::loadavg().map_err(|e| format!("Unable to get loadavg: {:?}", e))?;
|
||
|
|
||
|
Ok(Self {
|
||
|
pid: process.pid(),
|
||
|
pid_num_threads: stat.num_threads,
|
||
|
pid_mem_resident_set_size: process_mem.rss(),
|
||
|
pid_mem_virtual_memory_size: process_mem.vms(),
|
||
|
sys_virt_mem_total: vm.total(),
|
||
|
sys_virt_mem_available: vm.available(),
|
||
|
sys_virt_mem_used: vm.used(),
|
||
|
sys_virt_mem_free: vm.free(),
|
||
|
sys_virt_mem_percent: vm.percent(),
|
||
|
sys_loadavg_1: loadavg.one,
|
||
|
sys_loadavg_5: loadavg.five,
|
||
|
sys_loadavg_15: loadavg.fifteen,
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl BeaconNodeHttpClient {
|
||
|
/// `GET lighthouse/health`
|
||
|
pub async fn get_lighthouse_health(&self) -> Result<GenericResponse<Health>, Error> {
|
||
|
let mut path = self.server.clone();
|
||
|
|
||
|
path.path_segments_mut()
|
||
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||
|
.push("lighthouse")
|
||
|
.push("health");
|
||
|
|
||
|
self.get(path).await
|
||
|
}
|
||
|
|
||
|
/// `GET lighthouse/syncing`
|
||
|
pub async fn get_lighthouse_syncing(&self) -> Result<GenericResponse<SyncState>, Error> {
|
||
|
let mut path = self.server.clone();
|
||
|
|
||
|
path.path_segments_mut()
|
||
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||
|
.push("lighthouse")
|
||
|
.push("syncing");
|
||
|
|
||
|
self.get(path).await
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Note:
|
||
|
*
|
||
|
* The `lighthouse/peers` endpoints do not have functions here. We are yet to implement
|
||
|
* `Deserialize` on the `PeerInfo` struct since it contains use of `Instant`. This could be
|
||
|
* fairly simply achieved, if desired.
|
||
|
*/
|
||
|
|
||
|
/// `GET lighthouse/proto_array`
|
||
|
pub async fn get_lighthouse_proto_array(&self) -> Result<GenericResponse<ProtoArray>, Error> {
|
||
|
let mut path = self.server.clone();
|
||
|
|
||
|
path.path_segments_mut()
|
||
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||
|
.push("lighthouse")
|
||
|
.push("proto_array");
|
||
|
|
||
|
self.get(path).await
|
||
|
}
|
||
|
|
||
|
/// `GET lighthouse/validator_inclusion/{epoch}/global`
|
||
|
pub async fn get_lighthouse_validator_inclusion_global(
|
||
|
&self,
|
||
|
epoch: Epoch,
|
||
|
) -> Result<GenericResponse<GlobalValidatorInclusionData>, Error> {
|
||
|
let mut path = self.server.clone();
|
||
|
|
||
|
path.path_segments_mut()
|
||
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||
|
.push("lighthouse")
|
||
|
.push("validator_inclusion")
|
||
|
.push(&epoch.to_string())
|
||
|
.push("global");
|
||
|
|
||
|
self.get(path).await
|
||
|
}
|
||
|
|
||
|
/// `GET lighthouse/validator_inclusion/{epoch}/{validator_id}`
|
||
|
pub async fn get_lighthouse_validator_inclusion(
|
||
|
&self,
|
||
|
epoch: Epoch,
|
||
|
validator_id: ValidatorId,
|
||
|
) -> Result<GenericResponse<Option<ValidatorInclusionData>>, Error> {
|
||
|
let mut path = self.server.clone();
|
||
|
|
||
|
path.path_segments_mut()
|
||
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||
|
.push("lighthouse")
|
||
|
.push("validator_inclusion")
|
||
|
.push(&epoch.to_string())
|
||
|
.push(&validator_id.to_string());
|
||
|
|
||
|
self.get(path).await
|
||
|
}
|
||
|
}
|