validator client: start http api before genesis (#4714)
## Issue Addressed On a new network a user might require importing validators before waiting until genesis has occurred. ## Proposed Changes Starts the validator client http api before waiting for genesis ## Additional Info cc @antondlr
This commit is contained in:
parent
b88e57c989
commit
d386a07b0c
@ -8,6 +8,7 @@ use env_logger::{Builder, Env};
|
|||||||
use environment::{EnvironmentBuilder, LoggerConfig};
|
use environment::{EnvironmentBuilder, LoggerConfig};
|
||||||
use eth2_network_config::{Eth2NetworkConfig, DEFAULT_HARDCODED_NETWORK, HARDCODED_NET_NAMES};
|
use eth2_network_config::{Eth2NetworkConfig, DEFAULT_HARDCODED_NETWORK, HARDCODED_NET_NAMES};
|
||||||
use ethereum_hashing::have_sha_extensions;
|
use ethereum_hashing::have_sha_extensions;
|
||||||
|
use futures::TryFutureExt;
|
||||||
use lighthouse_version::VERSION;
|
use lighthouse_version::VERSION;
|
||||||
use malloc_utils::configure_memory_allocator;
|
use malloc_utils::configure_memory_allocator;
|
||||||
use slog::{crit, info, warn};
|
use slog::{crit, info, warn};
|
||||||
@ -659,8 +660,8 @@ fn run<E: EthSpec>(
|
|||||||
executor.clone().spawn(
|
executor.clone().spawn(
|
||||||
async move {
|
async move {
|
||||||
if let Err(e) = ProductionValidatorClient::new(context, config)
|
if let Err(e) = ProductionValidatorClient::new(context, config)
|
||||||
|
.and_then(|mut vc| async move { vc.start_service().await })
|
||||||
.await
|
.await
|
||||||
.and_then(|mut vc| vc.start_service())
|
|
||||||
{
|
{
|
||||||
crit!(log, "Failed to start validator client"; "reason" => e);
|
crit!(log, "Failed to start validator client"; "reason" => e);
|
||||||
// Ignore the error since it always occurs during normal operation when
|
// Ignore the error since it always occurs during normal operation when
|
||||||
|
@ -220,14 +220,13 @@ impl<E: EthSpec> LocalValidatorClient<E> {
|
|||||||
config.validator_dir = files.validator_dir.path().into();
|
config.validator_dir = files.validator_dir.path().into();
|
||||||
config.secrets_dir = files.secrets_dir.path().into();
|
config.secrets_dir = files.secrets_dir.path().into();
|
||||||
|
|
||||||
ProductionValidatorClient::new(context, config)
|
let mut client = ProductionValidatorClient::new(context, config).await?;
|
||||||
|
|
||||||
|
client
|
||||||
|
.start_service()
|
||||||
.await
|
.await
|
||||||
.map(move |mut client| {
|
.expect("should start validator services");
|
||||||
client
|
Ok(Self { client, files })
|
||||||
.start_service()
|
|
||||||
.expect("should start validator services");
|
|
||||||
Self { client, files }
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +98,8 @@ pub struct ProductionValidatorClient<T: EthSpec> {
|
|||||||
slot_clock: SystemTimeSlotClock,
|
slot_clock: SystemTimeSlotClock,
|
||||||
http_api_listen_addr: Option<SocketAddr>,
|
http_api_listen_addr: Option<SocketAddr>,
|
||||||
config: Config,
|
config: Config,
|
||||||
|
beacon_nodes: Arc<BeaconNodeFallback<SystemTimeSlotClock, T>>,
|
||||||
|
genesis_time: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: EthSpec> ProductionValidatorClient<T> {
|
impl<T: EthSpec> ProductionValidatorClient<T> {
|
||||||
@ -501,12 +503,6 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
|
|||||||
context.service_context("sync_committee".into()),
|
context.service_context("sync_committee".into()),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Wait until genesis has occurred.
|
|
||||||
//
|
|
||||||
// It seems most sensible to move this into the `start_service` function, but I'm caution
|
|
||||||
// of making too many changes this close to genesis (<1 week).
|
|
||||||
wait_for_genesis(&beacon_nodes, genesis_time, &context).await?;
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
context,
|
context,
|
||||||
duties_service,
|
duties_service,
|
||||||
@ -519,10 +515,12 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
|
|||||||
config,
|
config,
|
||||||
slot_clock,
|
slot_clock,
|
||||||
http_api_listen_addr: None,
|
http_api_listen_addr: None,
|
||||||
|
genesis_time,
|
||||||
|
beacon_nodes,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_service(&mut self) -> Result<(), String> {
|
pub async fn start_service(&mut self) -> Result<(), String> {
|
||||||
// We use `SLOTS_PER_EPOCH` as the capacity of the block notification channel, because
|
// We use `SLOTS_PER_EPOCH` as the capacity of the block notification channel, because
|
||||||
// we don't expect notifications to be delayed by more than a single slot, let alone a
|
// we don't expect notifications to be delayed by more than a single slot, let alone a
|
||||||
// whole epoch!
|
// whole epoch!
|
||||||
@ -530,6 +528,44 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
|
|||||||
let (block_service_tx, block_service_rx) = mpsc::channel(channel_capacity);
|
let (block_service_tx, block_service_rx) = mpsc::channel(channel_capacity);
|
||||||
let log = self.context.log();
|
let log = self.context.log();
|
||||||
|
|
||||||
|
let api_secret = ApiSecret::create_or_open(&self.config.validator_dir)?;
|
||||||
|
|
||||||
|
self.http_api_listen_addr = if self.config.http_api.enabled {
|
||||||
|
let ctx = Arc::new(http_api::Context {
|
||||||
|
task_executor: self.context.executor.clone(),
|
||||||
|
api_secret,
|
||||||
|
validator_store: Some(self.validator_store.clone()),
|
||||||
|
validator_dir: Some(self.config.validator_dir.clone()),
|
||||||
|
secrets_dir: Some(self.config.secrets_dir.clone()),
|
||||||
|
graffiti_file: self.config.graffiti_file.clone(),
|
||||||
|
graffiti_flag: self.config.graffiti,
|
||||||
|
spec: self.context.eth2_config.spec.clone(),
|
||||||
|
config: self.config.http_api.clone(),
|
||||||
|
sse_logging_components: self.context.sse_logging_components.clone(),
|
||||||
|
slot_clock: self.slot_clock.clone(),
|
||||||
|
log: log.clone(),
|
||||||
|
_phantom: PhantomData,
|
||||||
|
});
|
||||||
|
|
||||||
|
let exit = self.context.executor.exit();
|
||||||
|
|
||||||
|
let (listen_addr, server) = http_api::serve(ctx, exit)
|
||||||
|
.map_err(|e| format!("Unable to start HTTP API server: {:?}", e))?;
|
||||||
|
|
||||||
|
self.context
|
||||||
|
.clone()
|
||||||
|
.executor
|
||||||
|
.spawn_without_exit(server, "http-api");
|
||||||
|
|
||||||
|
Some(listen_addr)
|
||||||
|
} else {
|
||||||
|
info!(log, "HTTP API server is disabled");
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// Wait until genesis has occurred.
|
||||||
|
wait_for_genesis(&self.beacon_nodes, self.genesis_time, &self.context).await?;
|
||||||
|
|
||||||
duties_service::start_update_service(self.duties_service.clone(), block_service_tx);
|
duties_service::start_update_service(self.duties_service.clone(), block_service_tx);
|
||||||
|
|
||||||
self.block_service
|
self.block_service
|
||||||
@ -568,41 +604,6 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
|
|||||||
|
|
||||||
spawn_notifier(self).map_err(|e| format!("Failed to start notifier: {}", e))?;
|
spawn_notifier(self).map_err(|e| format!("Failed to start notifier: {}", e))?;
|
||||||
|
|
||||||
let api_secret = ApiSecret::create_or_open(&self.config.validator_dir)?;
|
|
||||||
|
|
||||||
self.http_api_listen_addr = if self.config.http_api.enabled {
|
|
||||||
let ctx = Arc::new(http_api::Context {
|
|
||||||
task_executor: self.context.executor.clone(),
|
|
||||||
api_secret,
|
|
||||||
validator_store: Some(self.validator_store.clone()),
|
|
||||||
validator_dir: Some(self.config.validator_dir.clone()),
|
|
||||||
secrets_dir: Some(self.config.secrets_dir.clone()),
|
|
||||||
graffiti_file: self.config.graffiti_file.clone(),
|
|
||||||
graffiti_flag: self.config.graffiti,
|
|
||||||
spec: self.context.eth2_config.spec.clone(),
|
|
||||||
config: self.config.http_api.clone(),
|
|
||||||
sse_logging_components: self.context.sse_logging_components.clone(),
|
|
||||||
slot_clock: self.slot_clock.clone(),
|
|
||||||
log: log.clone(),
|
|
||||||
_phantom: PhantomData,
|
|
||||||
});
|
|
||||||
|
|
||||||
let exit = self.context.executor.exit();
|
|
||||||
|
|
||||||
let (listen_addr, server) = http_api::serve(ctx, exit)
|
|
||||||
.map_err(|e| format!("Unable to start HTTP API server: {:?}", e))?;
|
|
||||||
|
|
||||||
self.context
|
|
||||||
.clone()
|
|
||||||
.executor
|
|
||||||
.spawn_without_exit(server, "http-api");
|
|
||||||
|
|
||||||
Some(listen_addr)
|
|
||||||
} else {
|
|
||||||
info!(log, "HTTP API server is disabled");
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
if self.config.enable_latency_measurement_service {
|
if self.config.enable_latency_measurement_service {
|
||||||
latency::start_latency_service(
|
latency::start_latency_service(
|
||||||
self.context.clone(),
|
self.context.clone(),
|
||||||
|
Loading…
Reference in New Issue
Block a user