mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-20 22:38:34 +00:00
Gloas cold DB (#8991)
Closes: - https://github.com/sigp/lighthouse/issues/8958 - Update the `HotColdStore` to handle storage of cold states. - Update `BeaconSnapshot` to hold the execution envelope. This is required to make `chain_dump`-related checks sane, and will be generally useful (see: https://github.com/sigp/lighthouse/issues/8956). - Bug fix in the `BlockReplayer` for the case where the starting state is already `Full` (we should not try to apply another payload). This happens on the cold DB path because we try to replay from the closest cached state (which is often full). - Update `test_gloas_hot_state_hierarchy` to cover the cold DB migration. Co-Authored-By: Michael Sproul <michael@sigmaprime.io> Co-Authored-By: Michael Sproul <michaelsproul@users.noreply.github.com>
This commit is contained in:
@@ -1906,6 +1906,51 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
|
||||
}
|
||||
}
|
||||
|
||||
/// Recompute the payload status for a state at `slot` that is stored in the cold DB.
|
||||
///
|
||||
/// This function returns an error for any `slot` that is outside the range of slots stored in
|
||||
/// the freezer DB.
|
||||
///
|
||||
/// For all slots prior to Gloas, it returns `Pending`.
|
||||
///
|
||||
/// For post-Gloas slots the algorithm is:
|
||||
///
|
||||
/// 1. Load the most recently applied block at `slot` (may not be from `slot` in case of a skip)
|
||||
/// 2. Load the canonical `state_root` at the slot of the block. If this `state_root` matches
|
||||
/// the one in the block then we know the state at *that* slot is canonically empty (no
|
||||
/// payload). Conversely, if it is different, we know that the block's slot is full (assuming
|
||||
/// no database corruption).
|
||||
/// 3. The payload status of `slot` is the same as the payload status of `block.slot()`, because
|
||||
/// we only care about whether a beacon block or payload was applied most recently, and
|
||||
/// `block` is by definition the most-recently-applied block.
|
||||
///
|
||||
/// All of this mucking around could be avoided if we do a schema migration to record the
|
||||
/// payload status in the database. For now, this is simpler.
|
||||
fn get_cold_state_payload_status(&self, slot: Slot) -> Result<StatePayloadStatus, Error> {
|
||||
// Pre-Gloas states are always `Pending`.
|
||||
if !self.spec.fork_name_at_slot::<E>(slot).gloas_enabled() {
|
||||
return Ok(StatePayloadStatus::Pending);
|
||||
}
|
||||
|
||||
let block_root = self
|
||||
.get_cold_block_root(slot)?
|
||||
.ok_or(HotColdDBError::MissingFrozenBlock(slot))?;
|
||||
|
||||
let block = self
|
||||
.get_blinded_block(&block_root)?
|
||||
.ok_or(Error::MissingBlock(block_root))?;
|
||||
|
||||
let state_root = self
|
||||
.get_cold_state_root(block.slot())?
|
||||
.ok_or(HotColdDBError::MissingRestorePointState(block.slot()))?;
|
||||
|
||||
if block.state_root() != state_root {
|
||||
Ok(StatePayloadStatus::Full)
|
||||
} else {
|
||||
Ok(StatePayloadStatus::Pending)
|
||||
}
|
||||
}
|
||||
|
||||
fn load_hot_hdiff_buffer(&self, state_root: Hash256) -> Result<HDiffBuffer, Error> {
|
||||
if let Some(buffer) = self
|
||||
.state_cache
|
||||
@@ -2454,8 +2499,7 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
|
||||
self.forwards_state_roots_iterator_until(base_state.slot(), slot, || {
|
||||
Err(Error::StateShouldNotBeRequired(slot))
|
||||
})?;
|
||||
// TODO(gloas): calculate correct payload status for cold states
|
||||
let payload_status = StatePayloadStatus::Pending;
|
||||
let payload_status = self.get_cold_state_payload_status(slot)?;
|
||||
let state = self.replay_blocks(
|
||||
base_state,
|
||||
blocks,
|
||||
@@ -2591,9 +2635,10 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
|
||||
{
|
||||
return Ok((blocks, vec![]));
|
||||
}
|
||||
// TODO(gloas): wire this up
|
||||
let end_block_root = Hash256::ZERO;
|
||||
let desired_payload_status = StatePayloadStatus::Pending;
|
||||
let end_block_root = self
|
||||
.get_cold_block_root(end_slot)?
|
||||
.ok_or(HotColdDBError::MissingFrozenBlock(end_slot))?;
|
||||
let desired_payload_status = self.get_cold_state_payload_status(end_slot)?;
|
||||
let envelopes = self.load_payload_envelopes_for_blocks(
|
||||
&blocks,
|
||||
end_block_root,
|
||||
|
||||
@@ -319,6 +319,10 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
|
||||
.spec
|
||||
.fulu_fork_epoch
|
||||
.map(|epoch| epoch.start_slot(E::slots_per_epoch()));
|
||||
let gloas_fork_slot = self
|
||||
.spec
|
||||
.gloas_fork_epoch
|
||||
.map(|epoch| epoch.start_slot(E::slots_per_epoch()));
|
||||
let oldest_blob_slot = self.get_blob_info().oldest_blob_slot;
|
||||
let oldest_data_column_slot = self.get_data_column_info().oldest_data_column_slot;
|
||||
|
||||
@@ -343,17 +347,28 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> HotColdDB<E, Hot, Cold>
|
||||
}
|
||||
|
||||
// Invariant 5: execution payload consistency.
|
||||
// TODO(gloas): reconsider this invariant
|
||||
if check_payloads
|
||||
&& let Some(bellatrix_slot) = bellatrix_fork_slot
|
||||
&& slot >= bellatrix_slot
|
||||
&& !self.execution_payload_exists(&block_root)?
|
||||
&& !self.payload_envelope_exists(&block_root)?
|
||||
{
|
||||
result.add_violation(InvariantViolation::ExecutionPayloadMissing {
|
||||
block_root,
|
||||
slot,
|
||||
});
|
||||
if let Some(gloas_slot) = gloas_fork_slot
|
||||
&& slot >= gloas_slot
|
||||
{
|
||||
// For Gloas there is never a true payload stored at slot 0.
|
||||
// TODO(gloas): still need to account for non-canonical payloads once pruning
|
||||
// is implemented.
|
||||
if slot != 0 && !self.payload_envelope_exists(&block_root)? {
|
||||
result.add_violation(InvariantViolation::ExecutionPayloadMissing {
|
||||
block_root,
|
||||
slot,
|
||||
});
|
||||
}
|
||||
} else if !self.execution_payload_exists(&block_root)? {
|
||||
result.add_violation(InvariantViolation::ExecutionPayloadMissing {
|
||||
block_root,
|
||||
slot,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Invariant 6: blob sidecar consistency.
|
||||
|
||||
Reference in New Issue
Block a user