From 612cdb709207d94f770cb389000061939d349c44 Mon Sep 17 00:00:00 2001 From: Pawan Dhananjay Date: Thu, 21 Jul 2022 05:45:39 +0000 Subject: [PATCH] Merge readiness endpoint (#3349) ## Issue Addressed Resolves final task in https://github.com/sigp/lighthouse/issues/3260 ## Proposed Changes Adds a lighthouse http endpoint to indicate merge readiness. Blocked on #3339 --- .../beacon_chain/src/merge_readiness.rs | 39 +++++++++++++------ beacon_node/client/src/notifier.rs | 4 +- beacon_node/http_api/src/lib.rs | 13 +++++++ book/src/api-lighthouse.md | 21 +++++++++- 4 files changed, 63 insertions(+), 14 deletions(-) diff --git a/beacon_node/beacon_chain/src/merge_readiness.rs b/beacon_node/beacon_chain/src/merge_readiness.rs index be158ecbe..4a7b38bdb 100644 --- a/beacon_node/beacon_chain/src/merge_readiness.rs +++ b/beacon_node/beacon_chain/src/merge_readiness.rs @@ -2,7 +2,7 @@ //! transition. use crate::{BeaconChain, BeaconChainTypes}; -use execution_layer::Error as EngineError; +use serde::{Deserialize, Serialize, Serializer}; use std::fmt; use std::fmt::Write; use types::*; @@ -11,10 +11,13 @@ use types::*; const SECONDS_IN_A_WEEK: u64 = 604800; pub const MERGE_READINESS_PREPARATION_SECONDS: u64 = SECONDS_IN_A_WEEK; -#[derive(Default, Debug)] +#[derive(Default, Debug, Serialize, Deserialize)] pub struct MergeConfig { + #[serde(serialize_with = "serialize_uint256")] pub terminal_total_difficulty: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub terminal_block_hash: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub terminal_block_hash_epoch: Option, } @@ -73,15 +76,19 @@ impl MergeConfig { } /// Indicates if a node is ready for the Bellatrix upgrade and subsequent merge transition. +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +#[serde(tag = "type")] pub enum MergeReadiness { /// The node is ready, as far as we can tell. Ready { config: MergeConfig, - current_difficulty: Result, + #[serde(serialize_with = "serialize_uint256")] + current_difficulty: Option, }, /// The transition configuration with the EL failed, there might be a problem with /// connectivity, authentication or a difference in configuration. - ExchangeTransitionConfigurationFailed(EngineError), + ExchangeTransitionConfigurationFailed { error: String }, /// The EL can be reached and has the correct configuration, however it's not yet synced. NotSynced, /// The user has not configured this node to use an execution endpoint. @@ -102,11 +109,11 @@ impl fmt::Display for MergeReadiness { params, current_difficulty ) } - MergeReadiness::ExchangeTransitionConfigurationFailed(e) => write!( + MergeReadiness::ExchangeTransitionConfigurationFailed { error } => write!( f, "Could not confirm the transition configuration with the \ execution endpoint: {:?}", - e + error ), MergeReadiness::NotSynced => write!( f, @@ -145,7 +152,9 @@ impl BeaconChain { if let Err(e) = el.exchange_transition_configuration(&self.spec).await { // The EL was either unreachable, responded with an error or has a different // configuration. - return MergeReadiness::ExchangeTransitionConfigurationFailed(e); + return MergeReadiness::ExchangeTransitionConfigurationFailed { + error: format!("{:?}", e), + }; } if !el.is_synced_for_notifier().await { @@ -153,10 +162,7 @@ impl BeaconChain { return MergeReadiness::NotSynced; } let params = MergeConfig::from_chainspec(&self.spec); - let current_difficulty = el - .get_current_difficulty() - .await - .map_err(|_| "Failed to get current difficulty from execution node".to_string()); + let current_difficulty = el.get_current_difficulty().await.ok(); MergeReadiness::Ready { config: params, current_difficulty, @@ -167,3 +173,14 @@ impl BeaconChain { } } } + +/// Utility function to serialize a Uint256 as a decimal string. +fn serialize_uint256(val: &Option, s: S) -> Result +where + S: Serializer, +{ + match val { + Some(v) => v.to_string().serialize(s), + None => s.serialize_none(), + } +} diff --git a/beacon_node/client/src/notifier.rs b/beacon_node/client/src/notifier.rs index 53478971a..74947c16f 100644 --- a/beacon_node/client/src/notifier.rs +++ b/beacon_node/client/src/notifier.rs @@ -359,7 +359,7 @@ async fn merge_readiness_logging( "terminal_total_difficulty" => %ttd, "current_difficulty" => current_difficulty .map(|d| d.to_string()) - .unwrap_or_else(|_| "??".into()), + .unwrap_or_else(|| "??".into()), ) } MergeConfig { @@ -382,7 +382,7 @@ async fn merge_readiness_logging( "config" => ?other ), }, - readiness @ MergeReadiness::ExchangeTransitionConfigurationFailed(_) => { + readiness @ MergeReadiness::ExchangeTransitionConfigurationFailed { error: _ } => { error!( log, "Not ready for merge"; diff --git a/beacon_node/http_api/src/lib.rs b/beacon_node/http_api/src/lib.rs index 606dfb64d..14f260e57 100644 --- a/beacon_node/http_api/src/lib.rs +++ b/beacon_node/http_api/src/lib.rs @@ -2887,6 +2887,18 @@ pub fn serve( }) }); + // GET lighthouse/merge_readiness + let get_lighthouse_merge_readiness = warp::path("lighthouse") + .and(warp::path("merge_readiness")) + .and(warp::path::end()) + .and(chain_filter.clone()) + .and_then(|chain: Arc>| async move { + let merge_readiness = chain.check_merge_readiness().await; + Ok::<_, warp::reject::Rejection>(warp::reply::json(&api_types::GenericResponse::from( + merge_readiness, + ))) + }); + let get_events = eth1_v1 .and(warp::path("events")) .and(warp::path::end()) @@ -3015,6 +3027,7 @@ pub fn serve( .or(get_lighthouse_block_rewards.boxed()) .or(get_lighthouse_attestation_performance.boxed()) .or(get_lighthouse_block_packing_efficiency.boxed()) + .or(get_lighthouse_merge_readiness.boxed()) .or(get_events.boxed()), ) .or(warp::post().and( diff --git a/book/src/api-lighthouse.md b/book/src/api-lighthouse.md index f5c4542b9..d9c8080b4 100644 --- a/book/src/api-lighthouse.md +++ b/book/src/api-lighthouse.md @@ -453,4 +453,23 @@ Caveats: loading a state on a boundary is most efficient. [block_reward_src]: -https://github.com/sigp/lighthouse/tree/unstable/common/eth2/src/lighthouse/block_rewards.rs \ No newline at end of file +https://github.com/sigp/lighthouse/tree/unstable/common/eth2/src/lighthouse/block_rewards.rs + + +### `/lighthouse/merge_readiness` + +```bash +curl -X GET "http://localhost:5052/lighthouse/merge_readiness" +``` + +``` +{ + "data":{ + "type":"ready", + "config":{ + "terminal_total_difficulty":"6400" + }, + "current_difficulty":"4800" + } + } +```