-
Notifications
You must be signed in to change notification settings - Fork 446
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
feat: signed peer records data types #681
Conversation
@jacobheun can I have an initial feedback on this implementation design? Once we are aligned, I plan to:
Follow up draft PRs for refactoring the Identify Protocol and CertifiedAddressBook for initial feedback should land during the next couple of days EDIT: #682 was created so that you can see how the records / envelopes will be created and consumed in identify. Go to the second commit of the PR, as the first one is this PR |
7f819eb
to
7c29e72
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR is for the support of Peer Routing Records. With that in mind I'd like to clarify the flow, the API specifically, of how these records are created and fetched, as this isn't very clear.
Right now it looks like the Record Manager is intended to be run like other services, but I don't think that's necessary. While addresses are not currently dynamic, I think we should make it so this system allows for easily invalidating the cached envelope, ideally we should update the cache on change, instead of doing lazy loading as this can adversely affect response times. It would be helpful to document the API for some of these known use cases to provide clarity to the design here.
- When we get a new address, how do we create a new routing record for
self
? (Assume we have AutoRelay/AutoNAT in place and we are able to determine addresses dynamically, how does this get updated from those subystems?) - How do subsystems (identify, dht, pubsub) get our current routing record?
- How do subsystems store routing records for other peers?
- How do subsystems get routing records for other peers?
// signature is the signature produced by the private key corresponding to | ||
// the enclosed public key, over the payload, prefixing a domain string for | ||
// additional security. | ||
bytes signature = 5; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This matches Go but not the spec, should be 4 https://github.com/libp2p/specs/pull/217/files#diff-1d3e44bb1e34e0581019f35b96151a0dR70.
Created an issue in Go libp2p/go-libp2p-core#160
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we already change it, or wait for go?
const protons = require('protons') | ||
|
||
const message = ` | ||
message Envelope { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Go calls this an Envelope
, but in the spec it's SignedEnvelope
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe also report in the spec? I think the SignedEnvelope
naming is redundant, as the Envelope purpose is to have the signature
src/record-manager/envelope/index.js
Outdated
* @param {PeerId} peerId | ||
* @return {Envelope} | ||
*/ | ||
exports.seal = async (record, peerId) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extend Envelope
instead of exports
. I recall issues in the past with exporting more than 1 thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are currently doing the same in the peer-id
. Anyway, I like that we move this like you suggest and also in the Record, as in the record we could also add it to the interface validations (createFromProtobuf
)
Yes, this is an important thing to discuss. I created #682 so that you could see it in practise. While the const Envelope = require('libp2p/src/...')
const PeerRecord = require('libp2p/src/...') or libp2p can provide some API methods to access them without going this way. For now, the open PRs are going on the first solution, but I personally don't like it.
There is lazy loading for the records and envelope so that when users do in different occasions Regarding its usability, I expect the following: Create self peer recordOnce the listen addresses are known, it should create a PeerRecord instance, and use Send own peer recordGet a cached signed peer record though Receive peer recordA protocol receives the envelope from the wire protocol and it should use Send other party peer recordGet it from the AddressBook |
Me and @jacobheun synced yesterday and we will do as follows:
-- Since we do not need the RecordManager anymore, at least until having more records in libp2p, the scope of this PR will change to have the implementations of the Envelope and Peer Record. #682 will create self and exchange it in the Identify Protocol. Follow up PR will handle the peer records storage in the PeerStore. |
src/record/README.md
Outdated
|
||
### Usage | ||
|
||
- create an envelope with an instance of an `interface-record` implementation and prepare it for being exchanged: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: link interface-record
once merged
// signature is the signature produced by the private key corresponding to | ||
// the enclosed public key, over the payload, prefixing a domain string for | ||
// additional security. | ||
bytes signature = 5; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we already change it, or wait for go?
9a96512
to
44eb3be
Compare
a947283
to
4792ebb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall this looks good, just some minor changes
doc/API.md
Outdated
| [options.peerId] | [`PeerId`][peer-id] | peerId instance (it will be created if not provided) | | ||
| [options.peerStore] | [`object`](./CONFIGURATION.md#configuring-peerstore) | libp2p PeerStore configuration | | ||
| [options.peerStore] | [`object`](./CONFIGURATION.md#configuring-peerstore) | libp2p PeerStore [configuration]((./CONFIGURATION.md#configuring-peerstore)) | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Several of these added links are broken due to double ()
's.
doc/CONFIGURATION.md
Outdated
@@ -52,7 +52,7 @@ The libp2p ecosystem contains at least one module for each of these subsystems. | |||
|
|||
After selecting the modules to use, it is also possible to configure each one according to your needs. | |||
|
|||
Bear in mind that only a **transport** and **connection encryption** are required, while all the other subsystems are optional. | |||
Bear in mind that a **transport** and **connection encryption** are **required**, while all the other subsystems are optional. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bear in mind that a **transport** and **connection encryption** are **required**, while all the other subsystems are optional. | |
Bear in mind that a **transport** and **connection encryption** module are **required**, while all the other subsystems are optional. |
src/record/README.md
Outdated
```js | ||
const Envelope = require('libp2p/src/record/envelop') | ||
|
||
// ... create a record named rec with domain X |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This description isn't clear to me. I don't see domain X listed in this snippet.
src/record/README.md
Outdated
|
||
```js | ||
const Envelope = require('libp2p/src/record/envelop') | ||
// const Record = ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO?
src/record/README.md
Outdated
const Envelope = require('libp2p/src/record/envelop') | ||
// const Record = ... | ||
|
||
// ... receive envelope data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify this. Maybe create a utility function that takes an envelope and a domain and returns a record?
src/record/peer-record/index.js
Outdated
const arraysAreEqual = (a, b) => a.length === b.length && a.sort().every((item, index) => b[index].equals(item)) | ||
|
||
/** | ||
* The PeerRecord is responsible for TODOTODOTRDO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably don't need to define responsibility here. What it is would be helpful though.
src/record/peer-record/index.js
Outdated
* @constructor | ||
* @param {object} params | ||
* @param {PeerId} params.peerId | ||
* @param {Array<multiaddr>} params.multiaddrs public addresses of the peer this record pertains to. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are not necessarily public. LAN peers could use this with local addresses.
* @param {Array<multiaddr>} params.multiaddrs public addresses of the peer this record pertains to. | |
* @param {Array<multiaddr>} params.multiaddrs addresses of the associated peer |
src/record/peer-record/index.js
Outdated
* @param {Record} other | ||
* @return {boolean} | ||
*/ | ||
isEqual (other) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change to equals
src/record/peer-record/index.js
Outdated
} | ||
|
||
/** | ||
* Verifies if the other PeerRecord is identical to this one. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Verifies if the other PeerRecord is identical to this one. | |
* Returns true if `this` record equals the `other` |
src/record/peer-record/index.js
Outdated
} | ||
|
||
// Validate multiaddrs | ||
if (this.multiaddrs.length !== other.multiaddrs.length || !arraysAreEqual(this.multiaddrs, other.multiaddrs)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The utility function already checks length.
if (this.multiaddrs.length !== other.multiaddrs.length || !arraysAreEqual(this.multiaddrs, other.multiaddrs)) { | |
if (!arraysAreEqual(this.multiaddrs, other.multiaddrs)) { |
Co-authored-by: Jacob Heun <jacobheun@gmail.com>
8859d23
to
b4fa13a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, one minor language change. Feel free to merge (probably rebase and merge as other PRs are using this).
Co-authored-by: Jacob Heun <jacobheun@gmail.com>
This PR adds the Libp2p Envelope and Peer Record data type for #653 .
Needs:
Solution design
A
Record
interface was created libp2p/js-libp2p-interfaces#52 was the base for anyRecord
compatible with a Libp2pEnvelope
. Arecord
implementation should run the interface tests to guarantee its compatibility with the Envelope.A Libp2p
Envelope
will be a container for a record implementing theRecord
interface. It will include the record marshalled data as apayload
property, as well as a signature and a payloadType for easing the decoding in the future, when we have multiple records differently serialised.A
PeerRecord
was created implementing theRecord
interface. This record will be using for many libp2p protocols that exchange peers' listen multiaddrs, such asIdentify
,Gossipsub1.1
,DHT
,Rendezvous
, etc. The protocols should support the legacy protocol for the time being.What is missing?
The envelope signature generate still is being used as a placeholder and not compliant with the spec. This should be solved for the creation of the module. There is no js implementation for the uvarint spec and I will work on it (there is one that I need to cross check with the spec).
What's next?
I expect to create the follow up PRs
References