mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-21 14:58:31 +00:00
Add range sync machinery on sync side
This commit is contained in:
@@ -2,10 +2,11 @@ use crate::data_availability_checker::{AvailabilityCheckError, DataAvailabilityC
|
||||
pub use crate::data_availability_checker::{
|
||||
AvailableBlock, AvailableBlockData, MaybeAvailableBlock,
|
||||
};
|
||||
use crate::payload_envelope_verification::AvailableEnvelope;
|
||||
use crate::{BeaconChainTypes, PayloadVerificationOutcome};
|
||||
use educe::Educe;
|
||||
use state_processing::ConsensusContext;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::sync::Arc;
|
||||
use types::data::BlobIdentifier;
|
||||
use types::{
|
||||
@@ -40,43 +41,63 @@ impl<E: EthSpec> LookupBlock<E> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A fully available block that has been constructed by range sync.
|
||||
/// The block contains all the data required to import into fork choice.
|
||||
/// This includes any and all blobs/columns required, including zero if
|
||||
/// none are required. This can happen if the block is pre-deneb or if
|
||||
/// it's simply past the DA boundary.
|
||||
#[derive(Clone, Educe)]
|
||||
#[educe(Hash(bound(E: EthSpec)))]
|
||||
pub struct RangeSyncBlock<E: EthSpec> {
|
||||
block: AvailableBlock<E>,
|
||||
/// A block that has been constructed by range sync with all required data.
|
||||
///
|
||||
/// - `Base`: Pre-Gloas blocks bundled as an `AvailableBlock` (block + blobs/columns).
|
||||
/// - `Gloas`: Post-Gloas blocks where the execution payload is a separate envelope.
|
||||
#[derive(Clone)]
|
||||
pub enum RangeSyncBlock<E: EthSpec> {
|
||||
Base(AvailableBlock<E>),
|
||||
Gloas {
|
||||
block: Arc<SignedBeaconBlock<E>>,
|
||||
envelope: Option<Box<AvailableEnvelope<E>>>,
|
||||
},
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Hash for RangeSyncBlock<E> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.block_root().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Debug for RangeSyncBlock<E> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "RpcBlock({:?})", self.block_root())
|
||||
write!(f, "RangeSyncBlock({:?})", self.block_root())
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> RangeSyncBlock<E> {
|
||||
pub fn block_root(&self) -> Hash256 {
|
||||
self.block.block_root()
|
||||
match self {
|
||||
Self::Base(block) => block.block_root(),
|
||||
Self::Gloas { block, .. } => block.canonical_root(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_block(&self) -> &SignedBeaconBlock<E> {
|
||||
self.block.block()
|
||||
match self {
|
||||
Self::Base(block) => block.block(),
|
||||
Self::Gloas { block, .. } => block,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn block_cloned(&self) -> Arc<SignedBeaconBlock<E>> {
|
||||
self.block.block_cloned()
|
||||
match self {
|
||||
Self::Base(block) => block.block_cloned(),
|
||||
Self::Gloas { block, .. } => block.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn block_data(&self) -> &AvailableBlockData<E> {
|
||||
self.block.data()
|
||||
match self {
|
||||
Self::Base(block) => block.data(),
|
||||
Self::Gloas { .. } => {
|
||||
unreachable!("block_data called on Gloas variant — use envelope data instead")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> RangeSyncBlock<E> {
|
||||
/// Constructs an `RangeSyncBlock` from a block and availability data.
|
||||
/// Constructs a `Base` variant from a block and availability data.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
@@ -94,32 +115,54 @@ impl<E: EthSpec> RangeSyncBlock<E> {
|
||||
T: BeaconChainTypes<EthSpec = E>,
|
||||
{
|
||||
let available_block = AvailableBlock::new(block, block_data, da_checker, spec)?;
|
||||
Ok(Self {
|
||||
block: available_block,
|
||||
})
|
||||
Ok(Self::Base(available_block))
|
||||
}
|
||||
|
||||
/// Constructs a `Gloas` variant from a block and optional available envelope.
|
||||
pub fn new_gloas(
|
||||
block: Arc<SignedBeaconBlock<E>>,
|
||||
envelope: Option<Box<AvailableEnvelope<E>>>,
|
||||
) -> Self {
|
||||
Self::Gloas { block, envelope }
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn deconstruct(self) -> (Hash256, Arc<SignedBeaconBlock<E>>, AvailableBlockData<E>) {
|
||||
self.block.deconstruct()
|
||||
match self {
|
||||
Self::Base(block) => block.deconstruct(),
|
||||
Self::Gloas { .. } => {
|
||||
unreachable!("deconstruct called on Gloas variant")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn n_blobs(&self) -> usize {
|
||||
match self.block_data() {
|
||||
AvailableBlockData::NoData | AvailableBlockData::DataColumns(_) => 0,
|
||||
AvailableBlockData::Blobs(blobs) => blobs.len(),
|
||||
match self {
|
||||
Self::Base(block) => match block.data() {
|
||||
AvailableBlockData::NoData | AvailableBlockData::DataColumns(_) => 0,
|
||||
AvailableBlockData::Blobs(blobs) => blobs.len(),
|
||||
},
|
||||
Self::Gloas { .. } => 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn n_data_columns(&self) -> usize {
|
||||
match self.block_data() {
|
||||
AvailableBlockData::NoData | AvailableBlockData::Blobs(_) => 0,
|
||||
AvailableBlockData::DataColumns(columns) => columns.len(),
|
||||
match self {
|
||||
Self::Base(block) => match block.data() {
|
||||
AvailableBlockData::NoData | AvailableBlockData::Blobs(_) => 0,
|
||||
AvailableBlockData::DataColumns(columns) => columns.len(),
|
||||
},
|
||||
Self::Gloas { .. } => 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_available_block(self) -> AvailableBlock<E> {
|
||||
self.block
|
||||
match self {
|
||||
Self::Base(block) => block,
|
||||
Self::Gloas { .. } => {
|
||||
unreachable!("into_available_block called on Gloas variant")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,13 +448,13 @@ impl<E: EthSpec> AsBlock<E> for RangeSyncBlock<E> {
|
||||
self.as_block().message()
|
||||
}
|
||||
fn as_block(&self) -> &SignedBeaconBlock<E> {
|
||||
self.block.as_block()
|
||||
RangeSyncBlock::as_block(self)
|
||||
}
|
||||
fn block_cloned(&self) -> Arc<SignedBeaconBlock<E>> {
|
||||
self.block.block_cloned()
|
||||
RangeSyncBlock::block_cloned(self)
|
||||
}
|
||||
fn canonical_root(&self) -> Hash256 {
|
||||
self.block.block_root()
|
||||
self.block_root()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ use tracing::{debug, error, instrument};
|
||||
use types::data::{BlobIdentifier, FixedBlobSidecarList};
|
||||
use types::{
|
||||
BlobSidecar, BlobSidecarList, BlockImportSource, ChainSpec, DataColumnSidecar,
|
||||
DataColumnSidecarList, Epoch, EthSpec, Hash256, SignedBeaconBlock, Slot,
|
||||
DataColumnSidecarList, Epoch, EthSpec, ForkName, Hash256, SignedBeaconBlock, Slot,
|
||||
};
|
||||
|
||||
mod error;
|
||||
@@ -420,6 +420,11 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
|
||||
self.da_check_required_for_epoch(epoch) && self.spec.is_peer_das_enabled_for_epoch(epoch)
|
||||
}
|
||||
|
||||
/// Determines if execution payload envelopes are required for an epoch (Gloas and later).
|
||||
pub fn envelopes_required_for_epoch(&self, epoch: Epoch) -> bool {
|
||||
self.spec.fork_name_at_epoch(epoch) >= ForkName::Gloas
|
||||
}
|
||||
|
||||
/// See `Self::blobs_required_for_epoch`
|
||||
fn blobs_required_for_block(&self, block: &SignedBeaconBlock<T::EthSpec>) -> bool {
|
||||
block.num_expected_blobs() > 0 && self.blobs_required_for_epoch(block.epoch())
|
||||
|
||||
@@ -47,7 +47,7 @@ pub struct EnvelopeImportData<E: EthSpec> {
|
||||
pub post_state: Box<BeaconState<E>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub struct AvailableEnvelope<E: EthSpec> {
|
||||
execution_block_hash: ExecutionBlockHash,
|
||||
|
||||
Reference in New Issue
Block a user