-
Notifications
You must be signed in to change notification settings - Fork 998
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(identify): implement signedPeerRecord #5785
base: master
Are you sure you want to change the base?
Conversation
Oh CI will compile the protobuf code, didn't see that. |
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.
Left some comments :)
you might rebase to main branch, as zlib license has added to ci, #5769 |
I think you might write some changelog text into this file, just like,
the pr might be okay now. |
Thanks for the review! Working on tests right now. |
version |
CHANGELOG will be fixed with #5803, you can just add the new entry 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.
Thank you @drHuangMHT! Looks like a great start.
I found a pending libp2p spec for signed peer records: libp2p/specs#630. Most of it matches this PR, just one thing is missing:
If the
signedPeerRecord
is present the implementation MUST use the data contained within it and ignore duplicated fields present in the main identify message
IMO that makes sense and should be added to this PR. So instead of copying the received record as it is in handle_incoming_info
, I think we should instead (when an signed envelope is present):
- Verify that the signature matches the remote's public key
- Deserialize the record, store the resulting addresses as
listen_addrs
, and ignore the originallisten_addrs
.
Wdyt?
protocols/identify/src/protocol.rs
Outdated
// When signedPeerRecord contains valid addresses, ignore addresses in listenAddrs. | ||
// When signedPeerRecord is invalid or signed by others, ignore the signedPeerRecord(set to `None`). | ||
let (signed_peer_record, listen_addrs) = signed_peer_record | ||
.as_ref() | ||
.and_then(|envelope| PeerRecord::try_deserialize_signed_envelope(&envelope).ok()) | ||
.and_then(|(envelope_public_key, _, _, addresses)| { | ||
(*envelope_public_key == public_key).then_some(addresses) | ||
}) | ||
.map(|addrs| (signed_peer_record, addrs)) | ||
.unwrap_or_else(|| (None, parse_listen_addrs(msg.listenAddrs))); |
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.
Do we really need to deserialize
the record again? Can't we just read out PeerRecord::adddresses
:
let listen_addrs = signed_peer_record.map_or_else(
|| parse_listen_addrs(msg.listenAddrs),
|record| record.addresses.to_vec()
);
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.
Ahh we also need to check that the envelope key matches, but that can be done as well by reading the PeerRecord::peer_id
and comparing it with the remote's id, right?
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.
Do we really need to
deserialize
the record again? Can't we just read outPeerRecord::adddresses
:let listen_addrs = signed_peer_record.map_or_else( || parse_listen_addrs(msg.listenAddrs), |record| record.addresses.to_vec() );
record
has type SignedEnvelope
, whose payload is in the form of Vec<u8>
(bytes) that doesn't have addresses
field unless we deserialize the payload into PeerRecord
. In order to own the addresses the only way is to call record.addresses().to_vec()
which in this case allocates twice, which is unnecessary. So I extracted PeerRecord::try_deserialize_signed_envelope
to cut down allocation.
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.
Ahh we also need to check that the envelope key matches, but that can be done as well by reading the
PeerRecord::peer_id
and comparing it with the remote's id, right?
PeerId
is derived from a public key, which indirectly proves its identity while the key itself does so directly. ID can collide, but the key is less likely, considering we support multiple key types. I believe it is safer to compare the keys directly when they are already present.
Description
May close #4017.
Notes & open questions
pb-rs
now usesCow<'_,T>
for the compiled Rust structs. But with borrowed type in the struct,FramedRead
can no longer process frames correctly(trait bound not statisfied).Change checklist