1#![allow(clippy::wrong_self_convention)]
23
24use crate::crypto::PublicKey;
25
26use multiaddr::{Multiaddr, Protocol};
27use multihash::{Code, Error, Multihash, MultihashDigest};
28use rand::Rng;
29use serde::{Deserialize, Serialize};
30use thiserror::Error;
31
32use std::{convert::TryFrom, fmt, str::FromStr};
33
34const MAX_INLINE_KEY_LENGTH: usize = 42;
37
38#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
43pub struct PeerId {
44 multihash: Multihash,
45}
46
47impl fmt::Debug for PeerId {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 f.debug_tuple("PeerId").field(&self.to_base58()).finish()
50 }
51}
52
53impl fmt::Display for PeerId {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 self.to_base58().fmt(f)
56 }
57}
58
59impl PeerId {
60 pub fn from_public_key(key: &PublicKey) -> PeerId {
62 let key_enc = key.to_protobuf_encoding();
63
64 let hash_algorithm = if key_enc.len() <= MAX_INLINE_KEY_LENGTH {
65 Code::Identity
66 } else {
67 Code::Sha2_256
68 };
69
70 let multihash = hash_algorithm.digest(&key_enc);
71
72 PeerId { multihash }
73 }
74
75 pub fn from_bytes(data: &[u8]) -> Result<PeerId, Error> {
77 PeerId::from_multihash(Multihash::from_bytes(data)?)
78 .map_err(|mh| Error::UnsupportedCode(mh.code()))
79 }
80
81 pub fn from_multihash(multihash: Multihash) -> Result<PeerId, Multihash> {
87 match Code::try_from(multihash.code()) {
88 Ok(Code::Sha2_256) => Ok(PeerId { multihash }),
89 Ok(Code::Identity) if multihash.digest().len() <= MAX_INLINE_KEY_LENGTH =>
90 Ok(PeerId { multihash }),
91 _ => Err(multihash),
92 }
93 }
94
95 pub fn try_from_multiaddr(address: &Multiaddr) -> Option<PeerId> {
100 address.iter().last().and_then(|p| match p {
101 Protocol::P2p(hash) => PeerId::from_multihash(hash).ok(),
102 _ => None,
103 })
104 }
105
106 pub fn random() -> PeerId {
110 let peer_id = rand::thread_rng().gen::<[u8; 32]>();
111 PeerId {
112 multihash: Multihash::wrap(Code::Identity.into(), &peer_id)
113 .expect("The digest size is never too large"),
114 }
115 }
116
117 pub fn to_bytes(&self) -> Vec<u8> {
119 self.multihash.to_bytes()
120 }
121
122 pub fn to_base58(&self) -> String {
124 bs58::encode(self.to_bytes()).into_string()
125 }
126
127 pub fn is_public_key(&self, public_key: &PublicKey) -> Option<bool> {
132 let alg = Code::try_from(self.multihash.code())
133 .expect("Internal multihash is always a valid `Code`");
134 let enc = public_key.to_protobuf_encoding();
135 Some(alg.digest(&enc) == self.multihash)
136 }
137}
138
139impl From<PublicKey> for PeerId {
140 fn from(key: PublicKey) -> PeerId {
141 PeerId::from_public_key(&key)
142 }
143}
144
145impl From<&PublicKey> for PeerId {
146 fn from(key: &PublicKey) -> PeerId {
147 PeerId::from_public_key(key)
148 }
149}
150
151impl TryFrom<Vec<u8>> for PeerId {
152 type Error = Vec<u8>;
153
154 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
155 PeerId::from_bytes(&value).map_err(|_| value)
156 }
157}
158
159impl TryFrom<Multihash> for PeerId {
160 type Error = Multihash;
161
162 fn try_from(value: Multihash) -> Result<Self, Self::Error> {
163 PeerId::from_multihash(value)
164 }
165}
166
167impl AsRef<Multihash> for PeerId {
168 fn as_ref(&self) -> &Multihash {
169 &self.multihash
170 }
171}
172
173impl From<PeerId> for Multihash {
174 fn from(peer_id: PeerId) -> Self {
175 peer_id.multihash
176 }
177}
178
179impl From<PeerId> for Vec<u8> {
180 fn from(peer_id: PeerId) -> Self {
181 peer_id.to_bytes()
182 }
183}
184
185impl Serialize for PeerId {
186 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
187 where
188 S: serde::Serializer,
189 {
190 if serializer.is_human_readable() {
191 serializer.serialize_str(&self.to_base58())
192 } else {
193 serializer.serialize_bytes(&self.to_bytes()[..])
194 }
195 }
196}
197
198impl<'de> Deserialize<'de> for PeerId {
199 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
200 where
201 D: serde::Deserializer<'de>,
202 {
203 use serde::de::*;
204
205 struct PeerIdVisitor;
206
207 impl<'de> Visitor<'de> for PeerIdVisitor {
208 type Value = PeerId;
209
210 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
211 write!(f, "valid peer id")
212 }
213
214 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
215 where
216 E: Error,
217 {
218 PeerId::from_bytes(v).map_err(|_| Error::invalid_value(Unexpected::Bytes(v), &self))
219 }
220
221 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
222 where
223 E: Error,
224 {
225 PeerId::from_str(v).map_err(|_| Error::invalid_value(Unexpected::Str(v), &self))
226 }
227 }
228
229 if deserializer.is_human_readable() {
230 deserializer.deserialize_str(PeerIdVisitor)
231 } else {
232 deserializer.deserialize_bytes(PeerIdVisitor)
233 }
234 }
235}
236
237#[derive(Debug, Error)]
238pub enum ParseError {
239 #[error("base-58 decode error: {0}")]
240 B58(#[from] bs58::decode::Error),
241 #[error("decoding multihash failed")]
242 MultiHash,
243}
244
245impl FromStr for PeerId {
246 type Err = ParseError;
247
248 #[inline]
249 fn from_str(s: &str) -> Result<Self, Self::Err> {
250 let bytes = bs58::decode(s).into_vec()?;
251 PeerId::from_bytes(&bytes).map_err(|_| ParseError::MultiHash)
252 }
253}
254
255#[cfg(test)]
256mod tests {
257 use crate::{crypto::ed25519::Keypair, PeerId};
258 use multiaddr::{Multiaddr, Protocol};
259 use multihash::Multihash;
260
261 #[test]
262 fn peer_id_is_public_key() {
263 let key = Keypair::generate().public();
264 let peer_id = key.to_peer_id();
265 assert_eq!(peer_id.is_public_key(&key.into()), Some(true));
266 }
267
268 #[test]
269 fn peer_id_into_bytes_then_from_bytes() {
270 let peer_id = Keypair::generate().public().to_peer_id();
271 let second = PeerId::from_bytes(&peer_id.to_bytes()).unwrap();
272 assert_eq!(peer_id, second);
273 }
274
275 #[test]
276 fn peer_id_to_base58_then_back() {
277 let peer_id = Keypair::generate().public().to_peer_id();
278 let second: PeerId = peer_id.to_base58().parse().unwrap();
279 assert_eq!(peer_id, second);
280 }
281
282 #[test]
283 fn random_peer_id_is_valid() {
284 for _ in 0..5000 {
285 let peer_id = PeerId::random();
286 assert_eq!(peer_id, PeerId::from_bytes(&peer_id.to_bytes()).unwrap());
287 }
288 }
289
290 #[test]
291 fn peer_id_from_multiaddr() {
292 let address = "[::1]:1337".parse::<std::net::SocketAddr>().unwrap();
293 let peer = PeerId::random();
294 let address = Multiaddr::empty()
295 .with(Protocol::from(address.ip()))
296 .with(Protocol::Tcp(address.port()))
297 .with(Protocol::P2p(Multihash::from(peer)));
298
299 assert_eq!(peer, PeerId::try_from_multiaddr(&address).unwrap());
300 }
301
302 #[test]
303 fn peer_id_from_multiaddr_no_peer_id() {
304 let address = "[::1]:1337".parse::<std::net::SocketAddr>().unwrap();
305 let address = Multiaddr::empty()
306 .with(Protocol::from(address.ip()))
307 .with(Protocol::Tcp(address.port()));
308
309 assert!(PeerId::try_from_multiaddr(&address).is_none());
310 }
311
312 #[test]
313 fn peer_id_from_bytes() {
314 let peer = PeerId::random();
315 let bytes = peer.to_bytes();
316
317 assert_eq!(PeerId::try_from(bytes).unwrap(), peer);
318 }
319
320 #[test]
321 fn peer_id_as_multihash() {
322 let peer = PeerId::random();
323 let multihash = Multihash::from(peer);
324
325 assert_eq!(&multihash, peer.as_ref());
326 assert_eq!(PeerId::try_from(multihash).unwrap(), peer);
327 }
328
329 #[test]
330 fn serialize_deserialize() {
331 let peer = PeerId::random();
332 let serialized = serde_json::to_string(&peer).unwrap();
333 let deserialized = serde_json::from_str(&serialized).unwrap();
334
335 assert_eq!(peer, deserialized);
336 }
337
338 #[test]
339 fn invalid_multihash() {
340 fn test() -> crate::Result<PeerId> {
341 let bytes = [
342 0x16, 0x20, 0x64, 0x4b, 0xcc, 0x7e, 0x56, 0x43, 0x73, 0x04, 0x09, 0x99, 0xaa, 0xc8,
343 0x9e, 0x76, 0x22, 0xf3, 0xca, 0x71, 0xfb, 0xa1, 0xd9, 0x72, 0xfd, 0x94, 0xa3, 0x1c,
344 0x3b, 0xfb, 0xf2, 0x4e, 0x39, 0x38,
345 ];
346
347 PeerId::from_multihash(Multihash::from_bytes(&bytes).unwrap()).map_err(From::from)
348 }
349 let _error = test().unwrap_err();
350 }
351}