mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-30 04:37:13 +00:00
Merge branch 'unstable' into merge-unstable-to-deneb-20230822
# Conflicts: # beacon_node/beacon_chain/src/builder.rs # beacon_node/beacon_chain/tests/store_tests.rs # beacon_node/client/src/builder.rs # beacon_node/src/config.rs # beacon_node/store/src/hot_cold_store.rs # lighthouse/tests/beacon_node.rs
This commit is contained in:
@@ -4943,6 +4943,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
self.log,
|
||||
"Produced block on state";
|
||||
"block_size" => block_size,
|
||||
"slot" => block.slot(),
|
||||
);
|
||||
|
||||
metrics::observe(&metrics::BLOCK_SIZE, block_size as f64);
|
||||
@@ -5921,14 +5922,16 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
let (mut state, state_root) = if let Some((state, state_root)) = head_state_opt {
|
||||
(state, state_root)
|
||||
} else {
|
||||
let state_root = head_block.state_root;
|
||||
let state = self
|
||||
let block_state_root = head_block.state_root;
|
||||
let max_slot = shuffling_epoch.start_slot(T::EthSpec::slots_per_epoch());
|
||||
let (state_root, state) = self
|
||||
.store
|
||||
.get_inconsistent_state_for_attestation_verification_only(
|
||||
&state_root,
|
||||
Some(head_block.slot),
|
||||
&head_block_root,
|
||||
max_slot,
|
||||
block_state_root,
|
||||
)?
|
||||
.ok_or(Error::MissingBeaconState(head_block.state_root))?;
|
||||
.ok_or(Error::MissingBeaconState(block_state_root))?;
|
||||
(state, state_root)
|
||||
};
|
||||
|
||||
|
||||
@@ -321,9 +321,17 @@ where
|
||||
.deconstruct()
|
||||
.0;
|
||||
|
||||
let state = self
|
||||
let max_slot = self
|
||||
.justified_checkpoint
|
||||
.epoch
|
||||
.start_slot(E::slots_per_epoch());
|
||||
let (_, state) = self
|
||||
.store
|
||||
.get_state(&justified_block.state_root(), Some(justified_block.slot()))
|
||||
.get_advanced_hot_state(
|
||||
self.justified_checkpoint.root,
|
||||
max_slot,
|
||||
justified_block.state_root(),
|
||||
)
|
||||
.map_err(Error::FailedToReadState)?
|
||||
.ok_or_else(|| Error::MissingState(justified_block.state_root()))?;
|
||||
|
||||
|
||||
@@ -1358,7 +1358,7 @@ impl<T: BeaconChainTypes> ExecutionPendingBlock<T> {
|
||||
|
||||
// Perform a sanity check on the pre-state.
|
||||
let parent_slot = parent.beacon_block.slot();
|
||||
if state.slot() < parent_slot || state.slot() > parent_slot + 1 {
|
||||
if state.slot() < parent_slot || state.slot() > block.slot() {
|
||||
return Err(BeaconChainError::BadPreState {
|
||||
parent_root: parent.beacon_block_root,
|
||||
parent_slot,
|
||||
@@ -1860,13 +1860,18 @@ fn load_parent<T: BeaconChainTypes, B: AsBlock<T::EthSpec>>(
|
||||
BlockError::from(BeaconChainError::MissingBeaconBlock(block.parent_root()))
|
||||
})?;
|
||||
|
||||
// Load the parent blocks state from the database, returning an error if it is not found.
|
||||
// Load the parent block's state from the database, returning an error if it is not found.
|
||||
// It is an error because if we know the parent block we should also know the parent state.
|
||||
let parent_state_root = parent_block.state_root();
|
||||
let parent_state = chain
|
||||
.get_state(&parent_state_root, Some(parent_block.slot()))?
|
||||
// Retrieve any state that is advanced through to at most `block.slot()`: this is
|
||||
// particularly important if `block` descends from the finalized/split block, but at a slot
|
||||
// prior to the finalized slot (which is invalid and inaccessible in our DB schema).
|
||||
let (parent_state_root, parent_state) = chain
|
||||
.store
|
||||
.get_advanced_hot_state(root, block.slot(), parent_block.state_root())?
|
||||
.ok_or_else(|| {
|
||||
BeaconChainError::DBInconsistent(format!("Missing state {:?}", parent_state_root))
|
||||
BeaconChainError::DBInconsistent(
|
||||
format!("Missing state for parent block {root:?}",),
|
||||
)
|
||||
})?;
|
||||
|
||||
metrics::inc_counter(&metrics::BLOCK_PROCESSING_SNAPSHOT_CACHE_MISSES);
|
||||
|
||||
@@ -26,8 +26,9 @@ use operation_pool::{OperationPool, PersistedOperationPool};
|
||||
use parking_lot::RwLock;
|
||||
use proto_array::{DisallowedReOrgOffsets, ReOrgThreshold};
|
||||
use slasher::Slasher;
|
||||
use slog::{crit, error, info, Logger};
|
||||
use slog::{crit, debug, error, info, Logger};
|
||||
use slot_clock::{SlotClock, TestingSlotClock};
|
||||
use state_processing::per_slot_processing;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
@@ -291,7 +292,7 @@ where
|
||||
let genesis_state = store
|
||||
.get_state(&genesis_block.state_root(), Some(genesis_block.slot()))
|
||||
.map_err(|e| descriptive_db_error("genesis state", &e))?
|
||||
.ok_or("Genesis block not found in store")?;
|
||||
.ok_or("Genesis state not found in store")?;
|
||||
|
||||
self.genesis_time = Some(genesis_state.genesis_time());
|
||||
|
||||
@@ -386,6 +387,16 @@ where
|
||||
let (genesis, updated_builder) = self.set_genesis_state(beacon_state)?;
|
||||
self = updated_builder;
|
||||
|
||||
// Stage the database's metadata fields for atomic storage when `build` is called.
|
||||
// Since v4.4.0 we will set the anchor with a dummy state upper limit in order to prevent
|
||||
// historic states from being retained (unless `--reconstruct-historic-states` is set).
|
||||
let retain_historic_states = self.chain_config.reconstruct_historic_states;
|
||||
self.pending_io_batch.push(
|
||||
store
|
||||
.init_anchor_info(genesis.beacon_block.message(), retain_historic_states)
|
||||
.map_err(|e| format!("Failed to initialize genesis anchor: {:?}", e))?,
|
||||
);
|
||||
|
||||
let fc_store = BeaconForkChoiceStore::get_forkchoice_store(store, &genesis)
|
||||
.map_err(|e| format!("Unable to initialize fork choice store: {e:?}"))?;
|
||||
let current_slot = None;
|
||||
@@ -412,21 +423,28 @@ where
|
||||
weak_subj_block: SignedBeaconBlock<TEthSpec>,
|
||||
genesis_state: BeaconState<TEthSpec>,
|
||||
) -> Result<Self, String> {
|
||||
let store = self.store.clone().ok_or("genesis_state requires a store")?;
|
||||
let store = self
|
||||
.store
|
||||
.clone()
|
||||
.ok_or("weak_subjectivity_state requires a store")?;
|
||||
let log = self
|
||||
.log
|
||||
.as_ref()
|
||||
.ok_or("weak_subjectivity_state requires a log")?;
|
||||
|
||||
let weak_subj_slot = weak_subj_state.slot();
|
||||
let weak_subj_block_root = weak_subj_block.canonical_root();
|
||||
let weak_subj_state_root = weak_subj_block.state_root();
|
||||
|
||||
// Check that the given state lies on an epoch boundary. Due to the database only storing
|
||||
// full states on epoch boundaries and at restore points it would be difficult to support
|
||||
// starting from a mid-epoch state.
|
||||
if weak_subj_slot % TEthSpec::slots_per_epoch() != 0 {
|
||||
return Err(format!(
|
||||
"Checkpoint state at slot {} is not aligned to epoch start. \
|
||||
Please supply an aligned checkpoint with state.slot % 32 == 0",
|
||||
weak_subj_slot,
|
||||
));
|
||||
// Ensure the state is advanced to an epoch boundary.
|
||||
let slots_per_epoch = TEthSpec::slots_per_epoch();
|
||||
if weak_subj_state.slot() % slots_per_epoch != 0 {
|
||||
debug!(
|
||||
log,
|
||||
"Advancing checkpoint state to boundary";
|
||||
"state_slot" => weak_subj_state.slot(),
|
||||
"block_slot" => weak_subj_block.slot(),
|
||||
);
|
||||
while weak_subj_state.slot() % slots_per_epoch != 0 {
|
||||
per_slot_processing(&mut weak_subj_state, None, &self.spec)
|
||||
.map_err(|e| format!("Error advancing state: {e:?}"))?;
|
||||
}
|
||||
}
|
||||
|
||||
// Prime all caches before storing the state in the database and computing the tree hash
|
||||
@@ -434,21 +452,20 @@ where
|
||||
weak_subj_state
|
||||
.build_caches(&self.spec)
|
||||
.map_err(|e| format!("Error building caches on checkpoint state: {e:?}"))?;
|
||||
weak_subj_state
|
||||
let weak_subj_state_root = weak_subj_state
|
||||
.update_tree_hash_cache()
|
||||
.map_err(|e| format!("Error computing checkpoint state root: {:?}", e))?;
|
||||
|
||||
let latest_block_slot = weak_subj_state.latest_block_header().slot;
|
||||
let weak_subj_slot = weak_subj_state.slot();
|
||||
let weak_subj_block_root = weak_subj_block.canonical_root();
|
||||
|
||||
// We can only validate the block root if it exists in the state. We can't calculated it
|
||||
// from the `latest_block_header` because the state root might be set to the zero hash.
|
||||
if let Ok(state_slot_block_root) = weak_subj_state.get_block_root(latest_block_slot) {
|
||||
if weak_subj_block_root != *state_slot_block_root {
|
||||
return Err(format!(
|
||||
"Snapshot state's most recent block root does not match block, expected: {:?}, got: {:?}",
|
||||
weak_subj_block_root, state_slot_block_root
|
||||
));
|
||||
}
|
||||
// Validate the state's `latest_block_header` against the checkpoint block.
|
||||
let state_latest_block_root = weak_subj_state.get_latest_block_root(weak_subj_state_root);
|
||||
if weak_subj_block_root != state_latest_block_root {
|
||||
return Err(format!(
|
||||
"Snapshot state's most recent block root does not match block, expected: {:?}, got: {:?}",
|
||||
weak_subj_block_root, state_latest_block_root
|
||||
));
|
||||
}
|
||||
|
||||
// Check that the checkpoint state is for the same network as the genesis state.
|
||||
@@ -464,7 +481,7 @@ where
|
||||
|
||||
// Set the store's split point *before* storing genesis so that genesis is stored
|
||||
// immediately in the freezer DB.
|
||||
store.set_split(weak_subj_slot, weak_subj_state_root);
|
||||
store.set_split(weak_subj_slot, weak_subj_state_root, weak_subj_block_root);
|
||||
let (_, updated_builder) = self.set_genesis_state(genesis_state)?;
|
||||
self = updated_builder;
|
||||
|
||||
@@ -480,10 +497,11 @@ where
|
||||
// Stage the database's metadata fields for atomic storage when `build` is called.
|
||||
// This prevents the database from restarting in an inconsistent state if the anchor
|
||||
// info or split point is written before the `PersistedBeaconChain`.
|
||||
let retain_historic_states = self.chain_config.reconstruct_historic_states;
|
||||
self.pending_io_batch.push(store.store_split_in_batch());
|
||||
self.pending_io_batch.push(
|
||||
store
|
||||
.init_anchor_info(weak_subj_block.message())
|
||||
.init_anchor_info(weak_subj_block.message(), retain_historic_states)
|
||||
.map_err(|e| format!("Failed to initialize anchor info: {:?}", e))?,
|
||||
);
|
||||
|
||||
@@ -685,9 +703,8 @@ where
|
||||
Err(e) => return Err(descriptive_db_error("head block", &e)),
|
||||
};
|
||||
|
||||
let head_state_root = head_block.state_root();
|
||||
let head_state = store
|
||||
.get_state(&head_state_root, Some(head_block.slot()))
|
||||
let (_head_state_root, head_state) = store
|
||||
.get_advanced_hot_state(head_block_root, current_slot, head_block.state_root())
|
||||
.map_err(|e| descriptive_db_error("head state", &e))?
|
||||
.ok_or("Head state not found in store")?;
|
||||
|
||||
|
||||
@@ -47,7 +47,8 @@ use crate::{
|
||||
};
|
||||
use eth2::types::{EventKind, SseChainReorg, SseFinalizedCheckpoint, SseHead, SseLateHead};
|
||||
use fork_choice::{
|
||||
ExecutionStatus, ForkChoiceView, ForkchoiceUpdateParameters, ProtoBlock, ResetPayloadStatuses,
|
||||
ExecutionStatus, ForkChoiceStore, ForkChoiceView, ForkchoiceUpdateParameters, ProtoBlock,
|
||||
ResetPayloadStatuses,
|
||||
};
|
||||
use itertools::process_results;
|
||||
use parking_lot::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
@@ -298,10 +299,10 @@ impl<T: BeaconChainTypes> CanonicalHead<T> {
|
||||
let beacon_block = store
|
||||
.get_full_block(&beacon_block_root)?
|
||||
.ok_or(Error::MissingBeaconBlock(beacon_block_root))?;
|
||||
let beacon_state_root = beacon_block.state_root();
|
||||
let beacon_state = store
|
||||
.get_state(&beacon_state_root, Some(beacon_block.slot()))?
|
||||
.ok_or(Error::MissingBeaconState(beacon_state_root))?;
|
||||
let current_slot = fork_choice.fc_store().get_current_slot();
|
||||
let (_, beacon_state) = store
|
||||
.get_advanced_hot_state(beacon_block_root, current_slot, beacon_block.state_root())?
|
||||
.ok_or(Error::MissingBeaconState(beacon_block.state_root()))?;
|
||||
|
||||
let snapshot = BeaconSnapshot {
|
||||
beacon_block_root,
|
||||
@@ -669,10 +670,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
.get_full_block(&new_view.head_block_root)?
|
||||
.ok_or(Error::MissingBeaconBlock(new_view.head_block_root))?;
|
||||
|
||||
let beacon_state_root = beacon_block.state_root();
|
||||
let beacon_state: BeaconState<T::EthSpec> = self
|
||||
.get_state(&beacon_state_root, Some(beacon_block.slot()))?
|
||||
.ok_or(Error::MissingBeaconState(beacon_state_root))?;
|
||||
let (_, beacon_state) = self
|
||||
.store
|
||||
.get_advanced_hot_state(
|
||||
new_view.head_block_root,
|
||||
current_slot,
|
||||
beacon_block.state_root(),
|
||||
)?
|
||||
.ok_or(Error::MissingBeaconState(beacon_block.state_root()))?;
|
||||
|
||||
Ok(BeaconSnapshot {
|
||||
beacon_block: Arc::new(beacon_block),
|
||||
|
||||
@@ -21,8 +21,11 @@ pub struct ServerSentEventHandler<T: EthSpec> {
|
||||
}
|
||||
|
||||
impl<T: EthSpec> ServerSentEventHandler<T> {
|
||||
pub fn new(log: Logger) -> Self {
|
||||
Self::new_with_capacity(log, DEFAULT_CHANNEL_CAPACITY)
|
||||
pub fn new(log: Logger, capacity_multiplier: usize) -> Self {
|
||||
Self::new_with_capacity(
|
||||
log,
|
||||
capacity_multiplier.saturating_mul(DEFAULT_CHANNEL_CAPACITY),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_with_capacity(log: Logger, capacity: usize) -> Self {
|
||||
|
||||
@@ -289,6 +289,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> BackgroundMigrator<E, Ho
|
||||
debug!(log, "Database consolidation started");
|
||||
|
||||
let finalized_state_root = notif.finalized_state_root;
|
||||
let finalized_block_root = notif.finalized_checkpoint.root;
|
||||
|
||||
let finalized_state = match db.get_state(&finalized_state_root.into(), None) {
|
||||
Ok(Some(state)) => state,
|
||||
@@ -342,7 +343,12 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> BackgroundMigrator<E, Ho
|
||||
}
|
||||
};
|
||||
|
||||
match migrate_database(db.clone(), finalized_state_root.into(), &finalized_state) {
|
||||
match migrate_database(
|
||||
db.clone(),
|
||||
finalized_state_root.into(),
|
||||
finalized_block_root,
|
||||
&finalized_state,
|
||||
) {
|
||||
Ok(()) => {}
|
||||
Err(Error::HotColdDBError(HotColdDBError::FreezeSlotUnaligned(slot))) => {
|
||||
debug!(
|
||||
|
||||
Reference in New Issue
Block a user