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
use super::config;
use crate::{
    network::p2p::Address,
    topology::{layers::LayersConfig, NodeId, QuarantineConfig},
};
use ::multiaddr::Multiaddr;
use chain_crypto::Ed25519;
use jormungandr_lib::{crypto::key::SigningKey, multiaddr};
use std::{net::SocketAddr, str, time::Duration};

/// Protocol to use for a connection.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Protocol {
    Ntt,
    Grpc,
}

/// represent a connection peer
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Peer {
    /// the connection to connect to
    pub connection: SocketAddr,
    /// Network protocol to use for this connection.
    pub protocol: Protocol,
    /// a timeout in case of inactivity or timout between request.
    pub timeout: Duration,
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Listen {
    /// connection to listen to and start accepting connection from
    pub connection: SocketAddr,
    /// Network protocol to use for this connection.
    pub protocol: Protocol,
    /// timeout of the connected peers. Will be set for when/if we
    /// send them commands, queries or else and they timedout.
    ///
    /// Every derived connection will receive this timeout
    pub timeout: Duration,
}

/// The limit on the number of simultaneous P2P connections
/// used unless the corresponding configuration option is specified.
pub const DEFAULT_MAX_CONNECTIONS: usize = 256;

/// The limit on the number of simultaneous P2P client connections
/// used unless the corresponding configuration option is specified.
pub const DEFAULT_MAX_CLIENT_CONNECTIONS: usize = 192;

/// The default timeout for connections
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);

///
/// The network static configuration settings
#[derive(Clone)]
pub struct Configuration {
    /// Local socket address to listen to, if different from public address.
    /// The IP address can be given as 0.0.0.0 or :: to bind to all
    /// network interfaces.
    pub listen_address: Option<SocketAddr>,

    pub public_address: Option<Address>,

    // Secret key used to authenticate communications, the public part is used as an identifier of the node
    pub node_key: SigningKey<Ed25519>,

    /// list of trusted addresses
    pub trusted_peers: Vec<TrustedPeer>,

    /// the protocol to utilise for the p2p network
    pub protocol: Protocol,

    /// Maximum allowed number of peer connections.
    pub max_connections: usize,

    /// Maximum allowed number of client connections.
    pub max_client_connections: usize,

    /// the default value for the timeout for inactive connection
    pub timeout: Duration,

    pub policy: QuarantineConfig,

    pub layers: LayersConfig,

    /// Whether to allow non-public IP addresses in gossip
    pub allow_private_addresses: bool,

    pub whitelist: Option<Vec<Multiaddr>>,

    pub gossip_interval: Duration,

    pub network_stuck_check: Duration,

    pub max_bootstrap_attempts: Option<usize>,

    /// Whether to limit bootstrap to trusted peers (which increase their load / reduce their connectivities)
    pub bootstrap_from_trusted_peers: bool,

    /// Whether to skip bootstrap, not recommended in normal settings. useful to true for self-node
    pub skip_bootstrap: bool,

    pub http_fetch_block0_service: Vec<String>,

    pub dns_server_address: Option<Address>,
}

/// Trusted peer with DNS address resolved.
#[derive(Clone, Hash)]
pub struct TrustedPeer {
    pub addr: SocketAddr,
    // This will need to become compulsory if we want to check validity of keys/ids
    pub id: Option<NodeId>,
}

#[derive(Debug, thiserror::Error)]
pub enum PeerResolveError {
    #[error("DNS address resolution failed")]
    Resolve(#[from] multiaddr::Error),
    #[error("Address shall consist of a host address and a TCP component")]
    InvalidAddress,
}

impl TrustedPeer {
    pub fn resolve(peer: &config::TrustedPeer) -> Result<Self, PeerResolveError> {
        let addr = multiaddr::to_tcp_socket_addr(&multiaddr::resolve_dns(&peer.address)?)
            .ok_or(PeerResolveError::InvalidAddress)?;
        Ok(TrustedPeer {
            addr,
            id: peer.id.clone().map(Into::into),
        })
    }
}

impl Peer {
    pub fn new(connection: SocketAddr) -> Self {
        Peer::with_timeout(connection, DEFAULT_TIMEOUT)
    }

    pub fn with_timeout(connection: SocketAddr, timeout: Duration) -> Self {
        Peer {
            connection,
            protocol: Protocol::Grpc,
            timeout,
        }
    }

    pub fn address(&self) -> SocketAddr {
        self.connection
    }
}

impl Listen {
    pub fn new(connection: SocketAddr) -> Self {
        Listen {
            connection,
            protocol: Protocol::Grpc,
            timeout: DEFAULT_TIMEOUT,
        }
    }

    pub fn address(&self) -> SocketAddr {
        self.connection
    }
}

impl Configuration {
    pub fn address(&self) -> Option<Address> {
        self.public_address
    }

    /// Returns the listener configuration, if the options defining it
    /// were set.
    pub fn listen(&self) -> Option<Listen> {
        self.listen_address.or(self.public_address).map(Listen::new)
    }
}