mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-16 12:28:24 +00:00
Add http api endpoint
This commit is contained in:
@@ -132,7 +132,7 @@ impl<E: Debug> fmt::Display for Errors<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Reasons why a candidate might not be ready.
|
/// Reasons why a candidate might not be ready.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
|
||||||
pub enum CandidateError {
|
pub enum CandidateError {
|
||||||
Uninitialized,
|
Uninitialized,
|
||||||
Offline,
|
Offline,
|
||||||
@@ -151,9 +151,9 @@ pub struct CandidateInfo {
|
|||||||
/// for a query.
|
/// for a query.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CandidateBeaconNode<E> {
|
pub struct CandidateBeaconNode<E> {
|
||||||
id: usize,
|
pub id: usize,
|
||||||
beacon_node: BeaconNodeHttpClient,
|
pub beacon_node: BeaconNodeHttpClient,
|
||||||
health: PLRwLock<Result<BeaconNodeHealth, CandidateError>>,
|
pub health: PLRwLock<Result<BeaconNodeHealth, CandidateError>>,
|
||||||
_phantom: PhantomData<E>,
|
_phantom: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,7 +324,7 @@ impl<E: EthSpec> CandidateBeaconNode<E> {
|
|||||||
/// identical query.
|
/// identical query.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct BeaconNodeFallback<T, E> {
|
pub struct BeaconNodeFallback<T, E> {
|
||||||
candidates: Arc<RwLock<Vec<CandidateBeaconNode<E>>>>,
|
pub candidates: Arc<RwLock<Vec<CandidateBeaconNode<E>>>>,
|
||||||
disable_run_on_all: bool,
|
disable_run_on_all: bool,
|
||||||
distance_tiers: BeaconNodeSyncDistanceTiers,
|
distance_tiers: BeaconNodeSyncDistanceTiers,
|
||||||
slot_clock: Option<T>,
|
slot_clock: Option<T>,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::beacon_node_fallback::Config;
|
use crate::beacon_node_fallback::Config;
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fmt::{Debug, Display, Formatter};
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
@@ -20,7 +21,7 @@ type HealthTier = u8;
|
|||||||
type SyncDistance = Slot;
|
type SyncDistance = Slot;
|
||||||
|
|
||||||
/// Helpful enum which is used when pattern matching to determine health tier.
|
/// Helpful enum which is used when pattern matching to determine health tier.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub enum SyncDistanceTier {
|
pub enum SyncDistanceTier {
|
||||||
Synced,
|
Synced,
|
||||||
Small,
|
Small,
|
||||||
@@ -95,19 +96,19 @@ impl Default for BeaconNodeSyncDistanceTiers {
|
|||||||
/// Execution Node health metrics.
|
/// Execution Node health metrics.
|
||||||
///
|
///
|
||||||
/// Currently only considers `el_offline`.
|
/// Currently only considers `el_offline`.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub enum ExecutionEngineHealth {
|
pub enum ExecutionEngineHealth {
|
||||||
Healthy,
|
Healthy,
|
||||||
Unhealthy,
|
Unhealthy,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub enum IsOptimistic {
|
pub enum IsOptimistic {
|
||||||
Yes,
|
Yes,
|
||||||
No,
|
No,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub struct BeaconNodeHealthTier {
|
pub struct BeaconNodeHealthTier {
|
||||||
pub tier: HealthTier,
|
pub tier: HealthTier,
|
||||||
pub sync_distance: SyncDistance,
|
pub sync_distance: SyncDistance,
|
||||||
@@ -158,7 +159,7 @@ impl BeaconNodeHealthTier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Beacon Node Health metrics.
|
/// Beacon Node Health metrics.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub struct BeaconNodeHealth {
|
pub struct BeaconNodeHealth {
|
||||||
// The ID of the Beacon Node. This should correspond with its position in the `--beacon-nodes`
|
// The ID of the Beacon Node. This should correspond with its position in the `--beacon-nodes`
|
||||||
// list. Note that the ID field is used to tie-break nodes with the same health so that nodes
|
// list. Note that the ID field is used to tie-break nodes with the same health so that nodes
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ impl From<Errors<BlockError>> for BlockError {
|
|||||||
pub struct BlockServiceBuilder<T, E: EthSpec> {
|
pub struct BlockServiceBuilder<T, E: EthSpec> {
|
||||||
validator_store: Option<Arc<ValidatorStore<T, E>>>,
|
validator_store: Option<Arc<ValidatorStore<T, E>>>,
|
||||||
slot_clock: Option<Arc<T>>,
|
slot_clock: Option<Arc<T>>,
|
||||||
beacon_nodes: Option<Arc<BeaconNodeFallback<T, E>>>,
|
pub beacon_nodes: Option<Arc<BeaconNodeFallback<T, E>>>,
|
||||||
proposer_nodes: Option<Arc<BeaconNodeFallback<T, E>>>,
|
pub proposer_nodes: Option<Arc<BeaconNodeFallback<T, E>>>,
|
||||||
context: Option<RuntimeContext<E>>,
|
context: Option<RuntimeContext<E>>,
|
||||||
graffiti: Option<Graffiti>,
|
graffiti: Option<Graffiti>,
|
||||||
graffiti_file: Option<GraffitiFile>,
|
graffiti_file: Option<GraffitiFile>,
|
||||||
@@ -190,8 +190,8 @@ impl<T: SlotClock, E: EthSpec> ProposerFallback<T, E> {
|
|||||||
pub struct Inner<T, E: EthSpec> {
|
pub struct Inner<T, E: EthSpec> {
|
||||||
validator_store: Arc<ValidatorStore<T, E>>,
|
validator_store: Arc<ValidatorStore<T, E>>,
|
||||||
slot_clock: Arc<T>,
|
slot_clock: Arc<T>,
|
||||||
beacon_nodes: Arc<BeaconNodeFallback<T, E>>,
|
pub beacon_nodes: Arc<BeaconNodeFallback<T, E>>,
|
||||||
proposer_nodes: Option<Arc<BeaconNodeFallback<T, E>>>,
|
pub proposer_nodes: Option<Arc<BeaconNodeFallback<T, E>>>,
|
||||||
context: RuntimeContext<E>,
|
context: RuntimeContext<E>,
|
||||||
graffiti: Option<Graffiti>,
|
graffiti: Option<Graffiti>,
|
||||||
graffiti_file: Option<GraffitiFile>,
|
graffiti_file: Option<GraffitiFile>,
|
||||||
|
|||||||
@@ -7,8 +7,10 @@ mod tests;
|
|||||||
|
|
||||||
pub mod test_utils;
|
pub mod test_utils;
|
||||||
|
|
||||||
|
use crate::beacon_node_fallback::CandidateError;
|
||||||
|
use crate::beacon_node_health::BeaconNodeHealth;
|
||||||
use crate::http_api::create_signed_voluntary_exit::create_signed_voluntary_exit;
|
use crate::http_api::create_signed_voluntary_exit::create_signed_voluntary_exit;
|
||||||
use crate::{determine_graffiti, GraffitiFile, ValidatorStore};
|
use crate::{determine_graffiti, BlockService, GraffitiFile, ValidatorStore};
|
||||||
use account_utils::{
|
use account_utils::{
|
||||||
mnemonic_from_phrase,
|
mnemonic_from_phrase,
|
||||||
validator_definitions::{SigningDefinition, ValidatorDefinition, Web3SignerDefinition},
|
validator_definitions::{SigningDefinition, ValidatorDefinition, Web3SignerDefinition},
|
||||||
@@ -73,6 +75,7 @@ impl From<String> for Error {
|
|||||||
pub struct Context<T: SlotClock, E: EthSpec> {
|
pub struct Context<T: SlotClock, E: EthSpec> {
|
||||||
pub task_executor: TaskExecutor,
|
pub task_executor: TaskExecutor,
|
||||||
pub api_secret: ApiSecret,
|
pub api_secret: ApiSecret,
|
||||||
|
pub block_service: Option<BlockService<T, E>>,
|
||||||
pub validator_store: Option<Arc<ValidatorStore<T, E>>>,
|
pub validator_store: Option<Arc<ValidatorStore<T, E>>>,
|
||||||
pub validator_dir: Option<PathBuf>,
|
pub validator_dir: Option<PathBuf>,
|
||||||
pub secrets_dir: Option<PathBuf>,
|
pub secrets_dir: Option<PathBuf>,
|
||||||
@@ -173,6 +176,17 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
|
|||||||
let signer = ctx.api_secret.signer();
|
let signer = ctx.api_secret.signer();
|
||||||
let signer = warp::any().map(move || signer.clone());
|
let signer = warp::any().map(move || signer.clone());
|
||||||
|
|
||||||
|
let inner_block_service = ctx.block_service.clone();
|
||||||
|
let block_service_filter = warp::any()
|
||||||
|
.map(move || inner_block_service.clone())
|
||||||
|
.and_then(|block_service: Option<_>| async move {
|
||||||
|
block_service.ok_or_else(|| {
|
||||||
|
warp_utils::reject::custom_not_found(
|
||||||
|
"block service is not initialized.".to_string(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
let inner_validator_store = ctx.validator_store.clone();
|
let inner_validator_store = ctx.validator_store.clone();
|
||||||
let validator_store_filter = warp::any()
|
let validator_store_filter = warp::any()
|
||||||
.map(move || inner_validator_store.clone())
|
.map(move || inner_validator_store.clone())
|
||||||
@@ -410,6 +424,29 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// GET lighthouse/ui/fallback_health
|
||||||
|
let get_lighthouse_ui_fallback_health = warp::path("lighthouse")
|
||||||
|
.and(warp::path("ui"))
|
||||||
|
.and(warp::path("fallback_health"))
|
||||||
|
.and(warp::path::end())
|
||||||
|
.and(signer.clone())
|
||||||
|
.and(block_service_filter.clone())
|
||||||
|
.and_then(|signer, block_filter: BlockService<T, E>| async move {
|
||||||
|
let mut result: HashMap<String, Result<BeaconNodeHealth, CandidateError>> =
|
||||||
|
HashMap::new();
|
||||||
|
for node in &*block_filter.beacon_nodes.candidates.read().await {
|
||||||
|
result.insert(node.beacon_node.to_string(), *node.health.read());
|
||||||
|
}
|
||||||
|
if let Some(proposer_nodes) = &block_filter.proposer_nodes {
|
||||||
|
for node in &*proposer_nodes.candidates.read().await {
|
||||||
|
result.insert(node.beacon_node.to_string(), *node.health.read());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blocking_signed_json_task(signer, move || Ok(api_types::GenericResponse::from(result)))
|
||||||
|
.await
|
||||||
|
});
|
||||||
|
|
||||||
// POST lighthouse/validators/
|
// POST lighthouse/validators/
|
||||||
let post_validators = warp::path("lighthouse")
|
let post_validators = warp::path("lighthouse")
|
||||||
.and(warp::path("validators"))
|
.and(warp::path("validators"))
|
||||||
@@ -1173,6 +1210,7 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
|
|||||||
.or(get_lighthouse_validators_pubkey)
|
.or(get_lighthouse_validators_pubkey)
|
||||||
.or(get_lighthouse_ui_health)
|
.or(get_lighthouse_ui_health)
|
||||||
.or(get_lighthouse_ui_graffiti)
|
.or(get_lighthouse_ui_graffiti)
|
||||||
|
.or(get_lighthouse_ui_fallback_health)
|
||||||
.or(get_fee_recipient)
|
.or(get_fee_recipient)
|
||||||
.or(get_gas_limit)
|
.or(get_gas_limit)
|
||||||
.or(get_std_keystores)
|
.or(get_std_keystores)
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ impl ApiTester {
|
|||||||
let context = Arc::new(Context {
|
let context = Arc::new(Context {
|
||||||
task_executor: test_runtime.task_executor.clone(),
|
task_executor: test_runtime.task_executor.clone(),
|
||||||
api_secret,
|
api_secret,
|
||||||
|
block_service: None,
|
||||||
validator_dir: Some(validator_dir.path().into()),
|
validator_dir: Some(validator_dir.path().into()),
|
||||||
secrets_dir: Some(secrets_dir.path().into()),
|
secrets_dir: Some(secrets_dir.path().into()),
|
||||||
validator_store: Some(validator_store.clone()),
|
validator_store: Some(validator_store.clone()),
|
||||||
|
|||||||
@@ -577,6 +577,7 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
|
|||||||
let ctx = Arc::new(http_api::Context {
|
let ctx = Arc::new(http_api::Context {
|
||||||
task_executor: self.context.executor.clone(),
|
task_executor: self.context.executor.clone(),
|
||||||
api_secret,
|
api_secret,
|
||||||
|
block_service: Some(self.block_service.clone()),
|
||||||
validator_store: Some(self.validator_store.clone()),
|
validator_store: Some(self.validator_store.clone()),
|
||||||
validator_dir: Some(self.config.validator_dir.clone()),
|
validator_dir: Some(self.config.validator_dir.clone()),
|
||||||
secrets_dir: Some(self.config.secrets_dir.clone()),
|
secrets_dir: Some(self.config.secrets_dir.clone()),
|
||||||
|
|||||||
Reference in New Issue
Block a user