-
Notifications
You must be signed in to change notification settings - Fork 445
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: keybook #626
feat: keybook #626
Conversation
doc/API.md
Outdated
|
||
Set known `peerId`. This can include its Public Key. | ||
|
||
`peerStore.keyBook.set(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.
What happens if there is no public key on the PeerId instance?
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.
Just keeps the PeerId in it, and might update in the future. I would see the peer-id
existing when we discover a new peer
src/peer-store/key-book.js
Outdated
const id = peerId.toB58String() | ||
const recPeerId = this.data.get(id) | ||
|
||
!recPeerId && this._ps.emit('peer', 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.
We should avoid other things triggering events on the peer store and instead rely on the peer store to determine when it should be emitting things. If we don't isolate we'll run the risk of having what we used to have, where several things are emitting peer events which can result in a lot of unnecessary events.
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.
It would probably be good to take a step back and think about the flow of the peers data into the peer store. I dont think that updating the keybook anytime we learn about the peer is the intuitive action. Updating the keybook after crypto negotiation makes sense.
It might be good to revisit the peer store readme and make sure that is up to date and makes sense with these flows.
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 should avoid other things triggering events on the peer store and instead rely on the peer store to determine when it should be emitting things. If we don't isolate we'll run the risk of having what we used to have, where several things are emitting peer events which can result in a lot of unnecessary events.
I did not understand your point here. Currently, the Book.js
base class is emitting the events for changed peers, while this is the previous event emitted when the peer was discovered (in the addressBook), but now that we have the keyBook keeping the peerIds, it feels that this is the place this should be.
It would probably be good to take a step back and think about the flow of the peers data into the peer store. I dont think that updating the keybook anytime we learn about the peer is the intuitive action. Updating the keybook after crypto negotiation makes sense.
It might be good to revisit the peer store readme and make sure that is up to date and makes sense with these flows.
I added it to update the keyBook because I did not want to keep track of the peerIds in two different data structures. If we move into only storing the peerId
in the keybook if we have a public key for it, we will need to go back with the peer
event into the addressBook.
Updating the keybook after crypto negotiation makes sense, and I forgot that flow. However, subsystems like the dht will also need to be able to set the public key for a peer.
All things considered, should we go into only storing the PeerId when it has a public key (we can reconstruct it into the getters with createFromCID
if we do not store it? With that, we do not update the keybook anymore on the other books set and we emit the peer
event from the addressBook? This way, the upgrader and the dht would call the keyBook.set()
...
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.
If we go this way, should we throw an error if there is no public key provided in the peerId to set? Probably we should change the API into keyBook.set(peerId, publicKey)
. While the parameter is redundant, it will sign in an easier way to the user that it is expected
dd94b20
to
9a25c84
Compare
Co-authored-by: Jacob Heun <jacobheun@gmail.com>
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. | ||
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. | ||
|
||
When a connection is being upgraded, more precisely after its encryption, or even in a discovery protocol, a libp2p node can get to know other parties public keys. In this scenario, libp2p will add the peer's public key to its `KeyBook`. |
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.
@jacobheun from what we discussed, I could only not do this by now.
I think that it makes sense, but afaik noise uses static public keys, which I would not expect to have here. In addition, we will need to provide libp2p to the crypto module for adding the key to the keyBook or change the crypto interface to also require the public key, so that we can update this in the upgrader.js
.
We should probably give some thought on this and follow up with a good solution.
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.
Noise has its own keycache and I dont think we need to worry about persistence of the crypto transport keys, just the libp2p id keys. I think this section is achieved by updating the peer after we've established a connection, because the crypto handshake will result in libp2p public key exchange and verification.
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.
For the inbound connection, we do have the public key after the connection being established. The same is not true for the outbound connection. Both for libp2p-secio
and libp2p-noise
I went deeper on secio to figure out why this is happening and I found this: https://github.com/libp2p/js-libp2p-secio/blob/master/src/handshake/crypto.js#L66-L73
When an inbound connection, we go to the else statement while in an outbound connection we go to the if side of things. In the if
part we basically do not add the public key. If I just add state.id.remote = remoteId
inside the if and after the validation condition, it works. Is this the expected?
In noise, I could not follow the flow so easily yet...
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.
Meanwhile, I already added the code for this here and a test. The validation of the outbound connection key being exchanged is currently commented as a result of what I described above
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.
Note: this is fixed in secio now, I'll look into it in noise as part of my work there.
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.
what do you recommend here? change the test configuration to use secio for now and create an issue to track this?
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.
Leave it for now, I'll work on getting a patch for noise to correct this. We can add a TODO item to the peer store epic to track getting this in.
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 fixes/suggestions.
The PeerId instead of publickey storage in the keybook is a bit odd, although I understand the reasoning. The API here makes it easy to change in the future if we find a better approach, so this is not a blocker for moving forward with this imo.
expect(err.code).to.equal(ERR_INVALID_PARAMETERS) | ||
return | ||
} | ||
throw new Error('invalid peerId should throw error') |
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.
No need to change but you could instead do something like:
expect(() => kb.set('invalid peerId')).to.throw()
.that.has.property('code', ERR_INVALID_PARAMETERS)
which avoids potentially forgetting the return/throw statements when a failure occurs.
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.
I tried this out and I got:
AssertionError: expected [Function] to have property 'code'
I will skip this for now, we can revisit later
|
||
const localPeers = libp2p.peerStore.peers | ||
expect(localPeers.size).to.equal(1) | ||
// const publicKeyInLocalPeer = localPeers.get(remoteIdStr).id.pubKey |
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.
Is there an issue to track this? Otherwise just add a TODO in the comments here.
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.
Adding a TODO with an issue in libp2p-noise
Co-authored-by: Jacob Heun <jacobheun@gmail.com>
This PR is part of the PeerStore improvements EPIC and tackles part of the milestone 4 - KeyBook.
As a follow up of the work in #590, #598, #610 and #619 , this PR adds they KeyBook and integrates it with the
PeerStorePersistence
.Needs: