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
//! ## 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, HNil};
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::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)> {
    pub fn with_adnl<T>(
        addr: T,
        keystore: Keystore,
        options: NodeOptions,
    ) -> NetworkBuilder<HCons<Deferred, HNil>, (Here, Here)>
    where
        T: ToSocketAddrs,
    {
        Self::with_adnl_ext(addr, keystore, options, None)
    }

    pub fn with_adnl_ext<T>(
        addr: T,
        keystore: Keystore,
        options: NodeOptions,
        peer_filter: Option<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, peer_filter)),
                tail: HNil,
            },
            Default::default(),
        )
    }
}

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"),
    }
}

impl<I> NetworkBuilder<HCons<Deferred, HNil>, I> {
    pub fn build(self) -> Result<Arc<Node>> {
        self.0.head.initialize()
    }
}