Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
2a09cdb
implement signedPeerRecord
drHuangMHT Dec 31, 2024
b5d7aec
apply suggestions
drHuangMHT Jan 1, 2025
85d7496
Merge branch 'master' into identify-peer-record
drHuangMHT Jan 3, 2025
4d3d692
add test
drHuangMHT Jan 3, 2025
59f80f2
reduce diff
drHuangMHT Jan 4, 2025
ef89b5b
Merge branch 'master' into identify-peer-record
drHuangMHT Jan 4, 2025
12b9a29
rename symbols
drHuangMHT Jan 10, 2025
d3d8ae6
prefer addresses in signedPeerRecord
drHuangMHT Jan 10, 2025
59151b6
rename symbols
drHuangMHT Jan 11, 2025
9b6a139
lint and fmt
drHuangMHT Jan 11, 2025
cf30682
Merge branch 'master' into identify-peer-record
drHuangMHT Feb 5, 2025
e0e4d9c
rename identifiers
drHuangMHT Feb 13, 2025
d26a692
Merge branch 'master' into identify-peer-record
drHuangMHT Feb 13, 2025
92a49a5
reduce enum variant size with Box
drHuangMHT Feb 16, 2025
b35cbd3
simplify envelope deserialization
drHuangMHT Feb 16, 2025
f29c58d
document try_deserialize_signed_envelope
drHuangMHT Feb 16, 2025
ec8f31b
CI lint
drHuangMHT Feb 16, 2025
c73d37a
dedup constructor, reference count KeyType
drHuangMHT Feb 20, 2025
7cbb3f2
doc and fmt lint
drHuangMHT Feb 21, 2025
c013293
opaque type on new_with_key
drHuangMHT Feb 21, 2025
54aed27
changelog and manifest
drHuangMHT Feb 21, 2025
cd70cb9
workspace manifest
drHuangMHT Feb 21, 2025
8df2279
Merge branch 'master' into identify-peer-record
drHuangMHT Feb 21, 2025
9ec20a4
Merge branch 'master' into identify-peer-record
drHuangMHT Feb 25, 2025
c5db873
fix definition link, simplify record parsing
drHuangMHT Feb 28, 2025
b882ad5
revert core version bump
drHuangMHT Feb 28, 2025
0d27658
Merge branch 'master' into identify-peer-record
drHuangMHT Feb 28, 2025
ec67ce6
Merge branch 'master' into identify-peer-record
mergify[bot] Mar 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 28 additions & 23 deletions core/src/peer_record.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use libp2p_identity::{Keypair, PeerId, SigningError};
use libp2p_identity::{Keypair, PeerId, PublicKey, SigningError};
use quick_protobuf::{BytesReader, Writer};
use web_time::SystemTime;

use crate::{proto, signed_envelope, signed_envelope::SignedEnvelope, DecodeError, Multiaddr};

const PAYLOAD_TYPE: &str = "/libp2p/routing-state-record";
const DOMAIN_SEP: &str = "libp2p-routing-state";
pub const PAYLOAD_TYPE: &str = "/libp2p/routing-state-record";
pub const DOMAIN_SEP: &str = "libp2p-routing-state";

/// Represents a peer routing record.
///
Expand All @@ -30,26 +30,7 @@ impl PeerRecord {
/// If this function succeeds, the [`SignedEnvelope`] contained a peer record with a valid
/// signature and can hence be considered authenticated.
pub fn from_signed_envelope(envelope: SignedEnvelope) -> Result<Self, FromEnvelopeError> {
use quick_protobuf::MessageRead;

let (payload, signing_key) =
envelope.payload_and_signing_key(String::from(DOMAIN_SEP), PAYLOAD_TYPE.as_bytes())?;
let mut reader = BytesReader::from_bytes(payload);
let record = proto::PeerRecord::from_reader(&mut reader, payload).map_err(DecodeError)?;

let peer_id = PeerId::from_bytes(&record.peer_id)?;

if peer_id != signing_key.to_peer_id() {
return Err(FromEnvelopeError::MismatchedSignature);
}

let seq = record.seq;
let addresses = record
.addresses
.into_iter()
.map(|a| a.multiaddr.to_vec().try_into())
.collect::<Result<Vec<_>, _>>()?;

let (_, peer_id, seq, addresses) = Self::try_deserialize_signed_envelope(&envelope)?;
Ok(Self {
peer_id,
seq,
Expand Down Expand Up @@ -126,6 +107,30 @@ impl PeerRecord {
pub fn addresses(&self) -> &[Multiaddr] {
self.addresses.as_slice()
}

pub fn try_deserialize_signed_envelope(
envelope: &SignedEnvelope,
) -> Result<(&PublicKey, PeerId, u64, Vec<Multiaddr>), FromEnvelopeError> {
use quick_protobuf::MessageRead;

let (payload, signing_key) =
envelope.payload_and_signing_key(String::from(DOMAIN_SEP), PAYLOAD_TYPE.as_bytes())?;
let mut reader = BytesReader::from_bytes(payload);
let record = proto::PeerRecord::from_reader(&mut reader, payload).map_err(DecodeError)?;

let peer_id = PeerId::from_bytes(&record.peer_id)?;

if peer_id != signing_key.to_peer_id() {
return Err(FromEnvelopeError::MismatchedSignature);
}

let addresses = record
.addresses
.into_iter()
.map(|a| a.multiaddr.to_vec().try_into())
.collect::<Result<Vec<_>, _>>()?;
Ok((signing_key, peer_id, record.seq, addresses))
}
}

#[derive(thiserror::Error, Debug)]
Expand Down
23 changes: 18 additions & 5 deletions protocols/identify/src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

use asynchronous_codec::{FramedRead, FramedWrite};
use futures::prelude::*;
use libp2p_core::{multiaddr, Multiaddr, SignedEnvelope};
use libp2p_core::{multiaddr, Multiaddr, PeerRecord, SignedEnvelope};
use libp2p_identity as identity;
use libp2p_identity::PublicKey;
use libp2p_swarm::StreamProtocol;
Expand Down Expand Up @@ -226,16 +226,29 @@
}
};

let signed_peer_record = msg
.signedPeerRecord
.and_then(|b| SignedEnvelope::from_protobuf_encoding(b.as_ref()).ok());

// 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())

Check failure on line 237 in protocols/identify/src/protocol.rs

View workflow job for this annotation

GitHub Actions / clippy (1.83.0)

this expression creates a reference which is immediately dereferenced by the compiler

Check failure on line 237 in protocols/identify/src/protocol.rs

View workflow job for this annotation

GitHub Actions / clippy (beta)

this expression creates a reference which is immediately dereferenced by the compiler
.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)));

let info = Info {
public_key,
protocol_version: msg.protocolVersion.unwrap_or_default(),
agent_version: msg.agentVersion.unwrap_or_default(),
listen_addrs: parse_listen_addrs(msg.listenAddrs),
listen_addrs,
protocols: parse_protocols(msg.protocols),
observed_addr: parse_observed_addr(msg.observedAddr).unwrap_or(Multiaddr::empty()),
signed_peer_record: msg
.signedPeerRecord
.and_then(|b| SignedEnvelope::from_protobuf_encoding(b.as_ref()).ok()),
signed_peer_record,
};

Ok(info)
Expand Down
Loading