error handling and wiring up

This commit is contained in:
Daniel Knopik
2026-04-29 15:35:31 +02:00
parent 58fd3dde40
commit 2d3354551e
15 changed files with 132 additions and 84 deletions

View File

@@ -3275,7 +3275,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
pub async fn process_gossip_blob(
self: &Arc<Self>,
blob: GossipVerifiedBlob<T>,
) -> Result<AvailabilityProcessingStatus, BlockOrEnvelopeError> {
) -> Result<AvailabilityProcessingStatus, BlockError> {
let block_root = blob.block_root();
// If this block has already been imported to forkchoice it must have been available, so
@@ -3285,12 +3285,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.fork_choice_read_lock()
.contains_block(&block_root)
{
return Err(BlockError::DuplicateFullyImported(blob.block_root()).into());
return Err(BlockError::DuplicateFullyImported(blob.block_root()));
}
// No need to process and import blobs beyond the PeerDAS epoch.
if self.spec.is_peer_das_enabled_for_epoch(blob.epoch()) {
return Err(BlockError::BlobNotRequired(blob.slot()).into());
return Err(BlockError::BlobNotRequired(blob.slot()));
}
self.emit_sse_blob_sidecar_events(&block_root, std::iter::once(blob.as_blob()));
@@ -3456,7 +3456,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
slot: Slot,
block_root: Hash256,
blobs: FixedBlobSidecarList<T::EthSpec>,
) -> Result<AvailabilityProcessingStatus, BlockOrEnvelopeError> {
) -> Result<AvailabilityProcessingStatus, BlockError> {
// If this block has already been imported to forkchoice it must have been available, so
// we don't need to process its blobs again.
if self
@@ -3464,7 +3464,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.fork_choice_read_lock()
.contains_block(&block_root)
{
return Err(BlockError::DuplicateFullyImported(block_root).into());
return Err(BlockError::DuplicateFullyImported(block_root));
}
// Reject RPC blobs referencing unknown parents. Otherwise we allow potentially invalid data
@@ -3479,7 +3479,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.fork_choice_read_lock()
.contains_block(&parent_root)
{
return Err(BlockError::ParentUnknown { parent_root }.into());
return Err(BlockError::ParentUnknown { parent_root });
}
self.emit_sse_blob_sidecar_events(&block_root, blobs.iter().flatten().map(Arc::as_ref));
@@ -3684,9 +3684,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
return Ok(None);
};
self.process_payload_availability(slot, availability, || Ok(()))
Ok(self
.process_payload_availability(slot, availability, || Ok(()))
.await
.map(|status| Some((status, data_columns_to_publish)))
.map(|status| Some((status, data_columns_to_publish)))?)
}
DataColumnReconstructionResultV2::NotStarted(reason)
| DataColumnReconstructionResultV2::RecoveredColumnsNotImported(reason) => {
@@ -3698,14 +3699,15 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
}
}
} else {
let pending_block_cache = self.data_availability_checker.clone();
let data_availability_checker = self.data_availability_checker.clone();
let result = self
.task_executor
.spawn_blocking_with_rayon_async(RayonPoolType::HighPriority, move || {
pending_block_cache.reconstruct_data_columns(&block_root)
data_availability_checker.reconstruct_data_columns(&block_root)
})
.await
.map_err(|_| BeaconChainError::RuntimeShutdown)??;
.map_err(|_| BlockError::from(BeaconChainError::RuntimeShutdown))?
.map_err(BlockError::from)?;
match result {
DataColumnReconstructionResultV1::Success((
@@ -3716,9 +3718,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
return Ok(None);
};
self.process_availability(slot, availability, || Ok(()))
Ok(self
.process_availability(slot, availability, || Ok(()))
.await
.map(|status| Some((status, data_columns_to_publish)))
.map(|status| Some((status, data_columns_to_publish)))?)
}
DataColumnReconstructionResultV1::NotStarted(reason)
| DataColumnReconstructionResultV1::RecoveredColumnsNotImported(reason) => {
@@ -3939,7 +3942,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
async fn check_gossip_blob_availability_and_import(
self: &Arc<Self>,
blob: GossipVerifiedBlob<T>,
) -> Result<AvailabilityProcessingStatus, BlockOrEnvelopeError> {
) -> Result<AvailabilityProcessingStatus, BlockError> {
let slot = blob.slot();
if let Some(slasher) = self.slasher.as_ref() {
slasher.accept_block_header(blob.signed_block_header());
@@ -3980,15 +3983,19 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
{
let availability = self
.pending_payload_cache
.put_gossip_verified_data_columns(block_root, slot, data_columns)?;
self.process_payload_availability(slot, availability, publish_fn)
.await
.put_gossip_verified_data_columns(block_root, slot, data_columns)
.map_err(EnvelopeError::from)?;
Ok(self
.process_payload_availability(slot, availability, publish_fn)
.await?)
} else {
let availability = self
.data_availability_checker
.put_gossip_verified_data_columns(block_root, slot, data_columns)?;
self.process_availability(slot, availability, publish_fn)
.await
.put_gossip_verified_data_columns(block_root, slot, data_columns)
.map_err(BlockError::from)?;
Ok(self
.process_availability(slot, availability, publish_fn)
.await?)
}
}
@@ -4029,7 +4036,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
slot: Slot,
block_root: Hash256,
blobs: FixedBlobSidecarList<T::EthSpec>,
) -> Result<AvailabilityProcessingStatus, BlockOrEnvelopeError> {
) -> Result<AvailabilityProcessingStatus, BlockError> {
self.check_blob_header_signature_and_slashability(
block_root,
blobs.iter().flatten().map(Arc::as_ref),
@@ -4057,10 +4064,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
)?;
let availability = self
.data_availability_checker
.put_kzg_verified_blobs(block_root, blobs)?;
.put_kzg_verified_blobs(block_root, blobs)
.map_err(BlockError::from)?;
self.process_availability(slot, availability, || Ok(()))
.await
Ok(self
.process_availability(slot, availability, || Ok(()))
.await?)
}
EngineGetBlobsOutput::CustodyColumns(data_columns) => {
// TODO(gloas) verify that this check is no longer relevant for gloas
@@ -4080,15 +4089,19 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
{
let availability = self
.pending_payload_cache
.put_kzg_verified_custody_data_columns(block_root, data_columns)?;
self.process_payload_availability(slot, availability, || Ok(()))
.await
.put_kzg_verified_custody_data_columns(block_root, data_columns)
.map_err(EnvelopeError::from)?;
Ok(self
.process_payload_availability(slot, availability, || Ok(()))
.await?)
} else {
let availability = self
.data_availability_checker
.put_kzg_verified_custody_data_columns(block_root, data_columns)?;
self.process_availability(slot, availability, || Ok(()))
.await
.put_kzg_verified_custody_data_columns(block_root, data_columns)
.map_err(BlockError::from)?;
Ok(self
.process_availability(slot, availability, || Ok(()))
.await?)
}
}
}
@@ -4116,21 +4129,21 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
.fork_name_at_slot::<T::EthSpec>(slot)
.gloas_enabled()
{
let availability = self.pending_payload_cache.put_rpc_custody_columns(
block_root,
slot,
custody_columns,
)?;
self.process_payload_availability(slot, availability, || Ok(()))
.await
let availability = self
.pending_payload_cache
.put_rpc_custody_columns(block_root, slot, custody_columns)
.map_err(EnvelopeError::from)?;
Ok(self
.process_payload_availability(slot, availability, || Ok(()))
.await?)
} else {
let availability = self.data_availability_checker.put_rpc_custody_columns(
block_root,
slot,
custody_columns,
)?;
self.process_availability(slot, availability, || Ok(()))
.await
let availability = self
.data_availability_checker
.put_rpc_custody_columns(block_root, slot, custody_columns)
.map_err(BlockError::from)?;
Ok(self
.process_availability(slot, availability, || Ok(()))
.await?)
}
}

View File

@@ -337,6 +337,7 @@ easy_from_to!(StateAdvanceError, BlockProductionError);
easy_from_to!(ForkChoiceError, BlockProductionError);
easy_from_to!(EpochCacheError, BlockProductionError);
#[derive(Debug)]
pub enum BlockOrEnvelopeError {
BlockError(BlockError),
EnvelopeError(EnvelopeError),
@@ -344,3 +345,12 @@ pub enum BlockOrEnvelopeError {
easy_from_to!(BlockError, BlockOrEnvelopeError);
easy_from_to!(EnvelopeError, BlockOrEnvelopeError);
impl AsRef<str> for BlockOrEnvelopeError {
fn as_ref(&self) -> &str {
match self {
BlockOrEnvelopeError::BlockError(e) => e.as_ref(),
BlockOrEnvelopeError::EnvelopeError(e) => e.as_ref(),
}
}
}

View File

@@ -138,7 +138,7 @@ impl<T: BeaconChainTypes> FetchBlobsBeaconAdapter<T> {
self.chain
.process_engine_blobs(slot, block_root, blobs)
.await
.map_err(FetchEngineBlobError::BlobProcessingError)
.map_err(|e| FetchEngineBlobError::BlobProcessingError(Box::new(e)))
}
pub(crate) fn fork_choice_contains_block(&self, block_root: &Hash256) -> bool {

View File

@@ -16,13 +16,13 @@ use crate::blob_verification::{GossipBlobError, KzgVerifiedBlob};
use crate::data_column_verification::{
KzgVerifiedCustodyDataColumn, KzgVerifiedCustodyPartialDataColumn, KzgVerifiedPartialDataColumn,
};
use crate::errors::BlockOrEnvelopeError;
#[cfg_attr(test, double)]
use crate::fetch_blobs::fetch_blobs_beacon_adapter::FetchBlobsBeaconAdapter;
use crate::kzg_utils::blobs_to_partial_data_columns;
use crate::observed_data_sidecars::ObservationKey;
use crate::{
AvailabilityProcessingStatus, BeaconChain, BeaconChainError, BeaconChainTypes, BlockError,
metrics,
AvailabilityProcessingStatus, BeaconChain, BeaconChainError, BeaconChainTypes, metrics,
};
use execution_layer::Error as ExecutionLayerError;
use execution_layer::json_structures::{BlobAndProofV1, BlobAndProofV2, BlobAndProofV3};
@@ -50,7 +50,7 @@ pub enum EngineGetBlobsOutput<T: BeaconChainTypes> {
pub enum FetchEngineBlobError {
BeaconStateError(BeaconStateError),
BeaconChainError(Box<BeaconChainError>),
BlobProcessingError(BlockError),
BlobProcessingError(Box<BlockOrEnvelopeError>),
BlobSidecarError(BlobSidecarError),
DataColumnSidecarError(DataColumnSidecarError),
ExecutionLayerMissing,

View File

@@ -76,7 +76,7 @@ pub use self::beacon_chain::{
};
pub use self::beacon_snapshot::BeaconSnapshot;
pub use self::chain_config::ChainConfig;
pub use self::errors::{BeaconChainError, BlockProductionError};
pub use self::errors::{BeaconChainError, BlockOrEnvelopeError, BlockProductionError};
pub use self::historical_blocks::HistoricalBlockError;
pub use attestation_verification::Error as AttestationError;
pub use beacon_fork_choice_store::{

View File

@@ -92,6 +92,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
}
self.check_envelope_availability_and_import(executed_envelope)
.await
};
// Verify and import the payload envelope.

View File

@@ -18,10 +18,10 @@
//!
//! ```
use std::sync::Arc;
use state_processing::{BlockProcessingError, envelope_processing::EnvelopeProcessingError};
use std::sync::Arc;
use store::Error as DBError;
use strum::AsRefStr;
use tracing::instrument;
use types::{
BeaconState, BeaconStateError, DataColumnSidecarList, EthSpec, ExecutionBlockHash,
@@ -190,7 +190,7 @@ impl<E: EthSpec> AvailableExecutedEnvelope<E> {
}
}
#[derive(Debug)]
#[derive(Debug, AsRefStr)]
pub enum EnvelopeError {
/// The envelope's block root is unknown.
BlockRootUnknown { block_root: Hash256 },