Skip to content

Add gossip validation spec tests for proposer/attester slashings#9323

Open
jimmygchen wants to merge 5 commits into
sigp:unstablefrom
jimmygchen:ef-tests-gossip
Open

Add gossip validation spec tests for proposer/attester slashings#9323
jimmygchen wants to merge 5 commits into
sigp:unstablefrom
jimmygchen:ef-tests-gossip

Conversation

@jimmygchen
Copy link
Copy Markdown
Member

@jimmygchen jimmygchen commented May 20, 2026

Issue Addressed

Addresses #9232 partially. This PR covers two topics only.

Wires up networking test vectors for gossip_proposer_slashing and gossip_attester_slashing topics.

The tests also revealed minor spec non-compliance where invalid slashings were ignored rather than rejected.

Proposed Changes

  • Refactor process_gossip_proposer_slashing and process_gossip_attester_slashing to return MessageAcceptance, so it can be verified in the tests
  • Add GossipValidation test case, handler, and test entries
  • Spec compliance fix: distinguish between internal errors and validation error - return Reject when the slashing is invalid and only penalise on invalid messages

AI Assistance Disclosure

Tools used (required — write none if no AI was used): claude for the test boilerplate. Rewrote most of the production changes manually.

Attestation (required):

  • I have read every line of this diff, understand what it does, and can explain it in review.

…tor `process_gossip_*_slashing` methods to return `MessageAcceptance` for testability.
@jimmygchen jimmygchen added test improvement Improve tests work-in-progress PR is a work-in-progress labels May 20, 2026
Validation errors were returning `Ignore` instead of `Reject`, which is incorrect per the spec. Internal errors still return `Ignore`.
@jimmygchen jimmygchen marked this pull request as ready for review May 20, 2026 06:19
@jimmygchen jimmygchen requested a review from jxs as a code owner May 20, 2026 06:19
@jimmygchen jimmygchen added ready-for-review The code is ready for review and removed work-in-progress PR is a work-in-progress labels May 20, 2026
Comment on lines +177 to +184
/// `MessageAcceptance` doesn't implement clone so we do a manual match here.
fn clone_message_acceptance(a: &MessageAcceptance) -> MessageAcceptance {
match a {
MessageAcceptance::Accept => MessageAcceptance::Accept,
MessageAcceptance::Reject => MessageAcceptance::Reject,
MessageAcceptance::Ignore => MessageAcceptance::Ignore,
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof. I opened libp2p/rust-libp2p#6445, let's add a comment here to remove this fn once that is available.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, added comment

Comment on lines +13 to +30
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "snake_case")]
enum ExpectedOutcome {
Valid,
Ignore,
Reject,
}

impl PartialEq<MessageAcceptance> for ExpectedOutcome {
fn eq(&self, other: &MessageAcceptance) -> bool {
matches!(
(self, other),
(Self::Valid, MessageAcceptance::Accept)
| (Self::Ignore, MessageAcceptance::Ignore)
| (Self::Reject, MessageAcceptance::Reject)
)
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once libp2p/rust-libp2p#6445 is merged, we might use MessageAcceptance directly, with a serde(deserialize_with = ...) attribute. Though that is a matter of taste, so no objection to just keeping this.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah i agree, the impact is pretty minimal - I would just keep it as it is, unless the Valid / Accept mismatch gets standardized.

Comment on lines +2228 to +2233
// Penalize peer slightly for invalids.
self.gossip_penalize_peer(
peer_id,
PeerAction::HighToleranceError,
"invalid_gossip_proposer_slashing",
);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it intentional that this now only happens on ProposerSlashingValidationError?

My intuition would actually keep or remove a HighToleranceError for the ignore case but upgrade to a LowToleranceError for the reject case.

Dito for attestatiion slashings.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My original intention was to not change any scoring logic in this PR unless it's not compliant with the spec. However, it doesn't really make sense to penalize peer if the node fails to load the head state at current slot (peer has nothing to do with it) - so I removed that but maintain the current HighToleranceError for potential invalids.

verify_proposer_slashing_for_gossip can return error from one of these sources:

  1. BeaconChainError from wall_clock_state(): Error loading head state at current slot - this is an internal error and can't be triggered by peer, so it doesn't make sense to penalize peers
  2. ProposerSlashingValidationError are mostly caused by peers, how could also be internal errors like BeaconStateError - we could try to categorise them but it gives us little gain - slashing processing is pretty low priority in the beacon processor queue so they just get dropped if malicious peers try to spam us with invalids, therefore I think the current high tolerance makes sense.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI the penalty was originally introduced here a long while ago: #1602

@jimmygchen jimmygchen requested a review from hopinheimer May 20, 2026 23:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-review The code is ready for review test improvement Improve tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants