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

use std::net::{SocketAddr, SocketAddrV4, ToSocketAddrs};
use std::sync::Arc;

use anyhow::{Context, Result};
use frunk_core::hlist::{HCons, HList, HNil, Selector};
use frunk_core::indices::Here;

pub use self::keystore::{Key, Keystore};
pub use self::node::{Node, NodeMetrics, NodeOptions};
pub use self::node_id::{ComputeNodeIds, NodeIdFull, NodeIdShort};
pub use self::peer::{NewPeerContext, PeerFilter};
pub use self::peers_set::PeersSet;

use crate::subscriber::{MessageSubscriber, QuerySubscriber};
use crate::util::{DeferredInitialization, NetworkBuilder};

mod channel;
mod encryption;
mod handshake;
mod keystore;
mod node;
mod node_id;
mod packet_view;
mod peer;
mod peers_set;
mod ping_subscriber;
mod queries_cache;
mod socket;
mod transfer;

pub(crate) type Deferred = Result<Arc<Node>>;

impl DeferredInitialization for Deferred {
    type Initialized = Arc<Node>;

    fn initialize(self) -> Result<Self::Initialized> {
        let adnl = self?;
        adnl.start()?;
        Ok(adnl)
    }
}

impl NetworkBuilder<HNil, (Here, Here)> {
    /// Creates a basic network layer that is an ADNL node
    ///
    /// See [`with_adnl_ext`] if you need a node with a peer filter
    ///
    /// [`with_adnl_ext`]: fn@crate::util::NetworkBuilder::with_adnl_ext
    ///
    /// # Examples
    ///
    /// ```
    /// # use anyhow::Result;
    /// # use everscale_network::{adnl, NetworkBuilder};
    /// #[tokio::main]
    /// async fn main() -> Result<()> {
    ///     let keystore = adnl::Keystore::builder()
    ///         .with_tagged_key([0; 32], 0)?
    ///         .build();
    ///
    ///     let options = adnl::NodeOptions::default();
    ///
    ///     let adnl = NetworkBuilder::with_adnl("127.0.0.1:10000", keystore, options).build()?;
    ///
    ///     Ok(())
    /// }
    /// ```
    pub fn with_adnl<T>(
        addr: T,
        keystore: Keystore,
        options: NodeOptions,
    ) -> NetworkBuilder<HCons<Deferred, HNil>, (Here, Here)>
    where
        T: ToSocketAddrs,
    {
        NetworkBuilder(
            HCons {
                head: parse_socket_addr(addr)
                    .and_then(|addr| Node::new(addr, keystore, options, None)),
                tail: HNil,
            },
            Default::default(),
        )
    }

    /// Creates a basic network layer that is an ADNL node with additional filter
    ///
    /// # Examples
    ///
    /// ```
    /// # use std::net::SocketAddrV4;
    /// # use std::sync::Arc;
    /// # use anyhow::Result;
    /// # use everscale_network::{adnl, NetworkBuilder};
    /// struct MyFilter;
    ///
    /// impl adnl::PeerFilter for MyFilter {
    ///     fn check(
    ///         &self,
    ///         ctx: adnl::NewPeerContext,
    ///         addr: SocketAddrV4,
    ///         peer_id: &adnl::NodeIdShort,
    ///     ) -> bool {
    ///         // Allow only non-loopback IPs
    ///         !addr.ip().is_loopback()
    ///     }
    /// }
    ///
    /// #[tokio::main]
    /// async fn main() -> Result<()> {
    ///     let keystore = adnl::Keystore::builder()
    ///         .with_tagged_key([0; 32], 0)?
    ///         .build();
    ///
    ///     let options = adnl::NodeOptions::default();
    ///
    ///     let peer_filter = Arc::new(MyFilter);
    ///
    ///     let adnl = NetworkBuilder::with_adnl_ext("127.0.0.1:10000", keystore, options, peer_filter)
    ///         .build()?;
    ///
    ///     Ok(())
    /// }
    /// ```
    pub fn with_adnl_ext<T>(
        addr: T,
        keystore: Keystore,
        options: NodeOptions,
        peer_filter: Arc<dyn PeerFilter>,
    ) -> NetworkBuilder<HCons<Deferred, HNil>, (Here, Here)>
    where
        T: ToSocketAddrs,
    {
        NetworkBuilder(
            HCons {
                head: parse_socket_addr(addr)
                    .and_then(|addr| Node::new(addr, keystore, options, Some(peer_filter))),
                tail: HNil,
            },
            Default::default(),
        )
    }
}

impl<L, A, R> NetworkBuilder<L, (A, R)>
where
    L: HList + Selector<Deferred, A>,
{
    /// Adds query subscriber if ADNL was successfully initialized.
    ///
    /// # Examples
    ///
    /// ```
    /// # use std::sync::Arc;
    /// # use std::borrow::Cow;
    /// # use anyhow::Result;
    /// # use everscale_network::{adnl, NetworkBuilder, QuerySubscriber, QueryConsumingResult, SubscriberContext};
    /// struct Service;
    ///
    /// #[async_trait::async_trait]
    /// impl QuerySubscriber for Service {
    ///     async fn try_consume_query<'a>(
    ///         &self,
    ///         _ctx: SubscriberContext<'a>,
    ///         _constructor: u32,
    ///         _query: Cow<'a, [u8]>,
    ///     ) -> Result<QueryConsumingResult<'a>> {
    ///         Ok(QueryConsumingResult::Consumed(None))
    ///     }
    /// }
    ///
    /// #[tokio::main]
    /// async fn main() -> Result<()> {
    ///     let keystore = adnl::Keystore::builder()
    ///         .with_tagged_key([0; 32], 0)?
    ///         .build();
    ///
    ///     let options = adnl::NodeOptions::default();
    ///
    ///     let adnl = NetworkBuilder::with_adnl("127.0.0.1:10000", keystore, options)
    ///         .with_query_subscriber(Arc::new(Service))
    ///         .build()?;
    ///
    ///     Ok(())
    /// }
    /// ```
    pub fn with_query_subscriber(self, subscriber: Arc<dyn QuerySubscriber>) -> Self {
        if let Ok(adnl) = self.0.get() {
            adnl.add_query_subscriber(subscriber).ok();
        }
        self
    }

    /// Adds custom message subscriber if ADNL was successfully initialized.
    ///
    /// # Examples
    ///
    /// ```
    /// # use std::sync::Arc;
    /// # use anyhow::Result;
    /// # use everscale_network::{adnl, MessageSubscriber, NetworkBuilder, SubscriberContext};
    /// struct Service;
    ///
    /// #[async_trait::async_trait]
    /// impl MessageSubscriber for Service {
    ///     async fn try_consume_custom<'a>(
    ///         &self,
    ///         _ctx: SubscriberContext<'a>,
    ///         _constructor: u32,
    ///         _data: &'a [u8],
    ///     ) -> Result<bool> {
    ///         Ok(true)
    ///     }
    /// }
    ///
    /// #[tokio::main]
    /// async fn main() -> Result<()> {
    ///     let keystore = adnl::Keystore::builder()
    ///         .with_tagged_key([0; 32], 0)?
    ///         .build();
    ///
    ///     let options = adnl::NodeOptions::default();
    ///
    ///     let adnl = NetworkBuilder::with_adnl("127.0.0.1:10000", keystore, options)
    ///         .with_message_subscriber(Arc::new(Service))
    ///         .build()?;
    ///
    ///     Ok(())
    /// }
    /// ```
    pub fn with_message_subscriber(self, subscriber: Arc<dyn MessageSubscriber>) -> Self {
        if let Ok(adnl) = self.0.get() {
            adnl.add_message_subscriber(subscriber).ok();
        }
        self
    }
}

fn parse_socket_addr<T: ToSocketAddrs>(addr: T) -> Result<SocketAddrV4> {
    match addr
        .to_socket_addrs()
        .context("Failed to parse socket addr")?
        .next()
    {
        Some(SocketAddr::V4(addr)) => Ok(addr),
        Some(SocketAddr::V6(_)) => anyhow::bail!("IPv6 is not supported"),
        None => anyhow::bail!("Invalid ip address"),
    }
}