github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/network/p2p/scoring/internal/appSpecificScoreCache.go (about) 1 package internal 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/libp2p/go-libp2p/core/peer" 8 "github.com/rs/zerolog" 9 10 "github.com/onflow/flow-go/model/flow" 11 "github.com/onflow/flow-go/module" 12 herocache "github.com/onflow/flow-go/module/mempool/herocache/backdata" 13 "github.com/onflow/flow-go/module/mempool/herocache/backdata/heropool" 14 "github.com/onflow/flow-go/module/mempool/stdmap" 15 "github.com/onflow/flow-go/network/p2p" 16 ) 17 18 // AppSpecificScoreCache is a cache that stores the application specific score of peers. 19 // The application specific score of a peer is used to calculate the GossipSub score of the peer. 20 // Note that the application specific score and the GossipSub score are solely used by the current peer to select the peers 21 // to which it will connect on a topic mesh. 22 type AppSpecificScoreCache struct { 23 c *stdmap.Backend 24 } 25 26 var _ p2p.GossipSubApplicationSpecificScoreCache = (*AppSpecificScoreCache)(nil) 27 28 // NewAppSpecificScoreCache creates a new application specific score cache with the given size limit. 29 // The cache has an LRU eviction policy. 30 // Args: 31 // - sizeLimit: the size limit of the cache. 32 // - logger: the logger to use for logging. 33 // - collector: the metrics collector to use for collecting metrics. 34 // Returns: 35 // - *AppSpecificScoreCache: the created cache. 36 func NewAppSpecificScoreCache(sizeLimit uint32, logger zerolog.Logger, collector module.HeroCacheMetrics) *AppSpecificScoreCache { 37 backData := herocache.NewCache(sizeLimit, 38 herocache.DefaultOversizeFactor, 39 heropool.LRUEjection, 40 logger.With().Str("mempool", "gossipsub-app-specific-score-cache").Logger(), 41 collector) 42 43 return &AppSpecificScoreCache{ 44 c: stdmap.NewBackend(stdmap.WithBackData(backData)), 45 } 46 } 47 48 // Get returns the application specific score of a peer from the cache. 49 // Args: 50 // - peerID: the peer ID of the peer in the GossipSub protocol. 51 // Returns: 52 // - float64: the application specific score of the peer. 53 // - time.Time: the time at which the score was last updated. 54 // - bool: true if the score was retrieved successfully, false otherwise. 55 func (a *AppSpecificScoreCache) Get(peerID peer.ID) (float64, time.Time, bool) { 56 e, ok := a.c.ByID(entityIdOf(peerID)) 57 if !ok { 58 return 0, time.Time{}, false 59 } 60 return e.(appSpecificScoreRecordEntity).Score, e.(appSpecificScoreRecordEntity).LastUpdated, true 61 } 62 63 // AdjustWithInit adds the application specific score of a peer to the cache. 64 // If the peer already has a score in the cache, the score is updated. 65 // Args: 66 // - peerID: the peer ID of the peer in the GossipSub protocol. 67 // - score: the application specific score of the peer. 68 // - time: the time at which the score was last updated. 69 // Returns: 70 // - error on failure to add the score. The returned error is irrecoverable and indicates an exception. 71 func (a *AppSpecificScoreCache) AdjustWithInit(peerID peer.ID, score float64, time time.Time) error { 72 entityId := entityIdOf(peerID) 73 74 initLogic := func() flow.Entity { 75 return appSpecificScoreRecordEntity{ 76 entityId: entityId, 77 PeerID: peerID, 78 Score: score, 79 LastUpdated: time, 80 } 81 } 82 adjustLogic := func(entity flow.Entity) flow.Entity { 83 r := entity.(appSpecificScoreRecordEntity) 84 r.Score = score 85 r.LastUpdated = time 86 return r 87 } 88 _, adjusted := a.c.AdjustWithInit(entityId, adjustLogic, initLogic) 89 if !adjusted { 90 return fmt.Errorf("failed to adjust app specific score for peer %s", peerID) 91 } 92 93 return nil 94 }