Add gossip check (#7652)

N/A


  Add an additional gossip condition.
This commit is contained in:
Pawan Dhananjay
2025-06-26 17:26:38 -07:00
committed by GitHub
parent a0a6b9300f
commit 9b1f3ed9d1
4 changed files with 60 additions and 2 deletions

View File

@@ -323,6 +323,16 @@ pub enum BlockError {
/// We were unable to process this block due to an internal error. It's unclear if the block is
/// valid.
InternalError(String),
/// The number of kzg commitments in the block exceed the max allowed blobs per block for
/// the block's epoch.
///
/// ## Peer scoring
///
/// This block is invalid and the peer should be penalised.
InvalidBlobCount {
max_blobs_at_epoch: usize,
block: usize,
},
}
/// Which specific signature(s) are invalid in a SignedBeaconBlock
@@ -856,6 +866,21 @@ impl<T: BeaconChainTypes> GossipVerifiedBlock<T> {
});
}
// Do not gossip blocks that claim to contain more blobs than the max allowed
// at the given block epoch.
if let Ok(commitments) = block.message().body().blob_kzg_commitments() {
let max_blobs_at_epoch = chain
.spec
.max_blobs_per_block(block.slot().epoch(T::EthSpec::slots_per_epoch()))
as usize;
if commitments.len() > max_blobs_at_epoch {
return Err(BlockError::InvalidBlobCount {
max_blobs_at_epoch,
block: commitments.len(),
});
}
}
let block_root = get_block_header_root(block_header);
// Do not gossip a block from a finalized slot.

View File

@@ -1247,6 +1247,38 @@ async fn block_gossip_verification() {
),
"the second proposal by this validator should be rejected"
);
/*
* This test ensures that:
*
* We do not accept blocks with blob_kzg_commitments length larger than the max_blobs for that epoch.
*/
let (mut block, signature) = chain_segment[block_index]
.beacon_block
.as_ref()
.clone()
.deconstruct();
let kzg_commitments_len = harness
.chain
.spec
.max_blobs_per_block(block.slot().epoch(E::slots_per_epoch()))
as usize;
if let Ok(kzg_commitments) = block.body_mut().blob_kzg_commitments_mut() {
*kzg_commitments = vec![KzgCommitment::empty_for_testing(); kzg_commitments_len + 1].into();
assert!(
matches!(
unwrap_err(harness.chain.verify_block_for_gossip(Arc::new(SignedBeaconBlock::from_block(block, signature))).await),
BlockError::InvalidBlobCount {
max_blobs_at_epoch,
block,
}
if max_blobs_at_epoch == kzg_commitments_len && block == kzg_commitments_len + 1
),
"should not import a block with higher blob_kzg_commitment length than the max_blobs at epoch"
);
}
}
async fn verify_and_process_gossip_data_sidecars(

View File

@@ -1304,7 +1304,8 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
| Err(e @ BlockError::ExecutionPayloadError(_))
| Err(e @ BlockError::ParentExecutionPayloadInvalid { .. })
| Err(e @ BlockError::KnownInvalidExecutionPayload(_))
| Err(e @ BlockError::GenesisBlock) => {
| Err(e @ BlockError::GenesisBlock)
| Err(e @ BlockError::InvalidBlobCount { .. }) => {
warn!(error = %e, "Could not verify block for gossip. Rejecting the block");
self.propagate_validation_result(message_id, peer_id, MessageAcceptance::Reject);
self.gossip_penalize_peer(

View File

@@ -3538,7 +3538,7 @@ pub fn get_ancestor_state_root<'a, E: EthSpec, Hot: ItemStore<E>, Cold: ItemStor
.get_cold_state_root(target_slot)
.map_err(Box::new)
.map_err(StateSummaryIteratorError::LoadStateRootError)?
.ok_or_else(|| StateSummaryIteratorError::MissingStateRoot {
.ok_or(StateSummaryIteratorError::MissingStateRoot {
target_slot,
state_upper_limit,
});