feat(api): expose peer-scoring fields on /eth/v1/node/peers#16794
Draft
barnabasbusa wants to merge 4 commits into
Draft
feat(api): expose peer-scoring fields on /eth/v1/node/peers#16794barnabasbusa wants to merge 4 commits into
barnabasbusa wants to merge 4 commits into
Conversation
Adds four optional fields to the beacon-API peer response objects
returned by /eth/v1/node/peers and /eth/v1/node/peers/{peer_id}:
- agent_version: libp2p identify-protocol agent string
- score: composite peer score from Prysm's scorer service
- disconnect_reason: reserved for future per-peer goodbye tracking
- downscore_reasons: live mapping of bad-peer scorer signals to the
beacon-API spec's controlled vocabulary
All fields are emitted with omitempty so existing consumers are
unaffected. Disconnect reasons are intentionally left empty pending
per-peer goodbye-code tracking in peers.Status.
…nnect_reason Adds per-peer tracking of the most recent goodbye code observed for each peer in peers.Status. Both inbound goodbye RPC messages and outbound goodbye messages sent by sendGoodByeMessage now record the code, the direction (sentByUs), and an observation timestamp on the peerdata store. The /eth/v1/node/peers handler uses this to populate disconnect_reason, mapping Prysm's goodbye code values to the beacon-API spec's controlled vocabulary (client_shutdown, irrelevant_network, io_error, unviable_fork, too_many_peers, bad_score). Unrecognized codes map to "unknown" so consumers can still differentiate between "we observed a goodbye" and "no goodbye seen" (which continues to omit the field).
PeerData's new LastGoodbye* fields needed reordering (uint64, time.Time, bool) to avoid padding waste flagged by Prysm's nogo maligned-struct check. Also wire @com_github_libp2p_go_libp2p//core/host into the beacon-chain/rpc/eth/node BUILD.bazel deps since handlers_peers.go now fetches AgentVersion via the libp2p host's Peerstore.
Per the proposed beacon-API spec (ethereum/beacon-APIs#606), `disconnect_reason` MUST only be populated when the peer's `state` is `disconnected` or `disconnecting`. Only look up the last goodbye when the (lowercased) peer state matches one of those values.
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
Extends
/eth/v1/node/peers(and/eth/v1/node/peers/{peer_id}) with four optional fields per a simplified beacon-API spec extension currently under discussion:agent_version— from libp2p peerstore (host.Peerstore().Get(id, "AgentVersion"))score— composite viapeerStatus.Scorers().Score(id)disconnect_reason— from newLastGoodbye*tracking persisted onpeerdata.PeerDatadownscore_reasons— live-derived from each scorer'sIsBadPeer(id)(snapshot of current bad-state flags)Spec proposal
ethereum/beacon-APIs#606
What's in this PR
structs.Peer(api/server/structs/endpoints_node.go) — adds 4 fields withomitemptyJSON tags.beacon-chain/rpc/eth/node/handlers_peers.go) — populates the new fields inpeerInfo()plus inline controlled-vocab translators (mapGoodbyeCode,mapDownscoreReasons).beacon-chain/p2p/peers/peerdata/store.go+status.go) — newLastGoodbye{Code, SentByUs, Observed}onPeerData, withSetLastGoodbye()/LastGoodbye()accessors.beacon-chain/sync/rpc_goodbye.go) — records inbound goodbyes ingoodbyeRPCHandlerand outbound insendGoodByeMessage.@com_github_libp2p_go_libp2p//core/hostdep for the newhost.Peerstore()call.Note on
downscore_reasonsRather than persisting per-event reason history, this derives the current bad-state classification at query time from each scorer:
BadResponsesScorer.IsBadPeer(id)→rpc_invalid_responsePeerStatusScorer.IsBadPeer(id)→status_unviable_forkGossipScorer.IsBadPeer(id)→behaviour_penaltyEmpty array when the peer isn't currently flagged. This sidesteps event-history storage but means
downscore_reasonsreflects "currently bad for these reasons" rather than "recently downscored for these reasons" — both are valid interpretations of the field; happy to revisit.Coordinated implementations
Part of a coordinated multi-client effort — see ethereum/beacon-APIs#606 for the other five client PRs.
Status
Draft.
go build ./beacon-chain/...+go test ./beacon-chain/p2p/peers/... ./beacon-chain/rpc/eth/node/...pass. Bazel build also clean (required a struct-field reordering onPeerDatato satisfynogo's maligned-struct check).