feat: remove multiaddr dependency from libp2p-identity

Related: https://github.com/multiformats/rust-multiaddr/issues/73.
Depends-On: https://github.com/libp2p/rust-libp2p/pull/3514.

Pull-Request: #3656.
This commit is contained in:
Thomas Eizinger
2023-06-06 19:27:13 +02:00
committed by GitHub
parent 86e8018016
commit 0db9937ee5
6 changed files with 135 additions and 111 deletions

View File

@ -18,8 +18,6 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
use multiaddr::{Multiaddr, Protocol};
use multihash::{Code, Error, MultihashGeneric};
use rand::Rng;
use sha2::Digest as _;
use std::{convert::TryFrom, fmt, str::FromStr};
@ -30,7 +28,7 @@ use thiserror::Error;
/// Must be big enough to accommodate for `MAX_INLINE_KEY_LENGTH`.
/// 64 satisfies that and can hold 512 bit hashes which is what the ecosystem typically uses.
/// Given that this appears in our type-signature, using a "common" number here makes us more compatible.
type Multihash = MultihashGeneric<64>;
type Multihash = multihash::Multihash<64>;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
@ -80,9 +78,9 @@ impl PeerId {
}
/// Parses a `PeerId` from bytes.
pub fn from_bytes(data: &[u8]) -> Result<PeerId, Error> {
pub fn from_bytes(data: &[u8]) -> Result<PeerId, ParseError> {
PeerId::from_multihash(Multihash::from_bytes(data)?)
.map_err(|mh| Error::UnsupportedCode(mh.code()))
.map_err(|mh| ParseError::UnsupportedCode(mh.code()))
}
/// Tries to turn a `Multihash` into a `PeerId`.
@ -100,25 +98,13 @@ impl PeerId {
}
}
/// Tries to extract a [`PeerId`] from the given [`Multiaddr`].
///
/// In case the given [`Multiaddr`] ends with `/p2p/<peer-id>`, this function
/// will return the encapsulated [`PeerId`], otherwise it will return `None`.
pub fn try_from_multiaddr(address: &Multiaddr) -> Option<PeerId> {
address.iter().last().and_then(|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.
pub fn random() -> PeerId {
let peer_id = rand::thread_rng().gen::<[u8; 32]>();
PeerId {
multihash: Multihash::wrap(Code::Identity.into(), &peer_id)
.expect("The digest size is never too large"),
multihash: Multihash::wrap(0x0, &peer_id).expect("The digest size is never too large"),
}
}
@ -131,19 +117,6 @@ impl PeerId {
pub fn to_base58(&self) -> String {
bs58::encode(self.to_bytes()).into_string()
}
/// Checks whether the public key passed as parameter matches the public key of this `PeerId`.
///
/// Returns `None` if this `PeerId`s hash algorithm is not supported when encoding the
/// given public key, otherwise `Some` boolean as the result of an equality check.
pub fn is_public_key(&self, public_key: &crate::PublicKey) -> Option<bool> {
use multihash::MultihashDigest as _;
let alg = Code::try_from(self.multihash.code())
.expect("Internal multihash is always a valid `Code`");
let enc = public_key.encode_protobuf();
Some(alg.digest(&enc) == self.multihash)
}
}
impl From<crate::PublicKey> for PeerId {
@ -246,12 +219,15 @@ impl<'de> Deserialize<'de> for PeerId {
}
}
/// Error when parsing a [`PeerId`] from string or bytes.
#[derive(Debug, Error)]
pub enum ParseError {
#[error("base-58 decode error: {0}")]
B58(#[from] bs58::decode::Error),
#[error("decoding multihash failed")]
MultiHash,
#[error("unsupported multihash code '{0}'")]
UnsupportedCode(u64),
#[error("invalid multihash")]
InvalidMultihash(#[from] multihash::Error),
}
impl FromStr for PeerId {
@ -260,7 +236,9 @@ impl FromStr for PeerId {
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
let bytes = bs58::decode(s).into_vec()?;
PeerId::from_bytes(&bytes).map_err(|_| ParseError::MultiHash)
let peer_id = PeerId::from_bytes(&bytes)?;
Ok(peer_id)
}
}
@ -268,14 +246,6 @@ impl FromStr for PeerId {
mod tests {
use super::*;
#[test]
#[cfg(feature = "ed25519")]
fn peer_id_is_public_key() {
let key = crate::Keypair::generate_ed25519().public();
let peer_id = key.to_peer_id();
assert_eq!(peer_id.is_public_key(&key), Some(true));
}
#[test]
#[cfg(feature = "ed25519")]
fn peer_id_into_bytes_then_from_bytes() {
@ -299,30 +269,4 @@ mod tests {
assert_eq!(peer_id, PeerId::from_bytes(&peer_id.to_bytes()).unwrap());
}
}
#[test]
fn extract_peer_id_from_multi_address() {
let address = "/memory/1234/p2p/12D3KooWGQmdpzHXCqLno4mMxWXKNFQHASBeF99gTm2JR8Vu5Bdc"
.to_string()
.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 = "/memory/1234".to_string().parse().unwrap();
let maybe_empty = PeerId::try_from_multiaddr(&address);
assert!(maybe_empty.is_none());
}
}