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

     1  package p2pconfig
     2  
     3  import "time"
     4  
     5  const (
     6  	PeerScoringKey = "peer-scoring"
     7  	InternalKey    = "internal"
     8  	ProtocolKey    = "protocol"
     9  )
    10  
    11  // PeerScoringParameters encapsulates the parameters of the GossipSub scoring system.
    12  type PeerScoringParameters struct {
    13  	// Internal is the internal parameters of the GossipSub scoring system that are hosted by
    14  	// the GossipSub system, and are not exposed to the Flow protocol.
    15  	// The internal parameters are hosted by the GossipSub system.
    16  	Internal InternalGossipSubScoreParams `validate:"required" mapstructure:"internal"`
    17  	// Protocol is the protocol parameters of the peer scoring system that is hosted by the Flow protocol.
    18  	Protocol ProtocolLevelGossipSubScoreParams `validate:"required" mapstructure:"protocol"`
    19  }
    20  
    21  const (
    22  	AppSpecificScoreWeightKey = "app-specific-score-weight"
    23  	DecayToZeroKey            = "decay-to-zero"
    24  	ThresholdsKey             = "thresholds"
    25  	BehaviourKey              = "behaviour"
    26  	TopicKey                  = "topic"
    27  )
    28  
    29  type InternalGossipSubScoreParams struct {
    30  	// AppSpecificScoreWeight is the  weight for app-specific scores. It is used to scale the app-specific
    31  	// scores to the same range as the other scores. At the current version, we don't distinguish between the app-specific
    32  	// scores and the other scores, so we set it to 1.
    33  	AppSpecificScoreWeight float64 `validate:"gt=0,lte=1" mapstructure:"app-specific-score-weight"`
    34  	// DecayInterval is the  decay interval for the overall score of a peer at the GossipSub scoring
    35  	// system. We set it to 1 minute so that it is not too short so that a malicious node can recover from a penalty
    36  	// and is not too long so that a well-behaved node can't recover from a penalty.
    37  	DecayInterval time.Duration `validate:"gte=1m" mapstructure:"decay-interval"`
    38  	// DecayToZero is the  decay to zero for the overall score of a peer at the GossipSub scoring system.
    39  	// It defines the maximum value below which a peer scoring counter is reset to zero.
    40  	// This is to prevent the counter from decaying to a very small value.
    41  	// The  value is 0.01, which means that a counter will be reset to zero if it decays to 0.01.
    42  	// When a counter hits the DecayToZero threshold, it means that the peer did not exhibit the behavior
    43  	// for a long time, and we can reset the counter.
    44  	DecayToZero     float64                    `validate:"required" mapstructure:"decay-to-zero"`
    45  	TopicParameters TopicScoringParameters     `validate:"required" mapstructure:"topic"`
    46  	Thresholds      InternalScoringThresholds  `validate:"required" mapstructure:"thresholds"`
    47  	Behaviour       InternalScoringBehavioural `validate:"required" mapstructure:"behaviour"`
    48  }
    49  
    50  const (
    51  	MaxDebugLogsKey = "max-debug-logs"
    52  	AppSpecificKey  = "application-specific"
    53  )
    54  
    55  type ProtocolLevelGossipSubScoreParams struct {
    56  	MaxDebugLogs     uint32                             `validate:"lte=50" mapstructure:"max-debug-logs"`
    57  	AppSpecificScore ApplicationSpecificScoreParameters `validate:"required" mapstructure:"application-specific"`
    58  }
    59  
    60  const (
    61  	MaxAppSpecificKey      = "max-app-specific"
    62  	MinAppSpecificKey      = "min-app-specific"
    63  	UnknownIdentityKey     = "unknown-identity"
    64  	InvalidSubscriptionKey = "invalid-subscription"
    65  	StakedIdentityKey      = "staked-identity"
    66  	RewardKey              = "reward"
    67  	PenaltyKey             = "penalty"
    68  )
    69  
    70  type ApplicationSpecificScoreParameters struct {
    71  	// MaxAppSpecificPenalty the maximum penalty for sever offenses that we apply to a remote node score. The score
    72  	// mechanism of GossipSub in Flow is designed in a way that all other infractions are penalized with a fraction of
    73  	// this value. We have also set the other parameters such as DefaultGraylistThreshold, DefaultGossipThreshold and DefaultPublishThreshold to
    74  	// be a bit higher than this, i.e., MaxAppSpecificPenalty + 1. This ensures that a node with a score of MaxAppSpecificPenalty
    75  	// will be graylisted (i.e., all incoming and outgoing RPCs are rejected) and will not be able to publish or gossip any messages.
    76  	MaxAppSpecificPenalty float64 `validate:"lt=0" mapstructure:"max-app-specific-penalty"`
    77  	// MinAppSpecificPenalty the minimum penalty for sever offenses that we apply to a remote node score.
    78  	MinAppSpecificPenalty float64 `validate:"lt=0" mapstructure:"min-app-specific-penalty"`
    79  	// UnknownIdentityPenalty is the  penalty for unknown identity. It is applied to the peer's score when
    80  	// the peer is not in the identity list.
    81  	UnknownIdentityPenalty float64 `validate:"lt=0" mapstructure:"unknown-identity-penalty"`
    82  	// InvalidSubscriptionPenalty is the  penalty for invalid subscription. It is applied to the peer's score when
    83  	// the peer subscribes to a topic that it is not authorized to subscribe to.
    84  	InvalidSubscriptionPenalty float64 `validate:"lt=0" mapstructure:"invalid-subscription-penalty"`
    85  	// MaxAppSpecificReward is the  reward for well-behaving staked peers. If a peer does not have
    86  	// any misbehavior record, e.g., invalid subscription, invalid message, etc., it will be rewarded with this score.
    87  	MaxAppSpecificReward float64 `validate:"gt=0" mapstructure:"max-app-specific-reward"`
    88  	// StakedIdentityReward is the  reward for staking peers. It is applied to the peer's score when
    89  	// the peer does not have any misbehavior record, e.g., invalid subscription, invalid message, etc.
    90  	// The purpose is to reward the staking peers for their contribution to the network and prioritize them in neighbor selection.
    91  	StakedIdentityReward float64 `validate:"gt=0" mapstructure:"staked-identity-reward"`
    92  }
    93  
    94  const (
    95  	GossipThresholdKey             = "gossip"
    96  	PublishThresholdKey            = "publish"
    97  	GraylistThresholdKey           = "graylist"
    98  	AcceptPXThresholdKey           = "accept-px"
    99  	OpportunisticGraftThresholdKey = "opportunistic-graft"
   100  )
   101  
   102  // InternalScoringThresholds score option threshold configuration parameters.
   103  type InternalScoringThresholds struct {
   104  	// Gossip when a peer's penalty drops below this threshold,
   105  	// no gossip is emitted towards that peer and gossip from that peer is ignored.
   106  	Gossip float64 `validate:"lt=0" mapstructure:"gossip"`
   107  	// Publish when a peer's penalty drops below this threshold,
   108  	// self-published messages are not propagated towards this peer.
   109  	Publish float64 `validate:"lt=0" mapstructure:"publish"`
   110  	// Graylist when a peer's penalty drops below this threshold, the peer is graylisted, i.e.,
   111  	// incoming RPCs from the peer are ignored.
   112  	Graylist float64 `validate:"lt=0" mapstructure:"graylist"`
   113  	// AcceptPX when a peer sends us PX information with a prune, we only accept it and connect to the supplied
   114  	// peers if the originating peer's penalty exceeds this threshold.
   115  	AcceptPX float64 `validate:"gt=0" mapstructure:"accept-px"`
   116  	// OpportunisticGraft when the median peer penalty in the mesh drops below this value,
   117  	// the peer may select more peers with penalty above the median to opportunistically graft on the mesh.
   118  	OpportunisticGraft float64 `validate:"gt=0" mapstructure:"opportunistic-graft"`
   119  }
   120  
   121  const (
   122  	BehaviourPenaltyThresholdKey = "penalty-threshold"
   123  	BehaviourPenaltyWeightKey    = "penalty-weight"
   124  	BehaviourPenaltyDecayKey     = "penalty-decay"
   125  )
   126  
   127  // InternalScoringBehavioural score option behaviour configuration parameters.
   128  type InternalScoringBehavioural struct {
   129  	// PenaltyThreshold is the threshold when the behavior of a peer is considered as bad by GossipSub.
   130  	// Currently, the misbehavior is defined as advertising an iHave without responding to the iWants (iHave broken promises), as well as attempting
   131  	// on GRAFT when the peer is considered for a PRUNE backoff, i.e., the local peer does not allow the peer to join the local topic mesh
   132  	// for a while, and the remote peer keep attempting on GRAFT (aka GRAFT flood).
   133  	// When the misbehavior counter of a peer goes beyond this threshold, the peer is penalized by BehaviorPenaltyWeight (see below) for the excess misbehavior.
   134  	//
   135  	// An iHave broken promise means that a peer advertises an iHave for a message, but does not respond to the iWant requests for that message.
   136  	// For iHave broken promises, the gossipsub scoring works as follows:
   137  	// It samples ONLY A SINGLE iHave out of the entire RPC.
   138  	// If that iHave is not followed by an actual message within the next 3 seconds, the peer misbehavior counter is incremented by 1.
   139  	//
   140  	// The counter is also decayed by (0.99) every decay interval (DecayInterval) i.e., every minute.
   141  	// Note that misbehaviors are counted by GossipSub across all topics (and is different from the Application Layer Misbehaviors that we count through
   142  	// the ALSP system).
   143  	PenaltyThreshold float64 `validate:"gt=0" mapstructure:"penalty-threshold"`
   144  	// PenaltyWeight is the weight for applying penalty when a peer misbehavior goes beyond the threshold.
   145  	// Misbehavior of a peer at gossipsub layer is defined as advertising an iHave without responding to the iWants (broken promises), as well as attempting
   146  	// on GRAFT when the peer is considered for a PRUNE backoff, i.e., the local peer does not allow the peer to join the local topic mesh
   147  	// This is detected by the GossipSub scoring system, and the peer is penalized by BehaviorPenaltyWeight.
   148  	//
   149  	// An iHave broken promise means that a peer advertises an iHave for a message, but does not respond to the iWant requests for that message.
   150  	// For iHave broken promises, the gossipsub scoring works as follows:
   151  	// It samples ONLY A SINGLE iHave out of the entire RPC.
   152  	// If that iHave is not followed by an actual message within the next 3 seconds, the peer misbehavior counter is incremented by 1.
   153  	PenaltyWeight float64 `validate:"lt=0" mapstructure:"penalty-weight"`
   154  	// PenaltyDecay is the decay interval for the misbehavior counter of a peer. The misbehavior counter is
   155  	// incremented by GossipSub for iHave broken promises or the GRAFT flooding attacks (i.e., each GRAFT received from a remote peer while that peer is on a PRUNE backoff).
   156  	//
   157  	// An iHave broken promise means that a peer advertises an iHave for a message, but does not respond to the iWant requests for that message.
   158  	// For iHave broken promises, the gossipsub scoring works as follows:
   159  	// It samples ONLY A SINGLE iHave out of the entire RPC.
   160  	// If that iHave is not followed by an actual message within the next 3 seconds, the peer misbehavior counter is incremented by 1.
   161  	// This means that regardless of how many iHave broken promises an RPC contains, the misbehavior counter is incremented by 1.
   162  	// That is why we decay the misbehavior counter very slow, as this counter indicates a severe misbehavior.
   163  	// The misbehavior counter is decayed per decay interval (i.e., DecayInterval = 1 minute) by GossipSub.
   164  	//
   165  	// Note that misbehaviors are counted by GossipSub across all topics (and is different from the Application Layer Misbehaviors that we count through
   166  	// the ALSP system that is based on the engines report).
   167  	PenaltyDecay float64 `validate:"gt=0,lt=1" mapstructure:"penalty-decay"`
   168  }
   169  
   170  const (
   171  	SkipAtomicValidationKey           = "skip-atomic-validation"
   172  	InvalidMessageDeliveriesWeightKey = "invalid-message-deliveries-weight"
   173  	InvalidMessageDeliveriesDecayKey  = "invalid-message-deliveries-decay"
   174  	TimeInMeshQuantumKey              = "time-in-mesh-quantum"
   175  	TopicWeightKey                    = "topic-weight"
   176  	MeshMessageDeliveriesDecayKey     = "mesh-message-deliveries-decay"
   177  	MeshMessageDeliveriesCapKey       = "mesh-message-deliveries-cap"
   178  	MeshMessageDeliveryThresholdKey   = "mesh-message-deliveries-threshold"
   179  	MeshDeliveriesWeightKey           = "mesh-deliveries-weight"
   180  	MeshMessageDeliveriesWindowKey    = "mesh-message-deliveries-window"
   181  	MeshMessageDeliveryActivationKey  = "mesh-message-delivery-activation"
   182  )
   183  
   184  // TopicScoringParameters score option topic validation configuration parameters.
   185  type TopicScoringParameters struct {
   186  	// SkipAtomicValidation is the  value for the skip atomic validation flag for topics.
   187  	// If set it to true, the gossipsub parameter validation will not fail if we leave some of the
   188  	// topic parameters at their  values, i.e., zero.
   189  	SkipAtomicValidation bool `validate:"required" mapstructure:"skip-atomic-validation"`
   190  	// InvalidMessageDeliveriesWeight this value is applied to the square of the number of invalid message deliveries on a topic.
   191  	// It is used to penalize peers that send invalid messages. By an invalid message, we mean a message that is not signed by the
   192  	// publisher, or a message that is not signed by the peer that sent it.
   193  	InvalidMessageDeliveriesWeight float64 `validate:"lt=0" mapstructure:"invalid-message-deliveries-weight"`
   194  	// InvalidMessageDeliveriesDecay decay factor used to decay the number of invalid message deliveries.
   195  	// The total number of invalid message deliveries is multiplied by this factor at each heartbeat interval to
   196  	// decay the number of invalid message deliveries, and prevent the peer from being disconnected if it stops
   197  	// sending invalid messages.
   198  	InvalidMessageDeliveriesDecay float64 `validate:"gt=0,lt=1" mapstructure:"invalid-message-deliveries-decay"`
   199  	// TimeInMeshQuantum is the  time in mesh quantum for the GossipSub scoring system. It is used to gauge
   200  	// a discrete time interval for the time in mesh counter.
   201  	TimeInMeshQuantum time.Duration `validate:"gte=1h" mapstructure:"time-in-mesh-quantum"`
   202  	// Weight is the  weight of a topic in the GossipSub scoring system.
   203  	// The overall score of a peer in a topic mesh is multiplied by the weight of the topic when calculating the overall score of the peer.
   204  	TopicWeight float64 `validate:"gt=0" mapstructure:"topic-weight"`
   205  	// MeshMessageDeliveriesDecay is applied to the number of actual message deliveries in a topic mesh
   206  	// at each decay interval (i.e., DecayInterval).
   207  	// It is used to decay the number of actual message deliveries, and prevents past message
   208  	// deliveries from affecting the current score of the peer.
   209  	MeshMessageDeliveriesDecay float64 `validate:"gt=0" mapstructure:"mesh-message-deliveries-decay"`
   210  	// MeshMessageDeliveriesCap is the maximum number of actual message deliveries in a topic
   211  	// mesh that is used to calculate the score of a peer in that topic mesh.
   212  	MeshMessageDeliveriesCap float64 `validate:"gt=0" mapstructure:"mesh-message-deliveries-cap"`
   213  	// MeshMessageDeliveryThreshold is the threshold for the number of actual message deliveries in a
   214  	// topic mesh that is used to calculate the score of a peer in that topic mesh.
   215  	// If the number of actual message deliveries in a topic mesh is less than this value,
   216  	// the peer will be penalized by square of the difference between the actual message deliveries and the threshold,
   217  	// i.e., -w * (actual - threshold)^2 where `actual` and `threshold` are the actual message deliveries and the
   218  	// threshold, respectively, and `w` is the weight (i.e., MeshMessageDeliveriesWeight).
   219  	MeshMessageDeliveryThreshold float64 `validate:"gt=0" mapstructure:"mesh-message-deliveries-threshold"`
   220  	// MeshDeliveriesWeight is the weight for applying penalty when a peer is under-performing in a topic mesh.
   221  	// Upon every decay interval, if the number of actual message deliveries is less than the topic mesh message deliveries threshold
   222  	// (i.e., MeshMessageDeliveriesThreshold), the peer will be penalized by square of the difference between the actual
   223  	// message deliveries and the threshold, multiplied by this weight, i.e., -w * (actual - threshold)^2 where w is the weight, and
   224  	// `actual` and `threshold` are the actual message deliveries and the threshold, respectively.
   225  	MeshDeliveriesWeight float64 `validate:"lt=0" mapstructure:"mesh-deliveries-weight"`
   226  	// MeshMessageDeliveriesWindow is the window size is time interval that we count a delivery of an already
   227  	// seen message towards the score of a peer in a topic mesh. The delivery is counted
   228  	// by GossipSub only if the previous sender of the message is different from the current sender.
   229  	MeshMessageDeliveriesWindow time.Duration `validate:"gte=1m" mapstructure:"mesh-message-deliveries-window"`
   230  	// MeshMessageDeliveryActivation is the time interval that we wait for a new peer that joins a topic mesh
   231  	// till start counting the number of actual message deliveries of that peer in that topic mesh.
   232  	MeshMessageDeliveryActivation time.Duration `validate:"gte=2m" mapstructure:"mesh-message-delivery-activation"`
   233  }