Files
lighthouse/beacon_node/network/src/status.rs
Eitan Seri-Levi db8b6be9df Data column custody info (#7648)
#7647


  Introduces a new record in the blobs db `DataColumnCustodyInfo`

When `DataColumnCustodyInfo` exists in the db this indicates that a recent cgc change has occurred and/or that a custody backfill sync is currently in progress (custody backfill will be added as a separate PR). When a cgc change has occurred `earliest_available_slot` will be equal to the slot at which the cgc change occured. During custody backfill sync`earliest_available_slot` should be updated incrementally as it progresses.

~~Note that if `advertise_false_custody_group_count` is enabled we do not add a `DataColumnCustodyInfo` record in the db as that would affect the status v2 response.~~
(See comment https://github.com/sigp/lighthouse/pull/7648#discussion_r2212403389)

~~If `DataColumnCustodyInfo` doesn't exist in the db this indicates that we have fulfilled our custody requirements up to the DA window.~~
(It now always exist, and the slot will be set to `None` once backfill is complete)

StatusV2 now uses `DataColumnCustodyInfo` to calculate the `earliest_available_slot` if a `DataColumnCustodyInfo` record exists in the db, if it's `None`, then we return the `oldest_block_slot`.
2025-07-22 13:30:30 +00:00

57 lines
2.3 KiB
Rust

use beacon_chain::{BeaconChain, BeaconChainTypes};
use types::{EthSpec, FixedBytesExtended, Hash256};
use lighthouse_network::rpc::{methods::StatusMessageV2, StatusMessage};
/// Trait to produce a `StatusMessage` representing the state of the given `beacon_chain`.
///
/// NOTE: The purpose of this is simply to obtain a `StatusMessage` from the `BeaconChain` without
/// polluting/coupling the type with RPC concepts.
pub trait ToStatusMessage {
fn status_message(&self) -> StatusMessage;
}
impl<T: BeaconChainTypes> ToStatusMessage for BeaconChain<T> {
fn status_message(&self) -> StatusMessage {
status_message(self)
}
}
/// Build a `StatusMessage` representing the state of the given `beacon_chain`.
pub(crate) fn status_message<T: BeaconChainTypes>(beacon_chain: &BeaconChain<T>) -> StatusMessage {
let fork_digest = beacon_chain.enr_fork_id().fork_digest;
let cached_head = beacon_chain.canonical_head.cached_head();
let mut finalized_checkpoint = cached_head.finalized_checkpoint();
// Alias the genesis checkpoint root to `0x00`.
let spec = &beacon_chain.spec;
let genesis_epoch = spec.genesis_slot.epoch(T::EthSpec::slots_per_epoch());
if finalized_checkpoint.epoch == genesis_epoch {
finalized_checkpoint.root = Hash256::zero();
}
// NOTE: We are making an assumption that `get_data_column_custody_info` wont fail.
let earliest_available_data_column_slot = beacon_chain
.store
.get_data_column_custody_info()
.ok()
.flatten()
.and_then(|info| info.earliest_data_column_slot);
// If data_column_custody_info.earliest_data_column_slot is `None`,
// no recent cgc changes have occurred and no cgc backfill is in progress.
let earliest_available_slot =
if let Some(earliest_available_data_column_slot) = earliest_available_data_column_slot {
earliest_available_data_column_slot
} else {
beacon_chain.store.get_anchor_info().oldest_block_slot
};
StatusMessage::V2(StatusMessageV2 {
fork_digest,
finalized_root: finalized_checkpoint.root,
finalized_epoch: finalized_checkpoint.epoch,
head_root: cached_head.head_block_root(),
head_slot: cached_head.head_slot(),
earliest_available_slot,
})
}