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  }