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