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
//! ## 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::sync::Arc;

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::utils::{NetworkBuilder, PackedSocketAddr};

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;

impl NetworkBuilder<HNil, Here> {
    pub fn with_adnl<T>(
        socket_addr: T,
        keystore: Keystore,
        options: NodeOptions,
    ) -> NetworkBuilder<HCons<Arc<Node>, HNil>, Here>
    where
        T: Into<PackedSocketAddr>,
    {
        NetworkBuilder(
            HCons {
                head: Node::new(socket_addr, keystore, options, None),
                tail: HNil,
            },
            Default::default(),
        )
    }
}

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