1#![allow(clippy::enum_variant_names)]
11#![allow(clippy::wrong_self_convention)]
13#![allow(clippy::expect_used)]
15#![allow(clippy::panic)]
16
17#[macro_use]
18extern crate tracing;
19
20pub mod constants;
22pub mod error;
24pub mod messages;
26pub mod node_rpc;
28pub mod storage;
30pub mod version;
32
33#[expect(clippy::unwrap_used, clippy::clone_on_ref_ptr)]
35#[cfg(feature = "rpc")]
36pub mod antnode_proto {
37 tonic::include_proto!("antnode_proto");
38}
39pub use error::Error;
40pub use error::Error as NetworkError;
41
42use self::storage::{ChunkAddress, GraphEntryAddress, PointerAddress, ScratchpadAddress};
43
44pub use bytes::Bytes;
46
47use libp2p::{
48 Multiaddr, PeerId,
49 kad::{KBucketDistance as Distance, KBucketKey as Key, RecordKey},
50 multiaddr::Protocol,
51};
52use serde::{Deserialize, Deserializer, Serialize, Serializer};
53use std::{
54 borrow::Cow,
55 fmt::{self, Debug, Display, Formatter, Write},
56};
57use xor_name::XorName;
58
59pub use constants::CLOSE_GROUP_SIZE;
60
61pub fn get_port_from_multiaddr(multi_addr: &Multiaddr) -> Option<u16> {
63 for protocol in multi_addr.iter() {
65 if let Protocol::Udp(port) = protocol {
66 return Some(port);
67 }
68 }
69 None
70}
71
72#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
81pub enum NetworkAddress {
82 PeerId(Bytes),
84 ChunkAddress(ChunkAddress),
86 GraphEntryAddress(GraphEntryAddress),
88 ScratchpadAddress(ScratchpadAddress),
90 PointerAddress(PointerAddress),
92 RecordKey(Bytes),
94}
95
96impl NetworkAddress {
97 pub fn as_bytes(&self) -> Vec<u8> {
99 match self {
100 NetworkAddress::PeerId(bytes) | NetworkAddress::RecordKey(bytes) => bytes.to_vec(),
101 NetworkAddress::ChunkAddress(chunk_address) => chunk_address.xorname().to_vec(),
102 NetworkAddress::GraphEntryAddress(graph_entry_address) => {
103 graph_entry_address.xorname().to_vec()
104 }
105 NetworkAddress::ScratchpadAddress(addr) => addr.xorname().to_vec(),
106 NetworkAddress::PointerAddress(pointer_address) => pointer_address.xorname().to_vec(),
107 }
108 }
109
110 pub fn as_peer_id(&self) -> Option<PeerId> {
112 if let NetworkAddress::PeerId(bytes) = self
113 && let Ok(peer_id) = PeerId::from_bytes(bytes)
114 {
115 return Some(peer_id);
116 }
117 None
118 }
119
120 pub fn as_record_key(&self) -> Option<RecordKey> {
122 match self {
123 NetworkAddress::RecordKey(bytes) => Some(RecordKey::new(bytes)),
124 _ => None,
125 }
126 }
127
128 pub fn to_record_key(&self) -> RecordKey {
130 match self {
131 NetworkAddress::RecordKey(bytes) => RecordKey::new(bytes),
132 NetworkAddress::ChunkAddress(chunk_address) => RecordKey::new(chunk_address.xorname()),
133 NetworkAddress::GraphEntryAddress(graph_entry_address) => {
134 RecordKey::new(&graph_entry_address.xorname())
135 }
136 NetworkAddress::PointerAddress(pointer_address) => {
137 RecordKey::new(&pointer_address.xorname())
138 }
139 NetworkAddress::ScratchpadAddress(addr) => RecordKey::new(&addr.xorname()),
140 NetworkAddress::PeerId(bytes) => RecordKey::new(bytes),
141 }
142 }
143
144 pub fn as_kbucket_key(&self) -> Key<Vec<u8>> {
151 Key::new(self.as_bytes())
152 }
153
154 pub fn distance(&self, other: &NetworkAddress) -> Distance {
156 self.as_kbucket_key().distance(&other.as_kbucket_key())
157 }
158}
159
160impl From<XorName> for NetworkAddress {
161 fn from(xorname: XorName) -> Self {
162 NetworkAddress::ChunkAddress(ChunkAddress::new(xorname))
163 }
164}
165
166impl From<ChunkAddress> for NetworkAddress {
167 fn from(chunk_address: ChunkAddress) -> Self {
168 NetworkAddress::ChunkAddress(chunk_address)
169 }
170}
171
172impl From<GraphEntryAddress> for NetworkAddress {
173 fn from(graph_entry_address: GraphEntryAddress) -> Self {
174 NetworkAddress::GraphEntryAddress(graph_entry_address)
175 }
176}
177
178impl From<ScratchpadAddress> for NetworkAddress {
179 fn from(scratchpad_address: ScratchpadAddress) -> Self {
180 NetworkAddress::ScratchpadAddress(scratchpad_address)
181 }
182}
183
184impl From<PointerAddress> for NetworkAddress {
185 fn from(pointer_address: PointerAddress) -> Self {
186 NetworkAddress::PointerAddress(pointer_address)
187 }
188}
189
190impl From<PeerId> for NetworkAddress {
191 fn from(peer_id: PeerId) -> Self {
192 NetworkAddress::PeerId(Bytes::from(peer_id.to_bytes()))
193 }
194}
195
196impl From<&RecordKey> for NetworkAddress {
197 fn from(record_key: &RecordKey) -> Self {
198 NetworkAddress::RecordKey(Bytes::copy_from_slice(record_key.as_ref()))
199 }
200}
201
202impl Debug for NetworkAddress {
203 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
204 let name_str = match self {
205 NetworkAddress::PeerId(_) => {
206 if let Some(peer_id) = self.as_peer_id() {
207 format!("NetworkAddress::{peer_id:?} - (")
208 } else {
209 "NetworkAddress::PeerId(".to_string()
210 }
211 }
212 NetworkAddress::ChunkAddress(chunk_address) => {
213 format!(
214 "NetworkAddress::ChunkAddress({}) - (",
215 &chunk_address.to_hex()
216 )
217 }
218 NetworkAddress::GraphEntryAddress(graph_entry_address) => {
219 format!(
220 "NetworkAddress::GraphEntryAddress({}) - (",
221 &graph_entry_address.to_hex()
222 )
223 }
224 NetworkAddress::ScratchpadAddress(scratchpad_address) => {
225 format!(
226 "NetworkAddress::ScratchpadAddress({}) - (",
227 &scratchpad_address.to_hex()
228 )
229 }
230 NetworkAddress::PointerAddress(pointer_address) => {
231 format!(
232 "NetworkAddress::PointerAddress({}) - (",
233 &pointer_address.to_hex()
234 )
235 }
236 NetworkAddress::RecordKey(bytes) => {
237 format!("NetworkAddress::RecordKey({:?}) - (", hex::encode(bytes))
238 }
239 };
240
241 write!(
242 f,
243 "{name_str}{:?})",
244 PrettyPrintKBucketKey(self.as_kbucket_key())
245 )
246 }
247}
248
249impl Display for NetworkAddress {
250 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
251 match self {
252 NetworkAddress::PeerId(id) => {
253 write!(f, "NetworkAddress::PeerId({})", hex::encode(id))
254 }
255 NetworkAddress::ChunkAddress(addr) => {
256 write!(f, "NetworkAddress::ChunkAddress({addr})")
257 }
258 NetworkAddress::GraphEntryAddress(addr) => {
259 write!(f, "NetworkAddress::GraphEntryAddress({addr})")
260 }
261 NetworkAddress::ScratchpadAddress(addr) => {
262 write!(f, "NetworkAddress::ScratchpadAddress({addr})")
263 }
264 NetworkAddress::RecordKey(key) => {
265 write!(f, "NetworkAddress::RecordKey({})", hex::encode(key))
266 }
267 NetworkAddress::PointerAddress(addr) => {
268 write!(f, "NetworkAddress::PointerAddress({addr})")
269 }
270 }
271 }
272}
273
274#[derive(Clone)]
276pub struct PrettyPrintKBucketKey(pub Key<Vec<u8>>);
277
278impl std::fmt::Display for PrettyPrintKBucketKey {
279 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
280 for byte in self.0.hashed_bytes() {
281 f.write_fmt(format_args!("{byte:02x}"))?;
282 }
283 Ok(())
284 }
285}
286
287impl std::fmt::Debug for PrettyPrintKBucketKey {
288 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
289 write!(f, "{self}")
290 }
291}
292
293#[derive(Clone, Hash, Eq, PartialEq)]
300pub struct PrettyPrintRecordKey<'a> {
301 key: Cow<'a, RecordKey>,
302}
303
304impl Serialize for PrettyPrintRecordKey<'_> {
305 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
306 where
307 S: Serializer,
308 {
309 let record_key_bytes = match &self.key {
310 Cow::Borrowed(borrowed_key) => borrowed_key.as_ref(),
311 Cow::Owned(owned_key) => owned_key.as_ref(),
312 };
313 record_key_bytes.serialize(serializer)
314 }
315}
316
317impl<'de> Deserialize<'de> for PrettyPrintRecordKey<'static> {
319 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
320 where
321 D: Deserializer<'de>,
322 {
323 let bytes = Vec::<u8>::deserialize(deserializer)?;
325 Ok(PrettyPrintRecordKey {
327 key: Cow::Owned(RecordKey::new(&bytes)),
328 })
329 }
330}
331impl<'a> From<&'a RecordKey> for PrettyPrintRecordKey<'a> {
334 fn from(key: &'a RecordKey) -> Self {
335 PrettyPrintRecordKey {
336 key: Cow::Borrowed(key),
337 }
338 }
339}
340
341impl PrettyPrintRecordKey<'_> {
342 pub fn into_owned(self) -> PrettyPrintRecordKey<'static> {
345 let cloned_key = match self.key {
346 Cow::Borrowed(key) => Cow::Owned(key.clone()),
347 Cow::Owned(key) => Cow::Owned(key),
348 };
349
350 PrettyPrintRecordKey { key: cloned_key }
351 }
352
353 pub fn no_kbucket_log(self) -> String {
354 let mut content = String::from("");
355 let record_key_bytes = match &self.key {
356 Cow::Borrowed(borrowed_key) => borrowed_key.as_ref(),
357 Cow::Owned(owned_key) => owned_key.as_ref(),
358 };
359 for byte in record_key_bytes {
360 let _ = content.write_fmt(format_args!("{byte:02x}"));
361 }
362 content
363 }
364}
365
366impl std::fmt::Display for PrettyPrintRecordKey<'_> {
367 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
368 let record_key_bytes = match &self.key {
369 Cow::Borrowed(borrowed_key) => borrowed_key.as_ref(),
370 Cow::Owned(owned_key) => owned_key.as_ref(),
371 };
372 for byte in record_key_bytes.iter().take(3) {
374 f.write_fmt(format_args!("{byte:02x}"))?;
375 }
376
377 write!(
378 f,
379 "({:?})",
380 PrettyPrintKBucketKey(NetworkAddress::from(self.key.as_ref()).as_kbucket_key())
381 )
382 }
383}
384
385impl std::fmt::Debug for PrettyPrintRecordKey<'_> {
386 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
387 write!(f, "{self}")
389 }
390}
391
392#[cfg(test)]
393mod tests {
394 use crate::{
395 NetworkAddress, PeerId,
396 messages::{Nonce, Query},
397 storage::GraphEntryAddress,
398 };
399 use serde::{Deserialize, Serialize};
400
401 #[test]
402 fn verify_graph_entry_addr_is_actionable() {
403 let pk = bls::SecretKey::random().public_key();
404 let graph_entry_addr = GraphEntryAddress::new(pk);
405 let net_addr = NetworkAddress::from(graph_entry_addr);
406
407 let graph_entry_addr_hex = &graph_entry_addr.to_hex();
408 let net_addr_fmt = format!("{net_addr}");
409
410 assert!(net_addr_fmt.contains(graph_entry_addr_hex));
411 }
412
413 #[derive(Eq, PartialEq, PartialOrd, Clone, Serialize, Deserialize, Debug)]
414 enum QueryExtended {
415 GetStoreQuote {
416 key: NetworkAddress,
417 data_type: u32,
418 data_size: usize,
419 nonce: Option<Nonce>,
420 difficulty: usize,
421 },
422 GetReplicatedRecord {
423 requester: NetworkAddress,
424 key: NetworkAddress,
425 },
426 GetChunkExistenceProof {
427 key: NetworkAddress,
428 nonce: Nonce,
429 difficulty: usize,
430 },
431 CheckNodeInProblem(NetworkAddress),
432 GetClosestPeers {
433 key: NetworkAddress,
434 num_of_peers: Option<usize>,
435 range: Option<[u8; 32]>,
436 sign_result: bool,
437 },
438 GetVersion(NetworkAddress),
439 AdditionalVariant(NetworkAddress), }
441
442 #[test]
443 fn test_query_serialization_deserialization() {
444 let peer_id = PeerId::random();
445 let original_query = Query::GetStoreQuote {
447 key: NetworkAddress::from(peer_id),
448 data_type: 1,
449 data_size: 100,
450 nonce: Some(0),
451 difficulty: 3,
452 };
453
454 let serialized = bincode::serialize(&original_query).expect("Serialization failed");
456
457 let deserialized: QueryExtended =
459 bincode::deserialize(&serialized).expect("Deserialization into QueryExtended failed");
460
461 match deserialized {
463 QueryExtended::GetStoreQuote {
464 key,
465 data_type,
466 data_size,
467 nonce,
468 difficulty,
469 } => {
470 assert_eq!(key, NetworkAddress::from(peer_id));
471 assert_eq!(data_type, 1);
472 assert_eq!(data_size, 100);
473 assert_eq!(nonce, Some(0));
474 assert_eq!(difficulty, 3);
475 }
476 _ => panic!("Deserialized into wrong variant"),
477 }
478 }
479
480 #[test]
481 fn test_query_extended_serialization() {
482 let extended_query =
484 QueryExtended::AdditionalVariant(NetworkAddress::from(PeerId::random()));
485
486 let serialized = bincode::serialize(&extended_query).expect("Serialization failed");
488
489 let result: Result<Query, _> = bincode::deserialize(&serialized);
491 assert!(
492 result.is_err(),
493 "Should fail to deserialize extended enum into original"
494 );
495
496 let peer_id = PeerId::random();
497 let extended_query = QueryExtended::GetStoreQuote {
499 key: NetworkAddress::from(peer_id),
500 data_type: 1,
501 data_size: 100,
502 nonce: Some(0),
503 difficulty: 3,
504 };
505
506 let serialized = bincode::serialize(&extended_query).expect("Serialization failed");
508
509 let deserialized: Query =
511 bincode::deserialize(&serialized).expect("Deserialization into Query failed");
512
513 match deserialized {
515 Query::GetStoreQuote {
516 key,
517 data_type,
518 data_size,
519 nonce,
520 difficulty,
521 } => {
522 assert_eq!(key, NetworkAddress::from(peer_id));
523 assert_eq!(data_type, 1);
524 assert_eq!(data_size, 100);
525 assert_eq!(nonce, Some(0));
526 assert_eq!(difficulty, 3);
527 }
528 _ => panic!("Deserialized into wrong variant"),
529 }
530 }
531}