Initial commit

This commit is contained in:
Pawan Dhananjay
2023-03-14 19:47:06 +05:30
parent 13b54f7879
commit 761df83597
4 changed files with 99 additions and 40 deletions

View File

@@ -7,12 +7,12 @@ 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, AvailabilityPendingBlock, AvailableBlock, BlobError, BlockWrapper, IntoAvailableBlock};
use crate::blob_verification::{AsBlock, AvailabilityPendingBlock, AvailableBlock, BlobError, BlockWrapper, IntoAvailableBlock, Blobs};
use crate::block_times_cache::BlockTimesCache;
use crate::block_verification::{
check_block_is_finalized_checkpoint_or_descendant, check_block_relevancy, get_block_root,
signature_verify_chain_segment, BlockError, ExecutionPendingBlock, GossipVerifiedBlock,
IntoExecutionPendingBlock, PayloadVerificationOutcome, POS_PANDA_BANNER,
IntoExecutionPendingBlock, PayloadVerificationOutcome, POS_PANDA_BANNER, ExecutedBlock,
};
pub use crate::canonical_head::{CanonicalHead, CanonicalHeadRwLock};
use crate::chain_config::ChainConfig;
@@ -273,6 +273,11 @@ pub enum StateSkipConfig {
WithoutStateRoots,
}
pub enum BlockProcessingResult<T: BeaconChainTypes> {
Verified(Hash256),
AvailabilityPending(ExecutedBlock<T>),
}
pub trait BeaconChainTypes: Send + Sync + 'static {
type HotStore: store::ItemStore<Self::EthSpec>;
type ColdStore: store::ItemStore<Self::EthSpec>;
@@ -2689,13 +2694,13 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
///
/// Returns an `Err` if the given block was invalid, or an error was encountered during
/// verification.
pub async fn process_block<A: IntoAvailableBlock<T>, B: IntoExecutionPendingBlock<T, A>>(
pub async fn process_block<B: IntoExecutionPendingBlock<T>>(
self: &Arc<Self>,
block_root: Hash256,
unverified_block: B,
count_unrealized: CountUnrealized,
notify_execution_layer: NotifyExecutionLayer,
) -> Result<Hash256, BlockError<T::EthSpec>> {
) -> Result<BlockProcessingResult<T>, BlockError<T::EthSpec>> {
// Start the Prometheus timer.
let _full_timer = metrics::start_timer(&metrics::BLOCK_PROCESSING_TIMES);
@@ -2704,17 +2709,26 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
let slot = unverified_block.block().slot();
// A small closure to group the verification and import errors.
let execution_pending = unverified_block.into_execution_pending_block(
block_root,
&chain,
notify_execution_layer,
)?;
// TODO(log required errors)
let executed_block = self
.into_executed_block(execution_pending, count_unrealized)
.await?;
let chain = self.clone();
let import_block = async move {
let execution_pending = unverified_block.into_execution_pending_block(
block_root,
&chain,
notify_execution_layer,
)?;
chain
.import_execution_pending_block(execution_pending, count_unrealized)
.await
// Check if the executed block has all it's blobs available to qualify as a fully
// available block
let import_block = if let Ok(blobs) = self.gossip_blob_cache.lock().blobs(executed_block.block_root) {
self.import_available_block(executed_block, blobs, count_unrealized)
} else {
return Ok(BlockProcessingResult::AvailabilityPending(executed_block));
};
// Verify and import the block.
@@ -2731,7 +2745,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
// Increment the Prometheus counter for block processing successes.
metrics::inc_counter(&metrics::BLOCK_PROCESSING_SUCCESSES);
Ok(block_root)
Ok(BlockProcessingResult::Verified(block_root))
}
Err(e @ BlockError::BeaconChainError(BeaconChainError::TokioJoin(_))) => {
debug!(
@@ -2763,16 +2777,15 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
}
}
/// Accepts a fully-verified block and imports it into the chain without performing any
/// additional verification.
/// Accepts a fully-verified block and awaits on it's payload verification handle to
/// get a fully `ExecutedBlock`
///
/// An error is returned if the block was unable to be imported. It may be partially imported
/// (i.e., this function is not atomic).
async fn import_execution_pending_block<B: IntoAvailableBlock<T>>(
/// An error is returned if the verification handle couldn't be awaited.
async fn into_executed_block(
self: Arc<Self>,
execution_pending_block: ExecutionPendingBlock<T, B>,
execution_pending_block: ExecutionPendingBlock<T>,
count_unrealized: CountUnrealized,
) -> Result<Hash256, BlockError<T::EthSpec>> {
) -> Result<ExecutedBlock<T>, BlockError<T::EthSpec>> {
let ExecutionPendingBlock {
block,
block_root,
@@ -2784,16 +2797,13 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
consensus_context,
} = execution_pending_block;
let PayloadVerificationOutcome {
payload_verification_status,
is_valid_merge_transition_block,
} = payload_verification_handle
let payload_verification_outcome = payload_verification_handle
.await
.map_err(BeaconChainError::TokioJoin)?
.ok_or(BeaconChainError::RuntimeShutdown)??;
// Log the PoS pandas if a merge transition just occurred.
if is_valid_merge_transition_block {
if payload_verification_outcome.is_valid_merge_transition_block {
info!(self.log, "{}", POS_PANDA_BANNER);
info!(
self.log,
@@ -2821,10 +2831,48 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.into_root()
);
}
Ok(ExecutedBlock {
block,
block_root,
state,
parent_block,
confirmed_state_roots,
parent_eth1_finalization_data,
consensus_context,
payload_verification_outcome
})
}
/// Accepts a fully-verified, available block and imports it into the chain without performing any
/// additional verification.
///
/// An error is returned if the block was unable to be imported. It may be partially imported
/// (i.e., this function is not atomic).
async fn import_available_block(
self: Arc<Self>,
executed_block: ExecutedBlock<T>,
blobs: Blobs<T::EthSpec>
count_unrealized: CountUnrealized,
) -> Result<Hash256, BlockError<T::EthSpec>> {
let ExecutedBlock {
block,
block_root,
state,
parent_block,
confirmed_state_roots,
payload_verification_outcome,
parent_eth1_finalization_data,
consensus_context,
} = execution_pending_block;
let available_block = block.into_available_block()?;
let chain = self.clone();
let available_block = AvailableBlock {
block: block,
blobs: blobs
};
let block_hash = self
.spawn_blocking_handle(
move || {

View File

@@ -658,11 +658,8 @@ type PayloadVerificationHandle<E> =
/// 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<
T: BeaconChainTypes,
B: IntoAvailablBlockk = AvailableBlock<T::EthSpec>,
> {
pub block: B,
pub struct ExecutionPendingBlock<T: BeaconChainTypes> {
pub block: Arc<SignedBeaconBlock<T::EthSpec>>,
pub block_root: Hash256,
pub state: BeaconState<T::EthSpec>,
pub parent_block: SignedBeaconBlock<T::EthSpec, BlindedPayload<T::EthSpec>>,
@@ -672,14 +669,21 @@ pub struct ExecutionPendingBlock<
pub payload_verification_handle: PayloadVerificationHandle<T::EthSpec>,
}
pub struct ExecutedBlock<T: BeaconChainTypes> {
pub block: Arc<SignedBeaconBlock<T::EthSpec>>,
pub block_root: Hash256,
pub state: BeaconState<T::EthSpec>,
pub parent_block: SignedBeaconBlock<T::EthSpec, BlindedPayload<T::EthSpec>>,
pub parent_eth1_finalization_data: Eth1FinalizationData,
pub confirmed_state_roots: Vec<Hash256>,
pub consensus_context: ConsensusContext<T::EthSpec>,
pub payload_verification_outcome: PayloadVerificationOutcome,
}
/// Implemented on types that can be converted into a `ExecutionPendingBlock`.
///
/// Used to allow functions to accept blocks at various stages of verification.
pub trait IntoExecutionPendingBlock<
T: BeaconChainTypes,
B: IntoAvailableBlock<T> = AvailableBlock<T::EthSpec>,
>: Sized
{
pub trait IntoExecutionPendingBlock<T: BeaconChainTypes>: Sized {
fn into_execution_pending_block(
self,
block_root: Hash256,