2018-04-10 06:44:09 +00:00
|
|
|
package peers
|
|
|
|
|
|
|
|
import (
|
2020-01-02 09:10:19 +00:00
|
|
|
"github.com/syndtr/goleveldb/leveldb"
|
|
|
|
"github.com/syndtr/goleveldb/leveldb/util"
|
|
|
|
|
2018-04-10 06:44:09 +00:00
|
|
|
"github.com/ethereum/go-ethereum/log"
|
|
|
|
"github.com/ethereum/go-ethereum/p2p/discv5"
|
2018-11-14 07:03:58 +00:00
|
|
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
2020-01-02 09:10:19 +00:00
|
|
|
|
2018-06-08 11:29:50 +00:00
|
|
|
"github.com/status-im/status-go/db"
|
2018-04-10 06:44:09 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// NewCache returns instance of PeersDatabase
|
|
|
|
func NewCache(db *leveldb.DB) *Cache {
|
|
|
|
return &Cache{db: db}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Cache maintains list of peers that were discovered.
|
|
|
|
type Cache struct {
|
|
|
|
db *leveldb.DB
|
|
|
|
}
|
|
|
|
|
2018-11-14 07:03:58 +00:00
|
|
|
func makePeerKey(peerID enode.ID, topic discv5.Topic) []byte {
|
|
|
|
return db.Key(db.PeersCache, []byte(topic), peerID.Bytes())
|
2018-04-10 06:44:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// AddPeer stores peer with a following key: <topic><peer ID>
|
|
|
|
func (d *Cache) AddPeer(peer *discv5.Node, topic discv5.Topic) error {
|
|
|
|
data, err := peer.MarshalText()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-11-14 07:03:58 +00:00
|
|
|
pk, err := peer.ID.Pubkey()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return d.db.Put(makePeerKey(enode.PubkeyToIDV4(pk), topic), data, nil)
|
2018-04-10 06:44:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// RemovePeer deletes a peer from database.
|
2018-11-14 07:03:58 +00:00
|
|
|
func (d *Cache) RemovePeer(nodeID enode.ID, topic discv5.Topic) error {
|
|
|
|
return d.db.Delete(makePeerKey(nodeID, topic), nil)
|
2018-04-10 06:44:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetPeersRange returns peers for a given topic with a limit.
|
|
|
|
func (d *Cache) GetPeersRange(topic discv5.Topic, limit int) (nodes []*discv5.Node) {
|
2018-04-20 11:26:54 +00:00
|
|
|
key := db.Key(db.PeersCache, []byte(topic))
|
2018-07-11 06:49:41 +00:00
|
|
|
// it is important to set Limit on the range passed to iterator, so that
|
|
|
|
// we limit reads only to particular topic.
|
|
|
|
iterator := d.db.NewIterator(util.BytesPrefix(key), nil)
|
2018-04-10 06:44:09 +00:00
|
|
|
defer iterator.Release()
|
|
|
|
count := 0
|
|
|
|
for iterator.Next() && count < limit {
|
|
|
|
node := discv5.Node{}
|
|
|
|
value := iterator.Value()
|
|
|
|
if err := node.UnmarshalText(value); err != nil {
|
|
|
|
log.Error("can't unmarshal node", "value", value, "error", err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
nodes = append(nodes, &node)
|
|
|
|
count++
|
|
|
|
}
|
|
|
|
return nodes
|
|
|
|
}
|