prysm-pulse/beacon-chain/p2p/peers/scorer.go
Victor Farazdagi f0ffd5af03
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

93 lines
2.6 KiB
Go

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
}
}
}