prysm-pulse/beacon-chain/p2p/peers/scorer_manager.go
Victor Farazdagi bf59530d93
Adds block provider scorer (#6756)
* prepares peer scorer collection

* decouples scoring service into separate object

* updates references

* renames package

* removes redundant test init

* gazelle

* gofmt

* updates comment

* fix build

* adds block provider scorer

* score rounding factor constant (per Nishant's suggestion)

* updates penalty applying

* updates score block provider tests

* updates scorer tests

* expand test suite

* get rid of penalties + counters for requested/returned blocks

* removes start score

* fixes provider test

* fixes scorer manager tests

* updates comments

* moves roundScore test function

* maxscore tests

* improves test coverage

* Update beacon-chain/p2p/peers/score_block_providers.go

Co-authored-by: Nishant Das <nishdas93@gmail.com>

* renames var to make it less ambigous - per Nishant's suggestion

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Nishant Das <nishdas93@gmail.com>
2020-08-01 12:20:05 +03:00

86 lines
2.6 KiB
Go

package peers
import (
"context"
"math"
"time"
"github.com/libp2p/go-libp2p-core/peer"
)
// ScoreRoundingFactor defines how many digits to keep in decimal part.
// This parameter is used in math.Round(score*ScoreRoundingFactor) / ScoreRoundingFactor.
const ScoreRoundingFactor = 10000
// PeerScorerManager keeps track of peer scorers that are used to calculate overall peer score.
type PeerScorerManager struct {
ctx context.Context
store *peerDataStore
scorers struct {
badResponsesScorer *BadResponsesScorer
blockProviderScorer *BlockProviderScorer
}
}
// PeerScorerConfig holds configuration parameters for scoring service.
type PeerScorerConfig struct {
BadResponsesScorerConfig *BadResponsesScorerConfig
BlockProviderScorerConfig *BlockProviderScorerConfig
}
// newPeerScorerManager provides fully initialized peer scoring service.
func newPeerScorerManager(ctx context.Context, store *peerDataStore, config *PeerScorerConfig) *PeerScorerManager {
mgr := &PeerScorerManager{
ctx: ctx,
store: store,
}
mgr.scorers.badResponsesScorer = newBadResponsesScorer(ctx, store, config.BadResponsesScorerConfig)
mgr.scorers.blockProviderScorer = newBlockProviderScorer(ctx, store, config.BlockProviderScorerConfig)
go mgr.loop(mgr.ctx)
return mgr
}
// BadResponsesScorer exposes bad responses scoring service.
func (m *PeerScorerManager) BadResponsesScorer() *BadResponsesScorer {
return m.scorers.badResponsesScorer
}
// BlockProviderScorer exposes block provider scoring service.
func (m *PeerScorerManager) BlockProviderScorer() *BlockProviderScorer {
return m.scorers.blockProviderScorer
}
// Score returns calculated peer score across all tracked metrics.
func (m *PeerScorerManager) Score(pid peer.ID) float64 {
m.store.RLock()
defer m.store.RUnlock()
score := float64(0)
if _, ok := m.store.peers[pid]; !ok {
return 0
}
score += m.scorers.badResponsesScorer.score(pid)
score += m.scorers.blockProviderScorer.score(pid)
return math.Round(score*ScoreRoundingFactor) / ScoreRoundingFactor
}
// loop handles background tasks.
func (m *PeerScorerManager) loop(ctx context.Context) {
decayBadResponsesStats := time.NewTicker(m.scorers.badResponsesScorer.Params().DecayInterval)
defer decayBadResponsesStats.Stop()
decayBlockProviderStats := time.NewTicker(m.scorers.blockProviderScorer.Params().DecayInterval)
defer decayBlockProviderStats.Stop()
for {
select {
case <-decayBadResponsesStats.C:
m.scorers.badResponsesScorer.Decay()
case <-decayBlockProviderStats.C:
m.scorers.blockProviderScorer.Decay()
case <-ctx.Done():
return
}
}
}