Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Initial Support For Gossip Scoring Service (#8275)
* checkpoint progress * gaz * fix * add it in * Update beacon-chain/p2p/pubsub.go * fmt * reformat imports Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
- Loading branch information
Showing
22 changed files
with
1,616 additions
and
483 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package scorers | ||
|
||
import ( | ||
"github.com/libp2p/go-libp2p-core/peer" | ||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers/peerdata" | ||
pbrpc "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1" | ||
) | ||
|
||
var _ Scorer = (*GossipScorer)(nil) | ||
|
||
// GossipScorer represents scorer that evaluates peers based on their gossip performance. | ||
// Gossip scoring metrics are periodically calculated in libp2p's internal pubsub module. | ||
type GossipScorer struct { | ||
config *GossipScorerConfig | ||
store *peerdata.Store | ||
} | ||
|
||
// GossipScorerConfig holds configuration parameters for gossip scoring service. | ||
type GossipScorerConfig struct{} | ||
|
||
// newGossipScorer creates new gossip scoring service. | ||
func newGossipScorer(store *peerdata.Store, config *GossipScorerConfig) *GossipScorer { | ||
if config == nil { | ||
config = &GossipScorerConfig{} | ||
} | ||
return &GossipScorer{ | ||
config: config, | ||
store: store, | ||
} | ||
} | ||
|
||
// Score returns calculated peer score. | ||
func (s *GossipScorer) Score(pid peer.ID) float64 { | ||
s.store.RLock() | ||
defer s.store.RUnlock() | ||
return s.score(pid) | ||
} | ||
|
||
// score is a lock-free version of Score. | ||
func (s *GossipScorer) score(pid peer.ID) float64 { | ||
peerData, ok := s.store.PeerData(pid) | ||
if !ok { | ||
return 0 | ||
} | ||
return peerData.GossipScore | ||
} | ||
|
||
// IsBadPeer states if the peer is to be considered bad. | ||
func (s *GossipScorer) IsBadPeer(pid peer.ID) bool { | ||
s.store.RLock() | ||
defer s.store.RUnlock() | ||
return s.isBadPeer(pid) | ||
} | ||
|
||
// isBadPeer is lock-free version of IsBadPeer. | ||
func (s *GossipScorer) isBadPeer(pid peer.ID) bool { | ||
peerData, ok := s.store.PeerData(pid) | ||
if !ok { | ||
return false | ||
} | ||
return peerData.GossipScore < 0 | ||
} | ||
|
||
// BadPeers returns the peers that are considered bad. | ||
func (s *GossipScorer) BadPeers() []peer.ID { | ||
s.store.RLock() | ||
defer s.store.RUnlock() | ||
|
||
badPeers := make([]peer.ID, 0) | ||
for pid := range s.store.Peers() { | ||
if s.isBadPeer(pid) { | ||
badPeers = append(badPeers, pid) | ||
} | ||
} | ||
return badPeers | ||
} | ||
|
||
// SetGossipData sets the gossip related data of a peer. | ||
func (s *GossipScorer) SetGossipData(pid peer.ID, gScore float64, | ||
bPenalty float64, topicScores map[string]*pbrpc.TopicScoreSnapshot) { | ||
s.store.Lock() | ||
defer s.store.Unlock() | ||
|
||
peerData := s.store.PeerDataGetOrCreate(pid) | ||
peerData.GossipScore = gScore | ||
peerData.BehaviourPenalty = bPenalty | ||
peerData.TopicScores = topicScores | ||
} | ||
|
||
// GossipData gets the gossip related information of the given remote peer. | ||
// This can return nil if there is no known gossip record the peer. | ||
// This will error if the peer does not exist. | ||
func (s *GossipScorer) GossipData(pid peer.ID) (float64, float64, map[string]*pbrpc.TopicScoreSnapshot, error) { | ||
s.store.RLock() | ||
defer s.store.RUnlock() | ||
return s.gossipData(pid) | ||
} | ||
|
||
// gossipData lock-free version of GossipData. | ||
func (s *GossipScorer) gossipData(pid peer.ID) (float64, float64, map[string]*pbrpc.TopicScoreSnapshot, error) { | ||
if peerData, ok := s.store.PeerData(pid); ok { | ||
return peerData.GossipScore, peerData.BehaviourPenalty, peerData.TopicScores, nil | ||
} | ||
return 0, 0, nil, peerdata.ErrPeerUnknown | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package scorers_test | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers" | ||
"github.com/prysmaticlabs/prysm/beacon-chain/p2p/peers/scorers" | ||
pbrpc "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1" | ||
"github.com/prysmaticlabs/prysm/shared/testutil/assert" | ||
) | ||
|
||
func TestScorers_Gossip_Score(t *testing.T) { | ||
ctx, cancel := context.WithCancel(context.Background()) | ||
defer cancel() | ||
|
||
tests := []struct { | ||
name string | ||
update func(scorer *scorers.GossipScorer) | ||
check func(scorer *scorers.GossipScorer) | ||
}{ | ||
{ | ||
name: "nonexistent peer", | ||
update: func(scorer *scorers.GossipScorer) { | ||
}, | ||
check: func(scorer *scorers.GossipScorer) { | ||
assert.Equal(t, 0.0, scorer.Score("peer1"), "Unexpected score") | ||
}, | ||
}, | ||
{ | ||
name: "existent bad peer", | ||
update: func(scorer *scorers.GossipScorer) { | ||
scorer.SetGossipData("peer1", -10.0, 1, nil) | ||
}, | ||
check: func(scorer *scorers.GossipScorer) { | ||
assert.Equal(t, -10.0, scorer.Score("peer1"), "Unexpected score") | ||
assert.Equal(t, true, scorer.IsBadPeer("peer1"), "Unexpected good peer") | ||
}, | ||
}, | ||
{ | ||
name: "good peer", | ||
update: func(scorer *scorers.GossipScorer) { | ||
scorer.SetGossipData("peer1", 10.0, 0, map[string]*pbrpc.TopicScoreSnapshot{"a": {TimeInMesh: 100}}) | ||
}, | ||
check: func(scorer *scorers.GossipScorer) { | ||
assert.Equal(t, 10.0, scorer.Score("peer1"), "Unexpected score") | ||
assert.Equal(t, false, scorer.IsBadPeer("peer1"), "Unexpected bad peer") | ||
_, _, topicMap, err := scorer.GossipData("peer1") | ||
assert.NoError(t, err) | ||
assert.Equal(t, uint64(100), topicMap["a"].TimeInMesh, "incorrect time in mesh") | ||
}, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
peerStatuses := peers.NewStatus(ctx, &peers.StatusConfig{ | ||
ScorerParams: &scorers.Config{}, | ||
}) | ||
scorer := peerStatuses.Scorers().GossipScorer() | ||
if tt.update != nil { | ||
tt.update(scorer) | ||
} | ||
tt.check(scorer) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.