-
Notifications
You must be signed in to change notification settings - Fork 511
feat: address and proto books #590
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
a1617e6
8dab477
72dea96
d3e4ad2
eb27b8d
f938535
1662065
7dcc78e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,122 @@ | ||
| # Peerstore | ||
| # PeerStore | ||
|
|
||
| WIP | ||
| Libp2p's PeerStore is responsible for keeping an updated register with the relevant information of the known peers. It should be the single source of truth for all peer data, where a subsystem can learn about peers' data and where someone can listen for updates. The PeerStore comprises four main components: `addressBook`, `keyBook`, `protocolBook` and `metadataBook`. | ||
|
|
||
| The PeerStore manages the high level operations on its inner books. Moreover, the PeerStore should be responsible for notifying interested parties of relevant events, through its Event Emitter. | ||
|
|
||
| ## Data gathering | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can do it in a followup PR but I think we should simplify the data gathering and consumption sections. Reading through this it was hard to figure out where data comes from and who/what/why it's being consumed. I think it would be good to be very direct about what should actually be putting data into the peer store so it's clear, and how someone can get data out of the peer store. IE: Submitting records to the PeerStoreIdentify
... Retrieving records from the PeerStoreProtocols
...
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I totally agree to use that text format. I will PR with that on a followup |
||
|
|
||
| Several libp2p subsystems will perform operations, which will gather relevant information about peers. Some operations might not have this as an end goal, but can also gather important data. | ||
|
|
||
| In a libp2p node's life, it will discover peers through its discovery protocols. In a typical discovery protocol, addresses of the peer are discovered along with its peer id. Once this happens, the PeerStore should collect this information for future (or immediate) usage by other subsystems. When the information is stored, the PeerStore should inform interested parties of the peer discovered (`peer` event). | ||
|
|
||
| Taking into account a different scenario, a peer might perform/receive a dial request to/from a unkwown peer. In such a scenario, the PeerStore must store the peer's multiaddr once a connection is established. | ||
|
|
||
| After a connection is established with a peer, the Identify protocol will run automatically. A stream is created and peers exchange their information (Multiaddrs, running protocols and their public key). Once this information is obtained, it should be added to the PeerStore. In this specific case, as we are speaking to the source of truth, we should ensure the PeerStore is prioritizing these records. If the recorded `multiaddrs` or `protocols` have changed, interested parties must be informed via the `change:multiaddrs` or `change:protocols` events respectively. | ||
|
|
||
| In the background, the Identify Service is also waiting for protocol change notifications of peers via the IdentifyPush protocol. Peers may leverage the `identify-push` message to communicate protocol changes to all connected peers, so that their PeerStore can be updated with the updated protocols. As the `identify-push` also sends complete and updated information, the data in the PeerStore can be replaced. | ||
|
|
||
| (To consider: Should we not replace until we get to multiaddr confidence? we might loose true information as we will talk with older nodes on the network.) | ||
|
|
||
| While it is currently not supported in js-libp2p, future iterations may also support the [IdentifyDelta protocol](https://github.com/libp2p/specs/pull/176). | ||
|
|
||
| It is also possible to gather relevant information for peers from other protocols / subsystems. For instance, in `DHT` operations, nodes can exchange peer data as part of the `DHT` operation. In this case, we can learn additional information about a peer we already know. In this scenario the PeerStore should not replace the existing data it has, just add it. | ||
|
|
||
| ## Data Consumption | ||
|
|
||
| When the PeerStore data is updated, this information might be important for different parties. | ||
|
|
||
| Every time a peer needs to dial another peer, it is essential that it knows the multiaddrs used by the peer, in order to perform a successful dial to it. The same is true for pinging a peer. While the `AddressBook` is going to keep its data updated, it will also emit `change:multiaddrs` events so that subsystems/users interested in knowing these changes can be notifyied instead of pooling the `AddressBook`. | ||
vasco-santos marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Everytime a peer starts/stops supporting a protocol, libp2p subsystems or users might need to act accordingly. `js-libp2p` registrar orchestrates known peers, established connections and protocol topologies. This way, once a protocol is supported for a peer, the topology of that protocol should be informed that a new peer may be used and the subsystem can decide if it should open a new stream with that peer or not. For these situations, the `ProtoBook` will emit `change:protocols` events whenever supported protocols of a peer change. | ||
|
|
||
| ## PeerStore implementation | ||
|
|
||
| The PeerStore wraps four main components: `addressBook`, `keyBook`, `protocolBook` and `metadataBook`. Moreover, it provides a high level API for those components, as well as data events. | ||
|
|
||
| ### API | ||
vasco-santos marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| For the complete API documentation, you should check the [API.md](../../doc/API.md). | ||
|
|
||
| Access to its underlying books: | ||
|
|
||
| - `peerStore.protoBook.*` | ||
| - `peerStore.addressBook.*` | ||
|
|
||
| High level operations: | ||
|
|
||
| - [`peerStore.delete(peerId)`](../../doc/API.md#peerstoredelete) | ||
|
|
||
| Deletes the provided peer from every book. | ||
|
|
||
| - [`peerStore.get(peerId)`](../../doc/API.md#peerstoreget) | ||
|
|
||
| Gets the stored information of a given peer. | ||
|
|
||
| - [`peerStore.peers()`](../../doc/API.md#peerstorepeers) | ||
|
|
||
| Gets an array of all the peers, as well as their information. | ||
|
|
||
| ### Events | ||
|
|
||
| - `peer` - emitted when a new peer is added. | ||
| - `change:multiaadrs` - emitted when a known peer has a different set of multiaddrs. | ||
| - `change:protocols` - emitted when a known peer supports a different set of protocols. | ||
|
|
||
| ### Components API | ||
|
|
||
| #### Address Book | ||
|
|
||
| The `addressBook` keeps the known multiaddrs of a peer. The multiaddrs of each peer may change over time and the Address Book must account for this. | ||
|
|
||
| `Map<string, multiaddrInfo>` | ||
|
|
||
| A `peerId.toString()` identifier mapping to a `multiaddrInfo` object, which should have the following structure: | ||
|
|
||
| ```js | ||
| { | ||
| multiaddr: , | ||
| } | ||
| ``` | ||
|
|
||
| **Note:** except for multiaddr naming, the other properties are placeholders for now and might not be as described in the future milestones. | ||
|
|
||
| - `addressBook.data` | ||
| - [`addressBook.add()`](../../doc/API.md#peerstoreaddressbookadd) | ||
| - [`addressBook.delete()`](../../doc/API.md#peerstoreaddressbookdelete) | ||
| - [`addressBook.get()`](../../doc/API.md#peerstoreaddressbookget) | ||
| - [`addressBook.getMultiaddrsForPeer()`](../../doc/API.md#peerstoreaddressbookgetmultiaddrsforpeer) | ||
| - [`addressBook.set()`](../../doc/API.md#peerstoreaddressbookset) | ||
|
|
||
| (Future considerations: Further API methods will probably be added in the context of multiaddr validity and multiaddr confidence.) | ||
|
|
||
| **Not Yet Implemented**: Multiaddr Confidence | ||
|
|
||
| #### Key Book | ||
|
|
||
| The `keyBook` tracks the keys of the peers. | ||
|
|
||
| **Not Yet Implemented** | ||
|
|
||
| #### Protocol Book | ||
|
|
||
| The `protoBook` holds the identifiers of the protocols supported by each peer. The protocols supported by each peer are dynamic and will change over time. | ||
|
|
||
| `Map<string, Set<string>>` | ||
|
|
||
| A `peerId.toString()` identifier mapping to a `Set` of protocol identifier strings. | ||
|
|
||
| - `protoBook.data` | ||
| - [`protoBook.add()`](../../doc/API.md#peerstoreprotobookadd) | ||
| - [`protoBook.delete()`](../../doc/API.md#peerstoreprotobookdelete) | ||
| - [`protoBook.get()`](../../doc/API.md#peerstoreprotobookget) | ||
| - [`protoBook.set()`](../../doc/API.md#peerstoreprotobookset) | ||
|
|
||
| #### Metadata Book | ||
|
|
||
| **Not Yet Implemented** | ||
|
|
||
| ## Future Considerations | ||
|
|
||
| - If multiaddr TTLs are added, the PeerStore may schedule jobs to delete all addresses that exceed the TTL to prevent AddressBook bloating | ||
| - Further API methods will probably need to be added in the context of multiaddr validity and confidence. | ||
Uh oh!
There was an error while loading. Please reload this page.