github.com/status-im/status-go@v1.1.0/peers/cache.go (about) 1 package peers 2 3 import ( 4 "github.com/syndtr/goleveldb/leveldb" 5 "github.com/syndtr/goleveldb/leveldb/util" 6 7 "github.com/ethereum/go-ethereum/log" 8 "github.com/ethereum/go-ethereum/p2p/discv5" 9 "github.com/ethereum/go-ethereum/p2p/enode" 10 11 "github.com/status-im/status-go/db" 12 ) 13 14 // NewCache returns instance of PeersDatabase 15 func NewCache(db *leveldb.DB) *Cache { 16 return &Cache{db: db} 17 } 18 19 // Cache maintains list of peers that were discovered. 20 type Cache struct { 21 db *leveldb.DB 22 } 23 24 func makePeerKey(peerID enode.ID, topic discv5.Topic) []byte { 25 return db.Key(db.PeersCache, []byte(topic), peerID.Bytes()) 26 } 27 28 // AddPeer stores peer with a following key: <topic><peer ID> 29 func (d *Cache) AddPeer(peer *discv5.Node, topic discv5.Topic) error { 30 data, err := peer.MarshalText() 31 if err != nil { 32 return err 33 } 34 pk, err := peer.ID.Pubkey() 35 if err != nil { 36 return err 37 } 38 return d.db.Put(makePeerKey(enode.PubkeyToIDV4(pk), topic), data, nil) 39 } 40 41 // RemovePeer deletes a peer from database. 42 func (d *Cache) RemovePeer(nodeID enode.ID, topic discv5.Topic) error { 43 return d.db.Delete(makePeerKey(nodeID, topic), nil) 44 } 45 46 // GetPeersRange returns peers for a given topic with a limit. 47 func (d *Cache) GetPeersRange(topic discv5.Topic, limit int) (nodes []*discv5.Node) { 48 key := db.Key(db.PeersCache, []byte(topic)) 49 // it is important to set Limit on the range passed to iterator, so that 50 // we limit reads only to particular topic. 51 iterator := d.db.NewIterator(util.BytesPrefix(key), nil) 52 defer iterator.Release() 53 count := 0 54 for iterator.Next() && count < limit { 55 node := discv5.Node{} 56 value := iterator.Value() 57 if err := node.UnmarshalText(value); err != nil { 58 log.Error("can't unmarshal node", "value", value, "error", err) 59 continue 60 } 61 nodes = append(nodes, &node) 62 count++ 63 } 64 return nodes 65 }