Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Ensure the listen addresses are consistent with the transport #6436

Merged
merged 12 commits into from
Jun 23, 2020
15 changes: 14 additions & 1 deletion client/network/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

//! Substrate network possible errors.

use crate::config::TransportConfig;
use libp2p::{PeerId, Multiaddr};

use std::fmt;
Expand Down Expand Up @@ -48,7 +49,18 @@ pub enum Error {
second_id: PeerId,
},
/// Prometheus metrics error.
Prometheus(prometheus_endpoint::PrometheusError)
Prometheus(prometheus_endpoint::PrometheusError),
/// The network addresses are invalid because they don't matche the transport.
cecton marked this conversation as resolved.
Show resolved Hide resolved
#[display(
fmt = "The following addresses are invalid because they don't match the transport: {:?}",
addresses,
)]
AddressesForAnotherTransport {
/// Transport used.
transport: TransportConfig,
/// The invalid addresses.
addresses: Vec<Multiaddr>,
},
}

// Make `Debug` use the `Display` implementation.
Expand All @@ -65,6 +77,7 @@ impl std::error::Error for Error {
Error::Client(ref err) => Some(err),
Error::DuplicateBootnode { .. } => None,
Error::Prometheus(ref err) => Some(err),
Error::AddressesForAnotherTransport { .. } => None,
}
}
}
55 changes: 55 additions & 0 deletions client/network/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,24 @@ impl<B: BlockT + 'static, H: ExHashT> NetworkWorker<B, H> {
/// for the network processing to advance. From it, you can extract a `NetworkService` using
/// `worker.service()`. The `NetworkService` can be shared through the codebase.
pub fn new(params: Params<B, H>) -> Result<NetworkWorker<B, H>, Error> {
// Ensure the listen addresses are consistent with the transport.
ensure_addresses_consistent_with_transport(
params.network_config.listen_addresses.iter(),
&params.network_config.transport,
)?;
ensure_addresses_consistent_with_transport(
params.network_config.boot_nodes.iter().map(|x| &x.multiaddr),
&params.network_config.transport,
)?;
ensure_addresses_consistent_with_transport(
params.network_config.reserved_nodes.iter().map(|x| &x.multiaddr),
&params.network_config.transport,
)?;
ensure_addresses_consistent_with_transport(
params.network_config.public_addresses.iter(),
&params.network_config.transport,
)?;

let (to_worker, from_worker) = tracing_unbounded("mpsc_network_worker");

if let Some(path) = params.network_config.net_config_path {
Expand Down Expand Up @@ -1447,3 +1465,40 @@ impl<'a, B: BlockT, H: ExHashT> Link<B> for NetworkLink<'a, B, H> {
}
}
}

fn ensure_addresses_consistent_with_transport<'a>(
addresses: impl Iterator<Item = &'a Multiaddr>,
transport: &TransportConfig,
) -> Result<(), Error> {
if matches!(transport, TransportConfig::MemoryOnly) {
let addresses: Vec<_> = addresses
.filter(|x| x.iter()
.any(|y| !matches!(y, libp2p::core::multiaddr::Protocol::Memory(_)))
)
.cloned()
.collect();

if !addresses.is_empty() {
return Err(Error::AddressesForAnotherTransport {
transport: transport.clone(),
addresses,
});
}
} else {
let addresses: Vec<_> = addresses
.filter(|x| x.iter()
.any(|y| matches!(y, libp2p::core::multiaddr::Protocol::Memory(_)))
)
.cloned()
.collect();

if !addresses.is_empty() {
return Err(Error::AddressesForAnotherTransport {
transport: transport.clone(),
addresses,
});
}
}

Ok(())
}
118 changes: 118 additions & 0 deletions client/network/src/service/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

use crate::{config, Event, NetworkService, NetworkWorker};

use libp2p::PeerId;
use futures::prelude::*;
use sp_runtime::traits::{Block as BlockT, Header as _};
use std::{sync::Arc, time::Duration};
Expand Down Expand Up @@ -138,6 +139,7 @@ fn build_nodes_one_proto()

let (node2, events_stream2) = build_test_full_node(config::NetworkConfiguration {
notifications_protocols: vec![(ENGINE_ID, From::from(&b"/foo"[..]))],
listen_addresses: vec![],
reserved_nodes: vec![config::MultiaddrWithPeerId {
multiaddr: listen_addr,
peer_id: node1.local_peer_id().clone(),
Expand Down Expand Up @@ -342,3 +344,119 @@ fn lots_of_incoming_peers_works() {
future::join_all(background_tasks_to_wait).await
});
}

#[test]
#[should_panic(expected = "don't match the transport")]
fn ensure_listen_addresses_consistent_with_transport_memory() {
let listen_addr = config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)];

let _ = build_test_full_node(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()],
transport: config::TransportConfig::MemoryOnly,
.. config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None)
});
}

#[test]
#[should_panic(expected = "don't match the transport")]
fn ensure_listen_addresses_consistent_with_transport_not_memory() {
let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())];

let _ = build_test_full_node(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()],
.. config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None)
});
}

#[test]
#[should_panic(expected = "don't match the transport")]
fn ensure_boot_node_addresses_consistent_with_transport_memory() {
let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())];
let boot_node = config::MultiaddrWithPeerId {
multiaddr: config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)],
peer_id: PeerId::random(),
};

let _ = build_test_full_node(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()],
transport: config::TransportConfig::MemoryOnly,
boot_nodes: vec![boot_node],
.. config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None)
});
}

#[test]
#[should_panic(expected = "don't match the transport")]
fn ensure_boot_node_addresses_consistent_with_transport_not_memory() {
let listen_addr = config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)];
let boot_node = config::MultiaddrWithPeerId {
multiaddr: config::build_multiaddr![Memory(rand::random::<u64>())],
peer_id: PeerId::random(),
};

let _ = build_test_full_node(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()],
boot_nodes: vec![boot_node],
.. config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None)
});
}

#[test]
#[should_panic(expected = "don't match the transport")]
fn ensure_reserved_node_addresses_consistent_with_transport_memory() {
let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())];
let reserved_node = config::MultiaddrWithPeerId {
multiaddr: config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)],
peer_id: PeerId::random(),
};

let _ = build_test_full_node(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()],
transport: config::TransportConfig::MemoryOnly,
reserved_nodes: vec![reserved_node],
.. config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None)
});
}

#[test]
#[should_panic(expected = "don't match the transport")]
fn ensure_reserved_node_addresses_consistent_with_transport_not_memory() {
let listen_addr = config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)];
let reserved_node = config::MultiaddrWithPeerId {
multiaddr: config::build_multiaddr![Memory(rand::random::<u64>())],
peer_id: PeerId::random(),
};

let _ = build_test_full_node(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()],
reserved_nodes: vec![reserved_node],
.. config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None)
});
}

#[test]
#[should_panic(expected = "don't match the transport")]
fn ensure_public_addresses_consistent_with_transport_memory() {
let listen_addr = config::build_multiaddr![Memory(rand::random::<u64>())];
let public_address = config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)];

let _ = build_test_full_node(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()],
transport: config::TransportConfig::MemoryOnly,
public_addresses: vec![public_address],
.. config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None)
});
}

#[test]
#[should_panic(expected = "don't match the transport")]
fn ensure_public_addresses_consistent_with_transport_not_memory() {
let listen_addr = config::build_multiaddr![Ip4([127, 0, 0, 1]), Tcp(0_u16)];
let public_address = config::build_multiaddr![Memory(rand::random::<u64>())];

let _ = build_test_full_node(config::NetworkConfiguration {
listen_addresses: vec![listen_addr.clone()],
public_addresses: vec![public_address],
.. config::NetworkConfiguration::new("test-node", "test-client", Default::default(), None)
});
}