github.com/ethereum-optimism/optimism@v1.7.2/op-node/p2p/store/scorebook.go (about) 1 package store 2 3 import ( 4 "context" 5 "sync/atomic" 6 "time" 7 8 "github.com/ethereum-optimism/optimism/op-service/clock" 9 "github.com/ethereum/go-ethereum/log" 10 ds "github.com/ipfs/go-datastore" 11 "github.com/libp2p/go-libp2p/core/peer" 12 "github.com/multiformats/go-base32" 13 ) 14 15 const ( 16 scoreCacheSize = 100 17 ) 18 19 var scoresBase = ds.NewKey("/peers/scores") 20 21 // LastUpdate requires atomic update operations. Use the helper functions SetLastUpdated and LastUpdated to modify and access this field. 22 type scoreRecord struct { 23 LastUpdate int64 `json:"lastUpdate"` // unix timestamp in seconds 24 PeerScores PeerScores `json:"peerScores"` 25 } 26 27 func (s *scoreRecord) SetLastUpdated(t time.Time) { 28 atomic.StoreInt64(&s.LastUpdate, t.Unix()) 29 } 30 31 func (s *scoreRecord) LastUpdated() time.Time { 32 return time.Unix(atomic.LoadInt64(&s.LastUpdate), 0) 33 } 34 35 func (s *scoreRecord) MarshalBinary() (data []byte, err error) { 36 return serializeScoresV0(*s) 37 } 38 39 func (s *scoreRecord) UnmarshalBinary(data []byte) error { 40 r, err := deserializeScoresV0(data) 41 if err != nil { 42 return err 43 } 44 *s = r 45 return nil 46 } 47 48 type scoreBook struct { 49 book *recordsBook[peer.ID, *scoreRecord] 50 } 51 52 func newScoreRecord() *scoreRecord { 53 return new(scoreRecord) 54 } 55 56 func peerIDKey(id peer.ID) ds.Key { 57 return ds.NewKey(base32.RawStdEncoding.EncodeToString([]byte(id))) 58 } 59 60 func newScoreBook(ctx context.Context, logger log.Logger, clock clock.Clock, store ds.Batching, retain time.Duration) (*scoreBook, error) { 61 book, err := newRecordsBook[peer.ID, *scoreRecord](ctx, logger, clock, store, scoreCacheSize, retain, scoresBase, newScoreRecord, peerIDKey) 62 if err != nil { 63 return nil, err 64 } 65 return &scoreBook{book: book}, nil 66 } 67 68 func (d *scoreBook) startGC() { 69 d.book.startGC() 70 } 71 72 func (d *scoreBook) GetPeerScores(id peer.ID) (PeerScores, error) { 73 record, err := d.book.getRecord(id) 74 if err == UnknownRecordErr { 75 return PeerScores{}, nil // return zeroed scores by default 76 } 77 if err != nil { 78 return PeerScores{}, err 79 } 80 return record.PeerScores, nil 81 } 82 83 func (d *scoreBook) GetPeerScore(id peer.ID) (float64, error) { 84 scores, err := d.GetPeerScores(id) 85 if err != nil { 86 return 0, err 87 } 88 return scores.Gossip.Total, nil 89 } 90 91 func (d *scoreBook) SetScore(id peer.ID, diff ScoreDiff) (PeerScores, error) { 92 v, err := d.book.SetRecord(id, diff) 93 return v.PeerScores, err 94 } 95 96 func (d *scoreBook) Close() { 97 d.book.Close() 98 }