diff --git a/Cargo.toml b/Cargo.toml index 961c167f..3818f6fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,7 +78,7 @@ instant = "0.1.11" # Explicit dependency to be used in `wasm-bindgen` feature lazy_static = "1.2" libp2p-autonat = { version = "0.3.0", path = "protocols/autonat", optional = true } -libp2p-core = { version = "0.32.0", path = "core", default-features = false } +libp2p-core = { version = "0.32.1", path = "core", default-features = false } libp2p-dcutr = { version = "0.2.0", path = "protocols/dcutr", optional = true } libp2p-floodsub = { version = "0.35.0", path = "protocols/floodsub", optional = true } libp2p-identify = { version = "0.35.0", path = "protocols/identify", optional = true } diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index bf4109f7..ed163295 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.32.1 [unreleased] + +- Add `PeerId::try_from_multiaddr` to extract a `PeerId` from a `Multiaddr` that ends in `/p2p/`. + # 0.32.0 [2022-02-22] - Remove `Network`. `libp2p-core` is from now on an auxiliary crate only. Users diff --git a/core/Cargo.toml b/core/Cargo.toml index 3dbe9602..29bf6831 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -3,7 +3,7 @@ name = "libp2p-core" edition = "2021" rust-version = "1.56.1" description = "Core traits and structs of libp2p" -version = "0.32.0" +version = "0.32.1" authors = ["Parity Technologies "] license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" diff --git a/core/src/peer_id.rs b/core/src/peer_id.rs index 518adcab..d9525831 100644 --- a/core/src/peer_id.rs +++ b/core/src/peer_id.rs @@ -19,6 +19,7 @@ // DEALINGS IN THE SOFTWARE. use crate::PublicKey; +use multiaddr::{Multiaddr, Protocol}; use multihash::{Code, Error, Multihash, MultihashDigest}; use rand::Rng; use std::{convert::TryFrom, fmt, str::FromStr}; @@ -88,6 +89,17 @@ impl PeerId { } } + /// Tries to extract a [`PeerId`] from the given [`Multiaddr`]. + /// + /// In case the given [`Multiaddr`] ends with `/p2p/`, this function + /// will return the encapsulated [`PeerId`], otherwise it will return `None`. + pub fn try_from_multiaddr(address: &Multiaddr) -> Option { + address.iter().last().map_or(None, |p| match p { + Protocol::P2p(hash) => PeerId::from_multihash(hash).ok(), + _ => None, + }) + } + /// Generates a random peer ID from a cryptographically secure PRNG. /// /// This is useful for randomly walking on a DHT, or for testing purposes. @@ -271,4 +283,30 @@ mod tests { assert_eq!(peer_id, PeerId::from_bytes(&peer_id.to_bytes()).unwrap()); } } + + #[test] + fn extract_peer_id_from_multi_address() { + let address = + format!("/memory/1234/p2p/12D3KooWGQmdpzHXCqLno4mMxWXKNFQHASBeF99gTm2JR8Vu5Bdc") + .parse() + .unwrap(); + + let peer_id = PeerId::try_from_multiaddr(&address).unwrap(); + + assert_eq!( + peer_id, + "12D3KooWGQmdpzHXCqLno4mMxWXKNFQHASBeF99gTm2JR8Vu5Bdc" + .parse() + .unwrap() + ); + } + + #[test] + fn no_panic_on_extract_peer_id_from_multi_address_if_not_present() { + let address = format!("/memory/1234").parse().unwrap(); + + let maybe_empty = PeerId::try_from_multiaddr(&address); + + assert!(maybe_empty.is_none()); + } }