Skip to content

feat(beaconrestapi): expose peer-scoring fields on /eth/v1/node/peers#10715

Draft
barnabasbusa wants to merge 4 commits into
Consensys:masterfrom
barnabasbusa:bbusa/peer-scores-last-action
Draft

feat(beaconrestapi): expose peer-scoring fields on /eth/v1/node/peers#10715
barnabasbusa wants to merge 4 commits into
Consensys:masterfrom
barnabasbusa:bbusa/peer-scores-last-action

Conversation

@barnabasbusa
Copy link
Copy Markdown
Contributor

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 identify (via LibP2PPeer.maybeAgentString)
  • score — from ReputationManager.getReputationScore(nodeId)
  • disconnect_reason — from LastAdjustment.reason when it matches a DisconnectReason enum
  • downscore_reasons — single-element array, currently always ["unknown"] for penalty events (see Notes)

Spec proposal

ethereum/beacon-APIs#606

What's in this PR

  1. Peer interface (networking/p2p/src/main/java/.../peer/Peer.java) — adds default Optional<String> getAgentVersion().
  2. LibP2PPeer.getAgentVersion() override + DelegatingPeer delegation.
  3. provider.Peer (data/serializer/.../api/provider/Peer.java) — adds 4 nullable Jackson fields with @JsonInclude(NON_NULL) and a 5-arg backward-compat constructor.
  4. Handler wiring (GetPeers.java, GetPeerById.java) — introduces a PeerView record wrapping Eth2PeerWithEnr + reputation data; threads ReputationManager through via existing NetworkDataProvider.getReputationManager().
  5. PeerScoreReasonMapper (new) — controlled-vocab translator for ReputationAdjustment and DisconnectReason.

Notes

  • Teku's ReputationAdjustment enum (LARGE_PENALTY/SMALL_PENALTY/LARGE_REWARD/SMALL_REWARD) carries no granular cause information. downscore_reasons is therefore ["unknown"] whenever a penalty event is recorded, or null (omitted) when the last event was a reward / disconnect. Surfacing a finer-grained reason would require extending ReputationAdjustment itself — happy to follow up.
  • disconnect_reason only populates when LastAdjustment.reason matches a DisconnectReason enum name (this is already how Teku's reputation manager records disconnects via DefaultReputationManager.Reputation.reportDisconnection).

Coordinated implementations

Part of a coordinated multi-client effort — see ethereum/beacon-APIs#606 for the other five client PRs.

Status

Draft. :data:serializer:compileJava + :data:beaconrestapi:compileJava clean (errorprone with -Werror passes). Existing GetPeersTest / GetPeerByIdTest may need follow-up updates since the response wrapper now nests a PeerView; production code is fine.

Bring Teku's /teku/v1/nodes/peer_scores endpoint to parity with the
patches already shipped for Lighthouse, Lodestar, and Prysm so dora's
matrix can render real downscore reasons rather than just a raw gossip
score.

Per peer, the response now also includes:
  - reputation_score: the internal ReputationAdjustment-driven int
  - last_action: { reason, delta, seconds_ago } for the most recent
    reputation-affecting event. reason is either a ReputationAdjustment
    enum name or a DisconnectReason enum name when a disconnection was
    the last event.

Both new fields are optional - they are omitted when no data has been
recorded yet - so existing consumers that only read peer_id and
gossip_score continue to work unchanged.

DefaultReputationManager now records the most recent adjustment (and
the most recent disconnection that carried a reason) per peer and
exposes getReputationScore / getLastAdjustment accessors. Eth2P2PNetwork
gains a getReputationManager() hook so REST handlers can reach the
manager without having to thread it through every test/mock variant.
Teku's errorprone is configured with -Werror, so the (int) cast on
Math.max(0L, ...) tripped the build with:

  warning: [MathTargetType] Neither of the function arguments are
  int types but the result is treated as such.

Extracts the conversion to a secondsSince() helper that clamps the
long age against Integer.MAX_VALUE before narrowing, so the cast
is local to a small helper that the linter accepts.
Add four optional fields to /eth/v1/node/peers and
/eth/v1/node/peers/{peer_id} per the simplified beacon-API peer scoring
proposal:

  - agent_version: libp2p identify agent string (now plumbed through the
    Peer interface and exposed by LibP2PPeer).
  - score: ReputationManager's internal reputation score as a double.
  - disconnect_reason: last DisconnectReason mapped to the spec's
    PeerDisconnectReason vocabulary.
  - downscore_reasons: list-wrapped reputation adjustment reason mapped
    to the spec's PeerScoreReason vocabulary (currently "unknown" for
    Teku's coarse penalty enum).

The Jackson Peer DTO in data:serializer gains matching nullable fields
so any consumer that deserialises it still works, while the live OpenAPI
schema is updated via a new PeerView record that wraps Eth2PeerWithEnr
together with the per-peer reputation snapshot. All four fields are
omitted when data is unavailable, so existing consumers are unaffected.
…ing state

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`. Teku exposes only `connected`/`disconnected` via
`Eth2Peer#isConnected()`, so suppress the field for connected peers.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant