UNPKG

@lodestar/beacon-node

Version:

A Typescript implementation of the beacon chain

69 lines 2.9 kB
import { MapDef, pruneSetToMax } from "@lodestar/utils"; import { DEFAULT_SCORE, MAX_ENTRIES, MAX_SCORE, MIN_SCORE, SCORE_THRESHOLD } from "./constants.js"; import { PeerAction } from "./interface.js"; import { MaxScore, RealScore } from "./score.js"; import { scoreToState } from "./utils.js"; const peerActionScore = { [PeerAction.Fatal]: -(MAX_SCORE - MIN_SCORE), [PeerAction.LowToleranceError]: -10, [PeerAction.MidToleranceError]: -5, [PeerAction.HighToleranceError]: -1, }; /** * A peer's score (perceived potential usefulness). * This simplistic version consists of a global score per peer which decays to 0 over time. * The decay rate applies equally to positive and negative scores. * Peer cool-down period will be checked before dialing and will only be dialed if score is not waiting to decay */ export class PeerRpcScoreStore { // TODO: Persist scores, at least BANNED status to disk constructor(opts = {}, metrics = null) { this.metrics = metrics; this.scores = opts.disablePeerScoring ? new MapDef(() => new MaxScore()) : new MapDef(() => new RealScore()); } getScore(peer) { return this.scores.get(peer.toString())?.getScore() ?? DEFAULT_SCORE; } getGossipScore(peer) { return this.scores.get(peer.toString())?.getGossipScore() ?? DEFAULT_SCORE; } getScoreState(peer) { return scoreToState(this.getScore(peer)); } isCoolingDown(peerIdStr) { return this.scores.get(peerIdStr)?.isCoolingDown() ?? false; } dumpPeerScoreStats() { return Array.from(this.scores.entries()).map(([peerId, peerScore]) => ({ peerId, ...peerScore.getStat() })); } applyAction(peer, action, actionName) { const peerScore = this.scores.getOrDefault(peer.toString()); peerScore.add(peerActionScore[action]); this.metrics?.peersReportPeerCount.inc({ reason: actionName }); } /** * Apply a reconnection cool-down period to prevent automatic reconnection. Sets peer * banning period and updates gossip score to -1 so next update removes the negative * score */ applyReconnectionCoolDown(peer, reason) { const peerScore = this.scores.getOrDefault(peer); return peerScore.applyReconnectionCoolDown(reason); } update() { // Bound size of data structures pruneSetToMax(this.scores, MAX_ENTRIES); for (const [peerIdStr, peerScore] of this.scores) { const newScore = peerScore.update(); // Prune scores below threshold if (Math.abs(newScore) < SCORE_THRESHOLD) { this.scores.delete(peerIdStr); } } } updateGossipsubScore(peerId, newScore, ignore) { const peerScore = this.scores.getOrDefault(peerId); peerScore.updateGossipsubScore(newScore, ignore); } } //# sourceMappingURL=store.js.map