diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index 8f39b3758d..9632e6e9dd 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -7,7 +7,7 @@ use crate::attester_cache::{AttesterCache, AttesterCacheKey}; use crate::beacon_proposer_cache::compute_proposer_duties_from_head; use crate::beacon_proposer_cache::BeaconProposerCache; use crate::blob_cache::BlobCache; -use crate::blob_verification::{AsBlock, AvailableBlock, BlockWrapper}; +use crate::blob_verification::{AsBlock, AvailabilityPendingBlock, BlockWrapper}; use crate::block_times_cache::BlockTimesCache; use crate::block_verification::{ check_block_is_finalized_checkpoint_or_descendant, check_block_relevancy, get_block_root, @@ -2818,6 +2818,8 @@ impl BeaconChain { ); } + + let chain = self.clone(); let block_hash = self .spawn_blocking_handle( @@ -2849,7 +2851,7 @@ impl BeaconChain { #[allow(clippy::too_many_arguments)] fn import_block( &self, - signed_block: AvailableBlock, + signed_block: AvailabilityPendingBlock, block_root: Hash256, mut state: BeaconState, confirmed_state_roots: Vec, diff --git a/beacon_node/beacon_chain/src/blob_verification.rs b/beacon_node/beacon_chain/src/blob_verification.rs index 7a4493c973..4a1e255870 100644 --- a/beacon_node/beacon_chain/src/blob_verification.rs +++ b/beacon_node/beacon_chain/src/blob_verification.rs @@ -1,9 +1,10 @@ use derivative::Derivative; use slot_clock::SlotClock; use std::sync::Arc; +use tokio::task::JoinHandle; use crate::beacon_chain::{BeaconChain, BeaconChainTypes, MAXIMUM_GOSSIP_CLOCK_DISPARITY}; -use crate::{kzg_utils, BeaconChainError}; +use crate::{kzg_utils, BeaconChainError, BlockError}; use state_processing::per_block_processing::eip4844::eip4844::verify_kzg_commitments_against_transactions; use types::signed_beacon_block::BlobReconstructionError; use types::{ @@ -12,6 +13,7 @@ use types::{ Transactions, }; use types::{Epoch, ExecPayload}; +use crate::block_verification::PayloadVerificationOutcome; #[derive(Debug)] pub enum BlobError { @@ -89,8 +91,8 @@ pub fn validate_blob_for_gossip( block_wrapper: BlockWrapper, block_root: Hash256, chain: &BeaconChain, -) -> Result, BlobError> { - if let BlockWrapper::BlockAndBlob(ref block, ref blobs_sidecar) = block_wrapper { +) -> Result, BlobError> { + if let BlockWrapper::BlockAndBlobs(ref block, ref blobs_sidecar) = block_wrapper { let blob_slot = blobs_sidecar.beacon_block_slot; // Do not gossip or process blobs from future or past slots. let latest_permissible_slot = chain @@ -112,7 +114,7 @@ pub fn validate_blob_for_gossip( } } - block_wrapper.into_available_block(block_root, chain) + block_wrapper.into_availablilty_pending_block(block_root, chain) } fn verify_data_availability( @@ -157,7 +159,8 @@ fn verify_data_availability( #[derivative(PartialEq, Hash(bound = "E: EthSpec"))] pub enum BlockWrapper { Block(Arc>), - BlockAndBlob(Arc>, Arc>), + BlockAndBlobs(Arc>, Arc>), + BlockAndBlobsFuture(Arc>, DataAvailabilityHandle), } impl BlockWrapper { @@ -166,7 +169,7 @@ impl BlockWrapper { blobs_sidecar: Option>>, ) -> Self { if let Some(blobs_sidecar) = blobs_sidecar { - BlockWrapper::BlockAndBlob(block, blobs_sidecar) + BlockWrapper::BlockAndBlobs(block, blobs_sidecar) } else { BlockWrapper::Block(block) } @@ -185,7 +188,7 @@ impl From> for BlockWrapper { beacon_block, blobs_sidecar, } = block; - BlockWrapper::BlockAndBlob(beacon_block, blobs_sidecar) + BlockWrapper::BlockAndBlobs(beacon_block, blobs_sidecar) } } @@ -201,20 +204,12 @@ pub enum DataAvailabilityCheckRequired { No, } -pub trait IntoAvailableBlock { - fn into_available_block( +impl BlockWrapper { + fn into_availablilty_pending_block( self, block_root: Hash256, chain: &BeaconChain, - ) -> Result, BlobError>; -} - -impl IntoAvailableBlock for BlockWrapper { - fn into_available_block( - self, - block_root: Hash256, - chain: &BeaconChain, - ) -> Result, BlobError> { + ) -> Result, BlobError> { let data_availability_boundary = chain.data_availability_boundary(); let da_check_required = data_availability_boundary.map_or(DataAvailabilityCheckRequired::No, |boundary| { @@ -225,8 +220,8 @@ impl IntoAvailableBlock for BlockWrapper { } }); match self { - BlockWrapper::Block(block) => AvailableBlock::new(block, block_root, da_check_required), - BlockWrapper::BlockAndBlob(block, blobs_sidecar) => { + BlockWrapper::Block(block) => AvailabilityPendingBlock::new(block, block_root, da_check_required), + BlockWrapper::BlockAndBlobs(block, blobs_sidecar) => { if matches!(da_check_required, DataAvailabilityCheckRequired::Yes) { let kzg_commitments = block .message() @@ -250,7 +245,7 @@ impl IntoAvailableBlock for BlockWrapper { )?; } - AvailableBlock::new_with_blobs(block, blobs_sidecar, da_check_required) + AvailabilityPendingBlock::new_with_blobs(block, blobs_sidecar, da_check_required) } } } @@ -262,7 +257,30 @@ impl IntoAvailableBlock for BlockWrapper { /// cannot be circumvented on construction. #[derive(Clone, Debug, Derivative)] #[derivative(PartialEq, Hash(bound = "E: EthSpec"))] -pub struct AvailableBlock(AvailableBlockInner); +pub struct AvailabilityPendingBlock{ + block: Arc>, + data_availability_handle: DataAvailabilityHandle +} + +/// Used to await the result of data availability check. +type DataAvailabilityHandle = JoinHandle>>, BlobError>>; + +#[derive(Clone, Debug, Derivative)] +#[derivative(PartialEq, Hash(bound = "E: EthSpec"))] +pub struct AvailableBlock { + block: Arc>, + blobs: Blobs, +} + +pub enum Blobs { + /// These blobs are available. + Available(Arc>), + /// This block is from outside the data availability boundary or the block is from prior + /// to the eip4844 fork. + NotRequired, + /// The block doesn't have any blob transactions. + None, +} /// A wrapper over a [`SignedBeaconBlock`] or a [`SignedBeaconBlockAndBlobsSidecar`]. #[derive(Clone, Debug, Derivative)] @@ -272,7 +290,7 @@ enum AvailableBlockInner { BlockAndBlob(SignedBeaconBlockAndBlobsSidecar), } -impl AvailableBlock { +impl AvailabilityPendingBlock { pub fn new( beacon_block: Arc>, block_root: Hash256, @@ -372,11 +390,11 @@ impl IntoBlockWrapper for BlockWrapper { } } -impl IntoBlockWrapper for AvailableBlock { +impl IntoBlockWrapper for AvailabilityPendingBlock { fn into_block_wrapper(self) -> BlockWrapper { let (block, blobs) = self.deconstruct(); if let Some(blobs) = blobs { - BlockWrapper::BlockAndBlob(block, blobs) + BlockWrapper::BlockAndBlobs(block, blobs) } else { BlockWrapper::Block(block) } @@ -399,49 +417,49 @@ impl AsBlock for BlockWrapper { fn slot(&self) -> Slot { match self { BlockWrapper::Block(block) => block.slot(), - BlockWrapper::BlockAndBlob(block, _) => block.slot(), + BlockWrapper::BlockAndBlobs(block, _) => block.slot(), } } fn epoch(&self) -> Epoch { match self { BlockWrapper::Block(block) => block.epoch(), - BlockWrapper::BlockAndBlob(block, _) => block.epoch(), + BlockWrapper::BlockAndBlobs(block, _) => block.epoch(), } } fn parent_root(&self) -> Hash256 { match self { BlockWrapper::Block(block) => block.parent_root(), - BlockWrapper::BlockAndBlob(block, _) => block.parent_root(), + BlockWrapper::BlockAndBlobs(block, _) => block.parent_root(), } } fn state_root(&self) -> Hash256 { match self { BlockWrapper::Block(block) => block.state_root(), - BlockWrapper::BlockAndBlob(block, _) => block.state_root(), + BlockWrapper::BlockAndBlobs(block, _) => block.state_root(), } } fn signed_block_header(&self) -> SignedBeaconBlockHeader { match &self { BlockWrapper::Block(block) => block.signed_block_header(), - BlockWrapper::BlockAndBlob(block, _) => block.signed_block_header(), + BlockWrapper::BlockAndBlobs(block, _) => block.signed_block_header(), } } fn message(&self) -> BeaconBlockRef { match &self { BlockWrapper::Block(block) => block.message(), - BlockWrapper::BlockAndBlob(block, _) => block.message(), + BlockWrapper::BlockAndBlobs(block, _) => block.message(), } } fn as_block(&self) -> &SignedBeaconBlock { match &self { - BlockWrapper::Block(block) => block, - BlockWrapper::BlockAndBlob(block, _) => block, + BlockWrapper::Block(block) => &block, + BlockWrapper::BlockAndBlobs(block, _) => &block, } } fn block_cloned(&self) -> Arc> { match &self { BlockWrapper::Block(block) => block.clone(), - BlockWrapper::BlockAndBlob(block, _) => block.clone(), + BlockWrapper::BlockAndBlobs(block, _) => block.clone(), } } fn canonical_root(&self) -> Hash256 { @@ -456,49 +474,49 @@ impl AsBlock for &BlockWrapper { fn slot(&self) -> Slot { match self { BlockWrapper::Block(block) => block.slot(), - BlockWrapper::BlockAndBlob(block, _) => block.slot(), + BlockWrapper::BlockAndBlobs(block, _) => block.slot(), } } fn epoch(&self) -> Epoch { match self { BlockWrapper::Block(block) => block.epoch(), - BlockWrapper::BlockAndBlob(block, _) => block.epoch(), + BlockWrapper::BlockAndBlobs(block, _) => block.epoch(), } } fn parent_root(&self) -> Hash256 { match self { BlockWrapper::Block(block) => block.parent_root(), - BlockWrapper::BlockAndBlob(block, _) => block.parent_root(), + BlockWrapper::BlockAndBlobs(block, _) => block.parent_root(), } } fn state_root(&self) -> Hash256 { match self { BlockWrapper::Block(block) => block.state_root(), - BlockWrapper::BlockAndBlob(block, _) => block.state_root(), + BlockWrapper::BlockAndBlobs(block, _) => block.state_root(), } } fn signed_block_header(&self) -> SignedBeaconBlockHeader { match &self { BlockWrapper::Block(block) => block.signed_block_header(), - BlockWrapper::BlockAndBlob(block, _) => block.signed_block_header(), + BlockWrapper::BlockAndBlobs(block, _) => block.signed_block_header(), } } fn message(&self) -> BeaconBlockRef { match &self { BlockWrapper::Block(block) => block.message(), - BlockWrapper::BlockAndBlob(block, _) => block.message(), + BlockWrapper::BlockAndBlobs(block, _) => block.message(), } } fn as_block(&self) -> &SignedBeaconBlock { match &self { - BlockWrapper::Block(block) => block, - BlockWrapper::BlockAndBlob(block, _) => block, + BlockWrapper::Block(block) => &block, + BlockWrapper::BlockAndBlobs(block, _) => &block, } } fn block_cloned(&self) -> Arc> { match &self { BlockWrapper::Block(block) => block.clone(), - BlockWrapper::BlockAndBlob(block, _) => block.clone(), + BlockWrapper::BlockAndBlobs(block, _) => block.clone(), } } fn canonical_root(&self) -> Hash256 { @@ -509,7 +527,7 @@ impl AsBlock for &BlockWrapper { } } -impl AsBlock for AvailableBlock { +impl AsBlock for AvailabilityPendingBlock { fn slot(&self) -> Slot { match &self.0 { AvailableBlockInner::Block(block) => block.slot(), diff --git a/beacon_node/beacon_chain/src/block_verification.rs b/beacon_node/beacon_chain/src/block_verification.rs index 269fc5aae3..b68e906640 100644 --- a/beacon_node/beacon_chain/src/block_verification.rs +++ b/beacon_node/beacon_chain/src/block_verification.rs @@ -52,7 +52,7 @@ #![allow(clippy::result_large_err)] use crate::blob_verification::{ - validate_blob_for_gossip, AsBlock, AvailableBlock, BlobError, BlockWrapper, IntoAvailableBlock, + validate_blob_for_gossip, AsBlock, AvailabilityPendingBlock, BlobError, BlockWrapper, IntoAvailableBlock, IntoBlockWrapper, }; use crate::eth1_finalization_cache::Eth1FinalizationData; @@ -637,7 +637,7 @@ pub fn signature_verify_chain_segment( #[derive(Derivative)] #[derivative(Debug(bound = "T: BeaconChainTypes"))] pub struct GossipVerifiedBlock { - pub block: AvailableBlock, + pub block: AvailabilityPendingBlock, pub block_root: Hash256, parent: Option>, consensus_context: ConsensusContext, @@ -646,7 +646,7 @@ pub struct GossipVerifiedBlock { /// A wrapper around a `SignedBeaconBlock` that indicates that all signatures (except the deposit /// signatures) have been verified. pub struct SignatureVerifiedBlock { - block: AvailableBlock, + block: AvailabilityPendingBlock, block_root: Hash256, parent: Option>, consensus_context: ConsensusContext, @@ -668,8 +668,8 @@ type PayloadVerificationHandle = /// Note: a `ExecutionPendingBlock` is not _forever_ valid to be imported, it may later become invalid /// due to finality or some other event. A `ExecutionPendingBlock` should be imported into the /// `BeaconChain` immediately after it is instantiated. -pub struct ExecutionPendingBlock { - pub block: AvailableBlock, +pub struct ExecutionPendingBlock { + pub block: B, pub block_root: Hash256, pub state: BeaconState, pub parent_block: SignedBeaconBlock>, @@ -978,7 +978,7 @@ impl SignatureVerifiedBlock { /// /// Returns an error if the block is invalid, or if the block was unable to be verified. pub fn new( - block: AvailableBlock, + block: AvailabilityPendingBlock, block_root: Hash256, chain: &BeaconChain, ) -> Result> { @@ -1028,7 +1028,7 @@ impl SignatureVerifiedBlock { /// As for `new` above but producing `BlockSlashInfo`. pub fn check_slashable( - block: AvailableBlock, + block: AvailabilityPendingBlock, block_root: Hash256, chain: &BeaconChain, ) -> Result>> { @@ -1151,7 +1151,7 @@ impl IntoExecutionPendingBlock for Arc IntoExecutionPendingBlock for AvailableBlock { +impl IntoExecutionPendingBlock for AvailabilityPendingBlock { /// Verifies the `SignedBeaconBlock` by first transforming it into a `SignatureVerifiedBlock` /// and then using that implementation of `IntoExecutionPendingBlock` to complete verification. fn into_execution_pending_block_slashable( @@ -1182,7 +1182,7 @@ impl ExecutionPendingBlock { /// /// Returns an error if the block is invalid, or if the block was unable to be verified. pub fn from_signature_verified_components( - block: AvailableBlock, + block: AvailabilityPendingBlock, block_root: Hash256, parent: PreProcessingSnapshot, mut consensus_context: ConsensusContext, diff --git a/beacon_node/beacon_chain/src/early_attester_cache.rs b/beacon_node/beacon_chain/src/early_attester_cache.rs index dd4109da9b..04d741819a 100644 --- a/beacon_node/beacon_chain/src/early_attester_cache.rs +++ b/beacon_node/beacon_chain/src/early_attester_cache.rs @@ -1,4 +1,4 @@ -use crate::blob_verification::AvailableBlock; +use crate::blob_verification::AvailabilityPendingBlock; use crate::{ attester_cache::{CommitteeLengths, Error}, metrics, @@ -51,7 +51,7 @@ impl EarlyAttesterCache { pub fn add_head_block( &self, beacon_block_root: Hash256, - block: AvailableBlock, + block: AvailabilityPendingBlock, proto_block: ProtoBlock, state: &BeaconState, spec: &ChainSpec,