github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/network/p2p/node/gossipSubAdapterConfig.go (about)

     1  package p2pnode
     2  
     3  import (
     4  	pubsub "github.com/libp2p/go-libp2p-pubsub"
     5  	pb "github.com/libp2p/go-libp2p-pubsub/pb"
     6  	"github.com/libp2p/go-libp2p/core/peer"
     7  	"github.com/libp2p/go-libp2p/core/routing"
     8  	discoveryrouting "github.com/libp2p/go-libp2p/p2p/discovery/routing"
     9  
    10  	"github.com/onflow/flow-go/module/component"
    11  	"github.com/onflow/flow-go/network/p2p"
    12  )
    13  
    14  // GossipSubAdapterConfig is a wrapper around libp2p pubsub options that
    15  // implements the PubSubAdapterConfig interface for the Flow network.
    16  type GossipSubAdapterConfig struct {
    17  	options      []pubsub.Option
    18  	scoreTracer  p2p.PeerScoreTracer
    19  	scoreOption  p2p.ScoreOptionBuilder
    20  	pubsubTracer p2p.PubSubTracer
    21  	inspector    p2p.GossipSubRPCInspector // currently only used to manage the lifecycle.
    22  }
    23  
    24  var _ p2p.PubSubAdapterConfig = (*GossipSubAdapterConfig)(nil)
    25  
    26  // NewGossipSubAdapterConfig creates a new GossipSubAdapterConfig with the default options.
    27  // Args:
    28  //   - base: the base pubsub adapter config
    29  //
    30  // Returns:
    31  //   - a new GossipSubAdapterConfig
    32  func NewGossipSubAdapterConfig(base *p2p.BasePubSubAdapterConfig) *GossipSubAdapterConfig {
    33  	return &GossipSubAdapterConfig{
    34  		options: defaultPubsubOptions(base),
    35  	}
    36  }
    37  
    38  // WithRoutingDiscovery adds a routing discovery option to the config.
    39  // Args:
    40  //   - routing: the routing discovery to use
    41  //
    42  // Returns:
    43  // -None
    44  func (g *GossipSubAdapterConfig) WithRoutingDiscovery(routing routing.ContentRouting) {
    45  	g.options = append(g.options, pubsub.WithDiscovery(discoveryrouting.NewRoutingDiscovery(routing)))
    46  }
    47  
    48  // WithSubscriptionFilter adds a subscription filter option to the config.
    49  // Args:
    50  //   - filter: the subscription filter to use
    51  //
    52  // Returns:
    53  // -None
    54  func (g *GossipSubAdapterConfig) WithSubscriptionFilter(filter p2p.SubscriptionFilter) {
    55  	g.options = append(g.options, pubsub.WithSubscriptionFilter(filter))
    56  }
    57  
    58  // WithScoreOption adds a score option to the config.
    59  // Args:
    60  // - option: the score option to use
    61  // Returns:
    62  // -None
    63  func (g *GossipSubAdapterConfig) WithScoreOption(option p2p.ScoreOptionBuilder) {
    64  	params, thresholds := option.BuildFlowPubSubScoreOption()
    65  	g.scoreOption = option
    66  	g.options = append(g.options, pubsub.WithPeerScore(params, thresholds))
    67  }
    68  
    69  // WithMessageIdFunction adds a message ID function option to the config.
    70  // Args:
    71  // - f: the message ID function to use
    72  // Returns:
    73  // -None
    74  func (g *GossipSubAdapterConfig) WithMessageIdFunction(f func([]byte) string) {
    75  	g.options = append(g.options, pubsub.WithMessageIdFn(func(pmsg *pb.Message) string {
    76  		return f(pmsg.Data)
    77  	}))
    78  }
    79  
    80  // WithInspectorSuite adds an inspector suite option to the config.
    81  // Args:
    82  // - suite: the inspector suite to use
    83  // Returns:
    84  // -None
    85  func (g *GossipSubAdapterConfig) WithRpcInspector(inspector p2p.GossipSubRPCInspector) {
    86  	g.options = append(g.options, pubsub.WithAppSpecificRpcInspector(inspector.Inspect))
    87  	g.inspector = inspector
    88  }
    89  
    90  // WithTracer adds a tracer option to the config.
    91  // Args:
    92  // - tracer: the tracer to use
    93  // Returns:
    94  // -None
    95  func (g *GossipSubAdapterConfig) WithTracer(tracer p2p.PubSubTracer) {
    96  	g.pubsubTracer = tracer
    97  	g.options = append(g.options, pubsub.WithRawTracer(tracer))
    98  }
    99  
   100  // ScoreTracer returns the tracer for the peer score.
   101  // Args:
   102  //   - None
   103  //
   104  // Returns:
   105  // - p2p.PeerScoreTracer: the tracer for the peer score.
   106  func (g *GossipSubAdapterConfig) ScoreTracer() p2p.PeerScoreTracer {
   107  	return g.scoreTracer
   108  }
   109  
   110  // PubSubTracer returns the tracer for the pubsub.
   111  // Args:
   112  // - None
   113  // Returns:
   114  // - p2p.PubSubTracer: the tracer for the pubsub.
   115  func (g *GossipSubAdapterConfig) PubSubTracer() p2p.PubSubTracer {
   116  	return g.pubsubTracer
   117  }
   118  
   119  func (g *GossipSubAdapterConfig) ScoringComponent() component.Component {
   120  	return g.scoreOption
   121  }
   122  
   123  // RpcInspectorComponent returns the component that manages the lifecycle of the inspector suite.
   124  // This is used to start and stop the inspector suite by the PubSubAdapter.
   125  // Args:
   126  //   - None
   127  //
   128  // Returns:
   129  //   - component.Component: the component that manages the lifecycle of the inspector suite.
   130  func (g *GossipSubAdapterConfig) RpcInspectorComponent() component.Component {
   131  	return g.inspector
   132  }
   133  
   134  // WithScoreTracer sets the tracer for the peer score.
   135  // Args:
   136  //   - tracer: the tracer for the peer score.
   137  //
   138  // Returns:
   139  //   - None
   140  func (g *GossipSubAdapterConfig) WithScoreTracer(tracer p2p.PeerScoreTracer) {
   141  	g.scoreTracer = tracer
   142  	g.options = append(g.options, pubsub.WithPeerScoreInspect(func(snapshot map[peer.ID]*pubsub.PeerScoreSnapshot) {
   143  		tracer.UpdatePeerScoreSnapshots(convertPeerScoreSnapshots(snapshot))
   144  	}, tracer.UpdateInterval()))
   145  }
   146  
   147  // convertPeerScoreSnapshots converts a libp2p pubsub peer score snapshot to a Flow peer score snapshot.
   148  // Args:
   149  //   - snapshot: the libp2p pubsub peer score snapshot.
   150  //
   151  // Returns:
   152  //   - map[peer.ID]*p2p.PeerScoreSnapshot: the Flow peer score snapshot.
   153  func convertPeerScoreSnapshots(snapshot map[peer.ID]*pubsub.PeerScoreSnapshot) map[peer.ID]*p2p.PeerScoreSnapshot {
   154  	newSnapshot := make(map[peer.ID]*p2p.PeerScoreSnapshot)
   155  	for id, snap := range snapshot {
   156  		newSnapshot[id] = &p2p.PeerScoreSnapshot{
   157  			Topics:             convertTopicScoreSnapshot(snap.Topics),
   158  			Score:              snap.Score,
   159  			AppSpecificScore:   snap.AppSpecificScore,
   160  			BehaviourPenalty:   snap.BehaviourPenalty,
   161  			IPColocationFactor: snap.IPColocationFactor,
   162  		}
   163  	}
   164  	return newSnapshot
   165  }
   166  
   167  // convertTopicScoreSnapshot converts a libp2p pubsub topic score snapshot to a Flow topic score snapshot.
   168  // Args:
   169  //   - snapshot: the libp2p pubsub topic score snapshot.
   170  //
   171  // Returns:
   172  //   - map[string]*p2p.TopicScoreSnapshot: the Flow topic score snapshot.
   173  func convertTopicScoreSnapshot(snapshot map[string]*pubsub.TopicScoreSnapshot) map[string]*p2p.TopicScoreSnapshot {
   174  	newSnapshot := make(map[string]*p2p.TopicScoreSnapshot)
   175  	for topic, snap := range snapshot {
   176  		newSnapshot[topic] = &p2p.TopicScoreSnapshot{
   177  			TimeInMesh:               snap.TimeInMesh,
   178  			FirstMessageDeliveries:   snap.FirstMessageDeliveries,
   179  			MeshMessageDeliveries:    snap.MeshMessageDeliveries,
   180  			InvalidMessageDeliveries: snap.InvalidMessageDeliveries,
   181  		}
   182  	}
   183  
   184  	return newSnapshot
   185  }
   186  
   187  // TopicScoreParamFunc returns the topic score param function. This function is used to get the topic score params for a topic.
   188  // The topic score params are used to set the topic parameters in GossipSub at the time of joining the topic.
   189  // Args:
   190  //   - None
   191  //
   192  // Returns:
   193  // - func(topic *pubsub.Topic) *pubsub.TopicScoreParams: the topic score param function if set, nil otherwise.
   194  // - bool: true if the topic score param function is set, false otherwise.
   195  func (g *GossipSubAdapterConfig) TopicScoreParamFunc() (func(topic *pubsub.Topic) *pubsub.TopicScoreParams, bool) {
   196  	if g.scoreOption != nil {
   197  		return func(topic *pubsub.Topic) *pubsub.TopicScoreParams {
   198  			return g.scoreOption.TopicScoreParams(topic)
   199  		}, true
   200  	}
   201  
   202  	return nil, false
   203  }
   204  
   205  // Build returns the libp2p pubsub options.
   206  // Args:
   207  //   - None
   208  //
   209  // Returns:
   210  //   - []pubsub.Option: the libp2p pubsub options.
   211  //
   212  // Build is idempotent.
   213  func (g *GossipSubAdapterConfig) Build() []pubsub.Option {
   214  	return g.options
   215  }
   216  
   217  // defaultPubsubOptions returns the default libp2p pubsub options. These options are used by the Flow network to create a libp2p pubsub.
   218  func defaultPubsubOptions(base *p2p.BasePubSubAdapterConfig) []pubsub.Option {
   219  	return []pubsub.Option{
   220  		pubsub.WithMessageSigning(true),
   221  		pubsub.WithStrictSignatureVerification(true),
   222  		pubsub.WithMaxMessageSize(base.MaxMessageSize),
   223  	}
   224  }