1use serde::{Deserialize, Serialize};
2use std::fmt;
3use std::hash::{Hash, Hasher};
4
5#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
7pub struct PeerId([u8; 32]);
8
9impl PeerId {
10 pub fn random() -> Self {
12 use bytes::Bytes;
13 let mut id = [0u8; 32];
14 for byte in &mut id {
16 *byte = rand::random();
17 }
18 Self(id)
19 }
20
21 pub fn from_bytes(bytes: [u8; 32]) -> Self {
23 Self(bytes)
24 }
25
26 pub fn as_bytes(&self) -> &[u8; 32] {
28 &self.0
29 }
30
31 pub fn xor_distance(&self, other: &PeerId) -> [u8; 32] {
33 let mut result = [0u8; 32];
34 for i in 0..32 {
35 result[i] = self.0[i] ^ other.0[i];
36 }
37 result
38 }
39
40 pub fn leading_zeros_to(&self, other: &PeerId) -> usize {
42 let distance = self.xor_distance(other);
43 let mut zeros = 0;
44 for byte in distance.iter() {
45 if *byte == 0 {
46 zeros += 8;
47 } else {
48 zeros += byte.leading_zeros() as usize;
49 break;
50 }
51 }
52 zeros
53 }
54}
55
56impl Hash for PeerId {
57 fn hash<H: Hasher>(&self, state: &mut H) {
58 self.0.hash(state);
59 }
60}
61
62impl fmt::Debug for PeerId {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 write!(f, "PeerId({}...)", hex::encode(&self.0[..4]))
65 }
66}
67
68impl fmt::Display for PeerId {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 write!(f, "{}", hex::encode(&self.0))
71 }
72}
73
74#[derive(Clone, Debug, Serialize, Deserialize)]
76pub struct PeerInfo {
77 pub id: PeerId,
79
80 pub addresses: Vec<String>,
82
83 pub public_key: [u8; 32],
85
86 pub verify_key: [u8; 32],
88
89 pub last_seen: u64,
91
92 pub reputation: f64,
94
95 pub location: Option<GeoLocation>,
97
98 pub supported_protocols: Vec<String>,
100}
101
102impl PeerInfo {
103 pub fn new(
105 id: PeerId,
106 addresses: Vec<String>,
107 public_key: [u8; 32],
108 verify_key: [u8; 32],
109 ) -> Self {
110 Self {
111 id,
112 addresses,
113 public_key,
114 verify_key,
115 last_seen: current_timestamp(),
116 reputation: 0.5, location: None,
118 supported_protocols: vec![],
119 }
120 }
121
122 pub fn touch(&mut self) {
124 self.last_seen = current_timestamp();
125 }
126
127 pub fn is_stale(&self, max_age_secs: u64) -> bool {
129 let now = current_timestamp();
130 now - self.last_seen > max_age_secs
131 }
132}
133
134#[derive(Clone, Debug, Serialize, Deserialize)]
136pub struct GeoLocation {
137 pub latitude: f64,
138 pub longitude: f64,
139 pub city: Option<String>,
140 pub country: Option<String>,
141}
142
143impl GeoLocation {
144 pub fn distance_to(&self, other: &GeoLocation) -> f64 {
146 const EARTH_RADIUS_KM: f64 = 6371.0;
148
149 let lat1 = self.latitude.to_radians();
150 let lat2 = other.latitude.to_radians();
151 let delta_lat = (other.latitude - self.latitude).to_radians();
152 let delta_lon = (other.longitude - self.longitude).to_radians();
153
154 let a = (delta_lat / 2.0).sin().powi(2)
155 + lat1.cos() * lat2.cos() * (delta_lon / 2.0).sin().powi(2);
156 let c = 2.0 * a.sqrt().atan2((1.0 - a).sqrt());
157
158 EARTH_RADIUS_KM * c
159 }
160}
161
162fn current_timestamp() -> u64 {
164 use std::time::{SystemTime, UNIX_EPOCH};
165 SystemTime::now()
166 .duration_since(UNIX_EPOCH)
167 .unwrap()
168 .as_secs()
169}
170
171mod hex {
173 pub fn encode(data: &[u8]) -> String {
174 data.iter().map(|b| format!("{:02x}", b)).collect()
175 }
176}
177
178mod rand {
180 pub fn random<T>() -> T
181 where
182 Standard: Distribution<T>,
183 {
184 Standard.sample(&mut thread_rng())
185 }
186
187 use std::sync::Mutex;
188 use std::collections::hash_map::RandomState;
189 use std::hash::{BuildHasher, Hash, Hasher};
190
191 static RNG_STATE: Mutex<u64> = Mutex::new(12345);
192
193 fn thread_rng() -> impl Iterator<Item = u8> {
194 std::iter::repeat_with(|| {
195 let mut state = RNG_STATE.lock().unwrap();
196 *state = state.wrapping_mul(6364136223846793005).wrapping_add(1);
197 (*state >> 32) as u8
198 })
199 }
200
201 pub struct Standard;
202
203 pub trait Distribution<T> {
204 fn sample<R>(&self, rng: &mut R) -> T
205 where
206 R: Iterator<Item = u8>;
207 }
208
209 impl Distribution<u8> for Standard {
210 fn sample<R>(&self, rng: &mut R) -> u8
211 where
212 R: Iterator<Item = u8>,
213 {
214 rng.next().unwrap()
215 }
216 }
217}