From 9446fc88edc8f687b5989b0c35119301efdb7509 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Tue, 3 Oct 2023 16:07:25 +1100 Subject: [PATCH] Fix semantic Deneb <> tree-states conflicts --- Cargo.lock | 2 +- beacon_node/beacon_chain/src/beacon_chain.rs | 4 +- .../beacon_chain/src/blob_verification.rs | 125 +++++------------- .../beacon_chain/src/block_verification.rs | 15 +-- beacon_node/beacon_chain/src/builder.rs | 2 +- .../overflow_lru_cache.rs | 2 +- .../beacon_chain/src/historical_blocks.rs | 3 +- beacon_node/beacon_chain/src/migrate.rs | 12 +- .../src/schema_change/migration_schema_v18.rs | 13 +- beacon_node/store/src/config.rs | 5 +- beacon_node/store/src/hot_cold_store.rs | 49 +++---- beacon_node/store/src/lib.rs | 1 + beacon_node/store/src/metadata.rs | 4 +- .../state_processing/src/upgrade/deneb.rs | 7 +- consensus/types/src/beacon_state.rs | 57 ++++---- .../types/src/beacon_state/compact_state.rs | 39 +++++- consensus/types/src/beacon_state/tests.rs | 5 +- consensus/types/src/chain_spec.rs | 2 +- .../types/src/execution_payload_header.rs | 3 + consensus/types/src/lib.rs | 2 +- 20 files changed, 165 insertions(+), 187 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3802998db1..6aaf844d50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2057,8 +2057,8 @@ dependencies = [ "fork_choice", "fs2", "hex", - "logging", "kzg", + "logging", "rayon", "serde", "serde_derive", diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index 5ce11f2d68..4504bd34a7 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -727,7 +727,7 @@ impl BeaconChain { let iter = self.store .forwards_block_roots_iterator_until(start_slot, end_slot, || { - (head.beacon_state.clone(), head.beacon_block_root) + Ok((head.beacon_state.clone(), head.beacon_block_root)) })?; Ok(iter .map(|result| result.map_err(Into::into)) @@ -817,7 +817,7 @@ impl BeaconChain { let iter = self.store .forwards_state_roots_iterator_until(start_slot, end_slot, || { - (head.beacon_state.clone(), head.beacon_state_root()) + Ok((head.beacon_state.clone(), head.beacon_state_root())) })?; Ok(iter .map(|result| result.map_err(Into::into)) diff --git a/beacon_node/beacon_chain/src/blob_verification.rs b/beacon_node/beacon_chain/src/blob_verification.rs index 5f575baf8d..7137b22e32 100644 --- a/beacon_node/beacon_chain/src/blob_verification.rs +++ b/beacon_node/beacon_chain/src/blob_verification.rs @@ -2,22 +2,18 @@ use derivative::Derivative; use slot_clock::SlotClock; use std::sync::Arc; -use crate::beacon_chain::{ - BeaconChain, BeaconChainTypes, BLOCK_PROCESSING_CACHE_LOCK_TIMEOUT, - VALIDATOR_PUBKEY_CACHE_LOCK_TIMEOUT, -}; +use crate::beacon_chain::{BeaconChain, BeaconChainTypes}; use crate::block_verification::cheap_state_advance_to_obtain_committees; use crate::data_availability_checker::AvailabilityCheckError; use crate::kzg_utils::{validate_blob, validate_blobs}; use crate::BeaconChainError; use kzg::Kzg; -use slog::{debug, warn}; +use slog::debug; use ssz_derive::{Decode, Encode}; use ssz_types::VariableList; use types::blob_sidecar::BlobIdentifier; use types::{ - BeaconStateError, BlobSidecar, BlobSidecarList, CloneConfig, EthSpec, Hash256, - SignedBlobSidecar, Slot, + BeaconStateError, BlobSidecar, BlobSidecarList, EthSpec, Hash256, SignedBlobSidecar, Slot, }; /// An error occurred while validating a gossip blob. @@ -286,91 +282,36 @@ pub fn validate_blob_sidecar_for_gossip( "block_root" => %block_root, "index" => %blob_index, ); - if let Some(mut snapshot) = chain - .snapshot_cache - .try_read_for(BLOCK_PROCESSING_CACHE_LOCK_TIMEOUT) - .and_then(|snapshot_cache| { - snapshot_cache.get_cloned(block_parent_root, CloneConfig::committee_caches_only()) - }) - { - if snapshot.beacon_state.slot() == blob_slot { - debug!( - chain.log, - "Cloning snapshot cache state for blob verification"; - "block_root" => %block_root, - "index" => %blob_index, - ); - ( - snapshot - .beacon_state - .get_beacon_proposer_index(blob_slot, &chain.spec)?, - snapshot.beacon_state.fork(), - ) - } else { - debug!( - chain.log, - "Cloning and advancing snapshot cache state for blob verification"; - "block_root" => %block_root, - "index" => %blob_index, - ); - let state = - cheap_state_advance_to_obtain_committees::<_, GossipBlobError>( - &mut snapshot.beacon_state, - Some(snapshot.beacon_block_root), - blob_slot, - &chain.spec, - )?; - ( - state.get_beacon_proposer_index(blob_slot, &chain.spec)?, - state.fork(), - ) - } - } - // Need to advance the state to get the proposer index - else { - warn!( - chain.log, - "Snapshot cache miss for blob verification"; - "block_root" => %block_root, - "index" => %blob_index, - ); + let (parent_state_root, mut parent_state) = chain + .store + .get_advanced_hot_state(block_parent_root, blob_slot, parent_block.state_root) + .map_err(|e| GossipBlobError::BeaconChainError(e.into()))? + .ok_or_else(|| { + BeaconChainError::DBInconsistent(format!( + "Missing state for parent block {block_parent_root:?}", + )) + })?; - let parent_block = chain - .get_blinded_block(&block_parent_root) - .map_err(GossipBlobError::BeaconChainError)? - .ok_or_else(|| { - GossipBlobError::from(BeaconChainError::MissingBeaconBlock(block_parent_root)) - })?; + let state = cheap_state_advance_to_obtain_committees::<_, GossipBlobError>( + &mut parent_state, + Some(parent_state_root), + blob_slot, + &chain.spec, + )?; - let mut parent_state = chain - .get_state(&parent_block.state_root(), Some(parent_block.slot()))? - .ok_or_else(|| { - BeaconChainError::DBInconsistent(format!( - "Missing state {:?}", - parent_block.state_root() - )) - })?; - let state = cheap_state_advance_to_obtain_committees::<_, GossipBlobError>( - &mut parent_state, - Some(parent_block.state_root()), - blob_slot, - &chain.spec, - )?; + let proposers = state.get_beacon_proposer_indices(&chain.spec)?; + let proposer_index = *proposers + .get(blob_slot.as_usize() % T::EthSpec::slots_per_epoch() as usize) + .ok_or_else(|| BeaconChainError::NoProposerForSlot(blob_slot))?; - let proposers = state.get_beacon_proposer_indices(&chain.spec)?; - let proposer_index = *proposers - .get(blob_slot.as_usize() % T::EthSpec::slots_per_epoch() as usize) - .ok_or_else(|| BeaconChainError::NoProposerForSlot(blob_slot))?; - - // Prime the proposer shuffling cache with the newly-learned value. - chain.beacon_proposer_cache.lock().insert( - blob_epoch, - proposer_shuffling_root, - proposers, - state.fork(), - )?; - (proposer_index, state.fork()) - } + // Prime the proposer shuffling cache with the newly-learned value. + chain.beacon_proposer_cache.lock().insert( + blob_epoch, + proposer_shuffling_root, + proposers, + state.fork(), + )?; + (proposer_index, state.fork()) }; if proposer_index != blob_proposer_index as usize { @@ -382,11 +323,7 @@ pub fn validate_blob_sidecar_for_gossip( // Signature verification let signature_is_valid = { - let pubkey_cache = chain - .validator_pubkey_cache - .try_read_for(VALIDATOR_PUBKEY_CACHE_LOCK_TIMEOUT) - .ok_or(BeaconChainError::ValidatorPubkeyCacheLockTimeout) - .map_err(GossipBlobError::BeaconChainError)?; + let pubkey_cache = chain.validator_pubkey_cache.read(); let pubkey = pubkey_cache .get(proposer_index) diff --git a/beacon_node/beacon_chain/src/block_verification.rs b/beacon_node/beacon_chain/src/block_verification.rs index b30c3ae744..e19fa31526 100644 --- a/beacon_node/beacon_chain/src/block_verification.rs +++ b/beacon_node/beacon_chain/src/block_verification.rs @@ -91,7 +91,6 @@ use std::fmt::Debug; use std::fs; use std::io::Write; use std::sync::Arc; -use std::time::Duration; use store::{Error as DBError, KeyValueStore, SignedBlobSidecarList, StoreOp}; use task_executor::JoinHandle; use tree_hash::TreeHash; @@ -564,7 +563,7 @@ pub fn signature_verify_chain_segment( } let (first_root, first_block) = chain_segment.remove(0); - let (mut parent, first_block) = load_parent(first_block, chain)?; + let (mut parent, first_block) = load_parent(first_root, first_block, chain)?; let slot = first_block.slot(); chain_segment.insert(0, (first_root, first_block)); @@ -871,7 +870,7 @@ impl GossipVerifiedBlock { } else { // The proposer index was *not* cached and we must load the parent in order to determine // the proposer index. - let (mut parent, block) = load_parent(block, chain)?; + let (mut parent, block) = load_parent(block_root, block, chain)?; debug!( chain.log, @@ -1011,7 +1010,7 @@ impl SignatureVerifiedBlock { // Check the anchor slot before loading the parent, to avoid spurious lookups. check_block_against_anchor_slot(block.message(), chain)?; - let (mut parent, block) = load_parent(block, chain)?; + let (mut parent, block) = load_parent(block_root, block, chain)?; let state = cheap_state_advance_to_obtain_committees::<_, BlockError>( &mut parent.pre_state, @@ -1061,7 +1060,7 @@ impl SignatureVerifiedBlock { let (mut parent, block) = if let Some(parent) = from.parent { (parent, from.block) } else { - load_parent(from.block, chain)? + load_parent(from.block_root, from.block, chain)? }; let state = cheap_state_advance_to_obtain_committees::<_, BlockError>( @@ -1121,7 +1120,7 @@ impl IntoExecutionPendingBlock for SignatureVerifiedBloc let (parent, block) = if let Some(parent) = self.parent { (parent, self.block) } else { - load_parent(self.block, chain) + load_parent(self.block_root, self.block, chain) .map_err(|e| BlockSlashInfo::SignatureValid(header.clone(), e))? }; @@ -1755,12 +1754,10 @@ fn verify_parent_block_is_known( /// whilst attempting the operation. #[allow(clippy::type_complexity)] fn load_parent>( - block_root: Hash256, + _block_root: Hash256, block: B, chain: &BeaconChain, ) -> Result<(PreProcessingSnapshot, B), BlockError> { - let spec = &chain.spec; - // Reject any block if its parent is not known to fork choice. // // A block that is not in fork choice is either: diff --git a/beacon_node/beacon_chain/src/builder.rs b/beacon_node/beacon_chain/src/builder.rs index c26ab7340b..0fa5d684a6 100644 --- a/beacon_node/beacon_chain/src/builder.rs +++ b/beacon_node/beacon_chain/src/builder.rs @@ -813,7 +813,7 @@ where .import_new_pubkeys(&head_snapshot.beacon_state) .map_err(|e| format!("error initializing pubkey cache: {e:?}"))?; store - .do_atomically(store_ops) + .do_atomically_with_block_and_blobs_cache(store_ops) .map_err(|e| format!("error writing validator store: {e:?}"))?; let migrator_config = self.store_migrator_config.unwrap_or_default(); diff --git a/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs b/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs index 21fcdc9efe..695c0a821e 100644 --- a/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs +++ b/beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs @@ -1078,7 +1078,7 @@ mod test { { let chain = &harness.chain; let head = chain.head_snapshot(); - let parent_state = head.beacon_state.clone_with_only_committee_caches(); + let parent_state = head.beacon_state.clone(); let target_slot = chain.slot().expect("should get slot") + 1; let parent_root = head.beacon_block_root; diff --git a/beacon_node/beacon_chain/src/historical_blocks.rs b/beacon_node/beacon_chain/src/historical_blocks.rs index ed32770e81..2b3236a513 100644 --- a/beacon_node/beacon_chain/src/historical_blocks.rs +++ b/beacon_node/beacon_chain/src/historical_blocks.rs @@ -9,7 +9,7 @@ use state_processing::{ use std::borrow::Cow; use std::iter; use std::time::Duration; -use store::{get_key_for_col, AnchorInfo, DBColumn, KeyValueStore, KeyValueStoreOp}; +use store::{get_key_for_col, AnchorInfo, BlobInfo, DBColumn, KeyValueStore, KeyValueStoreOp}; use types::{Hash256, Slot}; /// Use a longer timeout on the pubkey cache. @@ -160,7 +160,6 @@ impl BeaconChain { } signed_blocks.push(block); } - chunk_writer.write(&mut cold_batch)?; // these were pushed in reverse order so we reverse again signed_blocks.reverse(); diff --git a/beacon_node/beacon_chain/src/migrate.rs b/beacon_node/beacon_chain/src/migrate.rs index c9f0450828..44763f31e2 100644 --- a/beacon_node/beacon_chain/src/migrate.rs +++ b/beacon_node/beacon_chain/src/migrate.rs @@ -136,6 +136,7 @@ pub struct FinalizationNotification { genesis_block_root: Hash256, } +/* impl Notification { pub fn epoch(&self) -> Option { match self { @@ -144,9 +145,11 @@ impl Notification { .. }) => Some(finalized_checkpoint.epoch), Notification::Reconstruction => None, + Notification::PruneBlobs => None, } } } +*/ impl, Cold: ItemStore> BackgroundMigrator { /// Create a new `BackgroundMigrator` and spawn its thread if necessary. @@ -441,11 +444,12 @@ impl, Cold: ItemStore> BackgroundMigrator Some(f), _ => None, }) - .max_by_key(|f| f.finalized_checkpoint.epoch); + .max_by_key(|f| f.finalized_checkpoint.epoch) + .cloned(); let prune_blobs_notif = queue .iter() .filter_map(|n| match n { - Notification::PruneBlobs(dab) => Some(dab), + Notification::PruneBlobs(dab) => Some(*dab), _ => None, }) .max(); @@ -736,7 +740,7 @@ impl, Cold: ItemStore> BackgroundMigrator, Cold: ItemStore> BackgroundMigrator( log: &Logger, ) -> Result, Error> { let spec = db.get_chain_spec(); - let genesis_block = if let Some(block) = db.get_blinded_block(&Hash256::zero())? { - block - } else { - error!(log, "Missing genesis block"); - return Ok(None); - }; + let genesis_block = + if let Some(block) = db.get_blinded_block(&Hash256::zero(), Some(Slot::new(0)))? { + block + } else { + error!(log, "Missing genesis block"); + return Ok(None); + }; let genesis_state = if let Some(state) = db.get_state(&genesis_block.state_root(), Some(Slot::new(0)))? { state diff --git a/beacon_node/store/src/config.rs b/beacon_node/store/src/config.rs index d356e91e86..6582bc4810 100644 --- a/beacon_node/store/src/config.rs +++ b/beacon_node/store/src/config.rs @@ -161,10 +161,7 @@ impl StoreConfig { /// Check that epochs_per_blob_prune is at least 1 epoch to avoid attempting to prune the same /// epochs over and over again. - fn verify_epochs_per_blob_prune( - &self, - epochs_per_blob_prune: u64, - ) -> Result<(), StoreConfigError> { + fn verify_epochs_per_blob_prune(&self) -> Result<(), StoreConfigError> { if self.epochs_per_blob_prune > 0 { Ok(()) } else { diff --git a/beacon_node/store/src/hot_cold_store.rs b/beacon_node/store/src/hot_cold_store.rs index 071e7ead7e..87720e1304 100644 --- a/beacon_node/store/src/hot_cold_store.rs +++ b/beacon_node/store/src/hot_cold_store.rs @@ -26,7 +26,7 @@ use lru::LruCache; use parking_lot::{Mutex, RwLock}; use safe_arith::SafeArith; use serde_derive::{Deserialize, Serialize}; -use slog::{debug, error, info, warn, Logger}; +use slog::{debug, error, info, trace, warn, Logger}; use ssz::{Decode, Encode}; use ssz_derive::{Decode, Encode}; use state_processing::{ @@ -213,7 +213,7 @@ impl HotColdDB, MemoryStore> { cold_db: MemoryStore::open(), blobs_db: Some(MemoryStore::open()), hot_db: MemoryStore::open(), - block_cache: Mutex::new(BlockCache::new(config.block_cache_size.get())), + block_cache: Mutex::new(BlockCache::new(block_cache_size.get())), state_cache: Mutex::new(StateCache::new(state_cache_size)), immutable_validators: Arc::new(RwLock::new(Default::default())), historic_state_cache: Mutex::new(LruCache::new(historic_state_cache_size.get())), @@ -256,14 +256,14 @@ impl HotColdDB, LevelDB> { let diff_buffer_cache_size = NonZeroUsize::new(config.diff_buffer_cache_size).ok_or(Error::ZeroCacheSize)?; - let db = HotColdDB { + let mut db = HotColdDB { split: RwLock::new(Split::default()), anchor_info: RwLock::new(None), blob_info: RwLock::new(BlobInfo::default()), cold_db: LevelDB::open(cold_path)?, blobs_db: None, hot_db: LevelDB::open(hot_path)?, - block_cache: Mutex::new(BlockCache::new(config.block_cache_size.get())), + block_cache: Mutex::new(BlockCache::new(block_cache_size.get())), state_cache: Mutex::new(StateCache::new(state_cache_size)), immutable_validators: Arc::new(RwLock::new(Default::default())), historic_state_cache: Mutex::new(LruCache::new(historic_state_cache_size.get())), @@ -950,7 +950,10 @@ impl, Cold: ItemStore> HotColdDB /// (which are frozen, and won't be deleted), or valid descendents of the finalized checkpoint /// (which will be deleted by this function but shouldn't be). pub fn delete_state(&self, state_root: &Hash256, slot: Slot) -> Result<(), Error> { - self.do_atomically(vec![StoreOp::DeleteState(*state_root, Some(slot))]) + self.do_atomically_with_block_and_blobs_cache(vec![StoreOp::DeleteState( + *state_root, + Some(slot), + )]) } pub fn forwards_block_roots_iterator( @@ -1184,26 +1187,21 @@ impl, Cold: ItemStore> HotColdDB StoreOp::DeleteBlock(block_root) => { guard.delete_block(&block_root); - self.state_cache.lock().delete_block_states(block_root); + self.state_cache.lock().delete_block_states(&block_root); } StoreOp::DeleteState(state_root, _) => { - self.state_cache.lock().delete_state(state_root) + self.state_cache.lock().delete_state(&state_root) } StoreOp::DeleteBlobs(_) => (), - StoreOp::DeleteState(_, _) => (), - StoreOp::DeleteExecutionPayload(_) => (), StoreOp::KeyValueOp(_) => (), } } - self.hot_db - .do_atomically(self.convert_to_kv_batch(batch)?)?; - for op in blob_cache_ops { match op { StoreOp::PutBlobs(block_root, blobs) => { @@ -2205,7 +2203,7 @@ impl, Cold: ItemStore> HotColdDB ) -> Result { let mut blob_info = self.blob_info.write(); if *blob_info == prev_value { - let kv_op = self.store_blob_info_in_batch(&new_value); + let kv_op = self.store_blob_info_in_batch(&new_value)?; *blob_info = new_value; Ok(kv_op) } else { @@ -2232,7 +2230,7 @@ impl, Cold: ItemStore> HotColdDB /// /// The argument is intended to be `self.blob_info`, but is passed manually to avoid issues /// with recursive locking. - fn store_blob_info_in_batch(&self, blob_info: &BlobInfo) -> KeyValueStoreOp { + fn store_blob_info_in_batch(&self, blob_info: &BlobInfo) -> Result { blob_info.as_kv_store_op(BLOB_INFO_KEY) } @@ -2677,21 +2675,16 @@ impl, Cold: ItemStore> HotColdDB let mut ops = vec![]; let mut last_pruned_block_root = None; - for res in self.forwards_block_roots_iterator_until( - oldest_blob_slot, - end_slot, - || { - let (_, split_state) = self - .get_advanced_hot_state(split.block_root, split.slot, split.state_root)? - .ok_or(HotColdDBError::MissingSplitState( - split.state_root, - split.slot, - ))?; + for res in self.forwards_block_roots_iterator_until(oldest_blob_slot, end_slot, || { + let (_, split_state) = self + .get_advanced_hot_state(split.block_root, split.slot, split.state_root)? + .ok_or(HotColdDBError::MissingSplitState( + split.state_root, + split.slot, + ))?; - Ok((split_state, split.block_root)) - }, - &self.spec, - )? { + Ok((split_state, split.block_root)) + })? { let (block_root, slot) = match res { Ok(tuple) => tuple, Err(e) => { diff --git a/beacon_node/store/src/lib.rs b/beacon_node/store/src/lib.rs index 2c01a0e7b9..e0736deba3 100644 --- a/beacon_node/store/src/lib.rs +++ b/beacon_node/store/src/lib.rs @@ -289,6 +289,7 @@ impl DBColumn { /// This function returns the number of bytes used by keys in a given column. pub fn key_size(self) -> usize { match self { + Self::OverflowLRUCache => 40, Self::BeaconMeta | Self::BeaconBlock | Self::BeaconState diff --git a/beacon_node/store/src/metadata.rs b/beacon_node/store/src/metadata.rs index 0df301d815..fc610b186e 100644 --- a/beacon_node/store/src/metadata.rs +++ b/beacon_node/store/src/metadata.rs @@ -144,8 +144,8 @@ impl StoreItem for BlobInfo { DBColumn::BeaconMeta } - fn as_store_bytes(&self) -> Vec { - self.as_ssz_bytes() + fn as_store_bytes(&self) -> Result, Error> { + Ok(self.as_ssz_bytes()) } fn from_store_bytes(bytes: &[u8]) -> Result { diff --git a/consensus/state_processing/src/upgrade/deneb.rs b/consensus/state_processing/src/upgrade/deneb.rs index c253a8c162..c21e1361a5 100644 --- a/consensus/state_processing/src/upgrade/deneb.rs +++ b/consensus/state_processing/src/upgrade/deneb.rs @@ -1,5 +1,7 @@ use std::mem; -use types::{BeaconState, BeaconStateDeneb, BeaconStateError as Error, ChainSpec, EthSpec, Fork}; +use types::{ + BeaconState, BeaconStateDeneb, BeaconStateError as Error, ChainSpec, EpochCache, EthSpec, Fork, +}; /// Transform a `Capella` state into an `Deneb` state. pub fn upgrade_to_deneb( @@ -67,7 +69,8 @@ pub fn upgrade_to_deneb( committee_caches: mem::take(&mut pre.committee_caches), pubkey_cache: mem::take(&mut pre.pubkey_cache), exit_cache: mem::take(&mut pre.exit_cache), - tree_hash_cache: mem::take(&mut pre.tree_hash_cache), + slashings_cache: mem::take(&mut pre.slashings_cache), + epoch_cache: EpochCache::default(), }); *pre_state = post; diff --git a/consensus/types/src/beacon_state.rs b/consensus/types/src/beacon_state.rs index 27b0d4e007..c99bf29ddf 100644 --- a/consensus/types/src/beacon_state.rs +++ b/consensus/types/src/beacon_state.rs @@ -280,6 +280,19 @@ impl From for Hash256 { )), num_fields(all()), )), + Deneb(metastruct( + mappings( + map_beacon_state_deneb_fields(), + map_beacon_state_deneb_tree_list_fields(mutable, fallible, groups(tree_lists)), + ), + bimappings(bimap_beacon_state_deneb_tree_list_fields( + other_type = "BeaconStateDeneb", + self_mutable, + fallible, + groups(tree_lists) + )), + num_fields(all()), + )), ), cast_error(ty = "Error", expr = "Error::IncorrectStateVariant"), partial_getter_error(ty = "Error", expr = "Error::IncorrectStateVariant") @@ -414,6 +427,7 @@ where only(Deneb), partial_getter(rename = "latest_execution_payload_header_deneb") )] + #[metastruct(exclude_from(tree_lists))] pub latest_execution_payload_header: ExecutionPayloadHeaderDeneb, // Capella @@ -570,31 +584,6 @@ impl BeaconState { } } - /// Specialised deserialisation method that uses the `ChainSpec` as context. - #[allow(clippy::arithmetic_side_effects)] - pub fn from_ssz_bytes(bytes: &[u8], spec: &ChainSpec) -> Result { - // Slot is after genesis_time (u64) and genesis_validators_root (Hash256). - let slot_start = ::ssz_fixed_len() + ::ssz_fixed_len(); - let slot_end = slot_start + ::ssz_fixed_len(); - - let slot_bytes = bytes - .get(slot_start..slot_end) - .ok_or(DecodeError::InvalidByteLength { - len: bytes.len(), - expected: slot_end, - })?; - - let slot = Slot::from_ssz_bytes(slot_bytes)?; - let fork_at_slot = spec.fork_name_at_slot::(slot); - - Ok(map_fork_name!( - fork_at_slot, - Self, - <_>::from_ssz_bytes(bytes)? - )) ->>>>>>> origin/deneb-free-blobs - } - /// Returns the `tree_hash_root` of the state. /// /// Spec v0.12.1 @@ -1404,6 +1393,16 @@ impl BeaconState { &mut state.exit_cache, &mut state.epoch_cache, )), + BeaconState::Deneb(state) => Ok(( + &mut state.validators, + &mut state.balances, + &state.previous_epoch_participation, + &state.current_epoch_participation, + &mut state.inactivity_scores, + &mut state.progressive_balances_cache, + &mut state.exit_cache, + &mut state.epoch_cache, + )), } } @@ -2144,6 +2143,9 @@ impl BeaconState { map_beacon_state_capella_tree_list_fields!(inner, |_, x| { x.apply_updates() }) } + Self::Deneb(inner) => { + map_beacon_state_deneb_tree_list_fields!(inner, |_, x| { x.apply_updates() }) + } } self.eth1_data_votes_mut().apply_updates()?; Ok(()) @@ -2199,6 +2201,11 @@ impl BeaconState { + map_beacon_state_deneb_fields!(state, |_, field| { + leaves.push(field.tree_hash_root()); + }); + } }; // 3. Make deposit tree. diff --git a/consensus/types/src/beacon_state/compact_state.rs b/consensus/types/src/beacon_state/compact_state.rs index 58d81576d0..8c42a926a9 100644 --- a/consensus/types/src/beacon_state/compact_state.rs +++ b/consensus/types/src/beacon_state/compact_state.rs @@ -1,6 +1,7 @@ use crate::{ - BeaconState, BeaconStateAltair, BeaconStateBase, BeaconStateCapella, BeaconStateError as Error, - BeaconStateMerge, EthSpec, PublicKeyBytes, VList, Validator, ValidatorMutable, + BeaconState, BeaconStateAltair, BeaconStateBase, BeaconStateCapella, BeaconStateDeneb, + BeaconStateError as Error, BeaconStateMerge, EthSpec, PublicKeyBytes, VList, Validator, + ValidatorMutable, }; use itertools::process_results; use std::sync::Arc; @@ -180,6 +181,23 @@ impl BeaconState { next_withdrawal_validator_index ] ), + BeaconState::Deneb(s) => full_to_compact!( + s, + self, + Deneb, + BeaconStateDeneb, + [ + previous_epoch_participation, + current_epoch_participation, + current_sync_committee, + next_sync_committee, + inactivity_scores, + latest_execution_payload_header, + historical_summaries, + next_withdrawal_index, + next_withdrawal_validator_index + ] + ), } } } @@ -241,6 +259,23 @@ impl CompactBeaconState { next_withdrawal_validator_index ] ), + BeaconState::Deneb(inner) => compact_to_full!( + inner, + Deneb, + BeaconStateDeneb, + immutable_validators, + [ + previous_epoch_participation, + current_epoch_participation, + current_sync_committee, + next_sync_committee, + inactivity_scores, + latest_execution_payload_header, + historical_summaries, + next_withdrawal_index, + next_withdrawal_validator_index + ] + ), }; Ok(state) } diff --git a/consensus/types/src/beacon_state/tests.rs b/consensus/types/src/beacon_state/tests.rs index 9c1ed5e306..5bf6d38db6 100644 --- a/consensus/types/src/beacon_state/tests.rs +++ b/consensus/types/src/beacon_state/tests.rs @@ -3,8 +3,8 @@ use crate::{test_utils::*, ForkName}; use beacon_chain::test_utils::{BeaconChainHarness, EphemeralHarnessType}; use beacon_chain::types::{ test_utils::TestRandom, BeaconState, BeaconStateAltair, BeaconStateBase, BeaconStateCapella, - BeaconStateError, BeaconStateMerge, ChainSpec, Domain, Epoch, EthSpec, FixedVector, Hash256, - Keypair, MainnetEthSpec, MinimalEthSpec, RelativeEpoch, Slot, + BeaconStateDeneb, BeaconStateError, BeaconStateMerge, ChainSpec, Domain, Epoch, EthSpec, + FixedVector, Hash256, Keypair, MainnetEthSpec, MinimalEthSpec, RelativeEpoch, Slot, }; use ssz::Encode; use std::ops::Mul; @@ -416,6 +416,7 @@ fn check_num_fields_pow2() { ForkName::Altair => BeaconStateAltair::::NUM_FIELDS, ForkName::Merge => BeaconStateMerge::::NUM_FIELDS, ForkName::Capella => BeaconStateCapella::::NUM_FIELDS, + ForkName::Deneb => BeaconStateDeneb::::NUM_FIELDS, }; assert_eq!( num_fields.next_power_of_two(), diff --git a/consensus/types/src/chain_spec.rs b/consensus/types/src/chain_spec.rs index 0d90e4d0a2..9fb38fb2f4 100644 --- a/consensus/types/src/chain_spec.rs +++ b/consensus/types/src/chain_spec.rs @@ -320,7 +320,7 @@ impl ChainSpec { ForkName::Altair => self.inactivity_penalty_quotient_altair, ForkName::Merge => self.inactivity_penalty_quotient_bellatrix, ForkName::Capella => self.inactivity_penalty_quotient_bellatrix, - BeaconState::Deneb => self.inactivity_penalty_quotient_bellatrix, + ForkName::Deneb => self.inactivity_penalty_quotient_bellatrix, } } diff --git a/consensus/types/src/execution_payload_header.rs b/consensus/types/src/execution_payload_header.rs index b8d4c05f2c..f174058b28 100644 --- a/consensus/types/src/execution_payload_header.rs +++ b/consensus/types/src/execution_payload_header.rs @@ -313,6 +313,9 @@ impl<'a, T: EthSpec> ExecutionPayloadHeaderRefMut<'a, T> { ExecutionPayloadHeaderRefMut::Capella(mut_ref) => { *mut_ref = header.try_into()?; } + ExecutionPayloadHeaderRefMut::Deneb(mut_ref) => { + *mut_ref = header.try_into()?; + } } Ok(()) } diff --git a/consensus/types/src/lib.rs b/consensus/types/src/lib.rs index be8d3457ae..e36fa8fb68 100644 --- a/consensus/types/src/lib.rs +++ b/consensus/types/src/lib.rs @@ -210,7 +210,7 @@ pub type Uint256 = ethereum_types::U256; pub type Address = H160; pub type ForkVersion = [u8; 4]; pub type BLSFieldElement = Uint256; -pub type Blob = FixedVector::BytesPerBlob>; +pub type Blob = ssz_types::FixedVector::BytesPerBlob>; pub type KzgProofs = VariableList::MaxBlobCommitmentsPerBlock>; pub type VersionedHash = Hash256; pub type Hash64 = ethereum_types::H64;