litep2p/protocol/libp2p/kademlia/
types.rs1use crate::{protocol::libp2p::kademlia::schema, PeerId};
25
26use multiaddr::Multiaddr;
27use sha2::{
28 digest::generic_array::{typenum::U32, GenericArray},
29 Digest, Sha256,
30};
31use uint::*;
32
33use std::{
34 borrow::Borrow,
35 hash::{Hash, Hasher},
36};
37
38construct_uint! {
39 pub(super) struct U256(4);
41}
42
43#[derive(Clone, Debug)]
51pub struct Key<T: Clone> {
52 preimage: T,
53 bytes: KeyBytes,
54}
55
56impl<T: Clone> Key<T> {
57 pub fn new(preimage: T) -> Key<T>
63 where
64 T: Borrow<[u8]>,
65 {
66 let bytes = KeyBytes::new(preimage.borrow());
67 Key { preimage, bytes }
68 }
69
70 pub fn into_preimage(self) -> T {
72 self.preimage
73 }
74
75 pub fn distance<U>(&self, other: &U) -> Distance
77 where
78 U: AsRef<KeyBytes>,
79 {
80 self.bytes.distance(other)
81 }
82
83 #[cfg(test)]
89 pub fn for_distance(&self, d: Distance) -> KeyBytes {
90 self.bytes.for_distance(d)
91 }
92
93 #[cfg(test)]
97 pub fn from_bytes(bytes: KeyBytes, preimage: T) -> Key<T> {
98 Self { bytes, preimage }
99 }
100}
101
102impl<T: Clone> From<Key<T>> for KeyBytes {
103 fn from(key: Key<T>) -> KeyBytes {
104 key.bytes
105 }
106}
107
108impl From<PeerId> for Key<PeerId> {
109 fn from(p: PeerId) -> Self {
110 let bytes = KeyBytes(Sha256::digest(p.to_bytes()));
111 Key { preimage: p, bytes }
112 }
113}
114
115impl From<Vec<u8>> for Key<Vec<u8>> {
116 fn from(b: Vec<u8>) -> Self {
117 Key::new(b)
118 }
119}
120
121impl<T: Clone> AsRef<KeyBytes> for Key<T> {
122 fn as_ref(&self) -> &KeyBytes {
123 &self.bytes
124 }
125}
126
127impl<T: Clone, U: Clone> PartialEq<Key<U>> for Key<T> {
128 fn eq(&self, other: &Key<U>) -> bool {
129 self.bytes == other.bytes
130 }
131}
132
133impl<T: Clone> Eq for Key<T> {}
134
135impl<T: Clone> Hash for Key<T> {
136 fn hash<H: Hasher>(&self, state: &mut H) {
137 self.bytes.0.hash(state);
138 }
139}
140
141#[derive(PartialEq, Eq, Clone, Debug)]
143pub struct KeyBytes(GenericArray<u8, U32>);
144
145impl KeyBytes {
146 pub fn new<T>(value: T) -> Self
149 where
150 T: Borrow<[u8]>,
151 {
152 KeyBytes(Sha256::digest(value.borrow()))
153 }
154
155 pub fn distance<U>(&self, other: &U) -> Distance
157 where
158 U: AsRef<KeyBytes>,
159 {
160 let a = U256::from(self.0.as_slice());
161 let b = U256::from(other.as_ref().0.as_slice());
162 Distance(a ^ b)
163 }
164
165 #[cfg(test)]
171 pub fn for_distance(&self, d: Distance) -> KeyBytes {
172 let key_int = U256::from(self.0.as_slice()) ^ d.0;
173 KeyBytes(GenericArray::from(<[u8; 32]>::from(key_int)))
174 }
175}
176
177impl AsRef<KeyBytes> for KeyBytes {
178 fn as_ref(&self) -> &KeyBytes {
179 self
180 }
181}
182
183#[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Debug)]
185pub struct Distance(pub(super) U256);
186
187impl Distance {
188 pub fn ilog2(&self) -> Option<u32> {
192 (256 - self.0.leading_zeros()).checked_sub(1)
193 }
194}
195
196#[derive(Debug, Copy, Clone, PartialEq, Eq)]
198pub enum ConnectionType {
199 NotConnected,
201
202 Connected,
204
205 CanConnect,
207
208 CannotConnect,
210}
211
212impl TryFrom<i32> for ConnectionType {
213 type Error = ();
214
215 fn try_from(value: i32) -> Result<Self, Self::Error> {
216 match value {
217 0 => Ok(ConnectionType::NotConnected),
218 1 => Ok(ConnectionType::Connected),
219 2 => Ok(ConnectionType::CanConnect),
220 3 => Ok(ConnectionType::CannotConnect),
221 _ => Err(()),
222 }
223 }
224}
225
226impl From<ConnectionType> for i32 {
227 fn from(connection: ConnectionType) -> Self {
228 match connection {
229 ConnectionType::NotConnected => 0,
230 ConnectionType::Connected => 1,
231 ConnectionType::CanConnect => 2,
232 ConnectionType::CannotConnect => 3,
233 }
234 }
235}
236
237#[derive(Debug, Clone, PartialEq, Eq)]
239pub struct KademliaPeer {
240 pub(super) key: Key<PeerId>,
242
243 pub(super) peer: PeerId,
245
246 pub(super) addresses: Vec<Multiaddr>,
248
249 pub(super) connection: ConnectionType,
251}
252
253impl KademliaPeer {
254 pub fn new(peer: PeerId, addresses: Vec<Multiaddr>, connection: ConnectionType) -> Self {
256 Self {
257 peer,
258 addresses,
259 connection,
260 key: Key::from(peer),
261 }
262 }
263}
264
265impl TryFrom<&schema::kademlia::Peer> for KademliaPeer {
266 type Error = ();
267
268 fn try_from(record: &schema::kademlia::Peer) -> Result<Self, Self::Error> {
269 let peer = PeerId::from_bytes(&record.id).map_err(|_| ())?;
270
271 Ok(KademliaPeer {
272 key: Key::from(peer),
273 peer,
274 addresses: record
275 .addrs
276 .iter()
277 .filter_map(|address| Multiaddr::try_from(address.clone()).ok())
278 .collect(),
279 connection: ConnectionType::try_from(record.connection)?,
280 })
281 }
282}
283
284impl From<&KademliaPeer> for schema::kademlia::Peer {
285 fn from(peer: &KademliaPeer) -> Self {
286 schema::kademlia::Peer {
287 id: peer.peer.to_bytes(),
288 addrs: peer.addresses.iter().map(|address| address.to_vec()).collect(),
289 connection: peer.connection.into(),
290 }
291 }
292}