1use crate::{
9 config::{Error, SecureBackend},
10 keys::ConfigKey,
11 network_id::NetworkId,
12 utils,
13};
14use diem_crypto::{x25519, Uniform, ValidCryptoMaterial};
15use diem_secure_storage::{CryptoStorage, KVStorage, Storage};
16use diem_types::{
17 network_address::NetworkAddress,
18 transaction::authenticator::AuthenticationKey, PeerId,
19};
20use rand::{
21 rngs::{OsRng, StdRng},
22 Rng, SeedableRng,
23};
24use serde::{Deserialize, Serialize};
25use short_hex_str::AsShortHexStr;
26use std::{
27 collections::{HashMap, HashSet},
28 convert::TryFrom,
29 string::ToString,
30};
31
32pub const HANDSHAKE_VERSION: u8 = 0;
39pub const NETWORK_CHANNEL_SIZE: usize = 1024;
40pub const PING_INTERVAL_MS: u64 = 1000;
41pub const PING_TIMEOUT_MS: u64 = 10_000;
42pub const PING_FAILURES_TOLERATED: u64 = 5;
43pub const CONNECTIVITY_CHECK_INTERVAL_MS: u64 = 5000;
44pub const MAX_CONCURRENT_NETWORK_REQS: usize = 100;
45pub const MAX_CONNECTION_DELAY_MS: u64 = 60_000; pub const MAX_FULLNODE_OUTBOUND_CONNECTIONS: usize = 3;
47pub const MAX_INBOUND_CONNECTIONS: usize = 100;
48pub const MAX_FRAME_SIZE: usize = 8 * 1024 * 1024; pub const CONNECTION_BACKOFF_BASE: u64 = 2;
50pub const IP_BYTE_BUCKET_RATE: usize = 102400 ;
51pub const IP_BYTE_BUCKET_SIZE: usize = IP_BYTE_BUCKET_RATE;
52
53#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
54#[serde(default, deny_unknown_fields)]
55pub struct NetworkConfig {
56 pub max_connection_delay_ms: u64,
58 pub connection_backoff_base: u64,
60 pub connectivity_check_interval_ms: u64,
62 pub network_channel_size: usize,
64 pub max_concurrent_network_reqs: usize,
66 pub discovery_method: DiscoveryMethod,
70 pub identity: Identity,
71 pub listen_address: NetworkAddress,
74 pub mutual_authentication: bool,
77 pub network_address_key_backend: Option<SecureBackend>,
79 pub network_id: NetworkId,
80 pub seed_addrs: HashMap<PeerId, Vec<NetworkAddress>>,
85 pub seeds: PeerSet,
87 pub max_frame_size: usize,
89 pub enable_proxy_protocol: bool,
92 pub ping_interval_ms: u64,
94 pub ping_timeout_ms: u64,
96 pub ping_failures_tolerated: u64,
98 pub max_outbound_connections: usize,
100 pub max_inbound_connections: usize,
102 pub inbound_rate_limit_config: Option<RateLimitConfig>,
104 pub outbound_rate_limit_config: Option<RateLimitConfig>,
106}
107
108impl Default for NetworkConfig {
109 fn default() -> Self {
110 NetworkConfig::network_with_id(NetworkId::default())
111 }
112}
113
114impl NetworkConfig {
115 pub fn network_with_id(network_id: NetworkId) -> NetworkConfig {
116 let mut config = Self {
117 discovery_method: DiscoveryMethod::None,
118 identity: Identity::None,
119 listen_address: "/ip4/0.0.0.0/tcp/6180".parse().unwrap(),
120 mutual_authentication: false,
121 network_address_key_backend: None,
122 network_id,
123 seed_addrs: HashMap::new(),
124 seeds: PeerSet::default(),
125 max_frame_size: MAX_FRAME_SIZE,
126 enable_proxy_protocol: false,
127 max_connection_delay_ms: MAX_CONNECTION_DELAY_MS,
128 connectivity_check_interval_ms: CONNECTIVITY_CHECK_INTERVAL_MS,
129 network_channel_size: NETWORK_CHANNEL_SIZE,
130 max_concurrent_network_reqs: MAX_CONCURRENT_NETWORK_REQS,
131 connection_backoff_base: CONNECTION_BACKOFF_BASE,
132 ping_interval_ms: PING_INTERVAL_MS,
133 ping_timeout_ms: PING_TIMEOUT_MS,
134 ping_failures_tolerated: PING_FAILURES_TOLERATED,
135 max_outbound_connections: MAX_FULLNODE_OUTBOUND_CONNECTIONS,
136 max_inbound_connections: MAX_INBOUND_CONNECTIONS,
137 inbound_rate_limit_config: None,
138 outbound_rate_limit_config: None,
139 };
140 config.prepare_identity();
141 config
142 }
143}
144
145impl NetworkConfig {
146 pub fn identity_key(&self) -> x25519::PrivateKey {
147 let key = match &self.identity {
148 Identity::FromConfig(config) => Some(config.key.clone().key),
149 Identity::FromStorage(config) => {
150 let storage: Storage = (&config.backend).into();
151 let key = storage
152 .export_private_key(&config.key_name)
153 .expect("Unable to read key");
154 let key = x25519::PrivateKey::from_ed25519_private_bytes(
155 &key.to_bytes(),
156 )
157 .expect("Unable to convert key");
158 Some(key)
159 }
160 Identity::None => None,
161 };
162 key.expect("identity key should be present")
163 }
164
165 pub fn identity_from_storage(&self) -> IdentityFromStorage {
166 if let Identity::FromStorage(identity) = self.identity.clone() {
167 identity
168 } else {
169 panic!("Invalid identity found, expected a storage identity.");
170 }
171 }
172
173 pub fn load_validator_network(&mut self) -> Result<(), Error> {
176 self.network_id = NetworkId::Validator;
177 self.load()
178 }
179
180 pub fn load_fullnode_network(&mut self) -> Result<(), Error> {
181 if self.network_id.is_validator_network() {
182 return Err(Error::InvariantViolation(format!(
183 "Set {} network for a non-validator network",
184 self.network_id
185 )));
186 }
187 self.load()
188 }
189
190 fn load(&mut self) -> Result<(), Error> {
191 if self.listen_address.to_string().is_empty() {
192 self.listen_address = utils::get_local_ip().ok_or_else(|| {
193 Error::InvariantViolation("No local IP".to_string())
194 })?;
195 }
196
197 self.prepare_identity();
198 Ok(())
199 }
200
201 pub fn peer_id(&self) -> PeerId {
202 match &self.identity {
203 Identity::FromConfig(config) => Some(config.peer_id),
204 Identity::FromStorage(config) => {
205 let storage: Storage = (&config.backend).into();
206 let peer_id = storage
207 .get::<PeerId>(&config.peer_id_name)
208 .expect("Unable to read peer id")
209 .value;
210 Some(peer_id)
211 }
212 Identity::None => None,
213 }
214 .expect("peer id should be present")
215 }
216
217 fn prepare_identity(&mut self) {
218 match &mut self.identity {
219 Identity::FromStorage(_) => (),
220 Identity::None => {
221 let mut rng = StdRng::from_seed(OsRng.gen());
222 let key = x25519::PrivateKey::generate(&mut rng);
223 let peer_id =
224 diem_types::account_address::from_identity_public_key(
225 key.public_key(),
226 );
227 self.identity = Identity::from_config(key, peer_id);
228 }
229 Identity::FromConfig(config) => {
230 let peer_id =
231 diem_types::account_address::from_identity_public_key(
232 config.key.public_key(),
233 );
234 if config.peer_id == PeerId::ZERO {
235 config.peer_id = peer_id;
236 }
237 }
238 };
239 }
240
241 pub fn random(&mut self, rng: &mut StdRng) {
242 self.random_with_peer_id(rng, None);
243 }
244
245 pub fn random_with_peer_id(
246 &mut self, rng: &mut StdRng, peer_id: Option<PeerId>,
247 ) {
248 let identity_key = x25519::PrivateKey::generate(rng);
249 let peer_id = if let Some(peer_id) = peer_id {
250 peer_id
251 } else {
252 AuthenticationKey::try_from(identity_key.public_key().as_slice())
253 .unwrap()
254 .derived_address()
255 };
256 self.identity = Identity::from_config(identity_key, peer_id);
257 }
258
259 fn verify_address(
260 peer_id: &PeerId, addr: &NetworkAddress,
261 ) -> Result<(), Error> {
262 crate::config::invariant(
263 addr.is_diemnet_addr(),
264 format!(
265 "Unexpected seed peer address format: peer_id: {}, addr: '{}'",
266 peer_id.short_str(),
267 addr,
268 ),
269 )
270 }
271
272 pub fn verify_seeds(&self) -> Result<(), Error> {
274 for (peer_id, addrs) in self.seed_addrs.iter() {
275 for addr in addrs {
276 Self::verify_address(peer_id, addr)?;
277 }
278 }
279
280 for (peer_id, seed) in self.seeds.iter() {
281 for addr in seed.addresses.iter() {
282 Self::verify_address(peer_id, addr)?;
283 }
284
285 crate::config::invariant(
288 !seed.keys.is_empty() || !seed.addresses.is_empty(),
289 format!("Seed peer {} has no pubkeys", peer_id.short_str()),
290 )?;
291 }
292 Ok(())
293 }
294}
295
296#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
297#[serde(rename_all = "snake_case")]
298pub enum DiscoveryMethod {
299 Onchain,
300 None,
301}
302
303#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
304#[serde(rename_all = "snake_case", tag = "type")]
305pub enum Identity {
306 FromConfig(IdentityFromConfig),
307 FromStorage(IdentityFromStorage),
308 None,
309}
310
311impl Identity {
312 pub fn from_config(key: x25519::PrivateKey, peer_id: PeerId) -> Self {
313 let key = ConfigKey::new(key);
314 Identity::FromConfig(IdentityFromConfig { key, peer_id })
315 }
316
317 pub fn from_storage(
318 key_name: String, peer_id_name: String, backend: SecureBackend,
319 ) -> Self {
320 Identity::FromStorage(IdentityFromStorage {
321 backend,
322 key_name,
323 peer_id_name,
324 })
325 }
326}
327
328#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
330#[serde(deny_unknown_fields)]
331pub struct IdentityFromConfig {
332 #[serde(flatten)]
333 pub key: ConfigKey<x25519::PrivateKey>,
334 pub peer_id: PeerId,
335}
336
337#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
340#[serde(deny_unknown_fields)]
341pub struct IdentityFromStorage {
342 pub backend: SecureBackend,
343 pub key_name: String,
344 pub peer_id_name: String,
345}
346
347#[derive(Copy, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
348pub struct RateLimitConfig {
349 pub ip_byte_bucket_rate: usize,
351 pub ip_byte_bucket_size: usize,
353 pub initial_bucket_fill_percentage: u8,
355 pub enabled: bool,
357}
358
359impl Default for RateLimitConfig {
360 fn default() -> Self {
361 Self {
362 ip_byte_bucket_rate: IP_BYTE_BUCKET_RATE,
363 ip_byte_bucket_size: IP_BYTE_BUCKET_SIZE,
364 initial_bucket_fill_percentage: 25,
365 enabled: true,
366 }
367 }
368}
369
370pub type PeerSet = HashMap<PeerId, Peer>;
371
372#[derive(
389 Clone,
390 Copy,
391 Debug,
392 Deserialize,
393 Eq,
394 Hash,
395 Ord,
396 PartialEq,
397 PartialOrd,
398 Serialize,
399)]
400pub enum PeerRole {
401 Validator = 0,
402 PreferredUpstream,
403 Upstream,
404 ValidatorFullNode,
405 Downstream,
406 Known,
407 Unknown,
408}
409
410impl Default for PeerRole {
411 fn default() -> Self { PeerRole::Unknown }
413}
414
415#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
417#[serde(default)]
418pub struct Peer {
419 pub addresses: Vec<NetworkAddress>,
420 pub keys: HashSet<x25519::PublicKey>,
421 pub role: PeerRole,
422}
423
424impl Peer {
425 pub fn new(
427 addresses: Vec<NetworkAddress>, mut keys: HashSet<x25519::PublicKey>,
428 role: PeerRole,
429 ) -> Peer {
430 let addr_keys = addresses
431 .iter()
432 .filter_map(NetworkAddress::find_noise_proto);
433 keys.extend(addr_keys);
434 Peer {
435 addresses,
436 keys,
437 role,
438 }
439 }
440
441 pub fn extend(&mut self, other: Peer) -> Result<(), Error> {
444 crate::config::invariant(
445 self.role != other.role,
446 format!(
447 "Roles don't match self {:?} vs other {:?}",
448 self.role, other.role
449 ),
450 )?;
451 self.addresses.extend(other.addresses);
452 self.keys.extend(other.keys);
453 Ok(())
454 }
455
456 pub fn from_addrs(role: PeerRole, addresses: Vec<NetworkAddress>) -> Peer {
457 let keys: HashSet<x25519::PublicKey> = addresses
458 .iter()
459 .filter_map(NetworkAddress::find_noise_proto)
460 .collect();
461 Peer::new(addresses, keys, role)
462 }
463}