From d464c3e54581b347c3df9cb5ee81f7e4e2bfbc8d Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Mon, 13 Jan 2025 16:03:30 +0800 Subject: [PATCH 1/2] Dedup post merge readiness notifiers --- .../beacon_chain/src/capella_readiness.rs | 121 ------- .../beacon_chain/src/deneb_readiness.rs | 121 ------- .../beacon_chain/src/electra_readiness.rs | 115 ------ .../beacon_chain/src/fulu_readiness.rs | 114 ------ beacon_node/beacon_chain/src/lib.rs | 4 - beacon_node/client/src/notifier.rs | 331 ++++++------------ 6 files changed, 116 insertions(+), 690 deletions(-) delete mode 100644 beacon_node/beacon_chain/src/capella_readiness.rs delete mode 100644 beacon_node/beacon_chain/src/deneb_readiness.rs delete mode 100644 beacon_node/beacon_chain/src/electra_readiness.rs delete mode 100644 beacon_node/beacon_chain/src/fulu_readiness.rs diff --git a/beacon_node/beacon_chain/src/capella_readiness.rs b/beacon_node/beacon_chain/src/capella_readiness.rs deleted file mode 100644 index 88af7db0aaa..00000000000 --- a/beacon_node/beacon_chain/src/capella_readiness.rs +++ /dev/null @@ -1,121 +0,0 @@ -//! Provides tools for checking if a node is ready for the Capella upgrade. - -use crate::{BeaconChain, BeaconChainTypes}; -use execution_layer::http::{ - ENGINE_FORKCHOICE_UPDATED_V2, ENGINE_GET_PAYLOAD_V2, ENGINE_NEW_PAYLOAD_V2, -}; -use serde::{Deserialize, Serialize}; -use std::fmt; -use std::time::Duration; -use types::*; - -/// The time before the Capella fork when we will start issuing warnings about preparation. -use super::bellatrix_readiness::SECONDS_IN_A_WEEK; -pub const CAPELLA_READINESS_PREPARATION_SECONDS: u64 = SECONDS_IN_A_WEEK * 2; -pub const ENGINE_CAPABILITIES_REFRESH_INTERVAL: u64 = 300; - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[serde(tag = "type")] -pub enum CapellaReadiness { - /// The execution engine is capella-enabled (as far as we can tell) - Ready, - /// We are connected to an execution engine which doesn't support the V2 engine api methods - V2MethodsNotSupported { error: String }, - /// The transition configuration with the EL failed, there might be a problem with - /// connectivity, authentication or a difference in configuration. - ExchangeCapabilitiesFailed { error: String }, - /// The user has not configured an execution endpoint - NoExecutionEndpoint, -} - -impl fmt::Display for CapellaReadiness { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - CapellaReadiness::Ready => { - write!(f, "This node appears ready for Capella.") - } - CapellaReadiness::ExchangeCapabilitiesFailed { error } => write!( - f, - "Could not exchange capabilities with the \ - execution endpoint: {}", - error - ), - CapellaReadiness::NoExecutionEndpoint => write!( - f, - "The --execution-endpoint flag is not specified, this is a \ - requirement post-merge" - ), - CapellaReadiness::V2MethodsNotSupported { error } => write!( - f, - "Execution endpoint does not support Capella methods: {}", - error - ), - } - } -} - -impl BeaconChain { - /// Returns `true` if capella epoch is set and Capella fork has occurred or will - /// occur within `CAPELLA_READINESS_PREPARATION_SECONDS` - pub fn is_time_to_prepare_for_capella(&self, current_slot: Slot) -> bool { - if let Some(capella_epoch) = self.spec.capella_fork_epoch { - let capella_slot = capella_epoch.start_slot(T::EthSpec::slots_per_epoch()); - let capella_readiness_preparation_slots = - CAPELLA_READINESS_PREPARATION_SECONDS / self.spec.seconds_per_slot; - // Return `true` if Capella has happened or is within the preparation time. - current_slot + capella_readiness_preparation_slots > capella_slot - } else { - // The Capella fork epoch has not been defined yet, no need to prepare. - false - } - } - - /// Attempts to connect to the EL and confirm that it is ready for capella. - pub async fn check_capella_readiness(&self) -> CapellaReadiness { - if let Some(el) = self.execution_layer.as_ref() { - match el - .get_engine_capabilities(Some(Duration::from_secs( - ENGINE_CAPABILITIES_REFRESH_INTERVAL, - ))) - .await - { - Err(e) => { - // The EL was either unreachable or responded with an error - CapellaReadiness::ExchangeCapabilitiesFailed { - error: format!("{:?}", e), - } - } - Ok(capabilities) => { - let mut missing_methods = String::from("Required Methods Unsupported:"); - let mut all_good = true; - if !capabilities.get_payload_v2 { - missing_methods.push(' '); - missing_methods.push_str(ENGINE_GET_PAYLOAD_V2); - all_good = false; - } - if !capabilities.forkchoice_updated_v2 { - missing_methods.push(' '); - missing_methods.push_str(ENGINE_FORKCHOICE_UPDATED_V2); - all_good = false; - } - if !capabilities.new_payload_v2 { - missing_methods.push(' '); - missing_methods.push_str(ENGINE_NEW_PAYLOAD_V2); - all_good = false; - } - - if all_good { - CapellaReadiness::Ready - } else { - CapellaReadiness::V2MethodsNotSupported { - error: missing_methods, - } - } - } - } - } else { - CapellaReadiness::NoExecutionEndpoint - } - } -} diff --git a/beacon_node/beacon_chain/src/deneb_readiness.rs b/beacon_node/beacon_chain/src/deneb_readiness.rs deleted file mode 100644 index e11070a1f4f..00000000000 --- a/beacon_node/beacon_chain/src/deneb_readiness.rs +++ /dev/null @@ -1,121 +0,0 @@ -//! Provides tools for checking if a node is ready for the Deneb upgrade. - -use crate::{BeaconChain, BeaconChainTypes}; -use execution_layer::http::{ - ENGINE_FORKCHOICE_UPDATED_V3, ENGINE_GET_PAYLOAD_V3, ENGINE_NEW_PAYLOAD_V3, -}; -use serde::{Deserialize, Serialize}; -use std::fmt; -use std::time::Duration; -use types::*; - -/// The time before the Deneb fork when we will start issuing warnings about preparation. -use super::bellatrix_readiness::SECONDS_IN_A_WEEK; -pub const DENEB_READINESS_PREPARATION_SECONDS: u64 = SECONDS_IN_A_WEEK * 2; -pub const ENGINE_CAPABILITIES_REFRESH_INTERVAL: u64 = 300; - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[serde(tag = "type")] -pub enum DenebReadiness { - /// The execution engine is deneb-enabled (as far as we can tell) - Ready, - /// We are connected to an execution engine which doesn't support the V3 engine api methods - V3MethodsNotSupported { error: String }, - /// The transition configuration with the EL failed, there might be a problem with - /// connectivity, authentication or a difference in configuration. - ExchangeCapabilitiesFailed { error: String }, - /// The user has not configured an execution endpoint - NoExecutionEndpoint, -} - -impl fmt::Display for DenebReadiness { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - DenebReadiness::Ready => { - write!(f, "This node appears ready for Deneb.") - } - DenebReadiness::ExchangeCapabilitiesFailed { error } => write!( - f, - "Could not exchange capabilities with the \ - execution endpoint: {}", - error - ), - DenebReadiness::NoExecutionEndpoint => write!( - f, - "The --execution-endpoint flag is not specified, this is a \ - requirement post-merge" - ), - DenebReadiness::V3MethodsNotSupported { error } => write!( - f, - "Execution endpoint does not support Deneb methods: {}", - error - ), - } - } -} - -impl BeaconChain { - /// Returns `true` if deneb epoch is set and Deneb fork has occurred or will - /// occur within `DENEB_READINESS_PREPARATION_SECONDS` - pub fn is_time_to_prepare_for_deneb(&self, current_slot: Slot) -> bool { - if let Some(deneb_epoch) = self.spec.deneb_fork_epoch { - let deneb_slot = deneb_epoch.start_slot(T::EthSpec::slots_per_epoch()); - let deneb_readiness_preparation_slots = - DENEB_READINESS_PREPARATION_SECONDS / self.spec.seconds_per_slot; - // Return `true` if Deneb has happened or is within the preparation time. - current_slot + deneb_readiness_preparation_slots > deneb_slot - } else { - // The Deneb fork epoch has not been defined yet, no need to prepare. - false - } - } - - /// Attempts to connect to the EL and confirm that it is ready for capella. - pub async fn check_deneb_readiness(&self) -> DenebReadiness { - if let Some(el) = self.execution_layer.as_ref() { - match el - .get_engine_capabilities(Some(Duration::from_secs( - ENGINE_CAPABILITIES_REFRESH_INTERVAL, - ))) - .await - { - Err(e) => { - // The EL was either unreachable or responded with an error - DenebReadiness::ExchangeCapabilitiesFailed { - error: format!("{:?}", e), - } - } - Ok(capabilities) => { - let mut missing_methods = String::from("Required Methods Unsupported:"); - let mut all_good = true; - if !capabilities.get_payload_v3 { - missing_methods.push(' '); - missing_methods.push_str(ENGINE_GET_PAYLOAD_V3); - all_good = false; - } - if !capabilities.forkchoice_updated_v3 { - missing_methods.push(' '); - missing_methods.push_str(ENGINE_FORKCHOICE_UPDATED_V3); - all_good = false; - } - if !capabilities.new_payload_v3 { - missing_methods.push(' '); - missing_methods.push_str(ENGINE_NEW_PAYLOAD_V3); - all_good = false; - } - - if all_good { - DenebReadiness::Ready - } else { - DenebReadiness::V3MethodsNotSupported { - error: missing_methods, - } - } - } - } - } else { - DenebReadiness::NoExecutionEndpoint - } - } -} diff --git a/beacon_node/beacon_chain/src/electra_readiness.rs b/beacon_node/beacon_chain/src/electra_readiness.rs deleted file mode 100644 index 551d43f9fd6..00000000000 --- a/beacon_node/beacon_chain/src/electra_readiness.rs +++ /dev/null @@ -1,115 +0,0 @@ -//! Provides tools for checking if a node is ready for the Electra upgrade and following merge -//! transition. - -use crate::{BeaconChain, BeaconChainTypes}; -use execution_layer::http::{ENGINE_GET_PAYLOAD_V4, ENGINE_NEW_PAYLOAD_V4}; -use serde::{Deserialize, Serialize}; -use std::fmt; -use std::time::Duration; -use types::*; - -/// The time before the Electra fork when we will start issuing warnings about preparation. -use super::bellatrix_readiness::SECONDS_IN_A_WEEK; -pub const ELECTRA_READINESS_PREPARATION_SECONDS: u64 = SECONDS_IN_A_WEEK * 2; -pub const ENGINE_CAPABILITIES_REFRESH_INTERVAL: u64 = 300; - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[serde(tag = "type")] -pub enum ElectraReadiness { - /// The execution engine is electra-enabled (as far as we can tell) - Ready, - /// We are connected to an execution engine which doesn't support the V4 engine api methods - V4MethodsNotSupported { error: String }, - /// The transition configuration with the EL failed, there might be a problem with - /// connectivity, authentication or a difference in configuration. - ExchangeCapabilitiesFailed { error: String }, - /// The user has not configured an execution endpoint - NoExecutionEndpoint, -} - -impl fmt::Display for ElectraReadiness { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - ElectraReadiness::Ready => { - write!(f, "This node appears ready for Electra.") - } - ElectraReadiness::ExchangeCapabilitiesFailed { error } => write!( - f, - "Could not exchange capabilities with the \ - execution endpoint: {}", - error - ), - ElectraReadiness::NoExecutionEndpoint => write!( - f, - "The --execution-endpoint flag is not specified, this is a \ - requirement post-merge" - ), - ElectraReadiness::V4MethodsNotSupported { error } => write!( - f, - "Execution endpoint does not support Electra methods: {}", - error - ), - } - } -} - -impl BeaconChain { - /// Returns `true` if electra epoch is set and Electra fork has occurred or will - /// occur within `ELECTRA_READINESS_PREPARATION_SECONDS` - pub fn is_time_to_prepare_for_electra(&self, current_slot: Slot) -> bool { - if let Some(electra_epoch) = self.spec.electra_fork_epoch { - let electra_slot = electra_epoch.start_slot(T::EthSpec::slots_per_epoch()); - let electra_readiness_preparation_slots = - ELECTRA_READINESS_PREPARATION_SECONDS / self.spec.seconds_per_slot; - // Return `true` if Electra has happened or is within the preparation time. - current_slot + electra_readiness_preparation_slots > electra_slot - } else { - // The Electra fork epoch has not been defined yet, no need to prepare. - false - } - } - - /// Attempts to connect to the EL and confirm that it is ready for electra. - pub async fn check_electra_readiness(&self) -> ElectraReadiness { - if let Some(el) = self.execution_layer.as_ref() { - match el - .get_engine_capabilities(Some(Duration::from_secs( - ENGINE_CAPABILITIES_REFRESH_INTERVAL, - ))) - .await - { - Err(e) => { - // The EL was either unreachable or responded with an error - ElectraReadiness::ExchangeCapabilitiesFailed { - error: format!("{:?}", e), - } - } - Ok(capabilities) => { - let mut missing_methods = String::from("Required Methods Unsupported:"); - let mut all_good = true; - if !capabilities.get_payload_v4 { - missing_methods.push(' '); - missing_methods.push_str(ENGINE_GET_PAYLOAD_V4); - all_good = false; - } - if !capabilities.new_payload_v4 { - missing_methods.push(' '); - missing_methods.push_str(ENGINE_NEW_PAYLOAD_V4); - all_good = false; - } - - if all_good { - ElectraReadiness::Ready - } else { - ElectraReadiness::V4MethodsNotSupported { - error: missing_methods, - } - } - } - } - } else { - ElectraReadiness::NoExecutionEndpoint - } - } -} diff --git a/beacon_node/beacon_chain/src/fulu_readiness.rs b/beacon_node/beacon_chain/src/fulu_readiness.rs deleted file mode 100644 index 71494623f83..00000000000 --- a/beacon_node/beacon_chain/src/fulu_readiness.rs +++ /dev/null @@ -1,114 +0,0 @@ -//! Provides tools for checking if a node is ready for the Fulu upgrade. - -use crate::{BeaconChain, BeaconChainTypes}; -use execution_layer::http::{ENGINE_GET_PAYLOAD_V5, ENGINE_NEW_PAYLOAD_V5}; -use serde::{Deserialize, Serialize}; -use std::fmt; -use std::time::Duration; -use types::*; - -/// The time before the Fulu fork when we will start issuing warnings about preparation. -use super::bellatrix_readiness::SECONDS_IN_A_WEEK; -pub const FULU_READINESS_PREPARATION_SECONDS: u64 = SECONDS_IN_A_WEEK * 2; -pub const ENGINE_CAPABILITIES_REFRESH_INTERVAL: u64 = 300; - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[serde(tag = "type")] -pub enum FuluReadiness { - /// The execution engine is fulu-enabled (as far as we can tell) - Ready, - /// We are connected to an execution engine which doesn't support the V5 engine api methods - V5MethodsNotSupported { error: String }, - /// The transition configuration with the EL failed, there might be a problem with - /// connectivity, authentication or a difference in configuration. - ExchangeCapabilitiesFailed { error: String }, - /// The user has not configured an execution endpoint - NoExecutionEndpoint, -} - -impl fmt::Display for FuluReadiness { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - FuluReadiness::Ready => { - write!(f, "This node appears ready for Fulu.") - } - FuluReadiness::ExchangeCapabilitiesFailed { error } => write!( - f, - "Could not exchange capabilities with the \ - execution endpoint: {}", - error - ), - FuluReadiness::NoExecutionEndpoint => write!( - f, - "The --execution-endpoint flag is not specified, this is a \ - requirement post-merge" - ), - FuluReadiness::V5MethodsNotSupported { error } => write!( - f, - "Execution endpoint does not support Fulu methods: {}", - error - ), - } - } -} - -impl BeaconChain { - /// Returns `true` if fulu epoch is set and Fulu fork has occurred or will - /// occur within `FULU_READINESS_PREPARATION_SECONDS` - pub fn is_time_to_prepare_for_fulu(&self, current_slot: Slot) -> bool { - if let Some(fulu_epoch) = self.spec.fulu_fork_epoch { - let fulu_slot = fulu_epoch.start_slot(T::EthSpec::slots_per_epoch()); - let fulu_readiness_preparation_slots = - FULU_READINESS_PREPARATION_SECONDS / self.spec.seconds_per_slot; - // Return `true` if Fulu has happened or is within the preparation time. - current_slot + fulu_readiness_preparation_slots > fulu_slot - } else { - // The Fulu fork epoch has not been defined yet, no need to prepare. - false - } - } - - /// Attempts to connect to the EL and confirm that it is ready for fulu. - pub async fn check_fulu_readiness(&self) -> FuluReadiness { - if let Some(el) = self.execution_layer.as_ref() { - match el - .get_engine_capabilities(Some(Duration::from_secs( - ENGINE_CAPABILITIES_REFRESH_INTERVAL, - ))) - .await - { - Err(e) => { - // The EL was either unreachable or responded with an error - FuluReadiness::ExchangeCapabilitiesFailed { - error: format!("{:?}", e), - } - } - Ok(capabilities) => { - let mut missing_methods = String::from("Required Methods Unsupported:"); - let mut all_good = true; - if !capabilities.get_payload_v5 { - missing_methods.push(' '); - missing_methods.push_str(ENGINE_GET_PAYLOAD_V5); - all_good = false; - } - if !capabilities.new_payload_v5 { - missing_methods.push(' '); - missing_methods.push_str(ENGINE_NEW_PAYLOAD_V5); - all_good = false; - } - - if all_good { - FuluReadiness::Ready - } else { - FuluReadiness::V5MethodsNotSupported { - error: missing_methods, - } - } - } - } - } else { - FuluReadiness::NoExecutionEndpoint - } - } -} diff --git a/beacon_node/beacon_chain/src/lib.rs b/beacon_node/beacon_chain/src/lib.rs index 4783945eb15..a2149fea136 100644 --- a/beacon_node/beacon_chain/src/lib.rs +++ b/beacon_node/beacon_chain/src/lib.rs @@ -16,13 +16,10 @@ mod block_verification; pub mod block_verification_types; pub mod builder; pub mod canonical_head; -pub mod capella_readiness; pub mod chain_config; pub mod data_availability_checker; pub mod data_column_verification; -pub mod deneb_readiness; mod early_attester_cache; -pub mod electra_readiness; mod errors; pub mod eth1_chain; mod eth1_finalization_cache; @@ -31,7 +28,6 @@ pub mod execution_payload; pub mod fetch_blobs; pub mod fork_choice_signal; pub mod fork_revert; -pub mod fulu_readiness; pub mod graffiti_calculator; mod head_tracker; pub mod historical_blocks; diff --git a/beacon_node/client/src/notifier.rs b/beacon_node/client/src/notifier.rs index 0c3b1578d6e..79d6165de31 100644 --- a/beacon_node/client/src/notifier.rs +++ b/beacon_node/client/src/notifier.rs @@ -1,12 +1,18 @@ use crate::metrics; use beacon_chain::{ - bellatrix_readiness::{BellatrixReadiness, GenesisExecutionPayloadStatus, MergeConfig}, - capella_readiness::CapellaReadiness, - deneb_readiness::DenebReadiness, - electra_readiness::ElectraReadiness, - fulu_readiness::FuluReadiness, + bellatrix_readiness::{ + BellatrixReadiness, GenesisExecutionPayloadStatus, MergeConfig, SECONDS_IN_A_WEEK, + }, BeaconChain, BeaconChainTypes, ExecutionStatus, }; +use execution_layer::{ + http::{ + ENGINE_FORKCHOICE_UPDATED_V2, ENGINE_FORKCHOICE_UPDATED_V3, ENGINE_GET_PAYLOAD_V2, + ENGINE_GET_PAYLOAD_V3, ENGINE_GET_PAYLOAD_V4, ENGINE_GET_PAYLOAD_V5, ENGINE_NEW_PAYLOAD_V2, + ENGINE_NEW_PAYLOAD_V3, ENGINE_NEW_PAYLOAD_V4, ENGINE_NEW_PAYLOAD_V5, + }, + EngineCapabilities, +}; use lighthouse_network::{types::SyncState, NetworkGlobals}; use slog::{crit, debug, error, info, warn, Logger}; use slot_clock::SlotClock; @@ -29,6 +35,9 @@ const SPEEDO_OBSERVATIONS: usize = 4; /// The number of slots between logs that give detail about backfill process. const BACKFILL_LOG_INTERVAL: u64 = 5; +pub const FORK_READINESS_PREPARATION_SECONDS: u64 = SECONDS_IN_A_WEEK * 2; +pub const ENGINE_CAPABILITIES_REFRESH_INTERVAL: u64 = 300; + /// Spawns a notifier service which periodically logs information about the node. pub fn spawn_notifier( executor: task_executor::TaskExecutor, @@ -63,7 +72,7 @@ pub fn spawn_notifier( ); eth1_logging(&beacon_chain, &log); bellatrix_readiness_logging(Slot::new(0), &beacon_chain, &log).await; - capella_readiness_logging(Slot::new(0), &beacon_chain, &log).await; + post_capella_readiness_logging(Slot::new(0), &beacon_chain, &log).await; genesis_execution_payload_logging(&beacon_chain, &log).await; sleep(slot_duration).await; } @@ -313,10 +322,7 @@ pub fn spawn_notifier( eth1_logging(&beacon_chain, &log); bellatrix_readiness_logging(current_slot, &beacon_chain, &log).await; - capella_readiness_logging(current_slot, &beacon_chain, &log).await; - deneb_readiness_logging(current_slot, &beacon_chain, &log).await; - electra_readiness_logging(current_slot, &beacon_chain, &log).await; - fulu_readiness_logging(current_slot, &beacon_chain, &log).await; + post_capella_readiness_logging(current_slot, &beacon_chain, &log).await; } }; @@ -351,19 +357,6 @@ async fn bellatrix_readiness_logging( return; } - if merge_completed && !has_execution_layer { - // Logging of the EE being offline is handled in the other readiness logging functions. - if !beacon_chain.is_time_to_prepare_for_capella(current_slot) { - error!( - log, - "Execution endpoint required"; - "info" => "you need an execution engine to validate blocks, see: \ - https://lighthouse-book.sigmaprime.io/merge-migration.html" - ); - } - return; - } - match beacon_chain.check_bellatrix_readiness(current_slot).await { BellatrixReadiness::Ready { config, @@ -417,231 +410,139 @@ async fn bellatrix_readiness_logging( } /// Provides some helpful logging to users to indicate if their node is ready for Capella -async fn capella_readiness_logging( +async fn post_capella_readiness_logging( current_slot: Slot, beacon_chain: &BeaconChain, log: &Logger, ) { - let capella_completed = beacon_chain - .canonical_head - .cached_head() - .snapshot - .beacon_state - .fork_name_unchecked() - .capella_enabled(); - - let has_execution_layer = beacon_chain.execution_layer.is_some(); - - if capella_completed && has_execution_layer - || !beacon_chain.is_time_to_prepare_for_capella(current_slot) - { - return; - } + if let Some(fork) = find_next_fork_to_prepare(current_slot, beacon_chain) { + let readiness = if let Some(el) = beacon_chain.execution_layer.as_ref() { + match el + .get_engine_capabilities(Some(Duration::from_secs( + ENGINE_CAPABILITIES_REFRESH_INTERVAL, + ))) + .await + { + Err(e) => Err(format!("Exchange capabilities failed: {e:?}")), + Ok(capabilities) => { + let missing_methods = methods_required_for_fork(fork, capabilities); + if missing_methods.is_empty() { + Ok(()) + } else { + Err(format!("Missing required methods: {missing_methods:?}")) + } + } + } + } else { + Err("No execution endpoint".to_string()) + }; - if capella_completed && !has_execution_layer { - // Logging of the EE being offline is handled in the other readiness logging functions. - if !beacon_chain.is_time_to_prepare_for_deneb(current_slot) { - error!( + if let Err(readiness) = readiness { + warn!( log, - "Execution endpoint required"; - "info" => "you need a Capella enabled execution engine to validate blocks, see: \ - https://lighthouse-book.sigmaprime.io/merge-migration.html" + "Not ready for {}", fork; + "info" => %readiness, ); - } - return; - } - - match beacon_chain.check_capella_readiness().await { - CapellaReadiness::Ready => { + } else { info!( log, - "Ready for Capella"; - "info" => "ensure the execution endpoint is updated to the latest Capella/Shanghai release" - ) - } - readiness @ CapellaReadiness::ExchangeCapabilitiesFailed { error: _ } => { - error!( - log, - "Not ready for Capella"; - "hint" => "the execution endpoint may be offline", - "info" => %readiness, + "Ready for {}", fork; + "info" => "ensure the execution endpoint is updated to the latest release" ) } - readiness => warn!( - log, - "Not ready for Capella"; - "hint" => "try updating the execution endpoint", - "info" => %readiness, - ), } } -/// Provides some helpful logging to users to indicate if their node is ready for Deneb -async fn deneb_readiness_logging( +fn find_next_fork_to_prepare( current_slot: Slot, beacon_chain: &BeaconChain, - log: &Logger, -) { - let deneb_completed = beacon_chain +) -> Option { + let head_fork = beacon_chain .canonical_head .cached_head() .snapshot .beacon_state - .fork_name_unchecked() - .deneb_enabled(); + .fork_name_unchecked(); - let has_execution_layer = beacon_chain.execution_layer.is_some(); - - if deneb_completed && has_execution_layer - || !beacon_chain.is_time_to_prepare_for_deneb(current_slot) + // Iterate forks from latest to oldest + for (fork, fork_epoch) in ForkName::list_all_fork_epochs(&beacon_chain.spec) + .iter() + .rev() { - return; - } - - if deneb_completed && !has_execution_layer { - error!( - log, - "Execution endpoint required"; - "info" => "you need a Deneb enabled execution engine to validate blocks." - ); - return; - } - - match beacon_chain.check_deneb_readiness().await { - DenebReadiness::Ready => { - info!( - log, - "Ready for Deneb"; - "info" => "ensure the execution endpoint is updated to the latest Deneb/Cancun release" - ) + // This readiness only handles capella and post fork + if *fork <= ForkName::Bellatrix { + break; } - readiness @ DenebReadiness::ExchangeCapabilitiesFailed { error: _ } => { - error!( - log, - "Not ready for Deneb"; - "hint" => "the execution endpoint may be offline", - "info" => %readiness, - ) - } - readiness => warn!( - log, - "Not ready for Deneb"; - "hint" => "try updating the execution endpoint", - "info" => %readiness, - ), - } -} -/// Provides some helpful logging to users to indicate if their node is ready for Electra. -async fn electra_readiness_logging( - current_slot: Slot, - beacon_chain: &BeaconChain, - log: &Logger, -) { - let electra_completed = beacon_chain - .canonical_head - .cached_head() - .snapshot - .beacon_state - .fork_name_unchecked() - .electra_enabled(); - let has_execution_layer = beacon_chain.execution_layer.is_some(); + // head state has already activated this fork + if head_fork >= *fork { + break; + } - if electra_completed && has_execution_layer - || !beacon_chain.is_time_to_prepare_for_electra(current_slot) - { - return; + // Find the first fork that is scheduled and close to happen + if let Some(fork_epoch) = fork_epoch { + let fork_slot = fork_epoch.start_slot(T::EthSpec::slots_per_epoch()); + let preparation_slots = + FORK_READINESS_PREPARATION_SECONDS / beacon_chain.spec.seconds_per_slot; + let in_fork_preparation_period = current_slot + preparation_slots > fork_slot; + if in_fork_preparation_period { + return Some(*fork); + } + } } - if electra_completed && !has_execution_layer { - // When adding a new fork, add a check for the next fork readiness here. - error!( - log, - "Execution endpoint required"; - "info" => "you need a Electra enabled execution engine to validate blocks." - ); - return; - } + None +} - match beacon_chain.check_electra_readiness().await { - ElectraReadiness::Ready => { - info!( - log, - "Ready for Electra"; - "info" => "ensure the execution endpoint is updated to the latest Electra/Prague release" - ) +fn methods_required_for_fork( + fork: ForkName, + capabilities: EngineCapabilities, +) -> Vec<&'static str> { + let mut missing_methods = vec![]; + match fork { + ForkName::Base | ForkName::Altair | ForkName::Bellatrix => { + unreachable!() } - readiness @ ElectraReadiness::ExchangeCapabilitiesFailed { error: _ } => { - error!( - log, - "Not ready for Electra"; - "hint" => "the execution endpoint may be offline", - "info" => %readiness, - ) + ForkName::Capella => { + if !capabilities.get_payload_v2 { + missing_methods.push(ENGINE_GET_PAYLOAD_V2); + } + if !capabilities.forkchoice_updated_v2 { + missing_methods.push(ENGINE_FORKCHOICE_UPDATED_V2); + } + if !capabilities.new_payload_v2 { + missing_methods.push(ENGINE_NEW_PAYLOAD_V2); + } } - readiness => warn!( - log, - "Not ready for Electra"; - "hint" => "try updating the execution endpoint", - "info" => %readiness, - ), - } -} - -/// Provides some helpful logging to users to indicate if their node is ready for Fulu. -async fn fulu_readiness_logging( - current_slot: Slot, - beacon_chain: &BeaconChain, - log: &Logger, -) { - let fulu_completed = beacon_chain - .canonical_head - .cached_head() - .snapshot - .beacon_state - .fork_name_unchecked() - .fulu_enabled(); - - let has_execution_layer = beacon_chain.execution_layer.is_some(); - - if fulu_completed && has_execution_layer - || !beacon_chain.is_time_to_prepare_for_fulu(current_slot) - { - return; - } - - if fulu_completed && !has_execution_layer { - error!( - log, - "Execution endpoint required"; - "info" => "you need a Fulu enabled execution engine to validate blocks." - ); - return; - } - - match beacon_chain.check_fulu_readiness().await { - FuluReadiness::Ready => { - info!( - log, - "Ready for Fulu"; - "info" => "ensure the execution endpoint is updated to the latest Fulu release" - ) + ForkName::Deneb => { + if !capabilities.get_payload_v3 { + missing_methods.push(ENGINE_GET_PAYLOAD_V3); + } + if !capabilities.forkchoice_updated_v3 { + missing_methods.push(ENGINE_FORKCHOICE_UPDATED_V3); + } + if !capabilities.new_payload_v3 { + missing_methods.push(ENGINE_NEW_PAYLOAD_V3); + } } - readiness @ FuluReadiness::ExchangeCapabilitiesFailed { error: _ } => { - error!( - log, - "Not ready for Fulu"; - "hint" => "the execution endpoint may be offline", - "info" => %readiness, - ) + ForkName::Electra => { + if !capabilities.get_payload_v4 { + missing_methods.push(ENGINE_GET_PAYLOAD_V4); + } + if !capabilities.new_payload_v4 { + missing_methods.push(ENGINE_NEW_PAYLOAD_V4); + } + } + ForkName::Fulu => { + if !capabilities.get_payload_v5 { + missing_methods.push(ENGINE_GET_PAYLOAD_V5); + } + if !capabilities.new_payload_v5 { + missing_methods.push(ENGINE_NEW_PAYLOAD_V5); + } } - readiness => warn!( - log, - "Not ready for Fulu"; - "hint" => "try updating the execution endpoint", - "info" => %readiness, - ), } + missing_methods } async fn genesis_execution_payload_logging( From af49dc8c0fbd65abb10474c426f52b7df3945dea Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Tue, 28 Jan 2025 16:34:14 -0300 Subject: [PATCH 2/2] Rename post_bellatrix_readiness_logging --- beacon_node/client/src/notifier.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/beacon_node/client/src/notifier.rs b/beacon_node/client/src/notifier.rs index 79d6165de31..03cfa9bdff2 100644 --- a/beacon_node/client/src/notifier.rs +++ b/beacon_node/client/src/notifier.rs @@ -72,7 +72,7 @@ pub fn spawn_notifier( ); eth1_logging(&beacon_chain, &log); bellatrix_readiness_logging(Slot::new(0), &beacon_chain, &log).await; - post_capella_readiness_logging(Slot::new(0), &beacon_chain, &log).await; + post_bellatrix_readiness_logging(Slot::new(0), &beacon_chain, &log).await; genesis_execution_payload_logging(&beacon_chain, &log).await; sleep(slot_duration).await; } @@ -322,7 +322,7 @@ pub fn spawn_notifier( eth1_logging(&beacon_chain, &log); bellatrix_readiness_logging(current_slot, &beacon_chain, &log).await; - post_capella_readiness_logging(current_slot, &beacon_chain, &log).await; + post_bellatrix_readiness_logging(current_slot, &beacon_chain, &log).await; } }; @@ -410,7 +410,7 @@ async fn bellatrix_readiness_logging( } /// Provides some helpful logging to users to indicate if their node is ready for Capella -async fn post_capella_readiness_logging( +async fn post_bellatrix_readiness_logging( current_slot: Slot, beacon_chain: &BeaconChain, log: &Logger,