prysm-pulse/beacon-chain/p2p/peers/scorer.go

93 lines
2.6 KiB
Go
Raw Normal View History

Introduces peer scorer service (#6579) * introduces peer scorer service * gazelle * Merge branch 'master' into peer-scoring-service * fixes comment * fix build error * linter suggestions * Merge branch 'master' into peer-scoring-service * updates tests * Merge branch 'master' into peer-scoring-service * badresponses scorer tests * gazelle * Merge branch 'master' into peer-scoring-service * Merge branch 'master' into peer-scoring-service * adds scorer_test * gazelle * updates bad response default penalty * more comments * Merge branch 'master' into peer-scoring-service * Merge branch 'master' into peer-scoring-service * Merge branch 'master' into peer-scoring-service * Merge refs/heads/master into peer-scoring-service * Merge refs/heads/master into peer-scoring-service * Merge refs/heads/master into peer-scoring-service * Merge refs/heads/master into peer-scoring-service * Merge refs/heads/master into peer-scoring-service * Merge refs/heads/master into peer-scoring-service * Merge refs/heads/master into peer-scoring-service * Merge refs/heads/master into peer-scoring-service * introduces peerdatastore into status * makes sure that commong peer data store is used * Merge branch 'peer-scoring-service' of github.com:prysmaticlabs/prysm into peer-scoring-service * linter * gazelle * updates tests * Merge branch 'master' into peer-scoring-service * fixes tests * Nishant's suggestions * Merge refs/heads/master into peer-scoring-service * Merge refs/heads/master into peer-scoring-service * Merge refs/heads/master into peer-scoring-service * Merge refs/heads/master into peer-scoring-service * Merge refs/heads/master into peer-scoring-service * Merge refs/heads/master into peer-scoring-service * Merge refs/heads/master into peer-scoring-service * Merge branch 'master' into peer-scoring-service * gofmt * Nishant's suggestion to use isBadPeer * Merge refs/heads/master into peer-scoring-service
2020-07-20 15:12:59 +00:00
package peers
import (
"context"
"time"
"github.com/libp2p/go-libp2p-core/peer"
)
const (
// DefaultBadResponsesThreshold defines how many bad responses to tolerate before peer is deemed bad.
DefaultBadResponsesThreshold = 6
// DefaultBadResponsesWeight is a default weight. Since score represents penalty, it has negative weight.
DefaultBadResponsesWeight = -1.0
// DefaultBadResponsesDecayInterval defines how often to decay previous statistics.
// Every interval bad responses counter will be decremented by 1.
DefaultBadResponsesDecayInterval = time.Hour
)
// PeerScorer keeps track of peer counters that are used to calculate peer score.
type PeerScorer struct {
ctx context.Context
config *PeerScorerConfig
store *peerDataStore
}
// PeerScorerConfig holds configuration parameters for scoring service.
type PeerScorerConfig struct {
// BadResponsesThreshold specifies number of bad responses tolerated, before peer is banned.
BadResponsesThreshold int
BadResponsesWeight float64
BadResponsesDecayInterval time.Duration
}
// newPeerScorer provides fully initialized peer scoring service.
func newPeerScorer(ctx context.Context, store *peerDataStore, config *PeerScorerConfig) *PeerScorer {
scorer := &PeerScorer{
ctx: ctx,
config: config,
store: store,
}
if scorer.config.BadResponsesThreshold == 0 {
scorer.config.BadResponsesThreshold = DefaultBadResponsesThreshold
}
if scorer.config.BadResponsesWeight == 0.0 {
scorer.config.BadResponsesWeight = DefaultBadResponsesWeight
}
if scorer.config.BadResponsesDecayInterval == 0 {
scorer.config.BadResponsesDecayInterval = DefaultBadResponsesDecayInterval
}
go scorer.loop(scorer.ctx)
return scorer
}
// Score returns calculated peer score across all tracked metrics.
func (s *PeerScorer) Score(pid peer.ID) float64 {
s.store.RLock()
defer s.store.RUnlock()
var score float64
if _, ok := s.store.peers[pid]; !ok {
return 0
}
badResponsesScore := float64(s.store.peers[pid].badResponsesCount) / float64(s.config.BadResponsesThreshold)
badResponsesScore = badResponsesScore * s.config.BadResponsesWeight
score += badResponsesScore
return score
}
// Params exposes peer scorer parameters.
func (s *PeerScorer) Params() *PeerScorerConfig {
return s.config
}
// loop handles background tasks.
func (s *PeerScorer) loop(ctx context.Context) {
decayBadResponsesScores := time.NewTicker(s.config.BadResponsesDecayInterval)
defer decayBadResponsesScores.Stop()
for {
select {
case <-decayBadResponsesScores.C:
s.DecayBadResponsesStats()
case <-ctx.Done():
return
}
}
}