github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/network/p2p/scoring/subscription_validator.go (about) 1 package scoring 2 3 import ( 4 "github.com/libp2p/go-libp2p/core/peer" 5 "github.com/rs/zerolog" 6 7 "github.com/onflow/flow-go/model/flow" 8 "github.com/onflow/flow-go/module/component" 9 "github.com/onflow/flow-go/module/irrecoverable" 10 "github.com/onflow/flow-go/network/p2p" 11 p2plogging "github.com/onflow/flow-go/network/p2p/logging" 12 p2putils "github.com/onflow/flow-go/network/p2p/utils" 13 ) 14 15 // SubscriptionValidator validates that a peer is subscribed to topics that it is allowed to subscribe to. 16 // It is used to penalize peers that subscribe to topics that they are not allowed to subscribe to in GossipSub. 17 type SubscriptionValidator struct { 18 component.Component 19 logger zerolog.Logger 20 subscriptionProvider p2p.SubscriptionProvider 21 } 22 23 func NewSubscriptionValidator(logger zerolog.Logger, provider p2p.SubscriptionProvider) *SubscriptionValidator { 24 v := &SubscriptionValidator{ 25 logger: logger.With().Str("component", "subscription_validator").Logger(), 26 subscriptionProvider: provider, 27 } 28 29 v.Component = component.NewComponentManagerBuilder(). 30 AddWorker(func(ctx irrecoverable.SignalerContext, ready component.ReadyFunc) { 31 logger.Debug().Msg("starting subscription validator") 32 v.subscriptionProvider.Start(ctx) 33 select { 34 case <-ctx.Done(): 35 logger.Debug().Msg("subscription validator is stopping") 36 case <-v.subscriptionProvider.Ready(): 37 logger.Debug().Msg("subscription validator started") 38 ready() 39 logger.Debug().Msg("subscription validator is ready") 40 } 41 42 <-ctx.Done() 43 logger.Debug().Msg("subscription validator is stopping") 44 <-v.subscriptionProvider.Done() 45 logger.Debug().Msg("subscription validator stopped") 46 }).Build() 47 48 return v 49 } 50 51 var _ p2p.SubscriptionValidator = (*SubscriptionValidator)(nil) 52 53 // CheckSubscribedToAllowedTopics checks if a peer is subscribed to topics that it is allowed to subscribe to. 54 // Args: 55 // 56 // pid: the peer ID of the peer to check 57 // role: the role of the peer to check 58 // 59 // Returns: 60 // error: if the peer is subscribed to topics that it is not allowed to subscribe to, an InvalidSubscriptionError is returned. 61 // The error is benign, i.e., it does not indicate an illegal state in the execution of the code. We expect this error 62 // when there are malicious peers in the network. But such errors should not lead to a crash of the node. 63 func (v *SubscriptionValidator) CheckSubscribedToAllowedTopics(pid peer.ID, role flow.Role) error { 64 lg := v.logger.With().Str("remote_peer_id", p2plogging.PeerId(pid)).Logger() 65 66 topics := v.subscriptionProvider.GetSubscribedTopics(pid) 67 lg.Trace().Strs("topics", topics).Msg("checking subscription for remote peer id") 68 69 for _, topic := range topics { 70 if !p2putils.AllowedSubscription(role, topic) { 71 return p2p.NewInvalidSubscriptionError(topic) 72 } 73 } 74 75 lg.Trace().Msg("subscription is valid") 76 return nil 77 }