Skip to main content

everscale_network/adnl/
mod.rs

1//! ## ADNL - Abstract Datagram Network Layer
2//!
3//! ADNL is a UDP-based data transfer protocol. It is a base layer for other protocols, used
4//! in Everscale. It provides no guarantees of reliability, so it should only be used for
5//! small data transfers. There is a support for multipart transfers, but the user must be
6//! prepared, that some parts of them may be lost and full transfer will be lost.
7//!
8//! #### Brief overview
9//!
10//! Each peer has its own keypair. In most cases it is a ed25519 keypair
11//! (see [`KeyPair`]). The public key of this keypair is also called
12//! a **full peer id** ([`NodeIdFull`]). The hash of the TL representation
13//! of its full id is a **short peer id** ([`NodeIdShort`]).
14//!
15//! Each peer remembers unix timestamp (in seconds) at the moment of initialization.
16//! It is called **reinit date** and used to describe peer's state "version".
17//! If other peers see that the reinit date of peer `A` has changed, they must treat
18//! peer `A` as a completely new peer.
19//!
20//! ADNL maintains a state for each peer it has communicated with. This state contains
21//! unique channel keypair, reinit date of the remote peer and sequence numbers of packets
22//! for both directions.
23//!
24//! Communication between peers is done by sending packets through UDP. Each packet length must be
25//! less than MTU (*1500 bytes*). Packets are encrypted with a shared secret key and have some basic
26//! integrity checks (checksum), ordering (sequence numbers, timings) and deduplication
27//! (short packets history). Packet can contain multiple ADNL messages ([`Message`]) and must
28//! address a specific peer by specifying its short or full peer id.
29//!
30//! #### Packet versions
31//!
32//! - **Handshake packet**: when peer `A` sends its first message to the peer `B` it wraps it into
33//!   a handshake packet. For each packet peer `A` generates new keypair.
34//!   It computes shared secret using `x25519(random_secret_key, peer_B_public_key)` and uses it
35//!   to encrypt data. When peer `B` receives this packet it computes shared secret using
36//!   `x25519(peer_B_secret_key, random_public_key)` and uses it to decrypt data. So handshake
37//!   packet contains peer `B` short id, public key of the random keypair, checksum and encrypted data.
38//!
39//! - **Channel packet**: after channel has been established, each peer will use a smaller packet
40//!   structure called channel packet. Instead of generating a new keypair for each packet it will
41//!   use shared secret from the channel to encrypt and decrypt data. Channel packet contains
42//!   channel id, checksum and encrypted data.
43//!
44//! #### Message types
45//!
46//! - **`Nop`** - an empty message that is only used by the other peer to update the state of our peer.
47//! - **`Custom`** - a one-way message that just contains a raw data. Mostly used by RLDP or other
48//!   protocols on top of ADNL.
49//! - **`Query`** - a request to the other peer which in most cases requires a response.
50//! - **`Answer`** - a response to the **`Query`** message.
51//! - **`CreateChannel`** - a special message with the info about newly created channel. Remote peer
52//!   should also create a channel and send a confirmation about this.
53//! - **`ConfirmChannel`** - channel confirmation to the **`CreateChannel`** message.
54//! - **`Part`** - special message that is used to split a large message across multiple packets.
55//!   After all message parts are received, the data is combined and deserialized into the original
56//!   message. Will mostly be used for large **`Custom`**, **`Query`** or **`Answer`** messages.
57//!
58//! #### Channels
59//!
60//! Communication using only handshake packets is quite inefficient, so there is a some kind of
61//! short-lived connections. When new remove peer is added, the channel keypair is also generated.
62//! With the first packet, peer `A` sends a **`CreateChannel`** message where it specifies channel
63//! public key from its side (and the date of its creation). Peer `B` replies with a **`ConfirmChannel`**
64//! message where it specifies same values and the channel public key from its side.
65//!
66//! Each peer can now create four shared secrets: two for encryption and two for decryption. Why two?
67//! Because there are two versions of channels - ordinary and priority. There is not a lot of difference
68//! between them, but some nodes could handle packet from the priority channel first.
69//!
70//! When remove peer is inactive for some time, and any query to it completes with timeout, the channel
71//! is regenerated.
72//!
73//! [`KeyPair`]: everscale_crypto::ed25519::KeyPair
74//! [`NodeIdFull`]: NodeIdFull
75//! [`NodeIdShort`]: NodeIdShort
76//! [`Message`]: crate::proto::adnl::Message
77
78use std::net::{SocketAddr, SocketAddrV4, ToSocketAddrs};
79use std::sync::Arc;
80
81use anyhow::{Context, Result};
82use frunk_core::hlist::{HCons, HList, HNil, Selector};
83use frunk_core::indices::Here;
84
85pub use self::keystore::{Key, Keystore};
86pub use self::node::{Node, NodeMetrics, NodeOptions};
87pub use self::node_id::{ComputeNodeIds, NodeIdFull, NodeIdShort};
88pub use self::peer::{NewPeerContext, PeerFilter};
89pub use self::peers_set::PeersSet;
90
91use crate::subscriber::{MessageSubscriber, QuerySubscriber};
92use crate::util::{DeferredInitialization, NetworkBuilder};
93
94mod channel;
95mod encryption;
96mod handshake;
97mod keystore;
98mod node;
99mod node_id;
100mod packet_view;
101mod peer;
102mod peers_set;
103mod ping_subscriber;
104mod queries_cache;
105mod socket;
106mod transfer;
107
108pub(crate) type Deferred = Result<Arc<Node>>;
109
110impl DeferredInitialization for Deferred {
111    type Initialized = Arc<Node>;
112
113    fn initialize(self) -> Result<Self::Initialized> {
114        let adnl = self?;
115        adnl.start()?;
116        Ok(adnl)
117    }
118}
119
120impl NetworkBuilder<HNil, (Here, Here)> {
121    /// Creates a basic network layer that is an ADNL node
122    ///
123    /// See [`with_adnl_ext`] if you need a node with a peer filter
124    ///
125    /// [`with_adnl_ext`]: fn@crate::util::NetworkBuilder::with_adnl_ext
126    ///
127    /// # Examples
128    ///
129    /// ```
130    /// # use anyhow::Result;
131    /// # use everscale_network::{adnl, NetworkBuilder};
132    /// #[tokio::main]
133    /// async fn main() -> Result<()> {
134    ///     let keystore = adnl::Keystore::builder()
135    ///         .with_tagged_key([0; 32], 0)?
136    ///         .build();
137    ///
138    ///     let options = adnl::NodeOptions::default();
139    ///
140    ///     let adnl = NetworkBuilder::with_adnl("127.0.0.1:10000", keystore, options).build()?;
141    ///
142    ///     Ok(())
143    /// }
144    /// ```
145    pub fn with_adnl<T>(
146        addr: T,
147        keystore: Keystore,
148        options: NodeOptions,
149    ) -> NetworkBuilder<HCons<Deferred, HNil>, (Here, Here)>
150    where
151        T: ToSocketAddrs,
152    {
153        NetworkBuilder(
154            HCons {
155                head: parse_socket_addr(addr)
156                    .and_then(|addr| Node::new(addr, keystore, options, None)),
157                tail: HNil,
158            },
159            Default::default(),
160        )
161    }
162
163    /// Creates a basic network layer that is an ADNL node with additional filter
164    ///
165    /// # Examples
166    ///
167    /// ```
168    /// # use std::net::SocketAddrV4;
169    /// # use std::sync::Arc;
170    /// # use anyhow::Result;
171    /// # use everscale_network::{adnl, NetworkBuilder};
172    /// struct MyFilter;
173    ///
174    /// impl adnl::PeerFilter for MyFilter {
175    ///     fn check(
176    ///         &self,
177    ///         ctx: adnl::NewPeerContext,
178    ///         addr: SocketAddrV4,
179    ///         peer_id: &adnl::NodeIdShort,
180    ///     ) -> bool {
181    ///         // Allow only non-loopback IPs
182    ///         !addr.ip().is_loopback()
183    ///     }
184    /// }
185    ///
186    /// #[tokio::main]
187    /// async fn main() -> Result<()> {
188    ///     let keystore = adnl::Keystore::builder()
189    ///         .with_tagged_key([0; 32], 0)?
190    ///         .build();
191    ///
192    ///     let options = adnl::NodeOptions::default();
193    ///
194    ///     let peer_filter = Arc::new(MyFilter);
195    ///
196    ///     let adnl = NetworkBuilder::with_adnl_ext("127.0.0.1:10000", keystore, options, peer_filter)
197    ///         .build()?;
198    ///
199    ///     Ok(())
200    /// }
201    /// ```
202    pub fn with_adnl_ext<T>(
203        addr: T,
204        keystore: Keystore,
205        options: NodeOptions,
206        peer_filter: Arc<dyn PeerFilter>,
207    ) -> NetworkBuilder<HCons<Deferred, HNil>, (Here, Here)>
208    where
209        T: ToSocketAddrs,
210    {
211        NetworkBuilder(
212            HCons {
213                head: parse_socket_addr(addr)
214                    .and_then(|addr| Node::new(addr, keystore, options, Some(peer_filter))),
215                tail: HNil,
216            },
217            Default::default(),
218        )
219    }
220}
221
222impl<L, A, R> NetworkBuilder<L, (A, R)>
223where
224    L: HList + Selector<Deferred, A>,
225{
226    /// Adds query subscriber if ADNL was successfully initialized.
227    ///
228    /// # Examples
229    ///
230    /// ```
231    /// # use std::sync::Arc;
232    /// # use std::borrow::Cow;
233    /// # use anyhow::Result;
234    /// # use everscale_network::{adnl, NetworkBuilder, QuerySubscriber, QueryConsumingResult, SubscriberContext};
235    /// struct Service;
236    ///
237    /// #[async_trait::async_trait]
238    /// impl QuerySubscriber for Service {
239    ///     async fn try_consume_query<'a>(
240    ///         &self,
241    ///         _ctx: SubscriberContext<'a>,
242    ///         _constructor: u32,
243    ///         _query: Cow<'a, [u8]>,
244    ///     ) -> Result<QueryConsumingResult<'a>> {
245    ///         Ok(QueryConsumingResult::Consumed(None))
246    ///     }
247    /// }
248    ///
249    /// #[tokio::main]
250    /// async fn main() -> Result<()> {
251    ///     let keystore = adnl::Keystore::builder()
252    ///         .with_tagged_key([0; 32], 0)?
253    ///         .build();
254    ///
255    ///     let options = adnl::NodeOptions::default();
256    ///
257    ///     let adnl = NetworkBuilder::with_adnl("127.0.0.1:10000", keystore, options)
258    ///         .with_query_subscriber(Arc::new(Service))
259    ///         .build()?;
260    ///
261    ///     Ok(())
262    /// }
263    /// ```
264    pub fn with_query_subscriber(self, subscriber: Arc<dyn QuerySubscriber>) -> Self {
265        if let Ok(adnl) = self.0.get() {
266            adnl.add_query_subscriber(subscriber).ok();
267        }
268        self
269    }
270
271    /// Adds custom message subscriber if ADNL was successfully initialized.
272    ///
273    /// # Examples
274    ///
275    /// ```
276    /// # use std::sync::Arc;
277    /// # use anyhow::Result;
278    /// # use everscale_network::{adnl, MessageSubscriber, NetworkBuilder, SubscriberContext};
279    /// struct Service;
280    ///
281    /// #[async_trait::async_trait]
282    /// impl MessageSubscriber for Service {
283    ///     async fn try_consume_custom<'a>(
284    ///         &self,
285    ///         _ctx: SubscriberContext<'a>,
286    ///         _constructor: u32,
287    ///         _data: &'a [u8],
288    ///     ) -> Result<bool> {
289    ///         Ok(true)
290    ///     }
291    /// }
292    ///
293    /// #[tokio::main]
294    /// async fn main() -> Result<()> {
295    ///     let keystore = adnl::Keystore::builder()
296    ///         .with_tagged_key([0; 32], 0)?
297    ///         .build();
298    ///
299    ///     let options = adnl::NodeOptions::default();
300    ///
301    ///     let adnl = NetworkBuilder::with_adnl("127.0.0.1:10000", keystore, options)
302    ///         .with_message_subscriber(Arc::new(Service))
303    ///         .build()?;
304    ///
305    ///     Ok(())
306    /// }
307    /// ```
308    pub fn with_message_subscriber(self, subscriber: Arc<dyn MessageSubscriber>) -> Self {
309        if let Ok(adnl) = self.0.get() {
310            adnl.add_message_subscriber(subscriber).ok();
311        }
312        self
313    }
314}
315
316fn parse_socket_addr<T: ToSocketAddrs>(addr: T) -> Result<SocketAddrV4> {
317    match addr
318        .to_socket_addrs()
319        .context("Failed to parse socket addr")?
320        .next()
321    {
322        Some(SocketAddr::V4(addr)) => Ok(addr),
323        Some(SocketAddr::V6(_)) => anyhow::bail!("IPv6 is not supported"),
324        None => anyhow::bail!("Invalid ip address"),
325    }
326}