github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/p2p/peers/scorers/gossip_scorer.go (about) 1 package scorers 2 3 import ( 4 "github.com/libp2p/go-libp2p-core/peer" 5 "github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers/peerdata" 6 pbrpc "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1" 7 ) 8 9 var _ Scorer = (*GossipScorer)(nil) 10 11 // GossipScorer represents scorer that evaluates peers based on their gossip performance. 12 // Gossip scoring metrics are periodically calculated in libp2p's internal pubsub module. 13 type GossipScorer struct { 14 config *GossipScorerConfig 15 store *peerdata.Store 16 } 17 18 // GossipScorerConfig holds configuration parameters for gossip scoring service. 19 type GossipScorerConfig struct{} 20 21 // newGossipScorer creates new gossip scoring service. 22 func newGossipScorer(store *peerdata.Store, config *GossipScorerConfig) *GossipScorer { 23 if config == nil { 24 config = &GossipScorerConfig{} 25 } 26 return &GossipScorer{ 27 config: config, 28 store: store, 29 } 30 } 31 32 // Score returns calculated peer score. 33 func (s *GossipScorer) Score(pid peer.ID) float64 { 34 s.store.RLock() 35 defer s.store.RUnlock() 36 return s.score(pid) 37 } 38 39 // score is a lock-free version of Score. 40 func (s *GossipScorer) score(pid peer.ID) float64 { 41 peerData, ok := s.store.PeerData(pid) 42 if !ok { 43 return 0 44 } 45 return peerData.GossipScore 46 } 47 48 // IsBadPeer states if the peer is to be considered bad. 49 func (s *GossipScorer) IsBadPeer(pid peer.ID) bool { 50 s.store.RLock() 51 defer s.store.RUnlock() 52 return s.isBadPeer(pid) 53 } 54 55 // isBadPeer is lock-free version of IsBadPeer. 56 func (s *GossipScorer) isBadPeer(pid peer.ID) bool { 57 peerData, ok := s.store.PeerData(pid) 58 if !ok { 59 return false 60 } 61 return peerData.GossipScore < 0 62 } 63 64 // BadPeers returns the peers that are considered bad. 65 func (s *GossipScorer) BadPeers() []peer.ID { 66 s.store.RLock() 67 defer s.store.RUnlock() 68 69 badPeers := make([]peer.ID, 0) 70 for pid := range s.store.Peers() { 71 if s.isBadPeer(pid) { 72 badPeers = append(badPeers, pid) 73 } 74 } 75 return badPeers 76 } 77 78 // SetGossipData sets the gossip related data of a peer. 79 func (s *GossipScorer) SetGossipData(pid peer.ID, gScore float64, 80 bPenalty float64, topicScores map[string]*pbrpc.TopicScoreSnapshot) { 81 s.store.Lock() 82 defer s.store.Unlock() 83 84 peerData := s.store.PeerDataGetOrCreate(pid) 85 peerData.GossipScore = gScore 86 peerData.BehaviourPenalty = bPenalty 87 peerData.TopicScores = topicScores 88 } 89 90 // GossipData gets the gossip related information of the given remote peer. 91 // This can return nil if there is no known gossip record the peer. 92 // This will error if the peer does not exist. 93 func (s *GossipScorer) GossipData(pid peer.ID) (float64, float64, map[string]*pbrpc.TopicScoreSnapshot, error) { 94 s.store.RLock() 95 defer s.store.RUnlock() 96 return s.gossipData(pid) 97 } 98 99 // gossipData lock-free version of GossipData. 100 func (s *GossipScorer) gossipData(pid peer.ID) (float64, float64, map[string]*pbrpc.TopicScoreSnapshot, error) { 101 if peerData, ok := s.store.PeerData(pid); ok { 102 return peerData.GossipScore, peerData.BehaviourPenalty, peerData.TopicScores, nil 103 } 104 return 0, 0, nil, peerdata.ErrPeerUnknown 105 }