Description
As part of the PeerStore improvements epic, we intend to deprecate peer-info
and consolidate all peer's information on the PeerStore.
Background
On [email protected]
we introduced the PeerStore on the js-libp2p
codebase replacing the peer-book
module. The PeerStore is responsible for managing known peers, as well as their addresses and metadata.
The initial version of this PeerStore is similar to the previous peer-book
. It maps peer identifier strings to their peer-info
object and has the common operations of a store, such as put
, get
, has
, remove
and replace
.
Problem
Taking into account that peers' information might vary as the time passes and network operations are performed, we introduced two events in the initial version of the PeerStore: change:protocols
and change:multiaddrs
, but some other should be added in the future.
Since we currently rely on a PeerInfo instance stored in the PeerStore and a PeerInfo instance, we are prone to some data inconsistencies. For example, if a peer discovery protocol discovers a peer, it will create a PeerInfo with that peer and its discovered multiaddr and add it to the PeerStore. In the case that we already know the peer (other multiaddr or not, and possibly some protocols), we currently need to destruct the old information and merge it to the new one. This also creates complexity on finding the changes in multiaddr
/ protocols
/ ...
Therefore, peer-info
adds an extra layer of complexity without benefits, both in the PeerStore
store and on moving data around libp2p
subsystems. In addition, it is better to move around only the needed data, instead of creating unnecessary instances.
PeerInfo usage
Module | Details | PR |
---|---|---|
libp2p |
.create() |
libp2p/js-libp2p#610 |
ipfs |
used to access id, or to access data from PeerStore |
TODO |
libp2p-kad-dht |
peer-discovery / dht.findPeer /dht.findProvs return PeerInfo |
libp2p/js-libp2p-kad-dht#180 /libp2p/js-libp2p-kad-dht#181 |
libp2p-bootstrap |
interface-peer-discovery |
js-libp2p-bootstrap#103 |
libp2p-mdns |
interface-peer-discovery |
libp2p/js-libp2p-mdns#90 |
libp2p-webrtc-star |
interface-peer-discovery |
libp2p/js-libp2p-webrtc-star#213 |
libp2p-pubsub-discovery |
interface-peer-discovery |
libp2p/js-libp2p-pubsub-peer-discovery#5 |
discv5 | interface-peer-discovery |
ChainSafe/discv5#51 |
libp2p-gossipsub |
usage for getting id, protocols for fallback to floodsub | ChainSafe/gossipsub-js#70 |
libp2p-floodsub |
usage for getting id | libp2p/js-libp2p-floodsub#102 |
libp2p-pubsub |
usage for getting id, protocol is added to info, but can move to internal peer abstraction | libp2p/js-libp2p-pubsub#41 |
libp2p-delegated-content-routing |
.findProvs |
libp2p/js-libp2p-delegated-content-routing#34 |
libp2p-delegated-peer-routing |
.findPeer |
libp2p/js-libp2p-delegated-peer-routing#25 |
libp2p-interfaces |
peer-discovery / topology / content-routing and peer-routing |
libp2p/js-libp2p-interfaces#41 /libp2p/js-libp2p-interfaces#42 / libp2p/js-libp2p-interfaces#43 |
libp2p-daemon-client |
dht api | libp2p/js-libp2p-daemon-client#25 |
libp2p-daemon |
some logic achievable via libp2p.* |
libp2p/js-libp2p-daemon#38 |
Solution design
While most usages of PeerInfo
are easily removed, some will need to break APIs or to receive more parameters to be able to work without the PeerInfo
.
interface-peer-discovery
Currently, the peer discovery protocols emit a peer
event with the peerInfo
as follows discovery.on('peer', (peerInfo) => {}). We currently rely on peerInfo
because we need both the peerId
and the discovered multiaddr
.
We have 2 possible solutions for this:
-
We can emit an event with an object as follows:
discovery.emit('peer', { peerId, []multiaddrs })
, while theinterface
should validate that both properties are provided. -
We can provide the
peerStore
topeer-discovery
protocols and they would interact with it directly.
Since peerStore
will be divided into different components (AddressBook, KeyBook, ProtoBook , peerMetadataStore?), I think that js-libp2p
should be responsible for handling the events and update what it needs, instead of delegating the responsibility for other subsystems (consequently less logic and needed code changes)
To consider: future discovery mechanisms, like peer-exchange
might also provide known protocols?
interface-topology
A libp2p toplogy has a peers map, which maps peer identifiers to their peerInfo. They rely on the peerInfo
for checking the protocols they support.
We can simplify the Topology by having an array of peers important for the topology and provide access to the PeerStore
data so that the topology can identify the current known protocols of a peer.
pubsub internal peer
We currently have an internal peer instance on pubsub. We rely on this instance for managing the stream with peers, subscribed topics and other relevant information. This peer
also has an info
propery with the PeerInfo
of the peer. This is only used for checking the protocols available (particularly useful for fallback to floodsub on gossipsub)!
In this situation, we can just have a property for protocols
on the internal peer instance and rely on the peerId
instead. We have access for it on the incomingStream
function.
content-routing / peer-routing APIs
We should uniform this like the ipfs
api and get rid of peer-info
. This is a similar approach to the interface-peer-discovery
solution proposed.
libp2p
libp2p.create()
accepts a previously createdPeerInfo
.
This is particularly useful for listening on a previously specified set of multiaddr
. This should be part of the discussion around improving config, or js-libp2p
will need to improve its API around transport management
libp2p.contentRouting
,libp2p.peerRouting
Should be the same as above
- Events
Should use peer-id
instead of peer-info
and the users can gather the same information from the exposed peerStore
.
Review order
- libp2p-interfaces PRs
peer-discovery
PRspubsub
PRscontent-routing
andpeer-routing
PRs