Serve Bellatrix preset in BN API (#3425)
## Issue Addressed Resolves #3388 Resolves #2638 ## Proposed Changes - Return the `BellatrixPreset` on `/eth/v1/config/spec` by default. - Allow users to opt out of this by providing `--http-spec-fork=altair` (unless there's a Bellatrix fork epoch set). - Add the Altair constants from #2638 and make serving the constants non-optional (the `http-disable-legacy-spec` flag is deprecated). - Modify the VC to only read the `Config` and not to log extra fields. This prevents it from having to muck around parsing the `ConfigAndPreset` fields it doesn't need. ## Additional Info This change is backwards-compatible for the VC and the BN, but is marked as a breaking change for the removal of `--http-disable-legacy-spec`. I tried making `Config` a `superstruct` too, but getting the automatic decoding to work was a huge pain and was going to require a lot of hacks, so I gave up in favour of keeping the default-based approach we have now.
This commit is contained in:
parent
c25934956b
commit
4e05f19fb5
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -7073,6 +7073,7 @@ dependencies = [
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"maplit",
|
||||
"parking_lot 0.12.1",
|
||||
"rand 0.8.5",
|
||||
"rand_xorshift",
|
||||
|
@ -132,8 +132,7 @@ pub fn test_spec<E: EthSpec>() -> 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()
|
||||
|
@ -104,9 +104,9 @@ pub struct Config {
|
||||
pub listen_addr: IpAddr,
|
||||
pub listen_port: u16,
|
||||
pub allow_origin: Option<String>,
|
||||
pub serve_legacy_spec: bool,
|
||||
pub tls_config: Option<TlsConfig>,
|
||||
pub allow_sync_stalled: bool,
|
||||
pub spec_fork_name: Option<ForkName>,
|
||||
}
|
||||
|
||||
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<T: BeaconChainTypes>(
|
||||
});
|
||||
|
||||
// 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<BeaconChain<T>>| {
|
||||
blocking_json_task(move || {
|
||||
let mut config_and_preset =
|
||||
ConfigAndPreset::from_chain_spec::<T::EthSpec>(&chain.spec);
|
||||
if serve_legacy_spec {
|
||||
config_and_preset.make_backwards_compat(&chain.spec);
|
||||
}
|
||||
let config_and_preset =
|
||||
ConfigAndPreset::from_chain_spec::<T::EthSpec>(&chain.spec, spec_fork_name);
|
||||
Ok(api_types::GenericResponse::from(config_and_preset))
|
||||
})
|
||||
});
|
||||
|
@ -141,9 +141,9 @@ pub async fn create_api_server_on_port<T: BeaconChainTypes>(
|
||||
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),
|
||||
|
@ -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::<E>(&self.chain.spec);
|
||||
expected.make_backwards_compat(&self.chain.spec);
|
||||
let result = self
|
||||
.client
|
||||
.get_config_spec::<ConfigAndPresetBellatrix>()
|
||||
.await
|
||||
.map(|res| ConfigAndPreset::Bellatrix(res.data))
|
||||
.unwrap();
|
||||
let expected = ConfigAndPreset::from_chain_spec::<E>(&self.chain.spec, None);
|
||||
|
||||
assert_eq!(result, expected);
|
||||
|
||||
|
@ -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")
|
||||
|
@ -116,7 +116,14 @@ pub fn get_config<E: EthSpec>(
|
||||
}
|
||||
|
||||
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") {
|
||||
|
@ -977,7 +977,9 @@ impl BeaconNodeHttpClient {
|
||||
}
|
||||
|
||||
/// `GET config/spec`
|
||||
pub async fn get_config_spec(&self) -> Result<GenericResponse<ConfigAndPreset>, Error> {
|
||||
pub async fn get_config_spec<T: Serialize + DeserializeOwned>(
|
||||
&self,
|
||||
) -> Result<GenericResponse<T>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
|
@ -354,7 +354,9 @@ impl ValidatorClientHttpClient {
|
||||
}
|
||||
|
||||
/// `GET lighthouse/spec`
|
||||
pub async fn get_lighthouse_spec(&self) -> Result<GenericResponse<ConfigAndPreset>, Error> {
|
||||
pub async fn get_lighthouse_spec<T: Serialize + DeserializeOwned>(
|
||||
&self,
|
||||
) -> Result<GenericResponse<T>, Error> {
|
||||
let mut path = self.server.full.clone();
|
||||
|
||||
path.path_segments_mut()
|
||||
|
@ -21,17 +21,17 @@ impl ResponseOptional for Result<Response, Error> {
|
||||
/// 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<Option<ForkName>, ()>;
|
||||
fn fork_name_from_header(&self) -> Result<Option<ForkName>, String>;
|
||||
}
|
||||
|
||||
impl ResponseForkName for Response {
|
||||
fn fork_name_from_header(&self) -> Result<Option<ForkName>, ()> {
|
||||
fn fork_name_from_header(&self) -> Result<Option<ForkName>, 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()
|
||||
|
@ -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"
|
||||
|
@ -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<MaybeQuoted<Epoch>>,
|
||||
|
||||
// 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<MaybeQuoted<Epoch>>,
|
||||
@ -890,10 +888,6 @@ fn default_bellatrix_fork_version() -> [u8; 4] {
|
||||
[0xff, 0xff, 0xff, 0xff]
|
||||
}
|
||||
|
||||
fn default_bellatrix_fork_epoch() -> Option<MaybeQuoted<Epoch>> {
|
||||
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,
|
||||
|
@ -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<String, Value>,
|
||||
}
|
||||
|
||||
impl ConfigAndPreset {
|
||||
pub fn from_chain_spec<T: EthSpec>(spec: &ChainSpec) -> Self {
|
||||
pub fn from_chain_spec<T: EthSpec>(spec: &ChainSpec, fork_name: Option<ForkName>) -> Self {
|
||||
let config = Config::from_chain_spec::<T>(spec);
|
||||
let base_preset = BasePreset::from_chain_spec::<T>(spec);
|
||||
let altair_preset = AltairPreset::from_chain_spec::<T>(spec);
|
||||
// TODO(merge): re-enable
|
||||
let _bellatrix_preset = BellatrixPreset::from_chain_spec::<T>(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::<T>(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<String, Value> {
|
||||
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::<MainnetEthSpec>(&mainnet_spec);
|
||||
let mut yamlconfig =
|
||||
ConfigAndPreset::from_chain_spec::<MainnetEthSpec>(&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);
|
||||
}
|
||||
}
|
||||
|
@ -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<Self, ()> {
|
||||
fn from_str(fork_name: &str) -> Result<Self, String> {
|
||||
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<String> for ForkName {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
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]
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
@ -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<E: EthSpec> CandidateBeaconNode<E> {
|
||||
|
||||
/// 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::<Config>()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!(
|
||||
@ -228,25 +228,15 @@ impl<E: EthSpec> CandidateBeaconNode<E> {
|
||||
})?
|
||||
.data;
|
||||
|
||||
let beacon_node_spec =
|
||||
ChainSpec::from_config::<E>(&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::<E>(&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!(
|
||||
|
@ -217,8 +217,7 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
|
||||
.and(signer.clone())
|
||||
.and_then(|spec: Arc<_>, signer| {
|
||||
blocking_signed_json_task(signer, move || {
|
||||
let mut config = ConfigAndPreset::from_chain_spec::<E>(&spec);
|
||||
config.make_backwards_compat(&spec);
|
||||
let config = ConfigAndPreset::from_chain_spec::<E>(&spec, None);
|
||||
Ok(api_types::GenericResponse::from(config))
|
||||
})
|
||||
});
|
||||
|
@ -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>(&E::default_spec());
|
||||
expected.make_backwards_compat(&E::default_spec());
|
||||
let result = self
|
||||
.client
|
||||
.get_lighthouse_spec::<ConfigAndPresetBellatrix>()
|
||||
.await
|
||||
.map(|res| ConfigAndPreset::Bellatrix(res.data))
|
||||
.unwrap();
|
||||
let expected = ConfigAndPreset::from_chain_spec::<E>(&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::<types::Config>().await
|
||||
})
|
||||
.await
|
||||
.test_with_invalid_auth(
|
||||
|client| async move { client.get_lighthouse_validators().await },
|
||||
|
Loading…
Reference in New Issue
Block a user