From 33c615acbc49f2038c51ab36f4f7ff8cba232555 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Fri, 18 Nov 2022 15:51:39 +0800 Subject: [PATCH] add `WebRTCConfig::Ephemeral` option for tests --- bin/node/cli/benches/block_production.rs | 3 +- bin/node/cli/benches/transaction_pool.rs | 3 +- client/cli/src/config.rs | 24 ++++++++++++-- client/cli/src/params/mod.rs | 2 +- client/cli/src/params/network_params.rs | 13 ++++++-- .../src/params/webrtc_certificate_params.rs | 33 ++++++++++++++++++- client/network/src/config.rs | 27 ++++++++------- client/network/src/service/tests/service.rs | 18 +++++----- client/network/test/src/lib.rs | 11 +++++-- client/service/src/config.rs | 2 +- client/service/test/src/lib.rs | 6 +++- 11 files changed, 106 insertions(+), 36 deletions(-) diff --git a/bin/node/cli/benches/block_production.rs b/bin/node/cli/benches/block_production.rs index 4fcebb123d9e3..0b45dc25278f5 100644 --- a/bin/node/cli/benches/block_production.rs +++ b/bin/node/cli/benches/block_production.rs @@ -29,7 +29,7 @@ use sc_consensus::{ use sc_service::{ config::{ BlocksPruning, DatabaseSource, KeystoreConfig, NetworkConfiguration, OffchainWorkerConfig, - PruningMode, WasmExecutionMethod, WasmtimeInstantiationStrategy, + PruningMode, WasmExecutionMethod, WasmtimeInstantiationStrategy, WebRTCConfig, }, BasePath, Configuration, Role, }; @@ -52,6 +52,7 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { Sr25519Keyring::Alice.to_seed(), "network/test/0.1", Default::default(), + WebRTCConfig::Ephemeral, None, ); diff --git a/bin/node/cli/benches/transaction_pool.rs b/bin/node/cli/benches/transaction_pool.rs index a8839642ddc26..11e1c5fd4249a 100644 --- a/bin/node/cli/benches/transaction_pool.rs +++ b/bin/node/cli/benches/transaction_pool.rs @@ -27,7 +27,7 @@ use sc_client_api::execution_extensions::ExecutionStrategies; use sc_service::{ config::{ BlocksPruning, DatabaseSource, KeystoreConfig, NetworkConfiguration, OffchainWorkerConfig, - PruningMode, TransactionPoolOptions, WasmExecutionMethod, + PruningMode, TransactionPoolOptions, WasmExecutionMethod, WebRTCConfig, }, BasePath, Configuration, Role, }; @@ -46,6 +46,7 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { Sr25519Keyring::Alice.to_seed(), "network/test/0.1", Default::default(), + WebRTCConfig::Ephemeral, None, ); diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index 77689708a231f..a143f14a9b89f 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -21,6 +21,7 @@ use crate::{ arg_enums::Database, error::Result, DatabaseParams, ImportParams, KeystoreParams, NetworkParams, NodeKeyParams, OffchainWorkerParams, PruningParams, SharedParams, SubstrateCli, + WebRTCCertificateParams, }; use log::warn; use names::{Generator, Name}; @@ -29,7 +30,7 @@ use sc_service::{ config::{ BasePath, Configuration, DatabaseSource, KeystoreConfig, NetworkConfiguration, NodeKeyConfig, OffchainWorkerConfig, PrometheusConfig, PruningMode, Role, RpcMethods, - TelemetryEndpoints, TransactionPoolOptions, WasmExecutionMethod, + TelemetryEndpoints, TransactionPoolOptions, WasmExecutionMethod, WebRTCConfig, }, BlocksPruning, ChainSpec, TracingReceiver, }; @@ -116,6 +117,11 @@ pub trait CliConfiguration: Sized { self.network_params().map(|x| &x.node_key_params) } + /// Get the [`WebRTCCertificateParams`] for this object. + fn webrtc_certificate_params(&self) -> Option<&WebRTCCertificateParams> { + self.network_params().map(|x| &x.webrtc_certificate_params) + } + /// Get the DatabaseParams for this object fn database_params(&self) -> Option<&DatabaseParams> { self.import_params().map(|x| &x.database_params) @@ -163,6 +169,7 @@ pub trait CliConfiguration: Sized { client_id: &str, node_name: &str, node_key: NodeKeyConfig, + webrtc: WebRTCConfig, default_listen_port: u16, ) -> Result { Ok(if let Some(network_params) = self.network_params() { @@ -174,10 +181,11 @@ pub trait CliConfiguration: Sized { client_id, node_name, node_key, + webrtc, default_listen_port, ) } else { - NetworkConfiguration::new(node_name, client_id, node_key, Some(net_config_dir)) + NetworkConfiguration::new(node_name, client_id, node_key, webrtc, Some(net_config_dir)) }) } @@ -454,6 +462,16 @@ pub trait CliConfiguration: Sized { .unwrap_or_else(|| Ok(Default::default())) } + /// Get the WebRTC config from the current object. + /// + /// By default this is retrieved from [`WebRTCCertificateParams`] if it is available. Otherwise + /// its [`WebRTCConfig::Ephemeral`]. + fn webrtc(&self, net_config_dir: &PathBuf) -> Result { + self.webrtc_certificate_params() + .map(|x| x.webrtc_certificate(net_config_dir)) + .unwrap_or_else(|| Ok(WebRTCConfig::Ephemeral)) + } + /// Get maximum runtime instances /// /// By default this is `None`. @@ -502,6 +520,7 @@ pub trait CliConfiguration: Sized { }, ); let node_key = self.node_key(&net_config_dir)?; + let webrtc = self.webrtc(&net_config_dir)?; let role = self.role(is_dev)?; let max_runtime_instances = self.max_runtime_instances()?.unwrap_or(8); let is_validator = role.is_authority(); @@ -522,6 +541,7 @@ pub trait CliConfiguration: Sized { client_id.as_str(), self.node_name()?.as_str(), node_key, + webrtc, DCV::p2p_listen_port(), )?, keystore_remote, diff --git a/client/cli/src/params/mod.rs b/client/cli/src/params/mod.rs index 42253cdc8fd32..6d3038b658c1b 100644 --- a/client/cli/src/params/mod.rs +++ b/client/cli/src/params/mod.rs @@ -20,11 +20,11 @@ mod import_params; mod keystore_params; mod network_params; mod node_key_params; -mod webrtc_certificate_params; mod offchain_worker_params; mod pruning_params; mod shared_params; mod transaction_pool_params; +mod webrtc_certificate_params; use crate::arg_enums::{CryptoScheme, OutputType}; use clap::Args; diff --git a/client/cli/src/params/network_params.rs b/client/cli/src/params/network_params.rs index 280eee2f6c73c..8f1a60eb4ea9d 100644 --- a/client/cli/src/params/network_params.rs +++ b/client/cli/src/params/network_params.rs @@ -16,10 +16,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::{arg_enums::SyncMode, params::node_key_params::NodeKeyParams}; +use crate::{ + arg_enums::SyncMode, + params::{node_key_params::NodeKeyParams, webrtc_certificate_params::WebRTCCertificateParams}, +}; use clap::Args; use sc_network::{ - config::{NetworkConfiguration, NodeKeyConfig}, + config::{NetworkConfiguration, NodeKeyConfig, WebRTCConfig}, multiaddr::Protocol, }; use sc_network_common::config::{NonReservedPeerMode, SetConfig, TransportConfig}; @@ -111,6 +114,10 @@ pub struct NetworkParams { #[clap(flatten)] pub node_key_params: NodeKeyParams, + #[allow(missing_docs)] + #[clap(flatten)] + pub webrtc_certificate_params: WebRTCCertificateParams, + /// Enable peer discovery on local networks. /// /// By default this option is `true` for `--dev` or when the chain type is @@ -158,6 +165,7 @@ impl NetworkParams { client_id: &str, node_name: &str, node_key: NodeKeyConfig, + webrtc: WebRTCConfig, default_listen_port: u16, ) -> NetworkConfiguration { let port = self.port.unwrap_or(default_listen_port); @@ -245,6 +253,7 @@ impl NetworkParams { extra_sets: Vec::new(), request_response_protocols: Vec::new(), node_key, + webrtc, node_name: node_name.to_string(), client_version: client_id.to_string(), transport: TransportConfig::Normal { diff --git a/client/cli/src/params/webrtc_certificate_params.rs b/client/cli/src/params/webrtc_certificate_params.rs index 470898a20a3dd..8e89991408c7b 100644 --- a/client/cli/src/params/webrtc_certificate_params.rs +++ b/client/cli/src/params/webrtc_certificate_params.rs @@ -40,18 +40,31 @@ pub struct WebRTCCertificateParams { /// If the file does not exist, it is created with a newly generated certificate. #[clap(long, value_name = "FILE")] pub webrtc_certificate_file: Option, + + /// When set to `true`, a new WebRTC certificate will be created each time you start a node. + /// + /// The certificate won't be stored on disk. Use this option only if you DON'T want to preserve + /// node's WebRTC identity between (re)starts. + /// + /// This option takes precedence over `--webrtc-certificate-file` option. + #[arg(long, value_name = "EPHEMERAL")] + pub webrtc_certificate_ephemeral: Option, } impl WebRTCCertificateParams { /// Create a `WebRTCConfig` from the given `WebRTCCertificateParams` in the context /// of an optional network config storage directory. pub fn webrtc_certificate(&self, net_config_dir: &PathBuf) -> error::Result { + if let Some(true) = self.webrtc_certificate_ephemeral { + return Ok(WebRTCConfig::Ephemeral) + } + let filename = self .webrtc_certificate_file .clone() .unwrap_or_else(|| net_config_dir.join(WEBRTC_CERTIFICATE_FILENAME)); - Ok(WebRTCConfig::File(Some(filename))) + Ok(WebRTCConfig::File(filename)) } } @@ -84,4 +97,22 @@ mod tests { fs::write(&file, cert.serialize_pem().as_bytes()).expect("Writes certificate"); load_cert_and_assert_eq(file.clone(), &cert); } + + #[test] + fn test_webrtc_certificate_ephemeral() { + let filepath = PathBuf::from("not-used"); + let params = WebRTCCertificateParams { + webrtc_certificate_ephemeral: Some(true), + webrtc_certificate_file: Some(&filepath), + }; + + let _loaded_cert = params + .webrtc_certificate(&filepath) + .expect("Creates certificate config") + .into_certificate() + .expect("Creates certificate"); + + assert!(!filepath.exists(), "Does not create a file"); + assert!(!filepath.join(WEBRTC_CERTIFICATE_FILENAME).exists(), "Does not create a file"); + } } diff --git a/client/network/src/config.rs b/client/network/src/config.rs index 90cbc50f8b17f..e1314e126d398 100644 --- a/client/network/src/config.rs +++ b/client/network/src/config.rs @@ -187,7 +187,7 @@ pub struct NetworkConfiguration { pub boot_nodes: Vec, /// The node key configuration, which determines the node's network identity keypair. pub node_key: NodeKeyConfig, - /// The WebRTC configuration, which determines the WebRTC certificate. + /// The WebRTC configuration, which determines the node's WebRTC network identity. pub webrtc: WebRTCConfig, /// List of request-response protocols that the node supports. pub request_response_protocols: Vec, @@ -288,7 +288,7 @@ impl NetworkConfiguration { "test-node", "test-client", Default::default(), - Default::default(), + WebRTCConfig::Ephemeral, None, ); @@ -308,7 +308,7 @@ impl NetworkConfiguration { "test-node", "test-client", Default::default(), - Default::default(), + WebRTCConfig::Ephemeral, None, ); @@ -464,14 +464,12 @@ where /// The configuration of a node's WebRTC certificate, describing how it is obtained. #[derive(Clone, Debug)] pub enum WebRTCConfig { - /// A WebRTC certificate. - File(Option), -} + /// Certificate stored on disk. + /// A new certificate is randomly generated and written there if the file doesn't exist. + File(PathBuf), -impl Default for WebRTCConfig { - fn default() -> WebRTCConfig { - Self::File(None) - } + /// A new certifiticate is randomly generated each time you start the node. + Ephemeral, } impl WebRTCConfig { @@ -479,6 +477,7 @@ impl WebRTCConfig { /// /// * If the certificate is configured as a file, it is read from that file, if it exists. /// Otherwise a new certificate is generated and stored. + /// * If the certificate is configured as ephemeral, it is generated. pub fn into_certificate(self) -> io::Result { use rand::thread_rng; use std::os::unix::fs::OpenOptionsExt; @@ -490,7 +489,7 @@ impl WebRTCConfig { use WebRTCConfig::*; match self { - File(Some(filepath)) => { + File(filepath) => { let f = std::fs::read(&filepath).or_else(|e| { if e.kind() == io::ErrorKind::NotFound { >::as_ref(&filepath) @@ -517,7 +516,7 @@ impl WebRTCConfig { WebRTCCertificate::from_pem(&pem) .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string())) }, - File(None) => generate(), + Ephemeral => generate(), } } } @@ -566,8 +565,8 @@ mod tests { let tmp = tempdir_with_prefix("x"); std::fs::remove_dir(tmp.path()).unwrap(); // should be recreated let file = tmp.path().join("x").to_path_buf(); - let kp1 = WebRTCConfig::File(Some(file.clone())).into_certificate().unwrap(); - let kp2 = WebRTCConfig::File(Some(file.clone())).into_certificate().unwrap(); + let kp1 = WebRTCConfig::File(file.clone()).into_certificate().unwrap(); + let kp2 = WebRTCConfig::File(file.clone()).into_certificate().unwrap(); assert!(file.is_file() && kp1 == kp2) } } diff --git a/client/network/src/service/tests/service.rs b/client/network/src/service/tests/service.rs index db446bf2d455b..733a4e9c815cd 100644 --- a/client/network/src/service/tests/service.rs +++ b/client/network/src/service/tests/service.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::{config, service::tests::TestNetworkBuilder, NetworkService}; +use crate::{config, config::WebRTCConfig, service::tests::TestNetworkBuilder, NetworkService}; use futures::prelude::*; use libp2p::PeerId; @@ -450,7 +450,7 @@ fn ensure_listen_addresses_consistent_with_transport_memory() { "test-node", "test-client", Default::default(), - Default::default(), + WebRTCConfig::Ephemeral, None, ) }) @@ -470,7 +470,7 @@ fn ensure_listen_addresses_consistent_with_transport_not_memory() { "test-node", "test-client", Default::default(), - Default::default(), + WebRTCConfig::Ephemeral, None, ) }) @@ -496,7 +496,7 @@ fn ensure_boot_node_addresses_consistent_with_transport_memory() { "test-node", "test-client", Default::default(), - Default::default(), + WebRTCConfig::Ephemeral, None, ) }) @@ -521,7 +521,7 @@ fn ensure_boot_node_addresses_consistent_with_transport_not_memory() { "test-node", "test-client", Default::default(), - Default::default(), + WebRTCConfig::Ephemeral, None, ) }) @@ -550,7 +550,7 @@ fn ensure_reserved_node_addresses_consistent_with_transport_memory() { "test-node", "test-client", Default::default(), - Default::default(), + WebRTCConfig::Ephemeral, None, ) }) @@ -578,7 +578,7 @@ fn ensure_reserved_node_addresses_consistent_with_transport_not_memory() { "test-node", "test-client", Default::default(), - Default::default(), + WebRTCConfig::Ephemeral, None, ) }) @@ -601,7 +601,7 @@ fn ensure_public_addresses_consistent_with_transport_memory() { "test-node", "test-client", Default::default(), - Default::default(), + WebRTCConfig::Ephemeral, None, ) }) @@ -623,7 +623,7 @@ fn ensure_public_addresses_consistent_with_transport_not_memory() { "test-node", "test-client", Default::default(), - Default::default(), + WebRTCConfig::Ephemeral, None, ) }) diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index 035fc0a972a59..21bc2ce074d8b 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -48,7 +48,7 @@ use sc_consensus::{ Verifier, }; use sc_network::{ - config::{NetworkConfiguration, RequestResponseConfig, Role, SyncMode}, + config::{NetworkConfiguration, RequestResponseConfig, Role, SyncMode, WebRTCConfig}, Multiaddr, NetworkService, NetworkWorker, }; use sc_network_common::{ @@ -789,8 +789,13 @@ where let listen_addr = build_multiaddr![Memory(rand::random::())]; - let mut network_config = - NetworkConfiguration::new("test-node", "test-client", Default::default(), None); + let mut network_config = NetworkConfiguration::new( + "test-node", + "test-client", + Default::default(), + WebRTCConfig::Ephemeral, + None, + ); network_config.sync_mode = config.sync_mode; network_config.transport = TransportConfig::MemoryOnly; network_config.listen_addresses = vec![listen_addr.clone()]; diff --git a/client/service/src/config.rs b/client/service/src/config.rs index bca0697bcbd08..facbce331c88d 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -24,7 +24,7 @@ pub use sc_executor::WasmExecutionMethod; #[cfg(feature = "wasmtime")] pub use sc_executor::WasmtimeInstantiationStrategy; pub use sc_network::{ - config::{NetworkConfiguration, NodeKeyConfig, Role}, + config::{NetworkConfiguration, NodeKeyConfig, Role, WebRTCConfig}, Multiaddr, }; pub use sc_network_common::{ diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index 5d29d34a3cbf2..ebe799a910ac1 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -22,7 +22,10 @@ use futures::{task::Poll, Future, TryFutureExt as _}; use log::{debug, info}; use parking_lot::Mutex; use sc_client_api::{Backend, CallExecutor}; -use sc_network::{config::NetworkConfiguration, multiaddr}; +use sc_network::{ + config::{NetworkConfiguration, WebRTCConfig}, + multiaddr, +}; use sc_network_common::{ config::{MultiaddrWithPeerId, TransportConfig}, service::{NetworkBlock, NetworkPeers, NetworkStateInfo}, @@ -208,6 +211,7 @@ fn node_config< format!("Node {}", index), "network/test/0.1", Default::default(), + WebRTCConfig::Ephemeral, None, );