everscale_network/adnl/
node_id.rs

1use std::borrow::Borrow;
2use std::convert::TryFrom;
3
4use everscale_crypto::{ed25519, tl};
5use rand::Rng;
6
7/// Full ADNL node id.
8///
9/// See [`PublicKey::Ed25519`]
10///
11/// [`PublicKey::Ed25519`]: everscale_crypto::tl::PublicKey::Ed25519
12#[derive(Debug, Copy, Clone, Eq, PartialEq)]
13pub struct NodeIdFull(ed25519::PublicKey);
14
15impl NodeIdFull {
16    /// Constructs full node id from a valid ED25519 public key
17    pub const fn new(public_key: ed25519::PublicKey) -> Self {
18        Self(public_key)
19    }
20
21    /// Returns inner public key
22    #[inline(always)]
23    pub const fn public_key(&self) -> &ed25519::PublicKey {
24        &self.0
25    }
26
27    /// Represents public key as a TL structure
28    #[inline(always)]
29    pub fn as_tl(&self) -> tl::PublicKey {
30        self.0.as_tl()
31    }
32
33    /// Verifies the signature of an arbitrary serializable data
34    pub fn verify<T: tl_proto::TlWrite<Repr = tl_proto::Boxed>>(
35        &self,
36        data: T,
37        other_signature: &[u8],
38    ) -> Result<(), NodeIdFullError> {
39        match <[u8; 64]>::try_from(other_signature) {
40            Ok(other_signature) if self.0.verify(data, &other_signature) => Ok(()),
41            _ => Err(NodeIdFullError::InvalidSignature),
42        }
43    }
44
45    /// Hashes inner public key
46    pub fn compute_short_id(&self) -> NodeIdShort {
47        NodeIdShort::new(tl_proto::hash(self.0.as_tl()))
48    }
49}
50
51impl From<ed25519::PublicKey> for NodeIdFull {
52    fn from(key: ed25519::PublicKey) -> Self {
53        Self::new(key)
54    }
55}
56
57impl<'a> TryFrom<tl::PublicKey<'a>> for NodeIdFull {
58    type Error = NodeIdFullError;
59
60    fn try_from(value: tl::PublicKey<'a>) -> Result<Self, Self::Error> {
61        match value {
62            tl::PublicKey::Ed25519 { key } => match ed25519::PublicKey::from_bytes(*key) {
63                Some(public_key) => Ok(Self::new(public_key)),
64                None => Err(NodeIdFullError::InvalidPublicKey),
65            },
66            _ => Err(NodeIdFullError::UnsupportedPublicKey),
67        }
68    }
69}
70
71#[derive(Debug, thiserror::Error)]
72pub enum NodeIdFullError {
73    #[error("Unsupported public key")]
74    UnsupportedPublicKey,
75    #[error("Invalid public key")]
76    InvalidPublicKey,
77    #[error("Invalid signature")]
78    InvalidSignature,
79}
80
81/// Short ADNL node id.
82#[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
83#[repr(transparent)]
84pub struct NodeIdShort([u8; 32]);
85
86impl NodeIdShort {
87    /// Constructs short node id from public key hash
88    #[inline(always)]
89    pub const fn new(hash: [u8; 32]) -> Self {
90        Self(hash)
91    }
92
93    /// Generates random short node id
94    pub fn random() -> Self {
95        Self(rand::thread_rng().gen())
96    }
97
98    /// Returns inner bytes
99    #[inline(always)]
100    pub const fn as_slice(&self) -> &[u8; 32] {
101        &self.0
102    }
103
104    #[inline(always)]
105    pub fn is_zero(&self) -> bool {
106        self == &[0; 32]
107    }
108}
109
110impl std::fmt::Display for NodeIdShort {
111    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112        let mut output = [0u8; 64];
113        hex::encode_to_slice(self.0, &mut output).ok();
114
115        // SAFETY: output is guaranteed to contain only [0-9a-f]
116        let output = unsafe { std::str::from_utf8_unchecked(&output) };
117        f.write_str(output)
118    }
119}
120
121impl std::fmt::Debug for NodeIdShort {
122    #[inline(always)]
123    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124        std::fmt::Display::fmt(self, f)
125    }
126}
127
128impl PartialEq<[u8]> for NodeIdShort {
129    #[inline(always)]
130    fn eq(&self, other: &[u8]) -> bool {
131        self.0.eq(other)
132    }
133}
134
135impl PartialEq<[u8; 32]> for NodeIdShort {
136    #[inline(always)]
137    fn eq(&self, other: &[u8; 32]) -> bool {
138        self.0.eq(other)
139    }
140}
141
142impl From<NodeIdShort> for [u8; 32] {
143    #[inline(always)]
144    fn from(id: NodeIdShort) -> Self {
145        id.0
146    }
147}
148
149impl From<&NodeIdShort> for [u8; 32] {
150    #[inline(always)]
151    fn from(id: &NodeIdShort) -> Self {
152        id.0
153    }
154}
155
156impl From<[u8; 32]> for NodeIdShort {
157    #[inline(always)]
158    fn from(id: [u8; 32]) -> Self {
159        Self(id)
160    }
161}
162
163impl Borrow<[u8; 32]> for NodeIdShort {
164    #[inline(always)]
165    fn borrow(&self) -> &[u8; 32] {
166        &self.0
167    }
168}
169
170impl<'a> Borrow<[u8; 32]> for &'a NodeIdShort {
171    #[inline(always)]
172    fn borrow(&self) -> &[u8; 32] {
173        &self.0
174    }
175}
176
177/// Abstract trait to compute all node ids
178pub trait ComputeNodeIds {
179    fn compute_node_ids(&self) -> (NodeIdFull, NodeIdShort);
180}
181
182impl ComputeNodeIds for ed25519::SecretKey {
183    fn compute_node_ids(&self) -> (NodeIdFull, NodeIdShort) {
184        let public_key = ed25519::PublicKey::from(self);
185        let full_id = NodeIdFull::new(public_key);
186        let short_id = full_id.compute_short_id();
187        (full_id, short_id)
188    }
189}
190
191impl ComputeNodeIds for ed25519::PublicKey {
192    fn compute_node_ids(&self) -> (NodeIdFull, NodeIdShort) {
193        let full_id = NodeIdFull::new(*self);
194        let short_id = full_id.compute_short_id();
195        (full_id, short_id)
196    }
197}