diff --git a/Cargo.lock b/Cargo.lock index 3702b95485..a6b5f56374 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7073,6 +7073,7 @@ dependencies = [ "itertools", "lazy_static", "log", + "maplit", "parking_lot 0.12.1", "rand 0.8.5", "rand_xorshift", diff --git a/beacon_node/beacon_chain/src/test_utils.rs b/beacon_node/beacon_chain/src/test_utils.rs index 411bd7b1fd..9b62590703 100644 --- a/beacon_node/beacon_chain/src/test_utils.rs +++ b/beacon_node/beacon_chain/src/test_utils.rs @@ -132,8 +132,7 @@ pub fn test_spec() -> ChainSpec { FORK_NAME_ENV_VAR, e ) }); - let fork = ForkName::from_str(fork_name.as_str()) - .unwrap_or_else(|()| panic!("unknown FORK_NAME: {}", fork_name)); + let fork = ForkName::from_str(fork_name.as_str()).unwrap(); fork.make_genesis_spec(E::default_spec()) } else { E::default_spec() diff --git a/beacon_node/http_api/src/lib.rs b/beacon_node/http_api/src/lib.rs index ec34dd0663..bcd8788465 100644 --- a/beacon_node/http_api/src/lib.rs +++ b/beacon_node/http_api/src/lib.rs @@ -104,9 +104,9 @@ pub struct Config { pub listen_addr: IpAddr, pub listen_port: u16, pub allow_origin: Option, - pub serve_legacy_spec: bool, pub tls_config: Option, pub allow_sync_stalled: bool, + pub spec_fork_name: Option, } impl Default for Config { @@ -116,9 +116,9 @@ impl Default for Config { listen_addr: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), listen_port: 5052, allow_origin: None, - serve_legacy_spec: true, tls_config: None, allow_sync_stalled: false, + spec_fork_name: None, } } } @@ -1534,18 +1534,15 @@ pub fn serve( }); // GET config/spec - let serve_legacy_spec = ctx.config.serve_legacy_spec; + let spec_fork_name = ctx.config.spec_fork_name; let get_config_spec = config_path .and(warp::path("spec")) .and(warp::path::end()) .and(chain_filter.clone()) .and_then(move |chain: Arc>| { blocking_json_task(move || { - let mut config_and_preset = - ConfigAndPreset::from_chain_spec::(&chain.spec); - if serve_legacy_spec { - config_and_preset.make_backwards_compat(&chain.spec); - } + let config_and_preset = + ConfigAndPreset::from_chain_spec::(&chain.spec, spec_fork_name); Ok(api_types::GenericResponse::from(config_and_preset)) }) }); diff --git a/beacon_node/http_api/tests/common.rs b/beacon_node/http_api/tests/common.rs index 8f9856991f..1dd7aea923 100644 --- a/beacon_node/http_api/tests/common.rs +++ b/beacon_node/http_api/tests/common.rs @@ -141,9 +141,9 @@ pub async fn create_api_server_on_port( listen_addr: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), listen_port: port, allow_origin: None, - serve_legacy_spec: true, tls_config: None, allow_sync_stalled: false, + spec_fork_name: None, }, chain: Some(chain.clone()), network_tx: Some(network_tx), diff --git a/beacon_node/http_api/tests/tests.rs b/beacon_node/http_api/tests/tests.rs index fa41102292..bd25450a47 100644 --- a/beacon_node/http_api/tests/tests.rs +++ b/beacon_node/http_api/tests/tests.rs @@ -1253,10 +1253,13 @@ impl ApiTester { } pub async fn test_get_config_spec(self) -> Self { - let result = self.client.get_config_spec().await.unwrap().data; - - let mut expected = ConfigAndPreset::from_chain_spec::(&self.chain.spec); - expected.make_backwards_compat(&self.chain.spec); + let result = self + .client + .get_config_spec::() + .await + .map(|res| ConfigAndPreset::Bellatrix(res.data)) + .unwrap(); + let expected = ConfigAndPreset::from_chain_spec::(&self.chain.spec, None); assert_eq!(result, expected); diff --git a/beacon_node/src/cli.rs b/beacon_node/src/cli.rs index 3515263878..edf79ad34f 100644 --- a/beacon_node/src/cli.rs +++ b/beacon_node/src/cli.rs @@ -229,8 +229,14 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> { .arg( Arg::with_name("http-disable-legacy-spec") .long("http-disable-legacy-spec") - .help("Disable serving of legacy data on the /config/spec endpoint. May be \ - disabled by default in a future release.") + .hidden(true) + ) + .arg( + Arg::with_name("http-spec-fork") + .long("http-spec-fork") + .help("Serve the spec for a specific hard fork on /eth/v1/config/spec. It should \ + not be necessary to set this flag.") + .takes_value(true) ) .arg( Arg::with_name("http-enable-tls") diff --git a/beacon_node/src/config.rs b/beacon_node/src/config.rs index 6daee50de0..35d566d76e 100644 --- a/beacon_node/src/config.rs +++ b/beacon_node/src/config.rs @@ -116,7 +116,14 @@ pub fn get_config( } if cli_args.is_present("http-disable-legacy-spec") { - client_config.http_api.serve_legacy_spec = false; + warn!( + log, + "The flag --http-disable-legacy-spec is deprecated and will be removed" + ); + } + + if let Some(fork_name) = clap_utils::parse_optional(cli_args, "http-spec-fork")? { + client_config.http_api.spec_fork_name = Some(fork_name); } if cli_args.is_present("http-enable-tls") { diff --git a/common/eth2/src/lib.rs b/common/eth2/src/lib.rs index 21608ba6dd..6317523fee 100644 --- a/common/eth2/src/lib.rs +++ b/common/eth2/src/lib.rs @@ -977,7 +977,9 @@ impl BeaconNodeHttpClient { } /// `GET config/spec` - pub async fn get_config_spec(&self) -> Result, Error> { + pub async fn get_config_spec( + &self, + ) -> Result, Error> { let mut path = self.eth_path(V1)?; path.path_segments_mut() diff --git a/common/eth2/src/lighthouse_vc/http_client.rs b/common/eth2/src/lighthouse_vc/http_client.rs index abed4fe5e7..5f83e81aa0 100644 --- a/common/eth2/src/lighthouse_vc/http_client.rs +++ b/common/eth2/src/lighthouse_vc/http_client.rs @@ -354,7 +354,9 @@ impl ValidatorClientHttpClient { } /// `GET lighthouse/spec` - pub async fn get_lighthouse_spec(&self) -> Result, Error> { + pub async fn get_lighthouse_spec( + &self, + ) -> Result, Error> { let mut path = self.server.full.clone(); path.path_segments_mut() diff --git a/common/eth2/src/mixin.rs b/common/eth2/src/mixin.rs index 1de26961e6..a33cf8a40c 100644 --- a/common/eth2/src/mixin.rs +++ b/common/eth2/src/mixin.rs @@ -21,17 +21,17 @@ impl ResponseOptional for Result { /// Trait for extracting the fork name from the headers of a response. pub trait ResponseForkName { #[allow(clippy::result_unit_err)] - fn fork_name_from_header(&self) -> Result, ()>; + fn fork_name_from_header(&self) -> Result, String>; } impl ResponseForkName for Response { - fn fork_name_from_header(&self) -> Result, ()> { + fn fork_name_from_header(&self) -> Result, String> { self.headers() .get(CONSENSUS_VERSION_HEADER) .map(|fork_name| { fork_name .to_str() - .map_err(|_| ()) + .map_err(|e| e.to_string()) .and_then(ForkName::from_str) }) .transpose() diff --git a/consensus/types/Cargo.toml b/consensus/types/Cargo.toml index c3e454fdfc..68fdbf7990 100644 --- a/consensus/types/Cargo.toml +++ b/consensus/types/Cargo.toml @@ -47,6 +47,7 @@ superstruct = "0.5.0" serde_json = "1.0.74" smallvec = "1.8.0" serde_with = "1.13.0" +maplit = "1.0.2" [dev-dependencies] criterion = "0.3.3" diff --git a/consensus/types/src/chain_spec.rs b/consensus/types/src/chain_spec.rs index 3668d0524c..8d56ce2da9 100644 --- a/consensus/types/src/chain_spec.rs +++ b/consensus/types/src/chain_spec.rs @@ -803,6 +803,10 @@ impl Default for ChainSpec { } /// Exact implementation of the *config* object from the Ethereum spec (YAML/JSON). +/// +/// Fields relevant to hard forks after Altair should be optional so that we can continue +/// to parse Altair configs. This default approach turns out to be much simpler than trying to +/// make `Config` a superstruct because of the hassle of deserializing an untagged enum. #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] #[serde(rename_all = "UPPERCASE")] pub struct Config { @@ -813,17 +817,13 @@ pub struct Config { #[serde(default)] pub preset_base: String, - // TODO(merge): remove this default #[serde(default = "default_terminal_total_difficulty")] #[serde(with = "eth2_serde_utils::quoted_u256")] pub terminal_total_difficulty: Uint256, - // TODO(merge): remove this default #[serde(default = "default_terminal_block_hash")] pub terminal_block_hash: ExecutionBlockHash, - // TODO(merge): remove this default #[serde(default = "default_terminal_block_hash_activation_epoch")] pub terminal_block_hash_activation_epoch: Epoch, - // TODO(merge): remove this default #[serde(default = "default_safe_slots_to_import_optimistically")] #[serde(with = "eth2_serde_utils::quoted_u64")] pub safe_slots_to_import_optimistically: u64, @@ -843,12 +843,10 @@ pub struct Config { #[serde(deserialize_with = "deserialize_fork_epoch")] pub altair_fork_epoch: Option>, - // TODO(merge): remove this default #[serde(default = "default_bellatrix_fork_version")] #[serde(with = "eth2_serde_utils::bytes_4_hex")] bellatrix_fork_version: [u8; 4], - // TODO(merge): remove this default - #[serde(default = "default_bellatrix_fork_epoch")] + #[serde(default)] #[serde(serialize_with = "serialize_fork_epoch")] #[serde(deserialize_with = "deserialize_fork_epoch")] pub bellatrix_fork_epoch: Option>, @@ -890,10 +888,6 @@ fn default_bellatrix_fork_version() -> [u8; 4] { [0xff, 0xff, 0xff, 0xff] } -fn default_bellatrix_fork_epoch() -> Option> { - None -} - /// Placeholder value: 2^256-2^10 (115792089237316195423570985008687907853269984665640564039457584007913129638912). /// /// Taken from https://github.com/ethereum/consensus-specs/blob/d5e4828aecafaf1c57ef67a5f23c4ae7b08c5137/configs/mainnet.yaml#L15-L16 @@ -1335,10 +1329,7 @@ mod yaml_tests { default_safe_slots_to_import_optimistically() ); - assert_eq!( - chain_spec.bellatrix_fork_epoch, - default_bellatrix_fork_epoch() - ); + assert_eq!(chain_spec.bellatrix_fork_epoch, None); assert_eq!( chain_spec.bellatrix_fork_version, diff --git a/consensus/types/src/config_and_preset.rs b/consensus/types/src/config_and_preset.rs index 8b3a753bd5..e624afe2db 100644 --- a/consensus/types/src/config_and_preset.rs +++ b/consensus/types/src/config_and_preset.rs @@ -1,12 +1,21 @@ -use crate::{AltairPreset, BasePreset, BellatrixPreset, ChainSpec, Config, EthSpec}; +use crate::{ + consts::altair, AltairPreset, BasePreset, BellatrixPreset, ChainSpec, Config, EthSpec, ForkName, +}; +use maplit::hashmap; use serde_derive::{Deserialize, Serialize}; use serde_json::Value; use std::collections::HashMap; +use superstruct::superstruct; /// Fusion of a runtime-config with the compile-time preset values. /// /// Mostly useful for the API. +#[superstruct( + variants(Altair, Bellatrix), + variant_attributes(derive(Serialize, Deserialize, Debug, PartialEq, Clone)) +)] #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +#[serde(untagged)] pub struct ConfigAndPreset { #[serde(flatten)] pub config: Config, @@ -15,80 +24,75 @@ pub struct ConfigAndPreset { pub base_preset: BasePreset, #[serde(flatten)] pub altair_preset: AltairPreset, - // TODO(merge): re-enable - // #[serde(flatten)] - // pub bellatrix_preset: BellatrixPreset, + #[superstruct(only(Bellatrix))] + #[serde(flatten)] + pub bellatrix_preset: BellatrixPreset, /// The `extra_fields` map allows us to gracefully decode fields intended for future hard forks. #[serde(flatten)] pub extra_fields: HashMap, } impl ConfigAndPreset { - pub fn from_chain_spec(spec: &ChainSpec) -> Self { + pub fn from_chain_spec(spec: &ChainSpec, fork_name: Option) -> Self { let config = Config::from_chain_spec::(spec); let base_preset = BasePreset::from_chain_spec::(spec); let altair_preset = AltairPreset::from_chain_spec::(spec); - // TODO(merge): re-enable - let _bellatrix_preset = BellatrixPreset::from_chain_spec::(spec); - let extra_fields = HashMap::new(); + let extra_fields = get_extra_fields(spec); - Self { - config, - base_preset, - altair_preset, - extra_fields, + if spec.bellatrix_fork_epoch.is_some() + || fork_name == None + || fork_name == Some(ForkName::Merge) + { + let bellatrix_preset = BellatrixPreset::from_chain_spec::(spec); + + ConfigAndPreset::Bellatrix(ConfigAndPresetBellatrix { + config, + base_preset, + altair_preset, + bellatrix_preset, + extra_fields, + }) + } else { + ConfigAndPreset::Altair(ConfigAndPresetAltair { + config, + base_preset, + altair_preset, + extra_fields, + }) } } +} - /// Add fields that were previously part of the config but are now constants. - pub fn make_backwards_compat(&mut self, spec: &ChainSpec) { - let hex_string = |value: &[u8]| format!("0x{}", hex::encode(&value)); - let u32_hex = |v: u32| hex_string(&v.to_le_bytes()); - let u8_hex = |v: u8| hex_string(&v.to_le_bytes()); - let fields = vec![ - ( - "bls_withdrawal_prefix", - u8_hex(spec.bls_withdrawal_prefix_byte), - ), - ( - "domain_beacon_proposer", - u32_hex(spec.domain_beacon_proposer), - ), - ( - "domain_beacon_attester", - u32_hex(spec.domain_beacon_attester), - ), - ("domain_randao", u32_hex(spec.domain_randao)), - ("domain_deposit", u32_hex(spec.domain_deposit)), - ("domain_voluntary_exit", u32_hex(spec.domain_voluntary_exit)), - ( - "domain_selection_proof", - u32_hex(spec.domain_selection_proof), - ), - ( - "domain_aggregate_and_proof", - u32_hex(spec.domain_aggregate_and_proof), - ), - ( - "domain_application_mask", - u32_hex(spec.domain_application_mask), - ), - ( - "target_aggregators_per_committee", - spec.target_aggregators_per_committee.to_string(), - ), - ( - "random_subnets_per_validator", - spec.random_subnets_per_validator.to_string(), - ), - ( - "epochs_per_random_subnet_subscription", - spec.epochs_per_random_subnet_subscription.to_string(), - ), - ]; - for (key, value) in fields { - self.extra_fields.insert(key.to_uppercase(), value.into()); - } +/// Get a hashmap of constants to add to the `PresetAndConfig` +pub fn get_extra_fields(spec: &ChainSpec) -> HashMap { + let hex_string = |value: &[u8]| format!("0x{}", hex::encode(&value)).into(); + let u32_hex = |v: u32| hex_string(&v.to_le_bytes()); + let u8_hex = |v: u8| hex_string(&v.to_le_bytes()); + hashmap! { + "bls_withdrawal_prefix".to_uppercase() => u8_hex(spec.bls_withdrawal_prefix_byte), + "domain_beacon_proposer".to_uppercase() => u32_hex(spec.domain_beacon_proposer), + "domain_beacon_attester".to_uppercase() => u32_hex(spec.domain_beacon_attester), + "domain_randao".to_uppercase()=> u32_hex(spec.domain_randao), + "domain_deposit".to_uppercase()=> u32_hex(spec.domain_deposit), + "domain_voluntary_exit".to_uppercase() => u32_hex(spec.domain_voluntary_exit), + "domain_selection_proof".to_uppercase() => u32_hex(spec.domain_selection_proof), + "domain_aggregate_and_proof".to_uppercase() => u32_hex(spec.domain_aggregate_and_proof), + "domain_application_mask".to_uppercase()=> u32_hex(spec.domain_application_mask), + "target_aggregators_per_committee".to_uppercase() => + spec.target_aggregators_per_committee.to_string().into(), + "random_subnets_per_validator".to_uppercase() => + spec.random_subnets_per_validator.to_string().into(), + "epochs_per_random_subnet_subscription".to_uppercase() => + spec.epochs_per_random_subnet_subscription.to_string().into(), + "domain_contribution_and_proof".to_uppercase() => + u32_hex(spec.domain_contribution_and_proof), + "domain_sync_committee".to_uppercase() => u32_hex(spec.domain_sync_committee), + "domain_sync_committee_selection_proof".to_uppercase() => + u32_hex(spec.domain_sync_committee_selection_proof), + "sync_committee_subnet_count".to_uppercase() => + altair::SYNC_COMMITTEE_SUBNET_COUNT.to_string().into(), + "target_aggregators_per_sync_subcommittee".to_uppercase() => + altair::TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE.to_string().into(), } } @@ -108,15 +112,16 @@ mod test { .open(tmp_file.as_ref()) .expect("error opening file"); let mainnet_spec = ChainSpec::mainnet(); - let mut yamlconfig = ConfigAndPreset::from_chain_spec::(&mainnet_spec); + let mut yamlconfig = + ConfigAndPreset::from_chain_spec::(&mainnet_spec, None); let (k1, v1) = ("SAMPLE_HARDFORK_KEY1", "123456789"); let (k2, v2) = ("SAMPLE_HARDFORK_KEY2", "987654321"); let (k3, v3) = ("SAMPLE_HARDFORK_KEY3", 32); let (k4, v4) = ("SAMPLE_HARDFORK_KEY4", Value::Null); - yamlconfig.extra_fields.insert(k1.into(), v1.into()); - yamlconfig.extra_fields.insert(k2.into(), v2.into()); - yamlconfig.extra_fields.insert(k3.into(), v3.into()); - yamlconfig.extra_fields.insert(k4.into(), v4); + yamlconfig.extra_fields_mut().insert(k1.into(), v1.into()); + yamlconfig.extra_fields_mut().insert(k2.into(), v2.into()); + yamlconfig.extra_fields_mut().insert(k3.into(), v3.into()); + yamlconfig.extra_fields_mut().insert(k4.into(), v4); serde_yaml::to_writer(writer, &yamlconfig).expect("failed to write or serialize"); @@ -125,8 +130,8 @@ mod test { .write(false) .open(tmp_file.as_ref()) .expect("error while opening the file"); - let from: ConfigAndPreset = + let from: ConfigAndPresetBellatrix = serde_yaml::from_reader(reader).expect("error while deserializing"); - assert_eq!(from, yamlconfig); + assert_eq!(ConfigAndPreset::Bellatrix(from), yamlconfig); } } diff --git a/consensus/types/src/fork_name.rs b/consensus/types/src/fork_name.rs index 4a2e762087..e97b08309b 100644 --- a/consensus/types/src/fork_name.rs +++ b/consensus/types/src/fork_name.rs @@ -106,14 +106,14 @@ macro_rules! map_fork_name_with { } impl FromStr for ForkName { - type Err = (); + type Err = String; - fn from_str(fork_name: &str) -> Result { + fn from_str(fork_name: &str) -> Result { Ok(match fork_name.to_lowercase().as_ref() { "phase0" | "base" => ForkName::Base, "altair" => ForkName::Altair, "bellatrix" | "merge" => ForkName::Merge, - _ => return Err(()), + _ => return Err(format!("unknown fork name: {}", fork_name)), }) } } @@ -138,7 +138,7 @@ impl TryFrom for ForkName { type Error = String; fn try_from(s: String) -> Result { - Self::from_str(&s).map_err(|()| format!("Invalid fork name: {}", s)) + Self::from_str(&s) } } @@ -178,8 +178,8 @@ mod test { assert_eq!(ForkName::from_str("AlTaIr"), Ok(ForkName::Altair)); assert_eq!(ForkName::from_str("altair"), Ok(ForkName::Altair)); - assert_eq!(ForkName::from_str("NO_NAME"), Err(())); - assert_eq!(ForkName::from_str("no_name"), Err(())); + assert!(ForkName::from_str("NO_NAME").is_err()); + assert!(ForkName::from_str("no_name").is_err()); } #[test] diff --git a/consensus/types/src/lib.rs b/consensus/types/src/lib.rs index 7823ec223c..f05012c0b7 100644 --- a/consensus/types/src/lib.rs +++ b/consensus/types/src/lib.rs @@ -110,7 +110,9 @@ pub use crate::beacon_committee::{BeaconCommittee, OwnedBeaconCommittee}; pub use crate::beacon_state::{BeaconTreeHashCache, Error as BeaconStateError, *}; pub use crate::chain_spec::{ChainSpec, Config, Domain}; pub use crate::checkpoint::Checkpoint; -pub use crate::config_and_preset::ConfigAndPreset; +pub use crate::config_and_preset::{ + ConfigAndPreset, ConfigAndPresetAltair, ConfigAndPresetBellatrix, +}; pub use crate::contribution_and_proof::ContributionAndProof; pub use crate::deposit::{Deposit, DEPOSIT_TREE_DEPTH}; pub use crate::deposit_data::DepositData; diff --git a/lighthouse/tests/beacon_node.rs b/lighthouse/tests/beacon_node.rs index 0236ba6589..9d952e5cc5 100644 --- a/lighthouse/tests/beacon_node.rs +++ b/lighthouse/tests/beacon_node.rs @@ -11,7 +11,7 @@ use std::process::Command; use std::str::FromStr; use std::string::ToString; use tempfile::TempDir; -use types::{Address, Checkpoint, Epoch, ExecutionBlockHash, Hash256, MainnetEthSpec}; +use types::{Address, Checkpoint, Epoch, ExecutionBlockHash, ForkName, Hash256, MainnetEthSpec}; use unused_port::{unused_tcp_port, unused_udp_port}; const DEFAULT_ETH1_ENDPOINT: &str = "http://localhost:8545/"; @@ -949,6 +949,21 @@ fn http_tls_flags() { }); } +#[test] +fn http_spec_fork_default() { + CommandLineTest::new() + .run_with_zero_port() + .with_config(|config| assert_eq!(config.http_api.spec_fork_name, None)); +} + +#[test] +fn http_spec_fork_override() { + CommandLineTest::new() + .flag("http-spec-fork", Some("altair")) + .run_with_zero_port() + .with_config(|config| assert_eq!(config.http_api.spec_fork_name, Some(ForkName::Altair))); +} + // Tests for Metrics flags. #[test] fn metrics_flag() { diff --git a/validator_client/src/beacon_node_fallback.rs b/validator_client/src/beacon_node_fallback.rs index d4f7c6c874..0b808e71bb 100644 --- a/validator_client/src/beacon_node_fallback.rs +++ b/validator_client/src/beacon_node_fallback.rs @@ -7,7 +7,7 @@ use crate::http_metrics::metrics::{inc_counter_vec, ENDPOINT_ERRORS, ENDPOINT_RE use environment::RuntimeContext; use eth2::BeaconNodeHttpClient; use futures::future; -use slog::{debug, error, info, warn, Logger}; +use slog::{error, info, warn, Logger}; use slot_clock::SlotClock; use std::fmt; use std::fmt::Debug; @@ -16,7 +16,7 @@ use std::marker::PhantomData; use std::sync::Arc; use std::time::Duration; use tokio::{sync::RwLock, time::sleep}; -use types::{ChainSpec, EthSpec}; +use types::{ChainSpec, Config, EthSpec}; /// The number of seconds *prior* to slot start that we will try and update the state of fallback /// nodes. @@ -213,9 +213,9 @@ impl CandidateBeaconNode { /// Checks if the node has the correct specification. async fn is_compatible(&self, spec: &ChainSpec, log: &Logger) -> Result<(), CandidateError> { - let config_and_preset = self + let config = self .beacon_node - .get_config_spec() + .get_config_spec::() .await .map_err(|e| { error!( @@ -228,25 +228,15 @@ impl CandidateBeaconNode { })? .data; - let beacon_node_spec = - ChainSpec::from_config::(&config_and_preset.config).ok_or_else(|| { - error!( - log, - "The minimal/mainnet spec type of the beacon node does not match the validator \ - client. See the --network command."; - "endpoint" => %self.beacon_node, - ); - CandidateError::Incompatible - })?; - - if !config_and_preset.extra_fields.is_empty() { - debug!( + let beacon_node_spec = ChainSpec::from_config::(&config).ok_or_else(|| { + error!( log, - "Beacon spec includes unknown fields"; + "The minimal/mainnet spec type of the beacon node does not match the validator \ + client. See the --network command."; "endpoint" => %self.beacon_node, - "fields" => ?config_and_preset.extra_fields, ); - } + CandidateError::Incompatible + })?; if beacon_node_spec.genesis_fork_version != spec.genesis_fork_version { error!( diff --git a/validator_client/src/http_api/mod.rs b/validator_client/src/http_api/mod.rs index a5d8d0e71c..1e48e86c05 100644 --- a/validator_client/src/http_api/mod.rs +++ b/validator_client/src/http_api/mod.rs @@ -217,8 +217,7 @@ pub fn serve( .and(signer.clone()) .and_then(|spec: Arc<_>, signer| { blocking_signed_json_task(signer, move || { - let mut config = ConfigAndPreset::from_chain_spec::(&spec); - config.make_backwards_compat(&spec); + let config = ConfigAndPreset::from_chain_spec::(&spec, None); Ok(api_types::GenericResponse::from(config)) }) }); diff --git a/validator_client/src/http_api/tests.rs b/validator_client/src/http_api/tests.rs index e67a82634c..b121dda5b1 100644 --- a/validator_client/src/http_api/tests.rs +++ b/validator_client/src/http_api/tests.rs @@ -208,10 +208,13 @@ impl ApiTester { } pub async fn test_get_lighthouse_spec(self) -> Self { - let result = self.client.get_lighthouse_spec().await.unwrap().data; - - let mut expected = ConfigAndPreset::from_chain_spec::(&E::default_spec()); - expected.make_backwards_compat(&E::default_spec()); + let result = self + .client + .get_lighthouse_spec::() + .await + .map(|res| ConfigAndPreset::Bellatrix(res.data)) + .unwrap(); + let expected = ConfigAndPreset::from_chain_spec::(&E::default_spec(), None); assert_eq!(result, expected); @@ -623,7 +626,9 @@ fn routes_with_invalid_auth() { .await .test_with_invalid_auth(|client| async move { client.get_lighthouse_health().await }) .await - .test_with_invalid_auth(|client| async move { client.get_lighthouse_spec().await }) + .test_with_invalid_auth(|client| async move { + client.get_lighthouse_spec::().await + }) .await .test_with_invalid_auth( |client| async move { client.get_lighthouse_validators().await },