diff --git a/consensus/types/src/chain_spec.rs b/consensus/types/src/chain_spec.rs index b6dafaeb00..9b7a255ad1 100644 --- a/consensus/types/src/chain_spec.rs +++ b/consensus/types/src/chain_spec.rs @@ -2,6 +2,7 @@ use crate::application_domain::{ApplicationDomain, APPLICATION_DOMAIN_BUILDER}; use crate::blob_sidecar::BlobIdentifier; use crate::data_column_sidecar::DataColumnsByRootIdentifier; use crate::*; +use derivative::Derivative; use ethereum_hashing::hash; use int_to_bytes::int_to_bytes4; use safe_arith::{ArithError, SafeArith}; @@ -1472,8 +1473,17 @@ pub struct BlobParameters { // A wrapper around a vector of BlobParameters to ensure that the vector is reverse // sorted by epoch. #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] -#[derive(Debug, PartialEq, Clone)] -pub struct BlobSchedule(Vec); +#[derive(Debug, Derivative, Clone)] +#[derivative(PartialEq)] +pub struct BlobSchedule { + schedule: Vec, + // This is a hack to prevent the blob schedule being serialized on the /eth/v1/config/spec + // endpoint prior to the Fulu fork being scheduled. + // + // We can remove this once Fulu is live on mainnet. + #[derivative(PartialEq = "ignore")] + skip_serializing: bool, +} impl<'de> Deserialize<'de> for BlobSchedule { fn deserialize(deserializer: D) -> Result @@ -1489,30 +1499,48 @@ impl BlobSchedule { pub fn new(mut vec: Vec) -> Self { // reverse sort by epoch vec.sort_by(|a, b| b.epoch.cmp(&a.epoch)); - Self(vec) + Self { + schedule: vec, + skip_serializing: false, + } } pub fn is_empty(&self) -> bool { - self.0.is_empty() + self.schedule.is_empty() + } + + pub fn skip_serializing(&self) -> bool { + self.skip_serializing + } + + pub fn set_skip_serializing(&mut self) { + self.skip_serializing = true; } pub fn max_blobs_for_epoch(&self, epoch: Epoch) -> Option { - self.0 + self.schedule .iter() .find(|entry| epoch >= entry.epoch) .map(|entry| entry.max_blobs_per_block) } pub fn blob_parameters_for_epoch(&self, epoch: Epoch) -> Option { - self.0.iter().find(|entry| epoch >= entry.epoch).cloned() + self.schedule + .iter() + .find(|entry| epoch >= entry.epoch) + .cloned() } pub const fn default() -> Self { - Self(vec![]) + // TODO(EIP-7892): think about what the default should be + Self { + schedule: vec![], + skip_serializing: false, + } } pub fn as_vec(&self) -> &Vec { - &self.0 + &self.schedule } } @@ -1521,7 +1549,7 @@ impl Serialize for BlobSchedule { where S: Serializer, { - let mut schedule = self.0.clone(); + let mut schedule = self.schedule.clone(); // reversing the list to get an ascending order schedule.reverse(); schedule.serialize(serializer) @@ -1533,7 +1561,7 @@ impl<'a> IntoIterator for &'a BlobSchedule { type IntoIter = std::slice::Iter<'a, BlobParameters>; fn into_iter(self) -> Self::IntoIter { - self.0.iter() + self.schedule.iter() } } @@ -1542,7 +1570,7 @@ impl IntoIterator for BlobSchedule { type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() + self.schedule.into_iter() } } @@ -1747,8 +1775,8 @@ pub struct Config { #[serde(with = "serde_utils::quoted_u64")] custody_requirement: u64, #[serde(default = "BlobSchedule::default")] - #[serde(skip_serializing_if = "BlobSchedule::is_empty")] - blob_schedule: BlobSchedule, + #[serde(skip_serializing_if = "BlobSchedule::skip_serializing")] + pub blob_schedule: BlobSchedule, #[serde(default = "default_validator_custody_requirement")] #[serde(with = "serde_utils::quoted_u64")] validator_custody_requirement: u64, diff --git a/consensus/types/src/config_and_preset.rs b/consensus/types/src/config_and_preset.rs index 235bf20238..a613db78f0 100644 --- a/consensus/types/src/config_and_preset.rs +++ b/consensus/types/src/config_and_preset.rs @@ -43,9 +43,8 @@ pub struct ConfigAndPreset { } impl ConfigAndPreset { - // DEPRECATED: the `fork_name` argument is never used, we should remove it. pub fn from_chain_spec(spec: &ChainSpec, fork_name: Option) -> Self { - let config = Config::from_chain_spec::(spec); + let mut config = Config::from_chain_spec::(spec); let base_preset = BasePreset::from_chain_spec::(spec); let altair_preset = AltairPreset::from_chain_spec::(spec); let bellatrix_preset = BellatrixPreset::from_chain_spec::(spec); @@ -53,6 +52,11 @@ impl ConfigAndPreset { let deneb_preset = DenebPreset::from_chain_spec::(spec); let extra_fields = get_extra_fields(spec); + // Remove blob schedule for backwards-compatibility. + if spec.fulu_fork_epoch.is_none() { + config.blob_schedule.set_skip_serializing(); + } + if spec.fulu_fork_epoch.is_some() || fork_name.is_none() || fork_name == Some(ForkName::Fulu) @@ -140,7 +144,7 @@ pub fn get_extra_fields(spec: &ChainSpec) -> HashMap { #[cfg(test)] mod test { use super::*; - use crate::MainnetEthSpec; + use crate::{Epoch, MainnetEthSpec}; use std::fs::File; use tempfile::NamedTempFile; @@ -152,7 +156,9 @@ mod test { .write(true) .open(tmp_file.as_ref()) .expect("error opening file"); - let mainnet_spec = ChainSpec::mainnet(); + let mut mainnet_spec = ChainSpec::mainnet(); + // setting fulu_fork_epoch because we are roundtripping a fulu config + mainnet_spec.fulu_fork_epoch = Some(Epoch::new(42)); let mut yamlconfig = ConfigAndPreset::from_chain_spec::(&mainnet_spec, None); let (k1, v1) = ("SAMPLE_HARDFORK_KEY1", "123456789");