mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-27 09:43:36 +00:00
Breakup RPCBlock into LookupBlock & RangeSyncBlock (#8860)
Co-Authored-By: Mark Mackey <mark@sigmaprime.io>
This commit is contained in:
@@ -13,7 +13,7 @@ use crate::block_verification::{
|
||||
signature_verify_chain_segment, verify_header_signature,
|
||||
};
|
||||
use crate::block_verification_types::{
|
||||
AsBlock, AvailableExecutedBlock, BlockImportData, ExecutedBlock, RpcBlock,
|
||||
AsBlock, AvailableExecutedBlock, BlockImportData, ExecutedBlock, RangeSyncBlock,
|
||||
};
|
||||
pub use crate::canonical_head::CanonicalHead;
|
||||
use crate::chain_config::ChainConfig;
|
||||
@@ -137,7 +137,7 @@ use types::*;
|
||||
pub type ForkChoiceError = fork_choice::Error<crate::ForkChoiceStoreError>;
|
||||
|
||||
/// Alias to appease clippy.
|
||||
type HashBlockTuple<E> = (Hash256, RpcBlock<E>);
|
||||
type HashBlockTuple<E> = (Hash256, RangeSyncBlock<E>);
|
||||
|
||||
// These keys are all zero because they get stored in different columns, see `DBColumn` type.
|
||||
pub const BEACON_CHAIN_DB_KEY: Hash256 = Hash256::ZERO;
|
||||
@@ -2746,7 +2746,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
/// This method is potentially long-running and should not run on the core executor.
|
||||
pub fn filter_chain_segment(
|
||||
self: &Arc<Self>,
|
||||
chain_segment: Vec<RpcBlock<T::EthSpec>>,
|
||||
chain_segment: Vec<RangeSyncBlock<T::EthSpec>>,
|
||||
) -> Result<Vec<HashBlockTuple<T::EthSpec>>, Box<ChainSegmentResult>> {
|
||||
// This function will never import any blocks.
|
||||
let imported_blocks = vec![];
|
||||
@@ -2855,7 +2855,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
/// `Self::process_block`.
|
||||
pub async fn process_chain_segment(
|
||||
self: &Arc<Self>,
|
||||
chain_segment: Vec<RpcBlock<T::EthSpec>>,
|
||||
chain_segment: Vec<RangeSyncBlock<T::EthSpec>>,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> ChainSegmentResult {
|
||||
for block in chain_segment.iter() {
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
use crate::beacon_snapshot::PreProcessingSnapshot;
|
||||
use crate::blob_verification::GossipBlobError;
|
||||
use crate::block_verification_types::{AsBlock, BlockImportData, RpcBlock};
|
||||
use crate::block_verification_types::{AsBlock, BlockImportData, LookupBlock, RangeSyncBlock};
|
||||
use crate::data_availability_checker::{
|
||||
AvailabilityCheckError, AvailableBlock, AvailableBlockData, MaybeAvailableBlock,
|
||||
};
|
||||
@@ -585,7 +585,7 @@ pub(crate) fn process_block_slash_info<T: BeaconChainTypes, TErr: BlockBlobError
|
||||
/// will be returned.
|
||||
#[instrument(skip_all)]
|
||||
pub fn signature_verify_chain_segment<T: BeaconChainTypes>(
|
||||
mut chain_segment: Vec<(Hash256, RpcBlock<T::EthSpec>)>,
|
||||
mut chain_segment: Vec<(Hash256, RangeSyncBlock<T::EthSpec>)>,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<Vec<SignatureVerifiedBlock<T>>, BlockError> {
|
||||
if chain_segment.is_empty() {
|
||||
@@ -616,24 +616,14 @@ pub fn signature_verify_chain_segment<T: BeaconChainTypes>(
|
||||
let consensus_context =
|
||||
ConsensusContext::new(block.slot()).set_current_block_root(block_root);
|
||||
|
||||
match block {
|
||||
RpcBlock::FullyAvailable(available_block) => {
|
||||
available_blocks.push(available_block.clone());
|
||||
signature_verified_blocks.push(SignatureVerifiedBlock {
|
||||
block: MaybeAvailableBlock::Available(available_block),
|
||||
block_root,
|
||||
parent: None,
|
||||
consensus_context,
|
||||
});
|
||||
}
|
||||
RpcBlock::BlockOnly { .. } => {
|
||||
// RangeSync and BackfillSync already ensure that the chain segment is fully available
|
||||
// so this shouldn't be possible in practice.
|
||||
return Err(BlockError::InternalError(
|
||||
"Chain segment is not fully available".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
let available_block = block.into_available_block();
|
||||
available_blocks.push(available_block.clone());
|
||||
signature_verified_blocks.push(SignatureVerifiedBlock {
|
||||
block: MaybeAvailableBlock::Available(available_block),
|
||||
block_root,
|
||||
parent: None,
|
||||
consensus_context,
|
||||
});
|
||||
}
|
||||
|
||||
chain
|
||||
@@ -1300,11 +1290,11 @@ impl<T: BeaconChainTypes> IntoExecutionPendingBlock<T> for SignatureVerifiedBloc
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BeaconChainTypes> IntoExecutionPendingBlock<T> for RpcBlock<T::EthSpec> {
|
||||
impl<T: BeaconChainTypes> IntoExecutionPendingBlock<T> for RangeSyncBlock<T::EthSpec> {
|
||||
/// Verifies the `SignedBeaconBlock` by first transforming it into a `SignatureVerifiedBlock`
|
||||
/// and then using that implementation of `IntoExecutionPendingBlock` to complete verification.
|
||||
#[instrument(
|
||||
name = "rpc_block_into_execution_pending_block_slashable",
|
||||
name = "range_sync_block_into_execution_pending_block_slashable",
|
||||
level = "debug"
|
||||
skip_all,
|
||||
)]
|
||||
@@ -1318,24 +1308,51 @@ impl<T: BeaconChainTypes> IntoExecutionPendingBlock<T> for RpcBlock<T::EthSpec>
|
||||
let block_root = check_block_relevancy(self.as_block(), block_root, chain)
|
||||
.map_err(|e| BlockSlashInfo::SignatureNotChecked(self.signed_block_header(), e))?;
|
||||
|
||||
let maybe_available_block = match &self {
|
||||
RpcBlock::FullyAvailable(available_block) => {
|
||||
chain
|
||||
.data_availability_checker
|
||||
.verify_kzg_for_available_block(available_block)
|
||||
.map_err(|e| {
|
||||
BlockSlashInfo::SignatureNotChecked(
|
||||
self.signed_block_header(),
|
||||
BlockError::AvailabilityCheck(e),
|
||||
)
|
||||
})?;
|
||||
MaybeAvailableBlock::Available(available_block.clone())
|
||||
}
|
||||
// No need to perform KZG verification unless we have a fully available block
|
||||
RpcBlock::BlockOnly { block, block_root } => MaybeAvailableBlock::AvailabilityPending {
|
||||
block_root: *block_root,
|
||||
block: block.clone(),
|
||||
},
|
||||
let available_block = self.into_available_block();
|
||||
chain
|
||||
.data_availability_checker
|
||||
.verify_kzg_for_available_block(&available_block)
|
||||
.map_err(|e| {
|
||||
BlockSlashInfo::SignatureNotChecked(
|
||||
available_block.as_block().signed_block_header(),
|
||||
BlockError::AvailabilityCheck(e),
|
||||
)
|
||||
})?;
|
||||
let maybe_available_block = MaybeAvailableBlock::Available(available_block);
|
||||
SignatureVerifiedBlock::check_slashable(maybe_available_block, block_root, chain)?
|
||||
.into_execution_pending_block_slashable(block_root, chain, notify_execution_layer)
|
||||
}
|
||||
|
||||
fn block(&self) -> &SignedBeaconBlock<T::EthSpec> {
|
||||
self.as_block()
|
||||
}
|
||||
|
||||
fn block_cloned(&self) -> Arc<SignedBeaconBlock<T::EthSpec>> {
|
||||
self.block_cloned()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BeaconChainTypes> IntoExecutionPendingBlock<T> for LookupBlock<T::EthSpec> {
|
||||
/// Verifies the `SignedBeaconBlock` by first transforming it into a `SignatureVerifiedBlock`
|
||||
/// and then using that implementation of `IntoExecutionPendingBlock` to complete verification.
|
||||
#[instrument(
|
||||
name = "lookup_block_into_execution_pending_block_slashable",
|
||||
level = "debug"
|
||||
skip_all,
|
||||
)]
|
||||
fn into_execution_pending_block_slashable(
|
||||
self,
|
||||
block_root: Hash256,
|
||||
chain: &Arc<BeaconChain<T>>,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> Result<ExecutionPendingBlock<T>, BlockSlashInfo<BlockError>> {
|
||||
// Perform an early check to prevent wasting time on irrelevant blocks.
|
||||
let block_root = check_block_relevancy(self.as_block(), block_root, chain)
|
||||
.map_err(|e| BlockSlashInfo::SignatureNotChecked(self.signed_block_header(), e))?;
|
||||
|
||||
let maybe_available_block = MaybeAvailableBlock::AvailabilityPending {
|
||||
block_root,
|
||||
block: self.block_cloned(),
|
||||
};
|
||||
|
||||
SignatureVerifiedBlock::check_slashable(maybe_available_block, block_root, chain)?
|
||||
|
||||
@@ -13,76 +13,70 @@ use types::{
|
||||
SignedBeaconBlock, SignedBeaconBlockHeader, Slot,
|
||||
};
|
||||
|
||||
/// A block that has been received over RPC. It has 2 internal variants:
|
||||
///
|
||||
/// 1. `FullyAvailable`: A fully available block. This can either be a pre-deneb block, a
|
||||
/// post-Deneb block with blobs, a post-Fulu block with the columns the node is required to custody,
|
||||
/// or a post-Deneb block that doesn't require blobs/columns. Hence, it is fully self contained w.r.t
|
||||
/// verification. i.e. this block has all the required data to get verified and imported into fork choice.
|
||||
///
|
||||
/// 2. `BlockOnly`: This is a post-deneb block that requires blobs to be considered fully available.
|
||||
#[derive(Clone, Educe)]
|
||||
#[educe(Hash(bound(E: EthSpec)))]
|
||||
pub enum RpcBlock<E: EthSpec> {
|
||||
FullyAvailable(AvailableBlock<E>),
|
||||
BlockOnly {
|
||||
block: Arc<SignedBeaconBlock<E>>,
|
||||
block_root: Hash256,
|
||||
},
|
||||
/// A wrapper around a `SignedBeaconBlock`. This varaint is constructed
|
||||
/// when lookup sync only fetches a single block. It does not contain
|
||||
/// any blobs or data columns.
|
||||
pub struct LookupBlock<E: EthSpec> {
|
||||
block: Arc<SignedBeaconBlock<E>>,
|
||||
block_root: Hash256,
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Debug for RpcBlock<E> {
|
||||
impl<E: EthSpec> LookupBlock<E> {
|
||||
pub fn new(block: Arc<SignedBeaconBlock<E>>) -> Self {
|
||||
let block_root = block.canonical_root();
|
||||
Self { block, block_root }
|
||||
}
|
||||
|
||||
pub fn block(&self) -> &SignedBeaconBlock<E> {
|
||||
&self.block
|
||||
}
|
||||
|
||||
pub fn block_root(&self) -> Hash256 {
|
||||
self.block_root
|
||||
}
|
||||
|
||||
pub fn block_cloned(&self) -> Arc<SignedBeaconBlock<E>> {
|
||||
self.block.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// 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>,
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Debug for RangeSyncBlock<E> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "RpcBlock({:?})", self.block_root())
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> RpcBlock<E> {
|
||||
impl<E: EthSpec> RangeSyncBlock<E> {
|
||||
pub fn block_root(&self) -> Hash256 {
|
||||
match self {
|
||||
RpcBlock::FullyAvailable(available_block) => available_block.block_root(),
|
||||
RpcBlock::BlockOnly { block_root, .. } => *block_root,
|
||||
}
|
||||
self.block.block_root()
|
||||
}
|
||||
|
||||
pub fn as_block(&self) -> &SignedBeaconBlock<E> {
|
||||
match self {
|
||||
RpcBlock::FullyAvailable(available_block) => available_block.block(),
|
||||
RpcBlock::BlockOnly { block, .. } => block,
|
||||
}
|
||||
self.block.block()
|
||||
}
|
||||
|
||||
pub fn block_cloned(&self) -> Arc<SignedBeaconBlock<E>> {
|
||||
match self {
|
||||
RpcBlock::FullyAvailable(available_block) => available_block.block_cloned(),
|
||||
RpcBlock::BlockOnly { block, .. } => block.clone(),
|
||||
}
|
||||
self.block.block_cloned()
|
||||
}
|
||||
|
||||
pub fn block_data(&self) -> Option<&AvailableBlockData<E>> {
|
||||
match self {
|
||||
RpcBlock::FullyAvailable(available_block) => Some(available_block.data()),
|
||||
RpcBlock::BlockOnly { .. } => None,
|
||||
}
|
||||
pub fn block_data(&self) -> &AvailableBlockData<E> {
|
||||
self.block.data()
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> RpcBlock<E> {
|
||||
/// Constructs an `RpcBlock` from a block and optional availability data.
|
||||
///
|
||||
/// This function creates an RpcBlock which can be in one of two states:
|
||||
/// - `FullyAvailable`: When `block_data` is provided, the block contains all required
|
||||
/// data for verification.
|
||||
/// - `BlockOnly`: When `block_data` is `None`, the block may still need additional
|
||||
/// data to be considered fully available (used during block lookups or when blobs
|
||||
/// will arrive separately).
|
||||
///
|
||||
/// # Validation
|
||||
///
|
||||
/// When `block_data` is provided, this function validates that:
|
||||
/// - Block data is not provided when not required.
|
||||
/// - Required blobs are present and match the expected count.
|
||||
/// - Required custody columns are included based on the nodes custody requirements.
|
||||
impl<E: EthSpec> RangeSyncBlock<E> {
|
||||
/// Constructs an `RangeSyncBlock` from a block and availability data.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
@@ -92,62 +86,41 @@ impl<E: EthSpec> RpcBlock<E> {
|
||||
/// - `MissingCustodyColumns`: Block requires custody columns but they are incomplete.
|
||||
pub fn new<T>(
|
||||
block: Arc<SignedBeaconBlock<E>>,
|
||||
block_data: Option<AvailableBlockData<E>>,
|
||||
block_data: AvailableBlockData<E>,
|
||||
da_checker: &DataAvailabilityChecker<T>,
|
||||
spec: Arc<ChainSpec>,
|
||||
) -> Result<Self, AvailabilityCheckError>
|
||||
where
|
||||
T: BeaconChainTypes<EthSpec = E>,
|
||||
{
|
||||
match block_data {
|
||||
Some(block_data) => Ok(RpcBlock::FullyAvailable(AvailableBlock::new(
|
||||
block, block_data, da_checker, spec,
|
||||
)?)),
|
||||
None => Ok(RpcBlock::BlockOnly {
|
||||
block_root: block.canonical_root(),
|
||||
block,
|
||||
}),
|
||||
}
|
||||
let available_block = AvailableBlock::new(block, block_data, da_checker, spec)?;
|
||||
Ok(Self {
|
||||
block: available_block,
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn deconstruct(
|
||||
self,
|
||||
) -> (
|
||||
Hash256,
|
||||
Arc<SignedBeaconBlock<E>>,
|
||||
Option<AvailableBlockData<E>>,
|
||||
) {
|
||||
match self {
|
||||
RpcBlock::FullyAvailable(available_block) => {
|
||||
let (block_root, block, block_data) = available_block.deconstruct();
|
||||
(block_root, block, Some(block_data))
|
||||
}
|
||||
RpcBlock::BlockOnly { block, block_root } => (block_root, block, None),
|
||||
}
|
||||
pub fn deconstruct(self) -> (Hash256, Arc<SignedBeaconBlock<E>>, AvailableBlockData<E>) {
|
||||
self.block.deconstruct()
|
||||
}
|
||||
|
||||
pub fn n_blobs(&self) -> usize {
|
||||
if let Some(block_data) = self.block_data() {
|
||||
match block_data {
|
||||
AvailableBlockData::NoData | AvailableBlockData::DataColumns(_) => 0,
|
||||
AvailableBlockData::Blobs(blobs) => blobs.len(),
|
||||
}
|
||||
} else {
|
||||
0
|
||||
match self.block_data() {
|
||||
AvailableBlockData::NoData | AvailableBlockData::DataColumns(_) => 0,
|
||||
AvailableBlockData::Blobs(blobs) => blobs.len(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn n_data_columns(&self) -> usize {
|
||||
if let Some(block_data) = self.block_data() {
|
||||
match block_data {
|
||||
AvailableBlockData::NoData | AvailableBlockData::Blobs(_) => 0,
|
||||
AvailableBlockData::DataColumns(columns) => columns.len(),
|
||||
}
|
||||
} else {
|
||||
0
|
||||
match self.block_data() {
|
||||
AvailableBlockData::NoData | AvailableBlockData::Blobs(_) => 0,
|
||||
AvailableBlockData::DataColumns(columns) => columns.len(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_available_block(self) -> AvailableBlock<E> {
|
||||
self.block
|
||||
}
|
||||
}
|
||||
|
||||
/// A block that has gone through all pre-deneb block processing checks including block processing
|
||||
@@ -412,7 +385,7 @@ impl<E: EthSpec> AsBlock<E> for AvailableBlock<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> AsBlock<E> for RpcBlock<E> {
|
||||
impl<E: EthSpec> AsBlock<E> for RangeSyncBlock<E> {
|
||||
fn slot(&self) -> Slot {
|
||||
self.as_block().slot()
|
||||
}
|
||||
@@ -432,24 +405,42 @@ impl<E: EthSpec> AsBlock<E> for RpcBlock<E> {
|
||||
self.as_block().message()
|
||||
}
|
||||
fn as_block(&self) -> &SignedBeaconBlock<E> {
|
||||
match self {
|
||||
Self::BlockOnly {
|
||||
block,
|
||||
block_root: _,
|
||||
} => block,
|
||||
Self::FullyAvailable(available_block) => available_block.block(),
|
||||
}
|
||||
self.block.as_block()
|
||||
}
|
||||
fn block_cloned(&self) -> Arc<SignedBeaconBlock<E>> {
|
||||
match self {
|
||||
RpcBlock::FullyAvailable(available_block) => available_block.block_cloned(),
|
||||
RpcBlock::BlockOnly {
|
||||
block,
|
||||
block_root: _,
|
||||
} => block.clone(),
|
||||
}
|
||||
self.block.block_cloned()
|
||||
}
|
||||
fn canonical_root(&self) -> Hash256 {
|
||||
self.as_block().canonical_root()
|
||||
self.block.block_root()
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> AsBlock<E> for LookupBlock<E> {
|
||||
fn slot(&self) -> Slot {
|
||||
self.block().slot()
|
||||
}
|
||||
fn epoch(&self) -> Epoch {
|
||||
self.block().epoch()
|
||||
}
|
||||
fn parent_root(&self) -> Hash256 {
|
||||
self.block().parent_root()
|
||||
}
|
||||
fn state_root(&self) -> Hash256 {
|
||||
self.block().state_root()
|
||||
}
|
||||
fn signed_block_header(&self) -> SignedBeaconBlockHeader {
|
||||
self.block().signed_block_header()
|
||||
}
|
||||
fn message(&self) -> BeaconBlockRef<'_, E> {
|
||||
self.block().message()
|
||||
}
|
||||
fn as_block(&self) -> &SignedBeaconBlock<E> {
|
||||
self.block()
|
||||
}
|
||||
fn block_cloned(&self) -> Arc<SignedBeaconBlock<E>> {
|
||||
self.block_cloned()
|
||||
}
|
||||
fn canonical_root(&self) -> Hash256 {
|
||||
self.block_root
|
||||
}
|
||||
}
|
||||
|
||||
@@ -891,7 +891,7 @@ impl<E: EthSpec> MaybeAvailableBlock<E> {
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::CustodyContext;
|
||||
use crate::block_verification_types::RpcBlock;
|
||||
use crate::block_verification_types::RangeSyncBlock;
|
||||
use crate::custody_context::NodeCustodyType;
|
||||
use crate::data_column_verification::CustodyDataColumn;
|
||||
use crate::test_utils::{
|
||||
@@ -1085,7 +1085,7 @@ mod test {
|
||||
|
||||
/// Regression test for KZG verification truncation bug (https://github.com/sigp/lighthouse/pull/7927)
|
||||
#[test]
|
||||
fn verify_kzg_for_rpc_blocks_should_not_truncate_data_columns_fulu() {
|
||||
fn verify_kzg_for_range_sync_blocks_should_not_truncate_data_columns_fulu() {
|
||||
let spec = Arc::new(ForkName::Fulu.make_genesis_spec(E::default_spec()));
|
||||
let mut rng = StdRng::seed_from_u64(0xDEADBEEF0BAD5EEDu64);
|
||||
let da_checker = new_da_checker(spec.clone());
|
||||
@@ -1128,17 +1128,14 @@ mod test {
|
||||
|
||||
let block_data = AvailableBlockData::new_with_data_columns(custody_columns);
|
||||
let da_checker = Arc::new(new_da_checker(spec.clone()));
|
||||
RpcBlock::new(Arc::new(block), Some(block_data), &da_checker, spec.clone())
|
||||
RangeSyncBlock::new(Arc::new(block), block_data, &da_checker, spec.clone())
|
||||
.expect("should create RPC block with custody columns")
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let available_blocks = blocks_with_columns
|
||||
.iter()
|
||||
.filter_map(|block| match block {
|
||||
RpcBlock::FullyAvailable(available_block) => Some(available_block.clone()),
|
||||
RpcBlock::BlockOnly { .. } => None,
|
||||
})
|
||||
.into_iter()
|
||||
.map(|block| block.into_available_block())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// WHEN verifying all blocks together (totalling 256 data columns)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::blob_verification::GossipVerifiedBlob;
|
||||
use crate::block_verification_types::{AsBlock, AvailableBlockData, RpcBlock};
|
||||
use crate::block_verification_types::{AsBlock, AvailableBlockData, LookupBlock, RangeSyncBlock};
|
||||
use crate::custody_context::NodeCustodyType;
|
||||
use crate::data_availability_checker::DataAvailabilityChecker;
|
||||
use crate::graffiti_calculator::GraffitiSettings;
|
||||
@@ -823,20 +823,20 @@ where
|
||||
mock_builder_server
|
||||
}
|
||||
|
||||
pub fn get_head_block(&self) -> RpcBlock<E> {
|
||||
pub fn get_head_block(&self) -> RangeSyncBlock<E> {
|
||||
let block = self.chain.head_beacon_block();
|
||||
let block_root = block.canonical_root();
|
||||
self.build_rpc_block_from_store_blobs(Some(block_root), block)
|
||||
self.build_range_sync_block_from_store_blobs(Some(block_root), block)
|
||||
}
|
||||
|
||||
pub fn get_full_block(&self, block_root: &Hash256) -> RpcBlock<E> {
|
||||
pub fn get_full_block(&self, block_root: &Hash256) -> RangeSyncBlock<E> {
|
||||
let block = self
|
||||
.chain
|
||||
.get_blinded_block(block_root)
|
||||
.unwrap()
|
||||
.unwrap_or_else(|| panic!("block root does not exist in harness {block_root:?}"));
|
||||
let full_block = self.chain.store.make_full_block(block_root, block).unwrap();
|
||||
self.build_rpc_block_from_store_blobs(Some(*block_root), Arc::new(full_block))
|
||||
self.build_range_sync_block_from_store_blobs(Some(*block_root), Arc::new(full_block))
|
||||
}
|
||||
|
||||
pub fn get_all_validators(&self) -> Vec<usize> {
|
||||
@@ -1340,15 +1340,12 @@ where
|
||||
|
||||
let signed_block = self.sign_beacon_block(block, state);
|
||||
let block_root = signed_block.canonical_root();
|
||||
let rpc_block = RpcBlock::BlockOnly {
|
||||
block_root,
|
||||
block: Arc::new(signed_block),
|
||||
};
|
||||
let lookup_block = LookupBlock::new(Arc::new(signed_block));
|
||||
self.chain.slot_clock.set_slot(slot.as_u64());
|
||||
self.chain
|
||||
.process_block(
|
||||
block_root,
|
||||
rpc_block,
|
||||
lookup_block,
|
||||
NotifyExecutionLayer::No,
|
||||
BlockImportSource::Lookup,
|
||||
|| Ok(()),
|
||||
@@ -2607,20 +2604,33 @@ where
|
||||
.blob_kzg_commitments()
|
||||
.is_ok_and(|c| !c.is_empty());
|
||||
let is_available = !has_blob_commitments || blob_items.is_some();
|
||||
let block_hash: SignedBeaconBlockHash = if !is_available {
|
||||
self.chain
|
||||
.process_block(
|
||||
block_root,
|
||||
LookupBlock::new(block),
|
||||
NotifyExecutionLayer::Yes,
|
||||
BlockImportSource::Lookup,
|
||||
|| Ok(()),
|
||||
)
|
||||
.await?
|
||||
.try_into()
|
||||
.expect("block blobs are available")
|
||||
} else {
|
||||
let range_sync_block = self.build_range_sync_block_from_blobs(block, blob_items)?;
|
||||
self.chain
|
||||
.process_block(
|
||||
block_root,
|
||||
range_sync_block,
|
||||
NotifyExecutionLayer::Yes,
|
||||
BlockImportSource::RangeSync,
|
||||
|| Ok(()),
|
||||
)
|
||||
.await?
|
||||
.try_into()
|
||||
.expect("block blobs are available")
|
||||
};
|
||||
|
||||
let rpc_block = self.build_rpc_block_from_blobs(block, blob_items, is_available)?;
|
||||
let block_hash: SignedBeaconBlockHash = self
|
||||
.chain
|
||||
.process_block(
|
||||
block_root,
|
||||
rpc_block,
|
||||
NotifyExecutionLayer::Yes,
|
||||
BlockImportSource::RangeSync,
|
||||
|| Ok(()),
|
||||
)
|
||||
.await?
|
||||
.try_into()
|
||||
.expect("block blobs are available");
|
||||
self.chain.recompute_head_at_current_slot().await;
|
||||
Ok(block_hash)
|
||||
}
|
||||
@@ -2640,19 +2650,33 @@ where
|
||||
.blob_kzg_commitments()
|
||||
.is_ok_and(|c| !c.is_empty());
|
||||
let is_available = !has_blob_commitments || blob_items.is_some();
|
||||
let rpc_block = self.build_rpc_block_from_blobs(block, blob_items, is_available)?;
|
||||
let block_hash: SignedBeaconBlockHash = self
|
||||
.chain
|
||||
.process_block(
|
||||
block_root,
|
||||
rpc_block,
|
||||
NotifyExecutionLayer::Yes,
|
||||
BlockImportSource::RangeSync,
|
||||
|| Ok(()),
|
||||
)
|
||||
.await?
|
||||
.try_into()
|
||||
.expect("block blobs are available");
|
||||
let block_hash: SignedBeaconBlockHash = if is_available {
|
||||
let range_sync_block = self.build_range_sync_block_from_blobs(block, blob_items)?;
|
||||
self.chain
|
||||
.process_block(
|
||||
block_root,
|
||||
range_sync_block,
|
||||
NotifyExecutionLayer::Yes,
|
||||
BlockImportSource::RangeSync,
|
||||
|| Ok(()),
|
||||
)
|
||||
.await?
|
||||
.try_into()
|
||||
.expect("block blobs are available")
|
||||
} else {
|
||||
self.chain
|
||||
.process_block(
|
||||
block_root,
|
||||
LookupBlock::new(block),
|
||||
NotifyExecutionLayer::Yes,
|
||||
BlockImportSource::Lookup,
|
||||
|| Ok(()),
|
||||
)
|
||||
.await?
|
||||
.try_into()
|
||||
.expect("block blobs are available")
|
||||
};
|
||||
|
||||
self.chain.recompute_head_at_current_slot().await;
|
||||
Ok(block_hash)
|
||||
}
|
||||
@@ -2735,13 +2759,13 @@ where
|
||||
state_root
|
||||
}
|
||||
|
||||
/// Builds an `Rpc` block from a `SignedBeaconBlock` and blobs or data columns retrieved from
|
||||
/// Builds a `RangeSyncBlock` from a `SignedBeaconBlock` and blobs or data columns retrieved from
|
||||
/// the database.
|
||||
pub fn build_rpc_block_from_store_blobs(
|
||||
pub fn build_range_sync_block_from_store_blobs(
|
||||
&self,
|
||||
block_root: Option<Hash256>,
|
||||
block: Arc<SignedBeaconBlock<E>>,
|
||||
) -> RpcBlock<E> {
|
||||
) -> RangeSyncBlock<E> {
|
||||
let block_root = block_root.unwrap_or_else(|| get_block_root(&block));
|
||||
let has_blobs = block
|
||||
.message()
|
||||
@@ -2749,9 +2773,9 @@ where
|
||||
.blob_kzg_commitments()
|
||||
.is_ok_and(|c| !c.is_empty());
|
||||
if !has_blobs {
|
||||
return RpcBlock::new(
|
||||
return RangeSyncBlock::new(
|
||||
block,
|
||||
Some(AvailableBlockData::NoData),
|
||||
AvailableBlockData::NoData,
|
||||
&self.chain.data_availability_checker,
|
||||
self.chain.spec.clone(),
|
||||
)
|
||||
@@ -2768,9 +2792,9 @@ where
|
||||
.unwrap();
|
||||
let custody_columns = columns.into_iter().collect::<Vec<_>>();
|
||||
let block_data = AvailableBlockData::new_with_data_columns(custody_columns);
|
||||
RpcBlock::new(
|
||||
RangeSyncBlock::new(
|
||||
block,
|
||||
Some(block_data),
|
||||
block_data,
|
||||
&self.chain.data_availability_checker,
|
||||
self.chain.spec.clone(),
|
||||
)
|
||||
@@ -2783,9 +2807,9 @@ where
|
||||
AvailableBlockData::NoData
|
||||
};
|
||||
|
||||
RpcBlock::new(
|
||||
RangeSyncBlock::new(
|
||||
block,
|
||||
Some(block_data),
|
||||
block_data,
|
||||
&self.chain.data_availability_checker,
|
||||
self.chain.spec.clone(),
|
||||
)
|
||||
@@ -2793,18 +2817,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds an `RpcBlock` from a `SignedBeaconBlock` and `BlobsList`.
|
||||
pub fn build_rpc_block_from_blobs(
|
||||
/// Builds a `RangeSyncBlock` from a `SignedBeaconBlock` and `BlobsList`.
|
||||
pub fn build_range_sync_block_from_blobs(
|
||||
&self,
|
||||
block: Arc<SignedBeaconBlock<E, FullPayload<E>>>,
|
||||
blob_items: Option<(KzgProofs<E>, BlobsList<E>)>,
|
||||
is_available: bool,
|
||||
) -> Result<RpcBlock<E>, BlockError> {
|
||||
) -> Result<RangeSyncBlock<E>, BlockError> {
|
||||
Ok(if self.spec.is_peer_das_enabled_for_epoch(block.epoch()) {
|
||||
let epoch = block.slot().epoch(E::slots_per_epoch());
|
||||
let sampling_columns = self.chain.sampling_columns_for_epoch(epoch);
|
||||
|
||||
if blob_items.is_some_and(|(_, blobs)| !blobs.is_empty()) {
|
||||
if blob_items.is_some_and(|(kzg_proofs, _)| !kzg_proofs.is_empty()) {
|
||||
// Note: this method ignores the actual custody columns and just take the first
|
||||
// `sampling_column_count` for testing purpose only, because the chain does not
|
||||
// currently have any knowledge of the columns being custodied.
|
||||
@@ -2812,33 +2835,17 @@ where
|
||||
.into_iter()
|
||||
.filter(|d| sampling_columns.contains(d.index()))
|
||||
.collect::<Vec<_>>();
|
||||
if is_available {
|
||||
let block_data = AvailableBlockData::new_with_data_columns(columns);
|
||||
RpcBlock::new(
|
||||
block,
|
||||
Some(block_data),
|
||||
&self.chain.data_availability_checker,
|
||||
self.chain.spec.clone(),
|
||||
)?
|
||||
} else {
|
||||
RpcBlock::new(
|
||||
block,
|
||||
None,
|
||||
&self.chain.data_availability_checker,
|
||||
self.chain.spec.clone(),
|
||||
)?
|
||||
}
|
||||
} else if is_available {
|
||||
RpcBlock::new(
|
||||
let block_data = AvailableBlockData::new_with_data_columns(columns);
|
||||
RangeSyncBlock::new(
|
||||
block,
|
||||
Some(AvailableBlockData::NoData),
|
||||
block_data,
|
||||
&self.chain.data_availability_checker,
|
||||
self.chain.spec.clone(),
|
||||
)?
|
||||
} else {
|
||||
RpcBlock::new(
|
||||
RangeSyncBlock::new(
|
||||
block,
|
||||
None,
|
||||
AvailableBlockData::NoData,
|
||||
&self.chain.data_availability_checker,
|
||||
self.chain.spec.clone(),
|
||||
)?
|
||||
@@ -2850,27 +2857,18 @@ where
|
||||
})
|
||||
.transpose()
|
||||
.unwrap();
|
||||
if is_available {
|
||||
let block_data = if let Some(blobs) = blobs {
|
||||
AvailableBlockData::new_with_blobs(blobs)
|
||||
} else {
|
||||
AvailableBlockData::NoData
|
||||
};
|
||||
|
||||
RpcBlock::new(
|
||||
block,
|
||||
Some(block_data),
|
||||
&self.chain.data_availability_checker,
|
||||
self.chain.spec.clone(),
|
||||
)?
|
||||
let block_data = if let Some(blobs) = blobs {
|
||||
AvailableBlockData::new_with_blobs(blobs)
|
||||
} else {
|
||||
RpcBlock::new(
|
||||
block,
|
||||
None,
|
||||
&self.chain.data_availability_checker,
|
||||
self.chain.spec.clone(),
|
||||
)?
|
||||
}
|
||||
AvailableBlockData::NoData
|
||||
};
|
||||
|
||||
RangeSyncBlock::new(
|
||||
block,
|
||||
block_data,
|
||||
&self.chain.data_availability_checker,
|
||||
self.chain.spec.clone(),
|
||||
)?
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user