tentacle_secio/
peer_id.rs1use std::fmt;
3
4use rand::{Rng, thread_rng};
5use unsigned_varint::{decode, encode};
6
7use crate::handshake::handshake_struct::PublicKey;
8
9const SHA256_CODE: u64 = 0x12;
10const SHA256_SIZE: u8 = 32;
11
12#[derive(Clone, PartialOrd, PartialEq, Eq, Hash)]
16pub struct PeerId {
17 inner: Vec<u8>,
19}
20
21impl PeerId {
22 #[inline]
24 pub fn from_public_key(public_key: &PublicKey) -> Self {
25 let key_inner = public_key.inner_ref();
26 Self::from_seed(key_inner)
27 }
28
29 pub fn from_bytes(data: Vec<u8>) -> Result<Self, Error> {
31 if data.is_empty() {
32 return Err(Error::Empty);
33 }
34
35 let (code, bytes) = decode::u64(&data).map_err(|_| Error::InvalidData)?;
36
37 if code != SHA256_CODE {
38 return Err(Error::NotSupportHashCode);
39 }
40
41 if bytes.len() != SHA256_SIZE as usize + 1 {
42 return Err(Error::WrongLength);
43 }
44
45 if bytes[0] != SHA256_SIZE {
46 return Err(Error::InvalidData);
47 }
48
49 Ok(PeerId { inner: data })
50 }
51
52 pub fn random() -> Self {
54 let mut seed = [0u8; 20];
55 thread_rng().fill(&mut seed[..]);
56 Self::from_seed(&seed)
57 }
58
59 fn from_seed(seed: &[u8]) -> Self {
61 let mut buf = encode::u64_buffer();
62 let code = encode::u64(SHA256_CODE, &mut buf);
63
64 let header_len = code.len() + 1;
65
66 let mut inner = vec![0; header_len + SHA256_SIZE as usize];
67 inner[..code.len()].copy_from_slice(code);
68 inner[code.len()] = SHA256_SIZE;
69
70 let mut ctx = crate::sha256_compat::Context::new();
71 ctx.update(seed);
72 inner[header_len..].copy_from_slice(ctx.finish().as_ref());
73 PeerId { inner }
74 }
75
76 #[inline]
78 pub fn as_bytes(&self) -> &[u8] {
79 &self.inner
80 }
81
82 #[inline]
84 pub fn into_bytes(self) -> Vec<u8> {
85 self.inner
86 }
87
88 #[inline]
90 pub fn to_base58(&self) -> String {
91 bs58::encode(self.inner.clone()).into_string()
92 }
93
94 #[inline]
96 pub fn digest(&self) -> &[u8] {
97 let (_, bytes) = decode::u16(&self.inner).expect("a invalid digest");
98 &bytes[1..]
99 }
100
101 pub fn is_public_key(&self, public_key: &PublicKey) -> bool {
103 let peer_id = Self::from_public_key(public_key);
104 &peer_id == self
105 }
106}
107
108impl fmt::Debug for PeerId {
109 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
110 write!(f, "PeerId({})", self.to_base58())
111 }
112}
113
114impl fmt::Display for PeerId {
115 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116 write!(f, "{}", self.to_base58())
117 }
118}
119
120impl From<PublicKey> for PeerId {
121 #[inline]
122 fn from(key: PublicKey) -> PeerId {
123 PeerId::from_public_key(&key)
124 }
125}
126
127impl ::std::str::FromStr for PeerId {
128 type Err = Error;
129
130 #[inline]
131 fn from_str(s: &str) -> Result<Self, Self::Err> {
132 let bytes = bs58::decode(s).into_vec().map_err(|_| Error::InvalidData)?;
133 PeerId::from_bytes(bytes)
134 }
135}
136
137#[derive(Debug)]
139pub enum Error {
140 InvalidData,
142 WrongLength,
144 NotSupportHashCode,
146 Empty,
148}
149
150impl fmt::Display for Error {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152 match self {
153 Error::Empty => write!(f, "data is empty"),
154 Error::InvalidData => write!(f, "invalid data"),
155 Error::WrongLength => write!(f, "wrong length"),
156 Error::NotSupportHashCode => write!(f, "not support hash code"),
157 }
158 }
159}
160
161impl ::std::error::Error for Error {}
162
163#[cfg(test)]
164mod tests {
165 use crate::{SecioKeyPair, peer_id::PeerId};
166
167 #[test]
168 fn peer_id_is_public_key() {
169 let pub_key = SecioKeyPair::secp256k1_generated().public_key();
170 let peer_id = PeerId::from_public_key(&pub_key);
171 assert!(peer_id.is_public_key(&pub_key));
172 }
173
174 #[test]
175 fn peer_id_into_bytes_then_from_bytes() {
176 let peer_id = SecioKeyPair::secp256k1_generated().peer_id();
177 let second = PeerId::from_bytes(peer_id.as_bytes().to_vec()).unwrap();
178 assert_eq!(peer_id, second);
179 }
180
181 #[test]
182 fn peer_id_to_base58_then_back() {
183 let peer_id = SecioKeyPair::secp256k1_generated().peer_id();
184 let second: PeerId = peer_id.to_base58().parse().unwrap();
185 assert_eq!(peer_id, second);
186 }
187
188 #[test]
189 fn peer_id_randomness() {
190 let peer_id = PeerId::random();
191 let second: PeerId = PeerId::random();
192 assert_ne!(peer_id, second);
193 }
194}