Improve UX whilst VC is waiting for genesis (#1915)
## Issue Addressed - Resolves #1424 ## Proposed Changes Add a `GET lighthouse/staking` that returns 200 if the node is ready to stake (i.e., `--eth1` flag is present) or a 404 otherwise. Whilst the VC is waiting for the genesis time to start (i.e., when the genesis state is known), check the `lighthouse/staking` endpoint and log an error if the node isn't configured for staking. ## Additional Info NA
This commit is contained in:
parent
65b1cf2af1
commit
59b2247ab8
@ -2147,7 +2147,7 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
.and(warp::path::param::<StateId>())
|
||||
.and(warp::path("ssz"))
|
||||
.and(warp::path::end())
|
||||
.and(chain_filter)
|
||||
.and(chain_filter.clone())
|
||||
.and_then(|state_id: StateId, chain: Arc<BeaconChain<T>>| {
|
||||
blocking_task(move || {
|
||||
let state = state_id.state(&chain)?;
|
||||
@ -2164,6 +2164,25 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
})
|
||||
});
|
||||
|
||||
// GET lighthouse/staking
|
||||
let get_lighthouse_staking = warp::path("lighthouse")
|
||||
.and(warp::path("staking"))
|
||||
.and(warp::path::end())
|
||||
.and(chain_filter)
|
||||
.and_then(|chain: Arc<BeaconChain<T>>| {
|
||||
blocking_json_task(move || {
|
||||
if chain.eth1_chain.is_some() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(warp_utils::reject::custom_not_found(
|
||||
"staking is not enabled, \
|
||||
see the --staking CLI flag"
|
||||
.to_string(),
|
||||
))
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// Define the ultimate set of routes that will be provided to the server.
|
||||
let routes = warp::get()
|
||||
.and(
|
||||
@ -2211,7 +2230,8 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
.or(get_lighthouse_eth1_syncing.boxed())
|
||||
.or(get_lighthouse_eth1_block_cache.boxed())
|
||||
.or(get_lighthouse_eth1_deposit_cache.boxed())
|
||||
.or(get_lighthouse_beacon_states_ssz.boxed()),
|
||||
.or(get_lighthouse_beacon_states_ssz.boxed())
|
||||
.or(get_lighthouse_staking.boxed()),
|
||||
)
|
||||
.or(warp::post().and(
|
||||
post_beacon_blocks
|
||||
|
@ -1815,6 +1815,14 @@ impl ApiTester {
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn test_get_lighthouse_staking(self) -> Self {
|
||||
let result = self.client.get_lighthouse_staking().await.unwrap();
|
||||
|
||||
assert_eq!(result, self.chain.eth1_chain.is_some());
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test(core_threads = 2)]
|
||||
@ -2087,5 +2095,7 @@ async fn lighthouse_endpoints() {
|
||||
.test_get_lighthouse_eth1_deposit_cache()
|
||||
.await
|
||||
.test_get_lighthouse_beacon_states_ssz()
|
||||
.await
|
||||
.test_get_lighthouse_staking()
|
||||
.await;
|
||||
}
|
||||
|
@ -356,4 +356,16 @@ impl BeaconNodeHttpClient {
|
||||
.map(|bytes| BeaconState::from_ssz_bytes(&bytes).map_err(Error::InvalidSsz))
|
||||
.transpose()
|
||||
}
|
||||
|
||||
/// `GET lighthouse/staking`
|
||||
pub async fn get_lighthouse_staking(&self) -> Result<bool, Error> {
|
||||
let mut path = self.server.clone();
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("lighthouse")
|
||||
.push("staking");
|
||||
|
||||
self.get_opt::<(), _>(path).await.map(|opt| opt.is_some())
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,9 @@ use validator_store::ValidatorStore;
|
||||
/// The interval between attempts to contact the beacon node during startup.
|
||||
const RETRY_DELAY: Duration = Duration::from_secs(2);
|
||||
|
||||
/// The time between polls when waiting for genesis.
|
||||
const WAITING_FOR_GENESIS_POLL_TIME: Duration = Duration::from_secs(12);
|
||||
|
||||
/// The global timeout for HTTP requests to the beacon node.
|
||||
const HTTP_TIMEOUT: Duration = Duration::from_secs(12);
|
||||
|
||||
@ -378,7 +381,18 @@ async fn init_from_beacon_node<E: EthSpec>(
|
||||
"seconds_to_wait" => (genesis_time - now).as_secs()
|
||||
);
|
||||
|
||||
delay_for(genesis_time - now).await;
|
||||
// Start polling the node for pre-genesis information, cancelling the polling as soon as the
|
||||
// timer runs out.
|
||||
tokio::select! {
|
||||
result = poll_whilst_waiting_for_genesis(beacon_node, genesis_time, context.log()) => result?,
|
||||
() = delay_for(genesis_time - now) => ()
|
||||
};
|
||||
|
||||
info!(
|
||||
context.log(),
|
||||
"Genesis has occurred";
|
||||
"ms_since_genesis" => (genesis_time - now).as_millis()
|
||||
);
|
||||
} else {
|
||||
info!(
|
||||
context.log(),
|
||||
@ -427,3 +441,50 @@ async fn wait_for_node(beacon_node: &BeaconNodeHttpClient, log: &Logger) -> Resu
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Request the version from the node, looping back and trying again on failure. Exit once the node
|
||||
/// has been contacted.
|
||||
async fn poll_whilst_waiting_for_genesis(
|
||||
beacon_node: &BeaconNodeHttpClient,
|
||||
genesis_time: Duration,
|
||||
log: &Logger,
|
||||
) -> Result<(), String> {
|
||||
loop {
|
||||
match beacon_node.get_lighthouse_staking().await {
|
||||
Ok(is_staking) => {
|
||||
let now = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.map_err(|e| format!("Unable to read system time: {:?}", e))?;
|
||||
|
||||
if !is_staking {
|
||||
error!(
|
||||
log,
|
||||
"Staking is disabled for beacon node";
|
||||
"msg" => "this will caused missed duties",
|
||||
"info" => "see the --staking CLI flag on the beacon node"
|
||||
);
|
||||
}
|
||||
|
||||
if now < genesis_time {
|
||||
info!(
|
||||
log,
|
||||
"Waiting for genesis";
|
||||
"bn_staking_enabled" => is_staking,
|
||||
"seconds_to_wait" => (genesis_time - now).as_secs()
|
||||
);
|
||||
} else {
|
||||
break Ok(());
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!(
|
||||
log,
|
||||
"Error polling beacon node";
|
||||
"error" => format!("{:?}", e)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
delay_for(WAITING_FOR_GENESIS_POLL_TIME).await;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user