feat: leverage type-safe /p2p in multiaddr

This updates `multiaddr` to version `0.19`.

Depends-On: #3656.
Depends-On: https://github.com/multiformats/rust-multiaddr/pull/83.
Resolves: #4039.

Pull-Request: #4037.
This commit is contained in:
Thomas Eizinger
2023-06-08 03:38:18 +02:00
committed by GitHub
parent d2dab94b76
commit ed14630672
41 changed files with 172 additions and 348 deletions

View File

@ -22,7 +22,6 @@
use crate::ConnectionId;
use libp2p_core::connection::Endpoint;
use libp2p_core::multiaddr::Protocol;
use libp2p_core::multihash::Multihash;
use libp2p_core::Multiaddr;
use libp2p_identity::PeerId;
use std::num::NonZeroU8;
@ -81,9 +80,21 @@ impl DialOpts {
WithoutPeerId {}
}
/// Get the [`PeerId`] specified in a [`DialOpts`] if any.
/// Retrieves the [`PeerId`] from the [`DialOpts`] if specified or otherwise tries to extract it
/// from the multihash in the `/p2p` part of the address, if present.
pub fn get_peer_id(&self) -> Option<PeerId> {
self.peer_id
if let Some(peer_id) = self.peer_id {
return Some(peer_id);
}
let first_address = self.addresses.first()?;
let last_protocol = first_address.iter().last()?;
if let Protocol::P2p(p) = last_protocol {
return Some(p);
}
None
}
/// Get the [`ConnectionId`] of this dial attempt.
@ -94,40 +105,6 @@ impl DialOpts {
self.connection_id
}
/// Retrieves the [`PeerId`] from the [`DialOpts`] if specified or otherwise tries to parse it
/// from the multihash in the `/p2p` part of the address, if present.
///
/// Note: A [`Multiaddr`] with something else other than a [`PeerId`] within the `/p2p` protocol is invalid as per specification.
/// Unfortunately, we are not making good use of the type system here.
/// Really, this function should be merged with [`DialOpts::get_peer_id`] above.
/// If it weren't for the parsing error, the function signatures would be the same.
///
/// See <https://github.com/multiformats/rust-multiaddr/issues/73>.
pub(crate) fn get_or_parse_peer_id(&self) -> Result<Option<PeerId>, Multihash> {
if let Some(peer_id) = self.peer_id {
return Ok(Some(peer_id));
}
let first_address = match self.addresses.first() {
Some(first_address) => first_address,
None => return Ok(None),
};
let maybe_peer_id = first_address
.iter()
.last()
.and_then(|p| {
if let Protocol::P2p(ma) = p {
Some(PeerId::try_from(ma))
} else {
None
}
})
.transpose()?;
Ok(maybe_peer_id)
}
pub(crate) fn get_addresses(&self) -> Vec<Multiaddr> {
self.addresses.clone()
}

View File

@ -136,7 +136,6 @@ use futures::{prelude::*, stream::FusedStream};
use libp2p_core::{
connection::ConnectedPoint,
multiaddr,
multihash::Multihash,
muxing::StreamMuxerBox,
transport::{self, ListenerId, TransportError, TransportEvent},
Endpoint, Multiaddr, Transport,
@ -415,9 +414,7 @@ where
pub fn dial(&mut self, opts: impl Into<DialOpts>) -> Result<(), DialError> {
let dial_opts = opts.into();
let peer_id = dial_opts
.get_or_parse_peer_id()
.map_err(DialError::InvalidPeerId)?;
let peer_id = dial_opts.get_peer_id();
let condition = dial_opts.peer_condition();
let connection_id = dial_opts.connection_id();
@ -1008,11 +1005,11 @@ where
match event {
ToSwarm::GenerateEvent(event) => return Some(SwarmEvent::Behaviour(event)),
ToSwarm::Dial { opts } => {
let peer_id = opts.get_or_parse_peer_id();
let peer_id = opts.get_peer_id();
let connection_id = opts.connection_id();
if let Ok(()) = self.dial(opts) {
return Some(SwarmEvent::Dialing {
peer_id: peer_id.ok().flatten(),
peer_id,
connection_id,
});
}
@ -1519,8 +1516,6 @@ pub enum DialError {
DialPeerConditionFalse(dial_opts::PeerCondition),
/// Pending connection attempt has been aborted.
Aborted,
/// The provided peer identity is invalid.
InvalidPeerId(Multihash),
/// The peer identity obtained on the connection did not match the one that was expected.
WrongPeerId {
obtained: PeerId,
@ -1561,9 +1556,6 @@ impl fmt::Display for DialError {
f,
"Dial error: Pending connection attempt has been aborted."
),
DialError::InvalidPeerId(multihash) => {
write!(f, "Dial error: multihash {multihash:?} is not a PeerId")
}
DialError::WrongPeerId { obtained, endpoint } => write!(
f,
"Dial error: Unexpected peer ID {obtained} at {endpoint:?}."
@ -1604,7 +1596,6 @@ impl error::Error for DialError {
DialError::NoAddresses => None,
DialError::DialPeerConditionFalse(_) => None,
DialError::Aborted => None,
DialError::InvalidPeerId { .. } => None,
DialError::WrongPeerId { .. } => None,
DialError::Transport(_) => None,
DialError::Denied { cause } => Some(cause),
@ -1763,14 +1754,15 @@ fn p2p_addr(peer: Option<PeerId>, addr: Multiaddr) -> Result<Multiaddr, Multiadd
None => return Ok(addr),
};
if let Some(multiaddr::Protocol::P2p(hash)) = addr.iter().last() {
if &hash != peer.as_ref() {
if let Some(multiaddr::Protocol::P2p(peer_id)) = addr.iter().last() {
if peer_id != peer {
return Err(addr);
}
Ok(addr)
} else {
Ok(addr.with(multiaddr::Protocol::P2p(peer.into())))
return Ok(addr);
}
Ok(addr.with(multiaddr::Protocol::P2p(peer)))
}
#[cfg(test)]
@ -2173,7 +2165,7 @@ mod tests {
}));
let other_id = PeerId::random();
let other_addr = address.with(multiaddr::Protocol::P2p(other_id.into()));
let other_addr = address.with(multiaddr::Protocol::P2p(other_id));
swarm2.dial(other_addr.clone()).unwrap();
@ -2322,7 +2314,7 @@ mod tests {
let failed_addresses = errors.into_iter().map(|(addr, _)| addr).collect::<Vec<_>>();
let expected_addresses = addresses
.into_iter()
.map(|addr| addr.with(multiaddr::Protocol::P2p(target.into())))
.map(|addr| addr.with(multiaddr::Protocol::P2p(target)))
.collect::<Vec<_>>();
assert_eq!(expected_addresses, failed_addresses);