Skip to content

Commit

Permalink
prefer addresses in signedPeerRecord
Browse files Browse the repository at this point in the history
  • Loading branch information
drHuangMHT committed Jan 10, 2025
1 parent 12b9a29 commit d3d8ae6
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 28 deletions.
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 std::io;

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 @@ impl TryFrom<proto::Identify> for Info {
}
};

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

0 comments on commit d3d8ae6

Please sign in to comment.