mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-25 00:38:22 +00:00
Drop block data from BlockError and BlobError (#5735)
* Drop block data from BlockError and BlobError * Debug release tests * Fix release tests * Revert unnecessary changes to lighthouse_metrics
This commit is contained in:
@@ -206,7 +206,7 @@ impl TryInto<Hash256> for AvailabilityProcessingStatus {
|
||||
}
|
||||
|
||||
/// The result of a chain segment processing.
|
||||
pub enum ChainSegmentResult<E: EthSpec> {
|
||||
pub enum ChainSegmentResult {
|
||||
/// Processing this chain segment finished successfully.
|
||||
Successful {
|
||||
imported_blocks: Vec<(Hash256, Slot)>,
|
||||
@@ -215,7 +215,7 @@ pub enum ChainSegmentResult<E: EthSpec> {
|
||||
/// have been imported.
|
||||
Failed {
|
||||
imported_blocks: Vec<(Hash256, Slot)>,
|
||||
error: BlockError<E>,
|
||||
error: BlockError,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2159,7 +2159,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
self: &Arc<Self>,
|
||||
blob_sidecar: Arc<BlobSidecar<T::EthSpec>>,
|
||||
subnet_id: u64,
|
||||
) -> Result<GossipVerifiedBlob<T>, GossipBlobError<T::EthSpec>> {
|
||||
) -> Result<GossipVerifiedBlob<T>, GossipBlobError> {
|
||||
metrics::inc_counter(&metrics::BLOBS_SIDECAR_PROCESSING_REQUESTS);
|
||||
let _timer = metrics::start_timer(&metrics::BLOBS_SIDECAR_GOSSIP_VERIFICATION_TIMES);
|
||||
GossipVerifiedBlob::new(blob_sidecar, subnet_id, self).map(|v| {
|
||||
@@ -2698,7 +2698,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
pub fn filter_chain_segment(
|
||||
self: &Arc<Self>,
|
||||
chain_segment: Vec<RpcBlock<T::EthSpec>>,
|
||||
) -> Result<Vec<HashBlockTuple<T::EthSpec>>, ChainSegmentResult<T::EthSpec>> {
|
||||
) -> Result<Vec<HashBlockTuple<T::EthSpec>>, ChainSegmentResult> {
|
||||
// This function will never import any blocks.
|
||||
let imported_blocks = vec![];
|
||||
let mut filtered_chain_segment = Vec::with_capacity(chain_segment.len());
|
||||
@@ -2805,7 +2805,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
self: &Arc<Self>,
|
||||
chain_segment: Vec<RpcBlock<T::EthSpec>>,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> ChainSegmentResult<T::EthSpec> {
|
||||
) -> ChainSegmentResult {
|
||||
let mut imported_blocks = vec![];
|
||||
|
||||
// Filter uninteresting blocks from the chain segment in a blocking task.
|
||||
@@ -2938,7 +2938,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
pub async fn verify_block_for_gossip(
|
||||
self: &Arc<Self>,
|
||||
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
||||
) -> Result<GossipVerifiedBlock<T>, BlockError<T::EthSpec>> {
|
||||
) -> Result<GossipVerifiedBlock<T>, BlockError> {
|
||||
let chain = self.clone();
|
||||
self.task_executor
|
||||
.clone()
|
||||
@@ -2986,7 +2986,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
pub async fn process_gossip_blob(
|
||||
self: &Arc<Self>,
|
||||
blob: GossipVerifiedBlob<T>,
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>> {
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError> {
|
||||
let block_root = blob.block_root();
|
||||
|
||||
// If this block has already been imported to forkchoice it must have been available, so
|
||||
@@ -3026,7 +3026,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
AvailabilityProcessingStatus,
|
||||
DataColumnsToPublish<T::EthSpec>,
|
||||
),
|
||||
BlockError<T::EthSpec>,
|
||||
BlockError,
|
||||
> {
|
||||
let Ok((slot, block_root)) = data_columns
|
||||
.iter()
|
||||
@@ -3062,7 +3062,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
slot: Slot,
|
||||
block_root: Hash256,
|
||||
blobs: FixedBlobSidecarList<T::EthSpec>,
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>> {
|
||||
) -> 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
|
||||
@@ -3099,7 +3099,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
AvailabilityProcessingStatus,
|
||||
DataColumnsToPublish<T::EthSpec>,
|
||||
),
|
||||
BlockError<T::EthSpec>,
|
||||
BlockError,
|
||||
> {
|
||||
let Ok((slot, block_root)) = custody_columns
|
||||
.iter()
|
||||
@@ -3133,8 +3133,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
fn remove_notified(
|
||||
&self,
|
||||
block_root: &Hash256,
|
||||
r: Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>>,
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>> {
|
||||
r: Result<AvailabilityProcessingStatus, BlockError>,
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError> {
|
||||
let has_missing_components =
|
||||
matches!(r, Ok(AvailabilityProcessingStatus::MissingComponents(_, _)));
|
||||
if !has_missing_components {
|
||||
@@ -3148,8 +3148,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
fn remove_notified_custody_columns<P>(
|
||||
&self,
|
||||
block_root: &Hash256,
|
||||
r: Result<(AvailabilityProcessingStatus, P), BlockError<T::EthSpec>>,
|
||||
) -> Result<(AvailabilityProcessingStatus, P), BlockError<T::EthSpec>> {
|
||||
r: Result<(AvailabilityProcessingStatus, P), BlockError>,
|
||||
) -> Result<(AvailabilityProcessingStatus, P), BlockError> {
|
||||
let has_missing_components = matches!(
|
||||
r,
|
||||
Ok((AvailabilityProcessingStatus::MissingComponents(_, _), _))
|
||||
@@ -3168,7 +3168,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
unverified_block: B,
|
||||
block_source: BlockImportSource,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>> {
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError> {
|
||||
self.reqresp_pre_import_cache
|
||||
.write()
|
||||
.insert(block_root, unverified_block.block_cloned());
|
||||
@@ -3204,8 +3204,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
unverified_block: B,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
block_source: BlockImportSource,
|
||||
publish_fn: impl FnOnce() -> Result<(), BlockError<T::EthSpec>> + Send + 'static,
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>> {
|
||||
publish_fn: impl FnOnce() -> Result<(), BlockError> + Send + 'static,
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError> {
|
||||
// Start the Prometheus timer.
|
||||
let _full_timer = metrics::start_timer(&metrics::BLOCK_PROCESSING_TIMES);
|
||||
|
||||
@@ -3326,7 +3326,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
pub async fn into_executed_block(
|
||||
self: Arc<Self>,
|
||||
execution_pending_block: ExecutionPendingBlock<T>,
|
||||
) -> Result<ExecutedBlock<T::EthSpec>, BlockError<T::EthSpec>> {
|
||||
) -> Result<ExecutedBlock<T::EthSpec>, BlockError> {
|
||||
let ExecutionPendingBlock {
|
||||
block,
|
||||
import_data,
|
||||
@@ -3381,7 +3381,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
async fn check_block_availability_and_import(
|
||||
self: &Arc<Self>,
|
||||
block: AvailabilityPendingExecutedBlock<T::EthSpec>,
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>> {
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError> {
|
||||
let slot = block.block.slot();
|
||||
let availability = self
|
||||
.data_availability_checker
|
||||
@@ -3394,7 +3394,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
async fn check_gossip_blob_availability_and_import(
|
||||
self: &Arc<Self>,
|
||||
blob: GossipVerifiedBlob<T>,
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>> {
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError> {
|
||||
let slot = blob.slot();
|
||||
if let Some(slasher) = self.slasher.as_ref() {
|
||||
slasher.accept_block_header(blob.signed_block_header());
|
||||
@@ -3416,7 +3416,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
AvailabilityProcessingStatus,
|
||||
DataColumnsToPublish<T::EthSpec>,
|
||||
),
|
||||
BlockError<T::EthSpec>,
|
||||
BlockError,
|
||||
> {
|
||||
if let Some(slasher) = self.slasher.as_ref() {
|
||||
for data_colum in &data_columns {
|
||||
@@ -3440,7 +3440,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
slot: Slot,
|
||||
block_root: Hash256,
|
||||
blobs: FixedBlobSidecarList<T::EthSpec>,
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>> {
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError> {
|
||||
// Need to scope this to ensure the lock is dropped before calling `process_availability`
|
||||
// Even an explicit drop is not enough to convince the borrow checker.
|
||||
{
|
||||
@@ -3450,7 +3450,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
.filter_map(|b| b.as_ref().map(|b| b.signed_block_header.clone()))
|
||||
.unique()
|
||||
{
|
||||
if verify_header_signature::<T, BlockError<T::EthSpec>>(self, &header).is_ok() {
|
||||
if verify_header_signature::<T, BlockError>(self, &header).is_ok() {
|
||||
slashable_cache
|
||||
.observe_slashable(
|
||||
header.message.slot,
|
||||
@@ -3484,7 +3484,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
AvailabilityProcessingStatus,
|
||||
DataColumnsToPublish<T::EthSpec>,
|
||||
),
|
||||
BlockError<T::EthSpec>,
|
||||
BlockError,
|
||||
> {
|
||||
// Need to scope this to ensure the lock is dropped before calling `process_availability`
|
||||
// Even an explicit drop is not enough to convince the borrow checker.
|
||||
@@ -3493,7 +3493,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
// Assumes all items in custody_columns are for the same block_root
|
||||
if let Some(column) = custody_columns.first() {
|
||||
let header = &column.signed_block_header;
|
||||
if verify_header_signature::<T, BlockError<T::EthSpec>>(self, header).is_ok() {
|
||||
if verify_header_signature::<T, BlockError>(self, header).is_ok() {
|
||||
slashable_cache
|
||||
.observe_slashable(
|
||||
header.message.slot,
|
||||
@@ -3530,7 +3530,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
self: &Arc<Self>,
|
||||
slot: Slot,
|
||||
availability: Availability<T::EthSpec>,
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>> {
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError> {
|
||||
match availability {
|
||||
Availability::Available(block) => {
|
||||
// Block is fully available, import into fork choice
|
||||
@@ -3545,7 +3545,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
pub async fn import_available_block(
|
||||
self: &Arc<Self>,
|
||||
block: Box<AvailableExecutedBlock<T::EthSpec>>,
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>> {
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError> {
|
||||
let AvailableExecutedBlock {
|
||||
block,
|
||||
import_data,
|
||||
@@ -3624,7 +3624,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
parent_block: SignedBlindedBeaconBlock<T::EthSpec>,
|
||||
parent_eth1_finalization_data: Eth1FinalizationData,
|
||||
mut consensus_context: ConsensusContext<T::EthSpec>,
|
||||
) -> Result<Hash256, BlockError<T::EthSpec>> {
|
||||
) -> Result<Hash256, BlockError> {
|
||||
// ----------------------------- BLOCK NOT YET ATTESTABLE ----------------------------------
|
||||
// Everything in this initial section is on the hot path between processing the block and
|
||||
// being able to attest to it. DO NOT add any extra processing in this initial section
|
||||
@@ -3934,7 +3934,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
block: BeaconBlockRef<T::EthSpec>,
|
||||
block_root: Hash256,
|
||||
state: &BeaconState<T::EthSpec>,
|
||||
) -> Result<(), BlockError<T::EthSpec>> {
|
||||
) -> Result<(), BlockError> {
|
||||
// Only perform the weak subjectivity check if it was configured.
|
||||
let Some(wss_checkpoint) = self.config.weak_subjectivity_checkpoint else {
|
||||
return Ok(());
|
||||
@@ -4269,7 +4269,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
&self,
|
||||
block_root: Hash256,
|
||||
state: &mut BeaconState<T::EthSpec>,
|
||||
) -> Result<(), BlockError<T::EthSpec>> {
|
||||
) -> Result<(), BlockError> {
|
||||
for relative_epoch in [RelativeEpoch::Current, RelativeEpoch::Next] {
|
||||
let shuffling_id = AttestationShufflingId::new(block_root, state, relative_epoch)?;
|
||||
|
||||
@@ -7042,8 +7042,8 @@ impl From<BeaconStateError> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> ChainSegmentResult<E> {
|
||||
pub fn into_block_error(self) -> Result<(), BlockError<E>> {
|
||||
impl ChainSegmentResult {
|
||||
pub fn into_block_error(self) -> Result<(), BlockError> {
|
||||
match self {
|
||||
ChainSegmentResult::Failed { error, .. } => Err(error),
|
||||
ChainSegmentResult::Successful { .. } => Ok(()),
|
||||
|
||||
@@ -22,7 +22,7 @@ use types::{
|
||||
|
||||
/// An error occurred while validating a gossip blob.
|
||||
#[derive(Debug)]
|
||||
pub enum GossipBlobError<E: EthSpec> {
|
||||
pub enum GossipBlobError {
|
||||
/// The blob sidecar is from a slot that is later than the current slot (with respect to the
|
||||
/// gossip clock disparity).
|
||||
///
|
||||
@@ -95,7 +95,7 @@ pub enum GossipBlobError<E: EthSpec> {
|
||||
/// ## Peer scoring
|
||||
///
|
||||
/// We cannot process the blob without validating its parent, the peer isn't necessarily faulty.
|
||||
BlobParentUnknown(Arc<BlobSidecar<E>>),
|
||||
BlobParentUnknown { parent_root: Hash256 },
|
||||
|
||||
/// Invalid kzg commitment inclusion proof
|
||||
/// ## Peer scoring
|
||||
@@ -145,28 +145,19 @@ pub enum GossipBlobError<E: EthSpec> {
|
||||
NotFinalizedDescendant { block_parent_root: Hash256 },
|
||||
}
|
||||
|
||||
impl<E: EthSpec> std::fmt::Display for GossipBlobError<E> {
|
||||
impl std::fmt::Display for GossipBlobError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
GossipBlobError::BlobParentUnknown(blob_sidecar) => {
|
||||
write!(
|
||||
f,
|
||||
"BlobParentUnknown(parent_root:{})",
|
||||
blob_sidecar.block_parent_root()
|
||||
)
|
||||
}
|
||||
other => write!(f, "{:?}", other),
|
||||
}
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<BeaconChainError> for GossipBlobError<E> {
|
||||
impl From<BeaconChainError> for GossipBlobError {
|
||||
fn from(e: BeaconChainError) -> Self {
|
||||
GossipBlobError::BeaconChainError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<BeaconStateError> for GossipBlobError<E> {
|
||||
impl From<BeaconStateError> for GossipBlobError {
|
||||
fn from(e: BeaconStateError) -> Self {
|
||||
GossipBlobError::BeaconChainError(BeaconChainError::BeaconStateError(e))
|
||||
}
|
||||
@@ -190,12 +181,12 @@ impl<T: BeaconChainTypes> GossipVerifiedBlob<T> {
|
||||
blob: Arc<BlobSidecar<T::EthSpec>>,
|
||||
subnet_id: u64,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<Self, GossipBlobError<T::EthSpec>> {
|
||||
) -> Result<Self, GossipBlobError> {
|
||||
let header = blob.signed_block_header.clone();
|
||||
// We only process slashing info if the gossip verification failed
|
||||
// since we do not process the blob any further in that case.
|
||||
validate_blob_sidecar_for_gossip(blob, subnet_id, chain).map_err(|e| {
|
||||
process_block_slash_info::<_, GossipBlobError<T::EthSpec>>(
|
||||
process_block_slash_info::<_, GossipBlobError>(
|
||||
chain,
|
||||
BlockSlashInfo::from_early_error_blob(header, e),
|
||||
)
|
||||
@@ -384,7 +375,7 @@ pub fn validate_blob_sidecar_for_gossip<T: BeaconChainTypes>(
|
||||
blob_sidecar: Arc<BlobSidecar<T::EthSpec>>,
|
||||
subnet: u64,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<GossipVerifiedBlob<T>, GossipBlobError<T::EthSpec>> {
|
||||
) -> Result<GossipVerifiedBlob<T>, GossipBlobError> {
|
||||
let blob_slot = blob_sidecar.slot();
|
||||
let blob_index = blob_sidecar.index;
|
||||
let block_parent_root = blob_sidecar.block_parent_root();
|
||||
@@ -466,7 +457,9 @@ pub fn validate_blob_sidecar_for_gossip<T: BeaconChainTypes>(
|
||||
// We have already verified that the blob is past finalization, so we can
|
||||
// just check fork choice for the block's parent.
|
||||
let Some(parent_block) = fork_choice.get_block(&block_parent_root) else {
|
||||
return Err(GossipBlobError::BlobParentUnknown(blob_sidecar));
|
||||
return Err(GossipBlobError::BlobParentUnknown {
|
||||
parent_root: block_parent_root,
|
||||
});
|
||||
};
|
||||
|
||||
// Do not process a blob that does not descend from the finalized root.
|
||||
@@ -516,7 +509,7 @@ pub fn validate_blob_sidecar_for_gossip<T: BeaconChainTypes>(
|
||||
))
|
||||
})?;
|
||||
|
||||
let state = cheap_state_advance_to_obtain_committees::<_, GossipBlobError<T::EthSpec>>(
|
||||
let state = cheap_state_advance_to_obtain_committees::<_, GossipBlobError>(
|
||||
&mut parent_state,
|
||||
Some(parent_state_root),
|
||||
blob_slot,
|
||||
|
||||
@@ -144,14 +144,14 @@ const WRITE_BLOCK_PROCESSING_SSZ: bool = cfg!(feature = "write_ssz_files");
|
||||
/// - The block is malformed/invalid (indicated by all results other than `BeaconChainError`.
|
||||
/// - We encountered an error whilst trying to verify the block (a `BeaconChainError`).
|
||||
#[derive(Debug)]
|
||||
pub enum BlockError<E: EthSpec> {
|
||||
pub enum BlockError {
|
||||
/// The parent block was unknown.
|
||||
///
|
||||
/// ## Peer scoring
|
||||
///
|
||||
/// It's unclear if this block is valid, but it cannot be processed without already knowing
|
||||
/// its parent.
|
||||
ParentUnknown(RpcBlock<E>),
|
||||
ParentUnknown { parent_root: Hash256 },
|
||||
/// The block slot is greater than the present slot.
|
||||
///
|
||||
/// ## Peer scoring
|
||||
@@ -328,7 +328,7 @@ pub enum BlockError<E: EthSpec> {
|
||||
InternalError(String),
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<AvailabilityCheckError> for BlockError<E> {
|
||||
impl From<AvailabilityCheckError> for BlockError {
|
||||
fn from(e: AvailabilityCheckError) -> Self {
|
||||
Self::AvailabilityCheck(e)
|
||||
}
|
||||
@@ -436,30 +436,25 @@ impl From<execution_layer::Error> for ExecutionPayloadError {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<ExecutionPayloadError> for BlockError<E> {
|
||||
impl From<ExecutionPayloadError> for BlockError {
|
||||
fn from(e: ExecutionPayloadError) -> Self {
|
||||
BlockError::ExecutionPayloadError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<InconsistentFork> for BlockError<E> {
|
||||
impl From<InconsistentFork> for BlockError {
|
||||
fn from(e: InconsistentFork) -> Self {
|
||||
BlockError::InconsistentFork(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> std::fmt::Display for BlockError<E> {
|
||||
impl std::fmt::Display for BlockError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
BlockError::ParentUnknown(block) => {
|
||||
write!(f, "ParentUnknown(parent_root:{})", block.parent_root())
|
||||
}
|
||||
other => write!(f, "{:?}", other),
|
||||
}
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<BlockSignatureVerifierError> for BlockError<E> {
|
||||
impl From<BlockSignatureVerifierError> for BlockError {
|
||||
fn from(e: BlockSignatureVerifierError) -> Self {
|
||||
match e {
|
||||
// Make a special distinction for `IncorrectBlockProposer` since it indicates an
|
||||
@@ -476,31 +471,31 @@ impl<E: EthSpec> From<BlockSignatureVerifierError> for BlockError<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<BeaconChainError> for BlockError<E> {
|
||||
impl From<BeaconChainError> for BlockError {
|
||||
fn from(e: BeaconChainError) -> Self {
|
||||
BlockError::BeaconChainError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<BeaconStateError> for BlockError<E> {
|
||||
impl From<BeaconStateError> for BlockError {
|
||||
fn from(e: BeaconStateError) -> Self {
|
||||
BlockError::BeaconChainError(BeaconChainError::BeaconStateError(e))
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<SlotProcessingError> for BlockError<E> {
|
||||
impl From<SlotProcessingError> for BlockError {
|
||||
fn from(e: SlotProcessingError) -> Self {
|
||||
BlockError::BeaconChainError(BeaconChainError::SlotProcessingError(e))
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<DBError> for BlockError<E> {
|
||||
impl From<DBError> for BlockError {
|
||||
fn from(e: DBError) -> Self {
|
||||
BlockError::BeaconChainError(BeaconChainError::DBError(e))
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<ArithError> for BlockError<E> {
|
||||
impl From<ArithError> for BlockError {
|
||||
fn from(e: ArithError) -> Self {
|
||||
BlockError::BeaconChainError(BeaconChainError::ArithError(e))
|
||||
}
|
||||
@@ -524,8 +519,8 @@ pub enum BlockSlashInfo<TErr> {
|
||||
SignatureValid(SignedBeaconBlockHeader, TErr),
|
||||
}
|
||||
|
||||
impl<E: EthSpec> BlockSlashInfo<BlockError<E>> {
|
||||
pub fn from_early_error_block(header: SignedBeaconBlockHeader, e: BlockError<E>) -> Self {
|
||||
impl BlockSlashInfo<BlockError> {
|
||||
pub fn from_early_error_block(header: SignedBeaconBlockHeader, e: BlockError) -> Self {
|
||||
match e {
|
||||
BlockError::ProposalSignatureInvalid => BlockSlashInfo::SignatureInvalid(e),
|
||||
// `InvalidSignature` could indicate any signature in the block, so we want
|
||||
@@ -535,8 +530,8 @@ impl<E: EthSpec> BlockSlashInfo<BlockError<E>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> BlockSlashInfo<GossipBlobError<E>> {
|
||||
pub fn from_early_error_blob(header: SignedBeaconBlockHeader, e: GossipBlobError<E>) -> Self {
|
||||
impl BlockSlashInfo<GossipBlobError> {
|
||||
pub fn from_early_error_blob(header: SignedBeaconBlockHeader, e: GossipBlobError) -> Self {
|
||||
match e {
|
||||
GossipBlobError::ProposalSignatureInvalid => BlockSlashInfo::SignatureInvalid(e),
|
||||
// `InvalidSignature` could indicate any signature in the block, so we want
|
||||
@@ -604,7 +599,7 @@ pub(crate) fn process_block_slash_info<T: BeaconChainTypes, TErr: BlockBlobError
|
||||
pub fn signature_verify_chain_segment<T: BeaconChainTypes>(
|
||||
mut chain_segment: Vec<(Hash256, RpcBlock<T::EthSpec>)>,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<Vec<SignatureVerifiedBlock<T>>, BlockError<T::EthSpec>> {
|
||||
) -> Result<Vec<SignatureVerifiedBlock<T>>, BlockError> {
|
||||
if chain_segment.is_empty() {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
@@ -619,7 +614,7 @@ pub fn signature_verify_chain_segment<T: BeaconChainTypes>(
|
||||
.map(|(_, block)| block.slot())
|
||||
.unwrap_or_else(|| slot);
|
||||
|
||||
let state = cheap_state_advance_to_obtain_committees::<_, BlockError<T::EthSpec>>(
|
||||
let state = cheap_state_advance_to_obtain_committees::<_, BlockError>(
|
||||
&mut parent.pre_state,
|
||||
parent.beacon_state_root,
|
||||
highest_slot,
|
||||
@@ -689,8 +684,7 @@ pub struct SignatureVerifiedBlock<T: BeaconChainTypes> {
|
||||
}
|
||||
|
||||
/// Used to await the result of executing payload with a remote EE.
|
||||
type PayloadVerificationHandle<E> =
|
||||
JoinHandle<Option<Result<PayloadVerificationOutcome, BlockError<E>>>>;
|
||||
type PayloadVerificationHandle = JoinHandle<Option<Result<PayloadVerificationOutcome, BlockError>>>;
|
||||
|
||||
/// A wrapper around a `SignedBeaconBlock` that indicates that this block is fully verified and
|
||||
/// ready to import into the `BeaconChain`. The validation includes:
|
||||
@@ -706,14 +700,14 @@ type PayloadVerificationHandle<E> =
|
||||
pub struct ExecutionPendingBlock<T: BeaconChainTypes> {
|
||||
pub block: MaybeAvailableBlock<T::EthSpec>,
|
||||
pub import_data: BlockImportData<T::EthSpec>,
|
||||
pub payload_verification_handle: PayloadVerificationHandle<T::EthSpec>,
|
||||
pub payload_verification_handle: PayloadVerificationHandle,
|
||||
}
|
||||
|
||||
pub trait IntoGossipVerifiedBlockContents<T: BeaconChainTypes>: Sized {
|
||||
fn into_gossip_verified_block(
|
||||
self,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<GossipVerifiedBlockContents<T>, BlockContentsError<T::EthSpec>>;
|
||||
) -> Result<GossipVerifiedBlockContents<T>, BlockContentsError>;
|
||||
fn inner_block(&self) -> &SignedBeaconBlock<T::EthSpec>;
|
||||
}
|
||||
|
||||
@@ -721,7 +715,7 @@ impl<T: BeaconChainTypes> IntoGossipVerifiedBlockContents<T> for GossipVerifiedB
|
||||
fn into_gossip_verified_block(
|
||||
self,
|
||||
_chain: &BeaconChain<T>,
|
||||
) -> Result<GossipVerifiedBlockContents<T>, BlockContentsError<T::EthSpec>> {
|
||||
) -> Result<GossipVerifiedBlockContents<T>, BlockContentsError> {
|
||||
Ok(self)
|
||||
}
|
||||
fn inner_block(&self) -> &SignedBeaconBlock<T::EthSpec> {
|
||||
@@ -733,7 +727,7 @@ impl<T: BeaconChainTypes> IntoGossipVerifiedBlockContents<T> for PublishBlockReq
|
||||
fn into_gossip_verified_block(
|
||||
self,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<GossipVerifiedBlockContents<T>, BlockContentsError<T::EthSpec>> {
|
||||
) -> Result<GossipVerifiedBlockContents<T>, BlockContentsError> {
|
||||
let (block, blobs) = self.deconstruct();
|
||||
let peer_das_enabled = chain.spec.is_peer_das_enabled_for_epoch(block.epoch());
|
||||
|
||||
@@ -765,7 +759,7 @@ fn build_gossip_verified_blobs<T: BeaconChainTypes>(
|
||||
chain: &BeaconChain<T>,
|
||||
block: &Arc<SignedBeaconBlock<T::EthSpec, FullPayload<T::EthSpec>>>,
|
||||
blobs: Option<(KzgProofs<T::EthSpec>, BlobsList<T::EthSpec>)>,
|
||||
) -> Result<Option<GossipVerifiedBlobList<T>>, BlockContentsError<T::EthSpec>> {
|
||||
) -> Result<Option<GossipVerifiedBlobList<T>>, BlockContentsError> {
|
||||
blobs
|
||||
.map(|(kzg_proofs, blobs)| {
|
||||
let mut gossip_verified_blobs = vec![];
|
||||
@@ -780,7 +774,7 @@ fn build_gossip_verified_blobs<T: BeaconChainTypes>(
|
||||
gossip_verified_blobs.push(gossip_verified_blob);
|
||||
}
|
||||
let gossip_verified_blobs = VariableList::from(gossip_verified_blobs);
|
||||
Ok::<_, BlockContentsError<T::EthSpec>>(gossip_verified_blobs)
|
||||
Ok::<_, BlockContentsError>(gossip_verified_blobs)
|
||||
})
|
||||
.transpose()
|
||||
}
|
||||
@@ -789,7 +783,7 @@ fn build_gossip_verified_data_columns<T: BeaconChainTypes>(
|
||||
chain: &BeaconChain<T>,
|
||||
block: &SignedBeaconBlock<T::EthSpec, FullPayload<T::EthSpec>>,
|
||||
blobs: Option<BlobsList<T::EthSpec>>,
|
||||
) -> Result<Option<GossipVerifiedDataColumnList<T>>, BlockContentsError<T::EthSpec>> {
|
||||
) -> Result<Option<GossipVerifiedDataColumnList<T>>, BlockContentsError> {
|
||||
blobs
|
||||
// Only attempt to build data columns if blobs is non empty to avoid skewing the metrics.
|
||||
.filter(|b| !b.is_empty())
|
||||
@@ -819,7 +813,7 @@ fn build_gossip_verified_data_columns<T: BeaconChainTypes>(
|
||||
chain.spec.number_of_columns,
|
||||
)
|
||||
.map_err(DataColumnSidecarError::SszError)?;
|
||||
Ok::<_, BlockContentsError<T::EthSpec>>(gossip_verified_data_columns)
|
||||
Ok::<_, BlockContentsError>(gossip_verified_data_columns)
|
||||
})
|
||||
.transpose()
|
||||
}
|
||||
@@ -833,7 +827,7 @@ pub trait IntoExecutionPendingBlock<T: BeaconChainTypes>: Sized {
|
||||
block_root: Hash256,
|
||||
chain: &Arc<BeaconChain<T>>,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> Result<ExecutionPendingBlock<T>, BlockError<T::EthSpec>> {
|
||||
) -> Result<ExecutionPendingBlock<T>, BlockError> {
|
||||
self.into_execution_pending_block_slashable(block_root, chain, notify_execution_layer)
|
||||
.map(|execution_pending| {
|
||||
// Supply valid block to slasher.
|
||||
@@ -842,9 +836,7 @@ pub trait IntoExecutionPendingBlock<T: BeaconChainTypes>: Sized {
|
||||
}
|
||||
execution_pending
|
||||
})
|
||||
.map_err(|slash_info| {
|
||||
process_block_slash_info::<_, BlockError<T::EthSpec>>(chain, slash_info)
|
||||
})
|
||||
.map_err(|slash_info| process_block_slash_info::<_, BlockError>(chain, slash_info))
|
||||
}
|
||||
|
||||
/// Convert the block to fully-verified form while producing data to aid checking slashability.
|
||||
@@ -853,7 +845,7 @@ pub trait IntoExecutionPendingBlock<T: BeaconChainTypes>: Sized {
|
||||
block_root: Hash256,
|
||||
chain: &Arc<BeaconChain<T>>,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> Result<ExecutionPendingBlock<T>, BlockSlashInfo<BlockError<T::EthSpec>>>;
|
||||
) -> Result<ExecutionPendingBlock<T>, BlockSlashInfo<BlockError>>;
|
||||
|
||||
fn block(&self) -> &SignedBeaconBlock<T::EthSpec>;
|
||||
fn block_cloned(&self) -> Arc<SignedBeaconBlock<T::EthSpec>>;
|
||||
@@ -867,7 +859,7 @@ impl<T: BeaconChainTypes> GossipVerifiedBlock<T> {
|
||||
pub fn new(
|
||||
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<Self, BlockError<T::EthSpec>> {
|
||||
) -> Result<Self, BlockError> {
|
||||
// If the block is valid for gossip we don't supply it to the slasher here because
|
||||
// we assume it will be transformed into a fully verified block. We *do* need to supply
|
||||
// it to the slasher if an error occurs, because that's the end of this block's journey,
|
||||
@@ -877,7 +869,7 @@ impl<T: BeaconChainTypes> GossipVerifiedBlock<T> {
|
||||
// but it's way quicker to calculate root of the header since the hash of the tree rooted
|
||||
// at `BeaconBlockBody` is already computed in the header.
|
||||
Self::new_without_slasher_checks(block, &header, chain).map_err(|e| {
|
||||
process_block_slash_info::<_, BlockError<T::EthSpec>>(
|
||||
process_block_slash_info::<_, BlockError>(
|
||||
chain,
|
||||
BlockSlashInfo::from_early_error_block(header, e),
|
||||
)
|
||||
@@ -889,7 +881,7 @@ impl<T: BeaconChainTypes> GossipVerifiedBlock<T> {
|
||||
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
||||
block_header: &SignedBeaconBlockHeader,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<Self, BlockError<T::EthSpec>> {
|
||||
) -> Result<Self, BlockError> {
|
||||
// Ensure the block is the correct structure for the fork at `block.slot()`.
|
||||
block
|
||||
.fork_name(&chain.spec)
|
||||
@@ -938,7 +930,7 @@ impl<T: BeaconChainTypes> GossipVerifiedBlock<T> {
|
||||
|
||||
let block_epoch = block.slot().epoch(T::EthSpec::slots_per_epoch());
|
||||
let (parent_block, block) =
|
||||
verify_parent_block_is_known::<T>(block_root, &fork_choice_read_lock, block)?;
|
||||
verify_parent_block_is_known::<T>(&fork_choice_read_lock, block)?;
|
||||
drop(fork_choice_read_lock);
|
||||
|
||||
// Track the number of skip slots between the block and its parent.
|
||||
@@ -998,7 +990,7 @@ impl<T: BeaconChainTypes> GossipVerifiedBlock<T> {
|
||||
);
|
||||
|
||||
// The state produced is only valid for determining proposer/attester shuffling indices.
|
||||
let state = cheap_state_advance_to_obtain_committees::<_, BlockError<T::EthSpec>>(
|
||||
let state = cheap_state_advance_to_obtain_committees::<_, BlockError>(
|
||||
&mut parent.pre_state,
|
||||
parent.beacon_state_root,
|
||||
block.slot(),
|
||||
@@ -1107,7 +1099,7 @@ impl<T: BeaconChainTypes> IntoExecutionPendingBlock<T> for GossipVerifiedBlock<T
|
||||
block_root: Hash256,
|
||||
chain: &Arc<BeaconChain<T>>,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> Result<ExecutionPendingBlock<T>, BlockSlashInfo<BlockError<T::EthSpec>>> {
|
||||
) -> Result<ExecutionPendingBlock<T>, BlockSlashInfo<BlockError>> {
|
||||
let execution_pending =
|
||||
SignatureVerifiedBlock::from_gossip_verified_block_check_slashable(self, chain)?;
|
||||
execution_pending.into_execution_pending_block_slashable(
|
||||
@@ -1135,7 +1127,7 @@ impl<T: BeaconChainTypes> SignatureVerifiedBlock<T> {
|
||||
block: MaybeAvailableBlock<T::EthSpec>,
|
||||
block_root: Hash256,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<Self, BlockError<T::EthSpec>> {
|
||||
) -> Result<Self, BlockError> {
|
||||
// Ensure the block is the correct structure for the fork at `block.slot()`.
|
||||
block
|
||||
.as_block()
|
||||
@@ -1147,7 +1139,7 @@ impl<T: BeaconChainTypes> SignatureVerifiedBlock<T> {
|
||||
|
||||
let (mut parent, block) = load_parent(block, chain)?;
|
||||
|
||||
let state = cheap_state_advance_to_obtain_committees::<_, BlockError<T::EthSpec>>(
|
||||
let state = cheap_state_advance_to_obtain_committees::<_, BlockError>(
|
||||
&mut parent.pre_state,
|
||||
parent.beacon_state_root,
|
||||
block.slot(),
|
||||
@@ -1180,7 +1172,7 @@ impl<T: BeaconChainTypes> SignatureVerifiedBlock<T> {
|
||||
block: MaybeAvailableBlock<T::EthSpec>,
|
||||
block_root: Hash256,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<Self, BlockSlashInfo<BlockError<T::EthSpec>>> {
|
||||
) -> Result<Self, BlockSlashInfo<BlockError>> {
|
||||
let header = block.signed_block_header();
|
||||
Self::new(block, block_root, chain)
|
||||
.map_err(|e| BlockSlashInfo::from_early_error_block(header, e))
|
||||
@@ -1191,14 +1183,14 @@ impl<T: BeaconChainTypes> SignatureVerifiedBlock<T> {
|
||||
pub fn from_gossip_verified_block(
|
||||
from: GossipVerifiedBlock<T>,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<Self, BlockError<T::EthSpec>> {
|
||||
) -> Result<Self, BlockError> {
|
||||
let (mut parent, block) = if let Some(parent) = from.parent {
|
||||
(parent, from.block)
|
||||
} else {
|
||||
load_parent(from.block, chain)?
|
||||
};
|
||||
|
||||
let state = cheap_state_advance_to_obtain_committees::<_, BlockError<T::EthSpec>>(
|
||||
let state = cheap_state_advance_to_obtain_committees::<_, BlockError>(
|
||||
&mut parent.pre_state,
|
||||
parent.beacon_state_root,
|
||||
block.slot(),
|
||||
@@ -1234,7 +1226,7 @@ impl<T: BeaconChainTypes> SignatureVerifiedBlock<T> {
|
||||
pub fn from_gossip_verified_block_check_slashable(
|
||||
from: GossipVerifiedBlock<T>,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<Self, BlockSlashInfo<BlockError<T::EthSpec>>> {
|
||||
) -> Result<Self, BlockSlashInfo<BlockError>> {
|
||||
let header = from.block.signed_block_header();
|
||||
Self::from_gossip_verified_block(from, chain)
|
||||
.map_err(|e| BlockSlashInfo::from_early_error_block(header, e))
|
||||
@@ -1256,7 +1248,7 @@ impl<T: BeaconChainTypes> IntoExecutionPendingBlock<T> for SignatureVerifiedBloc
|
||||
block_root: Hash256,
|
||||
chain: &Arc<BeaconChain<T>>,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> Result<ExecutionPendingBlock<T>, BlockSlashInfo<BlockError<T::EthSpec>>> {
|
||||
) -> Result<ExecutionPendingBlock<T>, BlockSlashInfo<BlockError>> {
|
||||
let header = self.block.signed_block_header();
|
||||
let (parent, block) = if let Some(parent) = self.parent {
|
||||
(parent, self.block)
|
||||
@@ -1293,7 +1285,7 @@ impl<T: BeaconChainTypes> IntoExecutionPendingBlock<T> for Arc<SignedBeaconBlock
|
||||
block_root: Hash256,
|
||||
chain: &Arc<BeaconChain<T>>,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> Result<ExecutionPendingBlock<T>, BlockSlashInfo<BlockError<T::EthSpec>>> {
|
||||
) -> Result<ExecutionPendingBlock<T>, BlockSlashInfo<BlockError>> {
|
||||
// Perform an early check to prevent wasting time on irrelevant blocks.
|
||||
let block_root = check_block_relevancy(&self, block_root, chain)
|
||||
.map_err(|e| BlockSlashInfo::SignatureNotChecked(self.signed_block_header(), e))?;
|
||||
@@ -1327,7 +1319,7 @@ impl<T: BeaconChainTypes> IntoExecutionPendingBlock<T> for RpcBlock<T::EthSpec>
|
||||
block_root: Hash256,
|
||||
chain: &Arc<BeaconChain<T>>,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> Result<ExecutionPendingBlock<T>, BlockSlashInfo<BlockError<T::EthSpec>>> {
|
||||
) -> 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))?;
|
||||
@@ -1368,7 +1360,7 @@ impl<T: BeaconChainTypes> ExecutionPendingBlock<T> {
|
||||
mut consensus_context: ConsensusContext<T::EthSpec>,
|
||||
chain: &Arc<BeaconChain<T>>,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> Result<Self, BlockError<T::EthSpec>> {
|
||||
) -> Result<Self, BlockError> {
|
||||
chain
|
||||
.observed_slashable
|
||||
.write()
|
||||
@@ -1404,7 +1396,9 @@ impl<T: BeaconChainTypes> ExecutionPendingBlock<T> {
|
||||
// because it will revert finalization. Note that the finalized block is stored in fork
|
||||
// choice, so we will not reject any child of the finalized block (this is relevant during
|
||||
// genesis).
|
||||
return Err(BlockError::ParentUnknown(block.into_rpc_block()));
|
||||
return Err(BlockError::ParentUnknown {
|
||||
parent_root: block.parent_root(),
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1781,7 +1775,7 @@ impl<T: BeaconChainTypes> ExecutionPendingBlock<T> {
|
||||
fn check_block_against_anchor_slot<T: BeaconChainTypes>(
|
||||
block: BeaconBlockRef<'_, T::EthSpec>,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<(), BlockError<T::EthSpec>> {
|
||||
) -> Result<(), BlockError> {
|
||||
if let Some(anchor_slot) = chain.store.get_anchor_slot() {
|
||||
if block.slot() <= anchor_slot {
|
||||
return Err(BlockError::WeakSubjectivityConflict);
|
||||
@@ -1798,7 +1792,7 @@ fn check_block_against_finalized_slot<T: BeaconChainTypes>(
|
||||
block: BeaconBlockRef<'_, T::EthSpec>,
|
||||
block_root: Hash256,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<(), BlockError<T::EthSpec>> {
|
||||
) -> Result<(), BlockError> {
|
||||
// The finalized checkpoint is being read from fork choice, rather than the cached head.
|
||||
//
|
||||
// Fork choice has the most up-to-date view of finalization and there's no point importing a
|
||||
@@ -1833,7 +1827,7 @@ pub fn check_block_is_finalized_checkpoint_or_descendant<
|
||||
chain: &BeaconChain<T>,
|
||||
fork_choice: &BeaconForkChoice<T>,
|
||||
block: B,
|
||||
) -> Result<B, BlockError<T::EthSpec>> {
|
||||
) -> Result<B, BlockError> {
|
||||
if fork_choice.is_finalized_checkpoint_or_descendant(block.parent_root()) {
|
||||
Ok(block)
|
||||
} else {
|
||||
@@ -1854,7 +1848,9 @@ pub fn check_block_is_finalized_checkpoint_or_descendant<
|
||||
block_parent_root: block.parent_root(),
|
||||
})
|
||||
} else {
|
||||
Err(BlockError::ParentUnknown(block.into_rpc_block()))
|
||||
Err(BlockError::ParentUnknown {
|
||||
parent_root: block.parent_root(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1870,7 +1866,7 @@ pub fn check_block_relevancy<T: BeaconChainTypes>(
|
||||
signed_block: &SignedBeaconBlock<T::EthSpec>,
|
||||
block_root: Hash256,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<Hash256, BlockError<T::EthSpec>> {
|
||||
) -> Result<Hash256, BlockError> {
|
||||
let block = signed_block.message();
|
||||
|
||||
// Do not process blocks from the future.
|
||||
@@ -1938,17 +1934,15 @@ pub fn get_block_header_root(block_header: &SignedBeaconBlockHeader) -> Hash256
|
||||
/// fork choice.
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn verify_parent_block_is_known<T: BeaconChainTypes>(
|
||||
block_root: Hash256,
|
||||
fork_choice_read_lock: &RwLockReadGuard<BeaconForkChoice<T>>,
|
||||
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
||||
) -> Result<(ProtoBlock, Arc<SignedBeaconBlock<T::EthSpec>>), BlockError<T::EthSpec>> {
|
||||
) -> Result<(ProtoBlock, Arc<SignedBeaconBlock<T::EthSpec>>), BlockError> {
|
||||
if let Some(proto_block) = fork_choice_read_lock.get_block(&block.parent_root()) {
|
||||
Ok((proto_block, block))
|
||||
} else {
|
||||
Err(BlockError::ParentUnknown(RpcBlock::new_without_blobs(
|
||||
Some(block_root),
|
||||
block,
|
||||
)))
|
||||
Err(BlockError::ParentUnknown {
|
||||
parent_root: block.parent_root(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1960,7 +1954,7 @@ fn verify_parent_block_is_known<T: BeaconChainTypes>(
|
||||
fn load_parent<T: BeaconChainTypes, B: AsBlock<T::EthSpec>>(
|
||||
block: B,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<(PreProcessingSnapshot<T::EthSpec>, B), BlockError<T::EthSpec>> {
|
||||
) -> Result<(PreProcessingSnapshot<T::EthSpec>, B), BlockError> {
|
||||
// Reject any block if its parent is not known to fork choice.
|
||||
//
|
||||
// A block that is not in fork choice is either:
|
||||
@@ -1976,7 +1970,9 @@ fn load_parent<T: BeaconChainTypes, B: AsBlock<T::EthSpec>>(
|
||||
.fork_choice_read_lock()
|
||||
.contains_block(&block.parent_root())
|
||||
{
|
||||
return Err(BlockError::ParentUnknown(block.into_rpc_block()));
|
||||
return Err(BlockError::ParentUnknown {
|
||||
parent_root: block.parent_root(),
|
||||
});
|
||||
}
|
||||
|
||||
let db_read_timer = metrics::start_timer(&metrics::BLOCK_PROCESSING_DB_READ);
|
||||
@@ -2072,7 +2068,7 @@ pub trait BlockBlobError: From<BeaconStateError> + From<BeaconChainError> + Debu
|
||||
fn proposer_signature_invalid() -> Self;
|
||||
}
|
||||
|
||||
impl<E: EthSpec> BlockBlobError for BlockError<E> {
|
||||
impl BlockBlobError for BlockError {
|
||||
fn not_later_than_parent_error(block_slot: Slot, parent_slot: Slot) -> Self {
|
||||
BlockError::BlockIsNotLaterThanParent {
|
||||
block_slot,
|
||||
@@ -2089,7 +2085,7 @@ impl<E: EthSpec> BlockBlobError for BlockError<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> BlockBlobError for GossipBlobError<E> {
|
||||
impl BlockBlobError for GossipBlobError {
|
||||
fn not_later_than_parent_error(blob_slot: Slot, parent_slot: Slot) -> Self {
|
||||
GossipBlobError::BlobIsNotLaterThanParent {
|
||||
blob_slot,
|
||||
|
||||
@@ -397,39 +397,39 @@ pub type GossipVerifiedBlockContents<E> = (
|
||||
);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BlockContentsError<E: EthSpec> {
|
||||
BlockError(BlockError<E>),
|
||||
BlobError(GossipBlobError<E>),
|
||||
pub enum BlockContentsError {
|
||||
BlockError(BlockError),
|
||||
BlobError(GossipBlobError),
|
||||
BlobSidecarError(blob_sidecar::BlobSidecarError),
|
||||
DataColumnError(GossipDataColumnError),
|
||||
DataColumnSidecarError(data_column_sidecar::DataColumnSidecarError),
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<BlockError<E>> for BlockContentsError<E> {
|
||||
fn from(value: BlockError<E>) -> Self {
|
||||
impl From<BlockError> for BlockContentsError {
|
||||
fn from(value: BlockError) -> Self {
|
||||
Self::BlockError(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<GossipBlobError<E>> for BlockContentsError<E> {
|
||||
fn from(value: GossipBlobError<E>) -> Self {
|
||||
impl From<GossipBlobError> for BlockContentsError {
|
||||
fn from(value: GossipBlobError) -> Self {
|
||||
Self::BlobError(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<GossipDataColumnError> for BlockContentsError<E> {
|
||||
impl From<GossipDataColumnError> for BlockContentsError {
|
||||
fn from(value: GossipDataColumnError) -> Self {
|
||||
Self::DataColumnError(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<data_column_sidecar::DataColumnSidecarError> for BlockContentsError<E> {
|
||||
impl From<data_column_sidecar::DataColumnSidecarError> for BlockContentsError {
|
||||
fn from(value: data_column_sidecar::DataColumnSidecarError) -> Self {
|
||||
Self::DataColumnSidecarError(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> std::fmt::Display for BlockContentsError<E> {
|
||||
impl std::fmt::Display for BlockContentsError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
BlockContentsError::BlockError(err) => {
|
||||
@@ -462,7 +462,6 @@ pub trait AsBlock<E: EthSpec> {
|
||||
fn as_block(&self) -> &SignedBeaconBlock<E>;
|
||||
fn block_cloned(&self) -> Arc<SignedBeaconBlock<E>>;
|
||||
fn canonical_root(&self) -> Hash256;
|
||||
fn into_rpc_block(self) -> RpcBlock<E>;
|
||||
}
|
||||
|
||||
impl<E: EthSpec> AsBlock<E> for Arc<SignedBeaconBlock<E>> {
|
||||
@@ -501,10 +500,6 @@ impl<E: EthSpec> AsBlock<E> for Arc<SignedBeaconBlock<E>> {
|
||||
fn canonical_root(&self) -> Hash256 {
|
||||
SignedBeaconBlock::canonical_root(self)
|
||||
}
|
||||
|
||||
fn into_rpc_block(self) -> RpcBlock<E> {
|
||||
RpcBlock::new_without_blobs(None, self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> AsBlock<E> for MaybeAvailableBlock<E> {
|
||||
@@ -547,15 +542,6 @@ impl<E: EthSpec> AsBlock<E> for MaybeAvailableBlock<E> {
|
||||
fn canonical_root(&self) -> Hash256 {
|
||||
self.as_block().canonical_root()
|
||||
}
|
||||
|
||||
fn into_rpc_block(self) -> RpcBlock<E> {
|
||||
match self {
|
||||
MaybeAvailableBlock::Available(available_block) => available_block.into_rpc_block(),
|
||||
MaybeAvailableBlock::AvailabilityPending { block_root, block } => {
|
||||
RpcBlock::new_without_blobs(Some(block_root), block)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> AsBlock<E> for AvailableBlock<E> {
|
||||
@@ -594,36 +580,6 @@ impl<E: EthSpec> AsBlock<E> for AvailableBlock<E> {
|
||||
fn canonical_root(&self) -> Hash256 {
|
||||
self.block().canonical_root()
|
||||
}
|
||||
|
||||
fn into_rpc_block(self) -> RpcBlock<E> {
|
||||
let number_of_columns = self.spec.number_of_columns;
|
||||
let (block_root, block, blobs_opt, data_columns_opt) = self.deconstruct();
|
||||
// Circumvent the constructor here, because an Available block will have already had
|
||||
// consistency checks performed.
|
||||
let inner = match (blobs_opt, data_columns_opt) {
|
||||
(None, None) => RpcBlockInner::Block(block),
|
||||
(Some(blobs), _) => RpcBlockInner::BlockAndBlobs(block, blobs),
|
||||
(_, Some(data_columns)) => RpcBlockInner::BlockAndCustodyColumns(
|
||||
block,
|
||||
RuntimeVariableList::new(
|
||||
data_columns
|
||||
.into_iter()
|
||||
// TODO(das): This is an ugly hack that should be removed. After updating
|
||||
// store types to handle custody data columns this should not be required.
|
||||
// It's okay-ish because available blocks must have all the required custody
|
||||
// columns.
|
||||
.map(|d| CustodyDataColumn::from_asserted_custody(d))
|
||||
.collect(),
|
||||
number_of_columns,
|
||||
)
|
||||
.expect("data column list is within bounds"),
|
||||
),
|
||||
};
|
||||
RpcBlock {
|
||||
block_root,
|
||||
block: inner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> AsBlock<E> for RpcBlock<E> {
|
||||
@@ -662,8 +618,4 @@ impl<E: EthSpec> AsBlock<E> for RpcBlock<E> {
|
||||
fn canonical_root(&self) -> Hash256 {
|
||||
self.as_block().canonical_root()
|
||||
}
|
||||
|
||||
fn into_rpc_block(self) -> RpcBlock<E> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ impl<T: BeaconChainTypes> PayloadNotifier<T> {
|
||||
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
||||
state: &BeaconState<T::EthSpec>,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> Result<Self, BlockError<T::EthSpec>> {
|
||||
) -> Result<Self, BlockError> {
|
||||
let payload_verification_status = if is_execution_enabled(state, block.message().body()) {
|
||||
// Perform the initial stages of payload verification.
|
||||
//
|
||||
@@ -110,9 +110,7 @@ impl<T: BeaconChainTypes> PayloadNotifier<T> {
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn notify_new_payload(
|
||||
self,
|
||||
) -> Result<PayloadVerificationStatus, BlockError<T::EthSpec>> {
|
||||
pub async fn notify_new_payload(self) -> Result<PayloadVerificationStatus, BlockError> {
|
||||
if let Some(precomputed_status) = self.payload_verification_status {
|
||||
Ok(precomputed_status)
|
||||
} else {
|
||||
@@ -133,7 +131,7 @@ impl<T: BeaconChainTypes> PayloadNotifier<T> {
|
||||
async fn notify_new_payload<'a, T: BeaconChainTypes>(
|
||||
chain: &Arc<BeaconChain<T>>,
|
||||
block: BeaconBlockRef<'a, T::EthSpec>,
|
||||
) -> Result<PayloadVerificationStatus, BlockError<T::EthSpec>> {
|
||||
) -> Result<PayloadVerificationStatus, BlockError> {
|
||||
let execution_layer = chain
|
||||
.execution_layer
|
||||
.as_ref()
|
||||
@@ -237,7 +235,7 @@ pub async fn validate_merge_block<'a, T: BeaconChainTypes>(
|
||||
chain: &Arc<BeaconChain<T>>,
|
||||
block: BeaconBlockRef<'a, T::EthSpec>,
|
||||
allow_optimistic_import: AllowOptimisticImport,
|
||||
) -> Result<(), BlockError<T::EthSpec>> {
|
||||
) -> Result<(), BlockError> {
|
||||
let spec = &chain.spec;
|
||||
let block_epoch = block.slot().epoch(T::EthSpec::slots_per_epoch());
|
||||
let execution_payload = block.execution_payload()?;
|
||||
@@ -335,7 +333,7 @@ pub fn validate_execution_payload_for_gossip<T: BeaconChainTypes>(
|
||||
parent_block: &ProtoBlock,
|
||||
block: BeaconBlockRef<'_, T::EthSpec>,
|
||||
chain: &BeaconChain<T>,
|
||||
) -> Result<(), BlockError<T::EthSpec>> {
|
||||
) -> Result<(), BlockError> {
|
||||
// Only apply this validation if this is a Bellatrix beacon block.
|
||||
if let Ok(execution_payload) = block.body().execution_payload() {
|
||||
// This logic should match `is_execution_enabled`. We use only the execution block hash of
|
||||
|
||||
@@ -1986,7 +1986,7 @@ where
|
||||
slot: Slot,
|
||||
block_root: Hash256,
|
||||
block_contents: SignedBlockContentsTuple<E>,
|
||||
) -> Result<SignedBeaconBlockHash, BlockError<E>> {
|
||||
) -> Result<SignedBeaconBlockHash, BlockError> {
|
||||
self.set_current_slot(slot);
|
||||
let (block, blob_items) = block_contents;
|
||||
|
||||
@@ -2013,7 +2013,7 @@ where
|
||||
pub async fn process_block_result(
|
||||
&self,
|
||||
block_contents: SignedBlockContentsTuple<E>,
|
||||
) -> Result<SignedBeaconBlockHash, BlockError<E>> {
|
||||
) -> Result<SignedBeaconBlockHash, BlockError> {
|
||||
let (block, blob_items) = block_contents;
|
||||
|
||||
let sidecars = blob_items
|
||||
@@ -2098,7 +2098,7 @@ where
|
||||
SignedBlockContentsTuple<E>,
|
||||
BeaconState<E>,
|
||||
),
|
||||
BlockError<E>,
|
||||
BlockError,
|
||||
> {
|
||||
self.set_current_slot(slot);
|
||||
let (block_contents, new_state) = self.make_block(state, slot).await;
|
||||
@@ -2144,7 +2144,7 @@ where
|
||||
state: BeaconState<E>,
|
||||
state_root: Hash256,
|
||||
validators: &[usize],
|
||||
) -> Result<(SignedBeaconBlockHash, BeaconState<E>), BlockError<E>> {
|
||||
) -> Result<(SignedBeaconBlockHash, BeaconState<E>), BlockError> {
|
||||
self.add_attested_block_at_slot_with_sync(
|
||||
slot,
|
||||
state,
|
||||
@@ -2162,7 +2162,7 @@ where
|
||||
state_root: Hash256,
|
||||
validators: &[usize],
|
||||
sync_committee_strategy: SyncCommitteeStrategy,
|
||||
) -> Result<(SignedBeaconBlockHash, BeaconState<E>), BlockError<E>> {
|
||||
) -> Result<(SignedBeaconBlockHash, BeaconState<E>), BlockError> {
|
||||
let (block_hash, block, state) = self.add_block_at_slot(slot, state).await?;
|
||||
self.attest_block(&state, state_root, block_hash, &block.0, validators);
|
||||
|
||||
|
||||
@@ -1098,8 +1098,8 @@ async fn block_gossip_verification() {
|
||||
assert!(
|
||||
matches!(
|
||||
unwrap_err(harness.chain.verify_block_for_gossip(Arc::new(SignedBeaconBlock::from_block(block, signature))).await),
|
||||
BlockError::ParentUnknown(block)
|
||||
if block.parent_root() == parent_root
|
||||
BlockError::ParentUnknown {parent_root: p}
|
||||
if p == parent_root
|
||||
),
|
||||
"should not import a block for an unknown parent"
|
||||
);
|
||||
|
||||
@@ -212,7 +212,7 @@ impl InvalidPayloadRig {
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
async fn import_block_parametric<F: Fn(&BlockError<E>) -> bool>(
|
||||
async fn import_block_parametric<F: Fn(&BlockError) -> bool>(
|
||||
&mut self,
|
||||
new_payload_response: Payload,
|
||||
forkchoice_response: Payload,
|
||||
|
||||
@@ -544,7 +544,7 @@ fn check_slashable<T: BeaconChainTypes>(
|
||||
block_root: Hash256,
|
||||
block_clone: &SignedBeaconBlock<T::EthSpec, FullPayload<T::EthSpec>>,
|
||||
log_clone: &Logger,
|
||||
) -> Result<(), BlockError<T::EthSpec>> {
|
||||
) -> Result<(), BlockError> {
|
||||
let slashable_cache = chain_clone.observed_slashable.read();
|
||||
if let Some(blobs) = blobs_opt.as_ref() {
|
||||
blobs.iter().try_for_each(|blob| {
|
||||
|
||||
@@ -81,9 +81,7 @@ pub async fn gossip_invalid() {
|
||||
/* mandated by Beacon API spec */
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string())
|
||||
);
|
||||
assert_server_message_error(error_response, "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string());
|
||||
}
|
||||
|
||||
/// This test checks that a block that is valid from a gossip perspective is accepted when using `broadcast_validation=gossip`.
|
||||
@@ -268,10 +266,7 @@ pub async fn consensus_invalid() {
|
||||
|
||||
/* mandated by Beacon API spec */
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string())
|
||||
);
|
||||
assert_server_message_error(error_response, "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string());
|
||||
}
|
||||
|
||||
/// This test checks that a block that is only valid from a gossip perspective is rejected when using `broadcast_validation=consensus`.
|
||||
@@ -317,10 +312,7 @@ pub async fn consensus_gossip() {
|
||||
|
||||
/* mandated by Beacon API spec */
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: Invalid block: StateRootMismatch { block: 0x0000000000000000000000000000000000000000000000000000000000000000, local: 0xfc675d642ff7a06458eb33c7d7b62a5813e34d1b2bb1aee3e395100b579da026 }".to_string())
|
||||
);
|
||||
assert_server_message_error(error_response, "BAD_REQUEST: Invalid block: StateRootMismatch { block: 0x0000000000000000000000000000000000000000000000000000000000000000, local: 0xfc675d642ff7a06458eb33c7d7b62a5813e34d1b2bb1aee3e395100b579da026 }".to_string());
|
||||
}
|
||||
|
||||
/// This test checks that a block that is valid from both a gossip and consensus perspective, but nonetheless equivocates, is accepted when using `broadcast_validation=consensus`.
|
||||
@@ -489,10 +481,7 @@ pub async fn equivocation_invalid() {
|
||||
|
||||
/* mandated by Beacon API spec */
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string())
|
||||
);
|
||||
assert_server_message_error(error_response, "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string());
|
||||
}
|
||||
|
||||
/// This test checks that a block that is valid from both a gossip and consensus perspective is rejected when using `broadcast_validation=consensus_and_equivocation`.
|
||||
@@ -566,9 +555,9 @@ pub async fn equivocation_consensus_early_equivocation() {
|
||||
let error_response: eth2::Error = response.err().unwrap();
|
||||
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: BlockError(Slashable)".to_string())
|
||||
assert_server_message_error(
|
||||
error_response,
|
||||
"BAD_REQUEST: BlockError(Slashable)".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -616,10 +605,7 @@ pub async fn equivocation_gossip() {
|
||||
|
||||
/* mandated by Beacon API spec */
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: Invalid block: StateRootMismatch { block: 0x0000000000000000000000000000000000000000000000000000000000000000, local: 0xfc675d642ff7a06458eb33c7d7b62a5813e34d1b2bb1aee3e395100b579da026 }".to_string())
|
||||
);
|
||||
assert_server_message_error(error_response, "BAD_REQUEST: Invalid block: StateRootMismatch { block: 0x0000000000000000000000000000000000000000000000000000000000000000, local: 0xfc675d642ff7a06458eb33c7d7b62a5813e34d1b2bb1aee3e395100b579da026 }".to_string());
|
||||
}
|
||||
|
||||
/// This test checks that a block that is valid from both a gossip and consensus perspective but
|
||||
@@ -797,10 +783,7 @@ pub async fn blinded_gossip_invalid() {
|
||||
|
||||
/* mandated by Beacon API spec */
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string())
|
||||
);
|
||||
assert_server_message_error(error_response, "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string());
|
||||
}
|
||||
|
||||
/// This test checks that a block that is valid from a gossip perspective is accepted when using `broadcast_validation=gossip`.
|
||||
@@ -978,10 +961,7 @@ pub async fn blinded_consensus_invalid() {
|
||||
|
||||
/* mandated by Beacon API spec */
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string())
|
||||
);
|
||||
assert_server_message_error(error_response, "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string());
|
||||
}
|
||||
|
||||
/// This test checks that a block that is only valid from a gossip perspective is rejected when using `broadcast_validation=consensus`.
|
||||
@@ -1027,10 +1007,7 @@ pub async fn blinded_consensus_gossip() {
|
||||
|
||||
/* mandated by Beacon API spec */
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: Invalid block: StateRootMismatch { block: 0x0000000000000000000000000000000000000000000000000000000000000000, local: 0xfc675d642ff7a06458eb33c7d7b62a5813e34d1b2bb1aee3e395100b579da026 }".to_string())
|
||||
);
|
||||
assert_server_message_error(error_response, "BAD_REQUEST: Invalid block: StateRootMismatch { block: 0x0000000000000000000000000000000000000000000000000000000000000000, local: 0xfc675d642ff7a06458eb33c7d7b62a5813e34d1b2bb1aee3e395100b579da026 }".to_string());
|
||||
}
|
||||
|
||||
/// This test checks that a block that is valid from both a gossip and consensus perspective is accepted when using `broadcast_validation=consensus`.
|
||||
@@ -1122,10 +1099,7 @@ pub async fn blinded_equivocation_invalid() {
|
||||
|
||||
/* mandated by Beacon API spec */
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string())
|
||||
);
|
||||
assert_server_message_error(error_response, "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string());
|
||||
}
|
||||
|
||||
/// This test checks that a block that is valid from both a gossip and consensus perspective is rejected when using `broadcast_validation=consensus_and_equivocation`.
|
||||
@@ -1195,9 +1169,9 @@ pub async fn blinded_equivocation_consensus_early_equivocation() {
|
||||
let error_response: eth2::Error = response.err().unwrap();
|
||||
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: BlockError(Slashable)".to_string())
|
||||
assert_server_message_error(
|
||||
error_response,
|
||||
"BAD_REQUEST: BlockError(Slashable)".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1246,9 +1220,7 @@ pub async fn blinded_equivocation_gossip() {
|
||||
/* mandated by Beacon API spec */
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: Invalid block: StateRootMismatch { block: 0x0000000000000000000000000000000000000000000000000000000000000000, local: 0xfc675d642ff7a06458eb33c7d7b62a5813e34d1b2bb1aee3e395100b579da026 }".to_string())
|
||||
);
|
||||
assert_server_message_error(error_response, "BAD_REQUEST: Invalid block: StateRootMismatch { block: 0x0000000000000000000000000000000000000000000000000000000000000000, local: 0xfc675d642ff7a06458eb33c7d7b62a5813e34d1b2bb1aee3e395100b579da026 }".to_string());
|
||||
}
|
||||
|
||||
/// This test checks that a block that is valid from both a gossip and
|
||||
@@ -1401,3 +1373,10 @@ pub async fn blinded_equivocation_full_pass() {
|
||||
.chain
|
||||
.block_is_known_to_fork_choice(&block.canonical_root()));
|
||||
}
|
||||
|
||||
fn assert_server_message_error(error_response: eth2::Error, expected_message: String) {
|
||||
let eth2::Error::ServerMessage(err) = error_response else {
|
||||
panic!("Not a eth2::Error::ServerMessage");
|
||||
};
|
||||
assert_eq!(err.message, expected_message);
|
||||
}
|
||||
|
||||
@@ -780,7 +780,7 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
|
||||
metrics::set_gauge(&metrics::BEACON_BLOB_DELAY_GOSSIP, delay.as_millis() as i64);
|
||||
match self
|
||||
.chain
|
||||
.verify_blob_sidecar_for_gossip(blob_sidecar, blob_index)
|
||||
.verify_blob_sidecar_for_gossip(blob_sidecar.clone(), blob_index)
|
||||
{
|
||||
Ok(gossip_verified_blob) => {
|
||||
metrics::inc_counter(&metrics::BEACON_PROCESSOR_GOSSIP_BLOB_VERIFIED_TOTAL);
|
||||
@@ -825,16 +825,19 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
|
||||
}
|
||||
Err(err) => {
|
||||
match err {
|
||||
GossipBlobError::BlobParentUnknown(blob) => {
|
||||
GossipBlobError::BlobParentUnknown { parent_root } => {
|
||||
debug!(
|
||||
self.log,
|
||||
"Unknown parent hash for blob";
|
||||
"action" => "requesting parent",
|
||||
"block_root" => %blob.block_root(),
|
||||
"parent_root" => %blob.block_parent_root(),
|
||||
"block_root" => %root,
|
||||
"parent_root" => %parent_root,
|
||||
"commitment" => %commitment,
|
||||
);
|
||||
self.send_sync_message(SyncMessage::UnknownParentBlob(peer_id, blob));
|
||||
self.send_sync_message(SyncMessage::UnknownParentBlob(
|
||||
peer_id,
|
||||
blob_sidecar,
|
||||
));
|
||||
}
|
||||
GossipBlobError::KzgNotInitialized
|
||||
| GossipBlobError::PubkeyCacheTimeout
|
||||
@@ -1224,7 +1227,7 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
|
||||
);
|
||||
return None;
|
||||
}
|
||||
Err(BlockError::ParentUnknown(block)) => {
|
||||
Err(BlockError::ParentUnknown { .. }) => {
|
||||
debug!(
|
||||
self.log,
|
||||
"Unknown parent for gossip block";
|
||||
@@ -1516,7 +1519,7 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
|
||||
"block_root" => %block_root,
|
||||
);
|
||||
}
|
||||
Err(BlockError::ParentUnknown(_)) => {
|
||||
Err(BlockError::ParentUnknown { .. }) => {
|
||||
// This should not occur. It should be checked by `should_forward_block`.
|
||||
// Do not send sync message UnknownParentBlock to prevent conflicts with the
|
||||
// BlockComponentProcessed message below. If this error ever happens, lookup sync
|
||||
@@ -3131,7 +3134,7 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
|
||||
invalid_block_storage: &InvalidBlockStorage,
|
||||
block_root: Hash256,
|
||||
block: &SignedBeaconBlock<T::EthSpec>,
|
||||
error: &BlockError<T::EthSpec>,
|
||||
error: &BlockError,
|
||||
log: &Logger,
|
||||
) {
|
||||
if let InvalidBlockStorage::Enabled(base_dir) = invalid_block_storage {
|
||||
|
||||
@@ -706,15 +706,12 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
|
||||
}
|
||||
|
||||
/// Helper function to handle a `BlockError` from `process_chain_segment`
|
||||
fn handle_failed_chain_segment(
|
||||
&self,
|
||||
error: BlockError<T::EthSpec>,
|
||||
) -> Result<(), ChainSegmentFailed> {
|
||||
fn handle_failed_chain_segment(&self, error: BlockError) -> Result<(), ChainSegmentFailed> {
|
||||
match error {
|
||||
BlockError::ParentUnknown(block) => {
|
||||
BlockError::ParentUnknown { parent_root, .. } => {
|
||||
// blocks should be sequential and all parents should exist
|
||||
Err(ChainSegmentFailed {
|
||||
message: format!("Block has an unknown parent: {}", block.parent_root()),
|
||||
message: format!("Block has an unknown parent: {}", parent_root),
|
||||
// Peers are faulty if they send non-sequential blocks.
|
||||
peer_action: Some(PeerAction::LowToleranceError),
|
||||
})
|
||||
|
||||
@@ -473,7 +473,7 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
pub fn on_processing_result(
|
||||
&mut self,
|
||||
process_type: BlockProcessType,
|
||||
result: BlockProcessingResult<T::EthSpec>,
|
||||
result: BlockProcessingResult,
|
||||
cx: &mut SyncNetworkContext<T>,
|
||||
) {
|
||||
let lookup_result = match process_type {
|
||||
@@ -493,7 +493,7 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
pub fn on_processing_result_inner<R: RequestState<T>>(
|
||||
&mut self,
|
||||
lookup_id: SingleLookupId,
|
||||
result: BlockProcessingResult<T::EthSpec>,
|
||||
result: BlockProcessingResult,
|
||||
cx: &mut SyncNetworkContext<T>,
|
||||
) -> Result<LookupResult, LookupRequestError> {
|
||||
let Some(lookup) = self.single_block_lookups.get_mut(&lookup_id) else {
|
||||
@@ -556,16 +556,14 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
error!(self.log, "Beacon chain error processing lookup component"; "block_root" => %block_root, "error" => ?e);
|
||||
Action::Drop
|
||||
}
|
||||
BlockError::ParentUnknown(block) => {
|
||||
BlockError::ParentUnknown { parent_root, .. } => {
|
||||
// Reverts the status of this request to `AwaitingProcessing` holding the
|
||||
// downloaded data. A future call to `continue_requests` will re-submit it
|
||||
// once there are no pending parent requests.
|
||||
// Note: `BlockError::ParentUnknown` is only returned when processing
|
||||
// blocks, not blobs.
|
||||
request_state.revert_to_awaiting_processing()?;
|
||||
Action::ParentUnknown {
|
||||
parent_root: block.parent_root(),
|
||||
}
|
||||
Action::ParentUnknown { parent_root }
|
||||
}
|
||||
ref e @ BlockError::ExecutionPayloadError(ref epe) if !epe.penalize_peer() => {
|
||||
// These errors indicate that the execution layer is offline
|
||||
|
||||
@@ -9,7 +9,7 @@ use super::*;
|
||||
|
||||
use crate::sync::block_lookups::common::ResponseType;
|
||||
use beacon_chain::blob_verification::GossipVerifiedBlob;
|
||||
use beacon_chain::block_verification_types::{BlockImportData, RpcBlock};
|
||||
use beacon_chain::block_verification_types::BlockImportData;
|
||||
use beacon_chain::builder::Witness;
|
||||
use beacon_chain::data_availability_checker::Availability;
|
||||
use beacon_chain::eth1_chain::CachingEth1Backend;
|
||||
@@ -211,11 +211,7 @@ impl TestRig {
|
||||
|
||||
fn trigger_unknown_parent_block(&mut self, peer_id: PeerId, block: Arc<SignedBeaconBlock<E>>) {
|
||||
let block_root = block.canonical_root();
|
||||
self.send_sync_message(SyncMessage::UnknownParentBlock(
|
||||
peer_id,
|
||||
RpcBlock::new_without_blobs(Some(block_root), block),
|
||||
block_root,
|
||||
))
|
||||
self.send_sync_message(SyncMessage::UnknownParentBlock(peer_id, block, block_root))
|
||||
}
|
||||
|
||||
fn trigger_unknown_parent_blob(&mut self, peer_id: PeerId, blob: BlobSidecar<E>) {
|
||||
@@ -440,12 +436,12 @@ impl TestRig {
|
||||
*parent_chain.last().unwrap()
|
||||
}
|
||||
|
||||
fn parent_block_processed(&mut self, chain_hash: Hash256, result: BlockProcessingResult<E>) {
|
||||
fn parent_block_processed(&mut self, chain_hash: Hash256, result: BlockProcessingResult) {
|
||||
let id = self.find_single_lookup_for(self.find_oldest_parent_lookup(chain_hash));
|
||||
self.single_block_component_processed(id, result);
|
||||
}
|
||||
|
||||
fn parent_blob_processed(&mut self, chain_hash: Hash256, result: BlockProcessingResult<E>) {
|
||||
fn parent_blob_processed(&mut self, chain_hash: Hash256, result: BlockProcessingResult) {
|
||||
let id = self.find_single_lookup_for(self.find_oldest_parent_lookup(chain_hash));
|
||||
self.single_blob_component_processed(id, result);
|
||||
}
|
||||
@@ -457,7 +453,7 @@ impl TestRig {
|
||||
);
|
||||
}
|
||||
|
||||
fn single_block_component_processed(&mut self, id: Id, result: BlockProcessingResult<E>) {
|
||||
fn single_block_component_processed(&mut self, id: Id, result: BlockProcessingResult) {
|
||||
self.send_sync_message(SyncMessage::BlockComponentProcessed {
|
||||
process_type: BlockProcessType::SingleBlock { id },
|
||||
result,
|
||||
@@ -472,7 +468,7 @@ impl TestRig {
|
||||
)
|
||||
}
|
||||
|
||||
fn single_blob_component_processed(&mut self, id: Id, result: BlockProcessingResult<E>) {
|
||||
fn single_blob_component_processed(&mut self, id: Id, result: BlockProcessingResult) {
|
||||
self.send_sync_message(SyncMessage::BlockComponentProcessed {
|
||||
process_type: BlockProcessType::SingleBlob { id },
|
||||
result,
|
||||
@@ -1440,7 +1436,9 @@ fn test_single_block_lookup_becomes_parent_request() {
|
||||
// parent request after processing.
|
||||
rig.single_block_component_processed(
|
||||
id.lookup_id,
|
||||
BlockError::ParentUnknown(RpcBlock::new_without_blobs(None, block)).into(),
|
||||
BlockProcessingResult::Err(BlockError::ParentUnknown {
|
||||
parent_root: block.parent_root(),
|
||||
}),
|
||||
);
|
||||
assert_eq!(rig.active_single_lookups_count(), 2); // 2 = current + parent
|
||||
rig.expect_block_parent_request(parent_root);
|
||||
@@ -1661,7 +1659,9 @@ fn test_parent_lookup_too_deep_grow_ancestor() {
|
||||
// the processing result
|
||||
rig.parent_block_processed(
|
||||
chain_hash,
|
||||
BlockError::ParentUnknown(RpcBlock::new_without_blobs(None, block)).into(),
|
||||
BlockProcessingResult::Err(BlockError::ParentUnknown {
|
||||
parent_root: block.parent_root(),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1685,7 +1685,10 @@ fn test_parent_lookup_too_deep_grow_tip() {
|
||||
rig.expect_block_process(ResponseType::Block);
|
||||
rig.single_block_component_processed(
|
||||
id.lookup_id,
|
||||
BlockError::ParentUnknown(RpcBlock::new_without_blobs(None, block)).into(),
|
||||
BlockError::ParentUnknown {
|
||||
parent_root: block.parent_root(),
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1840,7 +1843,9 @@ fn test_same_chain_race_condition() {
|
||||
rig.log(&format!("Block {i} ParentUnknown"));
|
||||
rig.parent_block_processed(
|
||||
chain_hash,
|
||||
BlockError::ParentUnknown(RpcBlock::new_without_blobs(None, block)).into(),
|
||||
BlockProcessingResult::Err(BlockError::ParentUnknown {
|
||||
parent_root: block.parent_root(),
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -2130,7 +2135,7 @@ mod deneb_only {
|
||||
RequestTrigger::GossipUnknownParentBlock { .. } => {
|
||||
rig.send_sync_message(SyncMessage::UnknownParentBlock(
|
||||
peer_id,
|
||||
RpcBlock::new_without_blobs(Some(block_root), block.clone()),
|
||||
block.clone(),
|
||||
block_root,
|
||||
));
|
||||
|
||||
@@ -2412,7 +2417,9 @@ mod deneb_only {
|
||||
.unwrap();
|
||||
self.rig.parent_block_processed(
|
||||
self.block_root,
|
||||
BlockProcessingResult::Err(BlockError::ParentUnknown(block)),
|
||||
BlockProcessingResult::Err(BlockError::ParentUnknown {
|
||||
parent_root: block.parent_root(),
|
||||
}),
|
||||
);
|
||||
assert_eq!(self.rig.active_parent_lookups_count(), 1);
|
||||
self
|
||||
|
||||
@@ -48,7 +48,6 @@ use crate::sync::block_lookups::{
|
||||
use crate::sync::block_sidecar_coupling::RangeBlockComponentsRequest;
|
||||
use crate::sync::network_context::PeerGroup;
|
||||
use beacon_chain::block_verification_types::AsBlock;
|
||||
use beacon_chain::block_verification_types::RpcBlock;
|
||||
use beacon_chain::validator_monitor::timestamp_now;
|
||||
use beacon_chain::{
|
||||
AvailabilityProcessingStatus, BeaconChain, BeaconChainTypes, BlockError, EngineState,
|
||||
@@ -115,7 +114,7 @@ pub enum SyncMessage<E: EthSpec> {
|
||||
},
|
||||
|
||||
/// A block with an unknown parent has been received.
|
||||
UnknownParentBlock(PeerId, RpcBlock<E>, Hash256),
|
||||
UnknownParentBlock(PeerId, Arc<SignedBeaconBlock<E>>, Hash256),
|
||||
|
||||
/// A blob with an unknown parent has been received.
|
||||
UnknownParentBlob(PeerId, Arc<BlobSidecar<E>>),
|
||||
@@ -150,7 +149,7 @@ pub enum SyncMessage<E: EthSpec> {
|
||||
/// Block processed
|
||||
BlockComponentProcessed {
|
||||
process_type: BlockProcessType,
|
||||
result: BlockProcessingResult<E>,
|
||||
result: BlockProcessingResult,
|
||||
},
|
||||
|
||||
/// Sample data column verified
|
||||
@@ -182,9 +181,9 @@ impl BlockProcessType {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BlockProcessingResult<E: EthSpec> {
|
||||
pub enum BlockProcessingResult {
|
||||
Ok(AvailabilityProcessingStatus),
|
||||
Err(BlockError<E>),
|
||||
Err(BlockError),
|
||||
Ignored,
|
||||
}
|
||||
|
||||
@@ -1187,10 +1186,8 @@ impl<T: BeaconChainTypes> SyncManager<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<Result<AvailabilityProcessingStatus, BlockError<E>>>
|
||||
for BlockProcessingResult<E>
|
||||
{
|
||||
fn from(result: Result<AvailabilityProcessingStatus, BlockError<E>>) -> Self {
|
||||
impl From<Result<AvailabilityProcessingStatus, BlockError>> for BlockProcessingResult {
|
||||
fn from(result: Result<AvailabilityProcessingStatus, BlockError>) -> Self {
|
||||
match result {
|
||||
Ok(status) => BlockProcessingResult::Ok(status),
|
||||
Err(e) => BlockProcessingResult::Err(e),
|
||||
@@ -1198,8 +1195,8 @@ impl<E: EthSpec> From<Result<AvailabilityProcessingStatus, BlockError<E>>>
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> From<BlockError<E>> for BlockProcessingResult<E> {
|
||||
fn from(e: BlockError<E>) -> Self {
|
||||
impl From<BlockError> for BlockProcessingResult {
|
||||
fn from(e: BlockError) -> Self {
|
||||
BlockProcessingResult::Err(e)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user