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

     1  package p2p
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/libp2p/go-libp2p/core/peer"
     7  	"github.com/libp2p/go-libp2p/core/protocol"
     8  )
     9  
    10  // ProtocolPeerCache is an interface that stores a mapping from protocol ID to peers who support that protocol.
    11  type ProtocolPeerCache interface {
    12  	// RemovePeer removes the specified peer from the protocol cache.
    13  	RemovePeer(peerID peer.ID)
    14  
    15  	// AddProtocols adds the specified protocols for the given peer to the protocol cache.
    16  	AddProtocols(peerID peer.ID, protocols []protocol.ID)
    17  
    18  	// RemoveProtocols removes the specified protocols for the given peer from the protocol cache.
    19  	RemoveProtocols(peerID peer.ID, protocols []protocol.ID)
    20  
    21  	// GetPeers returns a copy of the set of peers that support the given protocol.
    22  	GetPeers(pid protocol.ID) map[peer.ID]struct{}
    23  }
    24  
    25  // UpdateFunction is a function that adjusts the GossipSub spam record of a peer.
    26  // Args:
    27  // - record: the GossipSubSpamRecord of the peer.
    28  // Returns:
    29  // - *GossipSubSpamRecord: the adjusted GossipSubSpamRecord of the peer.
    30  type UpdateFunction func(record GossipSubSpamRecord) GossipSubSpamRecord
    31  
    32  // GossipSubSpamRecordCache is a cache for storing the GossipSub spam records of peers.
    33  // The spam records of peers is used to calculate the application specific score, which is part of the GossipSub score of a peer.
    34  // Note that none of the spam records, application specific score, and GossipSub score are shared publicly with other peers.
    35  // Rather they are solely used by the current peer to select the peers to which it will connect on a topic mesh.
    36  //
    37  // Implementation must be thread-safe.
    38  type GossipSubSpamRecordCache interface {
    39  	// Get returns the GossipSubSpamRecord of a peer from the cache.
    40  	// Args:
    41  	// - peerID: the peer ID of the peer in the GossipSub protocol.
    42  	// Returns:
    43  	// - *GossipSubSpamRecord: the GossipSubSpamRecord of the peer.
    44  	// - error on failure to retrieve the record. The returned error is irrecoverable and indicates an exception.
    45  	// - bool: true if the record was retrieved successfully, false otherwise.
    46  	Get(peerID peer.ID) (*GossipSubSpamRecord, error, bool)
    47  
    48  	// Adjust updates the GossipSub spam penalty of a peer in the cache. If the peer does not have a record in the cache, a new record is created.
    49  	// The order of the pre-processing functions is the same as the order in which they were added to the cache.
    50  	// Args:
    51  	// - peerID: the peer ID of the peer in the GossipSub protocol.
    52  	// - updateFn: the update function to be applied to the record.
    53  	// Returns:
    54  	// - *GossipSubSpamRecord: the updated record.
    55  	// - error on failure to update the record. The returned error is irrecoverable and indicates an exception.
    56  	// Note that if any of the pre-processing functions returns an error, the record is reverted to its original state (prior to applying the update function).
    57  	Adjust(peerID peer.ID, updateFunc UpdateFunction) (*GossipSubSpamRecord, error)
    58  
    59  	// Has returns true if the cache contains the GossipSubSpamRecord of the given peer.
    60  	// Args:
    61  	// - peerID: the peer ID of the peer in the GossipSub protocol.
    62  	// Returns:
    63  	// - bool: true if the cache contains the GossipSubSpamRecord of the given peer, false otherwise.
    64  	Has(peerID peer.ID) bool
    65  }
    66  
    67  // GossipSubApplicationSpecificScoreCache is a cache for storing the application specific score of peers.
    68  // The application specific score of a peer is used to calculate the GossipSub score of the peer; it contains the spam penalty of the peer, staking score, and subscription penalty.
    69  // Note that none of the application specific scores, spam penalties, staking scores, and subscription penalties are shared publicly with other peers.
    70  // Rather they are solely used by the current peer to select the peers to which it will connect on a topic mesh.
    71  // The cache is expected to have an eject policy to remove the least recently used record when the cache is full.
    72  // Implementation must be thread-safe, but can be blocking.
    73  type GossipSubApplicationSpecificScoreCache interface {
    74  	// Get returns the application specific score of a peer from the cache.
    75  	// Args:
    76  	// - peerID: the peer ID of the peer in the GossipSub protocol.
    77  	// Returns:
    78  	// - float64: the application specific score of the peer.
    79  	// - time.Time: the time at which the score was last updated.
    80  	// - bool: true if the score was retrieved successfully, false otherwise.
    81  	Get(peerID peer.ID) (float64, time.Time, bool)
    82  
    83  	// AdjustWithInit  adds the application specific score of a peer to the cache.
    84  	// If the peer already has a score in the cache, the score is updated.
    85  	// Args:
    86  	// - peerID: the peer ID of the peer in the GossipSub protocol.
    87  	// - score: the application specific score of the peer.
    88  	// - time: the time at which the score was last updated.
    89  	// Returns:
    90  	// - error on failure to add the score. The returned error is irrecoverable and indicates an exception.
    91  	AdjustWithInit(peerID peer.ID, score float64, time time.Time) error
    92  }
    93  
    94  // GossipSubSpamRecord represents spam record of a peer in the GossipSub protocol.
    95  // It acts as a penalty card for a peer in the GossipSub protocol that keeps the
    96  // spam penalty of the peer as well as its decay factor.
    97  // GossipSubSpam record is used to calculate the application specific score of a peer in the GossipSub protocol.
    98  type GossipSubSpamRecord struct {
    99  	// Decay factor of gossipsub spam penalty.
   100  	// The Penalty is multiplied by the Decay factor every time the Penalty is updated.
   101  	// This is to prevent the Penalty from being stuck at a negative value.
   102  	// Each peer has its own Decay factor based on its behavior.
   103  	// Valid decay value is in the range [0, 1].
   104  	Decay float64
   105  	// Penalty is the application specific Penalty of the peer.
   106  	Penalty float64
   107  	// LastDecayAdjustment records the time of the most recent adjustment in the decay process for a spam record.
   108  	// At each interval, the system evaluates and potentially adjusts the decay rate, which affects how quickly a node's penalty diminishes.
   109  	// The decay process is multiplicative (newPenalty = decayRate * oldPenalty) and operates within a range of 0 to 1. At certain regular intervals, the decay adjustment is evaluated and if the node's penalty falls below the set threshold, the decay rate is modified by the reduction factor, such as 0.01. This modification incrementally increases the decay rate. For example, if the decay rate is `x`, adding the reduction factor results in a decay rate of `x + 0.01`, leading to a slower reduction in penalty. Thus, a higher decay rate actually slows down the recovery process, contrary to accelerating it.
   110  	// The LastDecayAdjustment timestamp is crucial in ensuring balanced and fair penalization, especially important during periods of high message traffic to prevent unintended rapid decay of penalties for malicious nodes.
   111  	LastDecayAdjustment time.Time
   112  }