p2p/sentry: cap and rate-limit inbound NewBlockHashes per peer#21557
Merged
Conversation
## Summary - Reject NewBlockHashes packets larger than maxNewBlockHashesBytes (~4096 entries) in the per-peer framing loop (runPeer), before the payload is buffered, so an oversized announcement is dropped at the sentry layer and never reaches the eth multi-client or polygon execution/p2p observer subscribers. The peer is kicked. - Add a per-peer token-bucket limiter (10 packets/s, burst 30) that kicks peers flooding NewBlockHashes. The limiter is local to runPeer, so its state is bounded and freed on disconnect. - Both gates run before the hasSubscribers short-circuit, so abusive peers are kicked regardless of sync state. The handler-level peek (closed PR #21476) is obviated by #21505, which removed the eth block-download handler; this places the protection at the framing layer where it also covers the surviving execution/p2p observer path. Closes erigontech/security#69 Closes erigontech/security#68 ## Test plan - [x] TestRunPeer_OversizedNewBlockHashesKicksPeer — oversized packet kicks peer (PeerErrorMessageSizeLimit) and is not forwarded - [x] TestRunPeer_NewBlockHashesFloodKicksPeer — flood past burst kicks peer (PeerErrorInvalidMessage) - [x] TestRunPeer_NormalNewBlockHashesForwarded — compliant traffic is forwarded and not penalized - [x] go test -race ./p2p/sentry/ (new tests, -count=5) - [x] make lint clean; make erigon integration Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds sentry-layer protections against abusive eth.NewBlockHashes traffic by rejecting oversized announcements before buffering and disconnecting peers that flood announcements, with accompanying unit tests for the new behavior.
Changes:
- Add a per-peer size gate for inbound
NewBlockHashesmessages inrunPeer(kick on oversize, discard payload early). - Add a per-peer token-bucket rate limiter for inbound
NewBlockHashesinrunPeer(kick on flood). - Add new
runPeertests covering oversize, flood, and normal forwarding behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| p2p/sentry/sentry_grpc_server.go | Adds per-peer NewBlockHashes byte cap and rate limiting in runPeer. |
| p2p/sentry/sentry_grpc_server_test.go | Adds helper + tests verifying oversize drop/kick, flood kick, and normal forwarding. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The byte ceiling alone let a peer pack more than maxBlockHashesPerMsg entries under maxNewBlockHashesBytes, since RLP entries are variable-length. Walk the byte-bounded payload and disconnect peers whose NewBlockHashes list exceeds maxBlockHashesPerMsg, so the documented per-message cap is actually enforced. The byte cap stays as a pre-read bound so the walk never sees more than maxNewBlockHashesBytes. Addresses Copilot review feedback on #21557. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
taratorio
approved these changes
Jun 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Harden the per-peer inbound loop (
runPeer) against abusiveNewBlockHashes:maxNewBlockHashesBytesbefore the payload is buffered — a multi-MB announcement is dropped without being allocated.maxBlockHashesPerMsg(4096) entries. The byte ceiling alone doesn't bound the entry count (RLP entries are variable-length), so this enforces the hard cap.runPeer, so its state is bounded and freed on disconnect.The peer is disconnected on any of these, and nothing is forwarded to subscribers (eth multi-client or the polygon
execution/p2pobserver). The size and rate gates run before thehasSubscribersshort-circuit, so abusive peers are kicked regardless of sync state.The handler-level peek (closed PR #21476) was obviated by #21505, which removed the eth block-download handler; this places the protection at the framing layer where it also covers the surviving
execution/p2pobserver path.Scope
The live consumer of inbound NewBlockHashes is polygon/Bor (
polygon/synctip-events viaexecution/p2p), which still gossips blocks over devp2p; post-Merge Ethereum doesn't use these messages — the eth multi-client drops them (#21505) — so there it's generic defense-in-depth against peers sending unsolicited announcements. The thresholds sit well above honest Bor rates (~1 announcement per block), so legitimate peers are unaffected.Closes erigontech/security#69
Closes erigontech/security#68
Test plan
TestRunPeer_OversizedNewBlockHashesKicksPeer— oversized (bytes) packet kicks peer (PeerErrorMessageSizeLimit) and is not forwarded to subscribersTestRunPeer_TooManyNewBlockHashesEntriesKicksPeer— a packet under the byte cap but over the 4096-entry cap kicks the peerTestRunPeer_NewBlockHashesFloodKicksPeer— flood past burst kicks peer (PeerErrorInvalidMessage)TestRunPeer_NormalNewBlockHashesForwarded— compliant traffic is forwarded and not penalizedgo test -race ./p2p/sentry/(new tests,-count=5)make lintclean;make erigon integration🤖 Generated with Claude Code