aboutsummaryrefslogtreecommitdiff
path: root/p2p/src/peer/peer_id.rs
blob: 145c1998de884b4bf2295c9ad54b2ff6e6474536 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use base64::{engine::general_purpose::STANDARD, Engine};
use bincode::{Decode, Encode};
use rand::{rngs::OsRng, RngCore};
use sha2::{Digest, Sha256};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use karyon_core::crypto::PublicKey;

use crate::Error;

/// Represents a unique identifier for a peer.
#[derive(Clone, Debug, Eq, PartialEq, Hash, Decode, Encode)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(into = "String"))]
pub struct PeerID(pub [u8; 32]);

impl std::fmt::Display for PeerID {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        let id = STANDARD.encode(self.0);
        write!(f, "{}", id)
    }
}

impl PeerID {
    /// Creates a new PeerID.
    pub fn new(src: &[u8]) -> Self {
        let mut hasher = Sha256::new();
        hasher.update(src);
        Self(hasher.finalize().into())
    }

    /// Generates a random PeerID.
    pub fn random() -> Self {
        let mut id: [u8; 32] = [0; 32];
        OsRng.fill_bytes(&mut id);
        Self(id)
    }
}

impl From<[u8; 32]> for PeerID {
    fn from(b: [u8; 32]) -> Self {
        PeerID(b)
    }
}

impl From<PeerID> for String {
    fn from(pid: PeerID) -> Self {
        pid.to_string()
    }
}

impl TryFrom<String> for PeerID {
    type Error = Error;

    fn try_from(i: String) -> Result<Self, Self::Error> {
        let result: [u8; 32] = STANDARD
            .decode(i)?
            .try_into()
            .map_err(|_| Error::PeerIDTryFromString)?;
        Ok(PeerID(result))
    }
}

impl TryFrom<PublicKey> for PeerID {
    type Error = Error;

    fn try_from(pk: PublicKey) -> Result<Self, Self::Error> {
        let pk: [u8; 32] = pk
            .as_bytes()
            .try_into()
            .map_err(|_| Error::PeerIDTryFromPublicKey)?;

        Ok(PeerID(pk))
    }
}