From d3c13c4cf081746741af48b4189633f6cf42b844 Mon Sep 17 00:00:00 2001 From: YoungWoo Yang <119781151+0u-Y@users.noreply.github.com> Date: Wed, 15 Apr 2026 01:41:56 +0900 Subject: [PATCH] Gloas: envelope peer penalties and REJECT/IGNORE mapping (#8981) Closes #8949 Implements peer penalties and REJECT/IGNORE message propagation for `SignedExecutionPayloadEnvelope` gossip handling, completing follow-up work from #8806. Feedback on the error classification would be appreciated. ### Key Implementation Details - Maps all 15 `EnvelopeError` variants to REJECT/IGNORE based on [Gloas p2p spec](https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/p2p-interface.md#execution_payload) - Follows `ExecutionPayloadError` handling pattern from block gossip (`penalize_peer()` method) - Uses explicit variant matching (rather than catch-all `_`) for type safety - Applies `LowToleranceError` penalty for protocol violations (invalid signatures, mismatches, etc.) - Ignores without penalty for spec-defined cases (unknown block root, prior to finalization) and internal errors Co-Authored-By: 0u-Y Co-Authored-By: Eitan Seri-Levi --- .../gossip_methods.rs | 179 +++++++++++++----- 1 file changed, 129 insertions(+), 50 deletions(-) diff --git a/beacon_node/network/src/network_beacon_processor/gossip_methods.rs b/beacon_node/network/src/network_beacon_processor/gossip_methods.rs index c0aa30ffcc..2238cb2f17 100644 --- a/beacon_node/network/src/network_beacon_processor/gossip_methods.rs +++ b/beacon_node/network/src/network_beacon_processor/gossip_methods.rs @@ -3337,63 +3337,112 @@ impl NetworkBeaconProcessor { verified_envelope } + Err(e) => { + match e { + EnvelopeError::ExecutionPayloadError(ref epe) if !epe.penalize_peer() => { + self.propagate_validation_result( + message_id, + peer_id, + MessageAcceptance::Ignore, + ); + } - Err(EnvelopeError::BlockRootUnknown { block_root }) => { - let envelope_slot = envelope.slot(); + EnvelopeError::BadSignature + | EnvelopeError::BuilderIndexMismatch { .. } + | EnvelopeError::SlotMismatch { .. } + | EnvelopeError::BlockHashMismatch { .. } + | EnvelopeError::UnknownValidator { .. } + | EnvelopeError::IncorrectBlockProposer { .. } + | EnvelopeError::ExecutionPayloadError(_) + | EnvelopeError::EnvelopeProcessingError(_) + | EnvelopeError::BlockError(_) => { + self.propagate_validation_result( + message_id, + peer_id, + MessageAcceptance::Reject, + ); + self.gossip_penalize_peer( + peer_id, + PeerAction::LowToleranceError, + "gossip_envelope_low", + ); + } - debug!( - ?block_root, - %envelope_slot, - "Envelope references unknown block, deferring to reprocess queue" - ); + EnvelopeError::BlockRootUnknown { block_root } => { + let envelope_slot = envelope.slot(); - self.propagate_validation_result(message_id, peer_id, MessageAcceptance::Ignore); + debug!( + ?block_root, + %envelope_slot, + "Envelope references unknown block, deferring to reprocess queue" + ); - let inner_self = self.clone(); - let chain = self.chain.clone(); - let process_fn = Box::pin(async move { - match chain.verify_envelope_for_gossip(envelope).await { - Ok(verified_envelope) => { - inner_self - .process_gossip_verified_execution_payload_envelope( - peer_id, - verified_envelope, - ) - .await; - } - Err(e) => { - debug!( - error = ?e, - "Deferred envelope failed verification" + self.propagate_validation_result( + message_id.clone(), + peer_id, + MessageAcceptance::Ignore, + ); + + let inner_self = self.clone(); + let chain = self.chain.clone(); + let process_fn = Box::pin(async move { + match chain.verify_envelope_for_gossip(envelope).await { + Ok(verified_envelope) => { + inner_self + .process_gossip_verified_execution_payload_envelope( + peer_id, + verified_envelope, + ) + .await; + } + Err(e) => { + debug!( + error = ?e, + "Deferred envelope failed verification" + ); + } + } + }); + + if self + .beacon_processor_send + .try_send(WorkEvent { + drop_during_sync: false, + work: Work::Reprocess( + ReprocessQueueMessage::UnknownBlockForEnvelope( + QueuedGossipEnvelope { + beacon_block_slot: envelope_slot, + beacon_block_root: block_root, + process_fn, + }, + ), + ), + }) + .is_err() + { + error!( + %envelope_slot, + ?block_root, + "Failed to defer envelope import" ); } } - }); - if self - .beacon_processor_send - .try_send(WorkEvent { - drop_during_sync: false, - work: Work::Reprocess(ReprocessQueueMessage::UnknownBlockForEnvelope( - QueuedGossipEnvelope { - beacon_block_slot: envelope_slot, - beacon_block_root: block_root, - process_fn, - }, - )), - }) - .is_err() - { - error!( - %envelope_slot, - ?block_root, - "Failed to defer envelope import" - ); + EnvelopeError::PriorToFinalization { .. } + | EnvelopeError::OptimisticSyncNotSupported { .. } + | EnvelopeError::BeaconChainError(_) + | EnvelopeError::BeaconStateError(_) + | EnvelopeError::BlockProcessingError(_) + | EnvelopeError::InternalError(_) => { + self.propagate_validation_result( + message_id, + peer_id, + MessageAcceptance::Ignore, + ); + } } return None; } - // TODO(gloas) penalize peers accordingly - Err(_) => return None, }; let envelope_slot = verified_envelope.signed_envelope.slot(); @@ -3441,7 +3490,7 @@ impl NetworkBeaconProcessor { async fn process_gossip_verified_execution_payload_envelope( self: Arc, - _peer_id: PeerId, + peer_id: PeerId, verified_envelope: GossipVerifiedEnvelope, ) { let _processing_start_time = Instant::now(); @@ -3467,9 +3516,39 @@ impl NetworkBeaconProcessor { | Ok(AvailabilityProcessingStatus::MissingComponents(_, _)) => { // Nothing to do } - Err(_) => { - // TODO(gloas) implement peer penalties - } + Err(e) => match e { + EnvelopeError::ExecutionPayloadError(epe) if !epe.penalize_peer() => {} + EnvelopeError::BadSignature + | EnvelopeError::BuilderIndexMismatch { .. } + | EnvelopeError::SlotMismatch { .. } + | EnvelopeError::BlockHashMismatch { .. } + | EnvelopeError::UnknownValidator { .. } + | EnvelopeError::IncorrectBlockProposer { .. } + | EnvelopeError::ExecutionPayloadError(_) => { + self.gossip_penalize_peer( + peer_id, + PeerAction::LowToleranceError, + "gossip_envelope_processing_low", + ); + } + + EnvelopeError::EnvelopeProcessingError(_) + | EnvelopeError::BlockError(_) + | EnvelopeError::BlockRootUnknown { .. } => { + self.gossip_penalize_peer( + peer_id, + PeerAction::LowToleranceError, + "gossip_envelope_processing_error", + ); + } + + EnvelopeError::PriorToFinalization { .. } + | EnvelopeError::OptimisticSyncNotSupported { .. } + | EnvelopeError::BeaconChainError(_) + | EnvelopeError::BeaconStateError(_) + | EnvelopeError::BlockProcessingError(_) + | EnvelopeError::InternalError(_) => {} + }, } }