github.com/onflow/flow-go@v0.33.17/network/p2p/consumers.go (about)

     1  package p2p
     2  
     3  import (
     4  	pubsub "github.com/libp2p/go-libp2p-pubsub"
     5  	"github.com/libp2p/go-libp2p/core/peer"
     6  
     7  	"github.com/onflow/flow-go/module/component"
     8  	p2pmsg "github.com/onflow/flow-go/network/p2p/message"
     9  )
    10  
    11  // GossipSubInspectorNotifDistributor is the interface for the distributor that distributes gossip sub inspector notifications.
    12  // It is used to distribute notifications to the consumers in an asynchronous manner and non-blocking manner.
    13  // The implementation should guarantee that all registered consumers are called upon distribution of a new event.
    14  type GossipSubInspectorNotifDistributor interface {
    15  	component.Component
    16  	// Distribute distributes the event to all the consumers.
    17  	// Any error returned by the distributor is non-recoverable and will cause the node to crash.
    18  	// Implementation must be concurrency safe, and non-blocking.
    19  	Distribute(notification *InvCtrlMsgNotif) error
    20  
    21  	// AddConsumer adds a consumer to the distributor. The consumer will be called the distributor distributes a new event.
    22  	// AddConsumer must be concurrency safe. Once a consumer is added, it must be called for all future events.
    23  	// There is no guarantee that the consumer will be called for events that were already received by the distributor.
    24  	AddConsumer(GossipSubInvCtrlMsgNotifConsumer)
    25  }
    26  
    27  // CtrlMsgTopicType represents the type of the topic within a control message.
    28  type CtrlMsgTopicType uint64
    29  
    30  const (
    31  	// CtrlMsgNonClusterTopicType represents a non-cluster-prefixed topic.
    32  	CtrlMsgNonClusterTopicType CtrlMsgTopicType = iota
    33  	// CtrlMsgTopicTypeClusterPrefixed represents a cluster-prefixed topic.
    34  	CtrlMsgTopicTypeClusterPrefixed
    35  )
    36  
    37  func (t CtrlMsgTopicType) String() string {
    38  	switch t {
    39  	case CtrlMsgNonClusterTopicType:
    40  		return "non-cluster-prefixed"
    41  	case CtrlMsgTopicTypeClusterPrefixed:
    42  		return "cluster-prefixed"
    43  	default:
    44  		return "unknown"
    45  	}
    46  }
    47  
    48  // InvCtrlMsgNotif is the notification sent to the consumer when an invalid control message is received.
    49  // It models the information that is available to the consumer about a misbehaving peer.
    50  type InvCtrlMsgNotif struct {
    51  	// PeerID is the ID of the peer that sent the invalid control message.
    52  	PeerID peer.ID
    53  	// Error the error that occurred during validation.
    54  	Error error
    55  	// MsgType the control message type.
    56  	MsgType p2pmsg.ControlMessageType
    57  	// Count the number of errors.
    58  	Count uint64
    59  	// TopicType reports whether the error occurred on a cluster-prefixed topic within the control message.
    60  	// Notifications must be explicitly marked as cluster-prefixed or not because the penalty applied to the GossipSub score
    61  	// for an error on a cluster-prefixed topic is more lenient than the penalty applied to a non-cluster-prefixed topic.
    62  	// This distinction ensures that nodes engaged in cluster-prefixed topic communication are not penalized too harshly,
    63  	// as such communication is vital to the progress of the chain.
    64  	TopicType CtrlMsgTopicType
    65  }
    66  
    67  // NewInvalidControlMessageNotification returns a new *InvCtrlMsgNotif
    68  // Args:
    69  //   - peerID: peer id of the offender.
    70  //   - ctlMsgType: the control message type of the rpc message that caused the error.
    71  //   - err: the error that occurred.
    72  //   - count: the number of occurrences of the error.
    73  //
    74  // Returns:
    75  //   - *InvCtlMsgNotif: invalid control message notification.
    76  func NewInvalidControlMessageNotification(peerID peer.ID, ctlMsgType p2pmsg.ControlMessageType, err error, count uint64, topicType CtrlMsgTopicType) *InvCtrlMsgNotif {
    77  	return &InvCtrlMsgNotif{
    78  		PeerID:    peerID,
    79  		Error:     err,
    80  		MsgType:   ctlMsgType,
    81  		Count:     count,
    82  		TopicType: topicType,
    83  	}
    84  }
    85  
    86  // GossipSubInvCtrlMsgNotifConsumer is the interface for the consumer that consumes gossipsub inspector notifications.
    87  // It is used to consume notifications in an asynchronous manner.
    88  // The implementation must be concurrency safe, but can be blocking. This is due to the fact that the consumer is called
    89  // asynchronously by the distributor.
    90  type GossipSubInvCtrlMsgNotifConsumer interface {
    91  	// OnInvalidControlMessageNotification is called when a new invalid control message notification is distributed.
    92  	// Any error on consuming event must handle internally.
    93  	// The implementation must be concurrency safe, but can be blocking.
    94  	OnInvalidControlMessageNotification(*InvCtrlMsgNotif)
    95  }
    96  
    97  // GossipSubInspectorSuite is the interface for the GossipSub inspector suite.
    98  // It encapsulates the rpc inspectors and the notification distributors.
    99  type GossipSubInspectorSuite interface {
   100  	component.Component
   101  	CollectionClusterChangesConsumer
   102  	// InspectFunc returns the inspect function that is used to inspect the gossipsub rpc messages.
   103  	// This function follows a dependency injection pattern, where the inspect function is injected into the gossipsu, and
   104  	// is called whenever a gossipsub rpc message is received.
   105  	InspectFunc() func(peer.ID, *pubsub.RPC) error
   106  
   107  	// AddInvalidControlMessageConsumer adds a consumer to the invalid control message notification distributor.
   108  	// This consumer is notified when a misbehaving peer regarding gossipsub control messages is detected. This follows a pub/sub
   109  	// pattern where the consumer is notified when a new notification is published.
   110  	// A consumer is only notified once for each notification, and only receives notifications that were published after it was added.
   111  	AddInvalidControlMessageConsumer(GossipSubInvCtrlMsgNotifConsumer)
   112  }