Skip to main content

karyon_p2p/discovery/kademlia/routing_table/
entry.rs

1use bincode::{Decode, Encode};
2
3use crate::{
4    discovery::kademlia::{bloom::Bloom, messages::PeerMsg},
5    message::PeerAddr,
6    PeerID,
7};
8
9/// Specifies the size of the key, in bytes.
10pub const KEY_SIZE: usize = 32;
11
12/// The unique key identifying the peer.
13pub type Key = [u8; KEY_SIZE];
14
15/// An Entry represents a peer in the routing table.
16#[derive(Encode, Decode, Clone, Debug)]
17pub struct Entry {
18    /// The unique key identifying the peer.
19    pub key: Key,
20    /// Connection addresses for peer-to-peer data, ordered by priority.
21    pub addrs: Vec<PeerAddr>,
22    /// Discovery addresses for lookup and refresh, ordered by priority.
23    pub discovery_addrs: Vec<PeerAddr>,
24    /// Bloom filter of protocols the peer claims to support.
25    /// Treated as a hint; handshake is the source of truth.
26    pub protocols: Bloom,
27}
28
29impl Entry {
30    /// Returns the primary address (first addr) for subnet checks, if available.
31    pub fn primary_addr(&self) -> Option<&karyon_net::Addr> {
32        self.addrs.first().map(|a| &a.addr)
33    }
34}
35
36impl PartialEq for Entry {
37    fn eq(&self, other: &Self) -> bool {
38        self.key == other.key
39    }
40}
41
42impl From<Entry> for PeerMsg {
43    fn from(entry: Entry) -> PeerMsg {
44        PeerMsg {
45            peer_id: PeerID(entry.key),
46            addrs: entry.addrs,
47            discovery_addrs: entry.discovery_addrs,
48            protocols: entry.protocols,
49        }
50    }
51}
52
53impl From<PeerMsg> for Entry {
54    fn from(peer: PeerMsg) -> Entry {
55        Entry {
56            key: peer.peer_id.0,
57            addrs: peer.addrs,
58            discovery_addrs: peer.discovery_addrs,
59            protocols: peer.protocols,
60        }
61    }
62}
63
64/// Calculates the XOR distance between two provided keys.
65///
66/// The XOR distance is a metric used in Kademlia to measure the closeness
67/// of keys.
68pub fn xor_distance(key: &Key, other: &Key) -> Key {
69    let mut res = [0; 32];
70    for (i, (k, o)) in key.iter().zip(other.iter()).enumerate() {
71        res[i] = k ^ o;
72    }
73    res
74}