rpc server: break legacy CLI options and remove "backward compatible HTTP server" (#13384)

* jsonrpsee v0.16

* breaking: remove old CLI configs

* remove patch.crates-io

* fix bad merge

* fix clippy

* fix bad merge

* fix grumbles

* Update client/service/src/lib.rs

Co-authored-by: Bastian Köcher <git@kchr.de>

* revert block_in_place

* add issue link in todo

* Update client/cli/src/config.rs

Co-authored-by: Dmitry Markin <dmitry@markin.tech>

* grumbles: add ipv6 loopback address

* Revert "grumbles: add ipv6 loopback address"

This reverts commit 3a0b1ece6c4e36055d666896c29d1da55ffa1c4f.

* remove nits

* bump zombienet version

* adress grumbles: provide structopt default_val_t

* remove duplicate from structopt

* bump zombienet v1.3.47

* bump zombienet version

---------

Co-authored-by: Bastian Köcher <git@kchr.de>
Co-authored-by: Dmitry Markin <dmitry@markin.tech>
Co-authored-by: Javier Viola <javier@parity.io>
This commit is contained in:
Niklas Adolfsson
2023-05-03 17:18:25 +02:00
committed by GitHub
parent b8a01127d7
commit 5a1074712a
11 changed files with 149 additions and 393 deletions
+1 -1
View File
@@ -61,7 +61,7 @@ variables:
NEXTEST_FAILURE_OUTPUT: immediate-final
NEXTEST_SUCCESS_OUTPUT: final
ZOMBIENET_IMAGE: "docker.io/paritytech/zombienet:v1.3.43"
ZOMBIENET_IMAGE: "docker.io/paritytech/zombienet:v1.3.48"
default:
retry:
@@ -84,18 +84,14 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase {
offchain_worker: execution_strategy,
other: execution_strategy,
},
rpc_http: None,
rpc_ws: None,
rpc_ipc: None,
rpc_ws_max_connections: None,
rpc_addr: None,
rpc_max_connections: Default::default(),
rpc_cors: None,
rpc_methods: Default::default(),
rpc_max_payload: None,
rpc_max_request_size: None,
rpc_max_response_size: None,
rpc_id_provider: None,
rpc_max_subs_per_conn: None,
ws_max_out_buffer_capacity: None,
rpc_max_request_size: Default::default(),
rpc_max_response_size: Default::default(),
rpc_id_provider: Default::default(),
rpc_max_subs_per_conn: Default::default(),
prometheus_config: None,
telemetry_endpoints: None,
default_heap_pages: None,
@@ -78,18 +78,14 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase {
offchain_worker: sc_client_api::ExecutionStrategy::NativeWhenPossible,
other: sc_client_api::ExecutionStrategy::NativeWhenPossible,
},
rpc_http: None,
rpc_ws: None,
rpc_ipc: None,
rpc_ws_max_connections: None,
rpc_addr: None,
rpc_max_connections: Default::default(),
rpc_cors: None,
rpc_methods: Default::default(),
rpc_max_payload: None,
rpc_max_request_size: None,
rpc_max_response_size: None,
rpc_id_provider: None,
rpc_max_subs_per_conn: None,
ws_max_out_buffer_capacity: None,
rpc_max_request_size: Default::default(),
rpc_max_response_size: Default::default(),
rpc_id_provider: Default::default(),
rpc_max_subs_per_conn: Default::default(),
prometheus_config: None,
telemetry_endpoints: None,
default_heap_pages: None,
+21 -77
View File
@@ -65,7 +65,7 @@ pub struct RunCmd {
/// RPC methods to expose.
/// - `unsafe`: Exposes every RPC method.
/// - `safe`: Exposes only a safe subset of RPC methods, denying unsafe RPC methods.
/// - `auto`: Acts as `safe` if RPC is served externally, e.g. when `--{rpc,ws}-external` is
/// - `auto`: Acts as `safe` if RPC is served externally, e.g. when `--rpc--external` is
/// passed, otherwise acts as `unsafe`.
#[arg(
long,
@@ -77,58 +77,25 @@ pub struct RunCmd {
)]
pub rpc_methods: RpcMethods,
/// Listen to all Websocket interfaces.
/// Default is local. Note: not all RPC methods are safe to be exposed publicly. Use an RPC
/// proxy server to filter out dangerous methods. More details:
/// <https://docs.substrate.io/main-docs/build/custom-rpc/#public-rpcs>.
/// Use `--unsafe-ws-external` to suppress the warning if you understand the risks.
#[arg(long)]
pub ws_external: bool,
/// Listen to all Websocket interfaces.
/// Same as `--ws-external` but doesn't warn you about it.
#[arg(long)]
pub unsafe_ws_external: bool,
/// DEPRECATED, this has no affect anymore. Use `rpc_max_request_size` or
/// `rpc_max_response_size` instead.
#[arg(long)]
pub rpc_max_payload: Option<usize>,
/// Set the the maximum RPC request payload size for both HTTP and WS in megabytes.
/// Default is 15MiB.
#[arg(long)]
pub rpc_max_request_size: Option<usize>,
#[arg(long, default_value_t = 15)]
pub rpc_max_request_size: u32,
/// Set the the maximum RPC response payload size for both HTTP and WS in megabytes.
/// Default is 15MiB.
#[arg(long)]
pub rpc_max_response_size: Option<usize>,
#[arg(long, default_value_t = 15)]
pub rpc_max_response_size: u32,
/// Set the the maximum concurrent subscriptions per connection.
/// Default is 1024.
#[arg(long)]
pub rpc_max_subscriptions_per_connection: Option<usize>,
#[arg(long, default_value_t = 1024)]
pub rpc_max_subscriptions_per_connection: u32,
/// DEPRECATED, IPC support has been removed.
#[arg(long, value_name = "PATH")]
pub ipc_path: Option<String>,
/// Specify JSON-RPC server TCP port.
#[arg(long, value_name = "PORT", default_value_t = 9944)]
pub rpc_port: u16,
/// Specify HTTP RPC server TCP port.
#[arg(long, value_name = "PORT")]
pub rpc_port: Option<u16>,
/// Specify WebSockets RPC server TCP port.
#[arg(long, value_name = "PORT")]
pub ws_port: Option<u16>,
/// Maximum number of WS RPC server connections.
#[arg(long, value_name = "COUNT")]
pub ws_max_connections: Option<usize>,
/// DEPRECATED, this has no affect anymore. Use `rpc_max_response_size` instead.
#[arg(long)]
pub ws_max_out_buffer_capacity: Option<usize>,
/// Maximum number of RPC server connections.
#[arg(long, value_name = "COUNT", default_value_t = 100)]
pub rpc_max_connections: u32,
/// Specify browser Origins allowed to access the HTTP & WS RPC servers.
/// A comma-separated list of origins (protocol://domain or special `null`
@@ -344,8 +311,8 @@ impl CliConfiguration for RunCmd {
Ok(self.no_grandpa)
}
fn rpc_ws_max_connections(&self) -> Result<Option<usize>> {
Ok(self.ws_max_connections)
fn rpc_max_connections(&self) -> Result<u32> {
Ok(self.rpc_max_connections)
}
fn rpc_cors(&self, is_dev: bool) -> Result<Option<Vec<String>>> {
@@ -369,7 +336,7 @@ impl CliConfiguration for RunCmd {
.into())
}
fn rpc_http(&self, default_listen_port: u16) -> Result<Option<SocketAddr>> {
fn rpc_addr(&self, _default_listen_port: u16) -> Result<Option<SocketAddr>> {
let interface = rpc_interface(
self.rpc_external,
self.unsafe_rpc_external,
@@ -377,48 +344,25 @@ impl CliConfiguration for RunCmd {
self.validator,
)?;
Ok(Some(SocketAddr::new(interface, self.rpc_port.unwrap_or(default_listen_port))))
}
fn rpc_ipc(&self) -> Result<Option<String>> {
Ok(self.ipc_path.clone())
}
fn rpc_ws(&self, default_listen_port: u16) -> Result<Option<SocketAddr>> {
let interface = rpc_interface(
self.ws_external,
self.unsafe_ws_external,
self.rpc_methods,
self.validator,
)?;
Ok(Some(SocketAddr::new(interface, self.ws_port.unwrap_or(default_listen_port))))
Ok(Some(SocketAddr::new(interface, self.rpc_port)))
}
fn rpc_methods(&self) -> Result<sc_service::config::RpcMethods> {
Ok(self.rpc_methods.into())
}
fn rpc_max_payload(&self) -> Result<Option<usize>> {
Ok(self.rpc_max_payload)
}
fn rpc_max_request_size(&self) -> Result<Option<usize>> {
fn rpc_max_request_size(&self) -> Result<u32> {
Ok(self.rpc_max_request_size)
}
fn rpc_max_response_size(&self) -> Result<Option<usize>> {
fn rpc_max_response_size(&self) -> Result<u32> {
Ok(self.rpc_max_response_size)
}
fn rpc_max_subscriptions_per_connection(&self) -> Result<Option<usize>> {
fn rpc_max_subscriptions_per_connection(&self) -> Result<u32> {
Ok(self.rpc_max_subscriptions_per_connection)
}
fn ws_max_out_buffer_capacity(&self) -> Result<Option<usize>> {
Ok(self.ws_max_out_buffer_capacity)
}
fn transaction_pool(&self, is_dev: bool) -> Result<TransactionPoolOptions> {
Ok(self.pool_config.transaction_pool(is_dev))
}
@@ -475,7 +419,7 @@ fn rpc_interface(
) -> Result<IpAddr> {
if is_external && is_validator && rpc_methods != RpcMethods::Unsafe {
return Err(Error::Input(
"--rpc-external and --ws-external options shouldn't be used if the node is running as \
"--rpc-external option shouldn't be used if the node is running as \
a validator. Use `--unsafe-rpc-external` or `--rpc-methods=unsafe` if you understand \
the risks. See the options description for more information."
.to_owned(),
+15 -54
View File
@@ -57,20 +57,13 @@ pub trait DefaultConfigurationValues {
30333
}
/// The port Substrate should listen on for websocket connections.
/// The port Substrate should listen on for JSON-RPC connections.
///
/// By default this is `9944`.
fn rpc_ws_listen_port() -> u16 {
fn rpc_listen_port() -> u16 {
9944
}
/// The port Substrate should listen on for http connections.
///
/// By default this is `9933`.
fn rpc_http_listen_port() -> u16 {
9933
}
/// The port Substrate should listen on for prometheus connections.
///
/// By default this is `9615`.
@@ -302,24 +295,8 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
.unwrap_or_default())
}
/// Get the RPC HTTP address (`None` if disabled).
///
/// By default this is `None`.
fn rpc_http(&self, _default_listen_port: u16) -> Result<Option<SocketAddr>> {
Ok(None)
}
/// Get the RPC IPC path (`None` if disabled).
///
/// By default this is `None`.
fn rpc_ipc(&self) -> Result<Option<String>> {
Ok(None)
}
/// Get the RPC websocket address (`None` if disabled).
///
/// By default this is `None`.
fn rpc_ws(&self, _default_listen_port: u16) -> Result<Option<SocketAddr>> {
/// Get the RPC address.
fn rpc_addr(&self, _default_listen_port: u16) -> Result<Option<SocketAddr>> {
Ok(None)
}
@@ -331,11 +308,9 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
Ok(Default::default())
}
/// Get the RPC websockets maximum connections (`None` if unlimited).
///
/// By default this is `None`.
fn rpc_ws_max_connections(&self) -> Result<Option<usize>> {
Ok(None)
/// Get the maximum number of RPC server connections.
fn rpc_max_connections(&self) -> Result<u32> {
Ok(Default::default())
}
/// Get the RPC cors (`None` if disabled)
@@ -345,29 +320,19 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
Ok(Some(Vec::new()))
}
/// Get maximum RPC payload.
fn rpc_max_payload(&self) -> Result<Option<usize>> {
Ok(None)
}
/// Get maximum RPC request payload size.
fn rpc_max_request_size(&self) -> Result<Option<usize>> {
Ok(None)
fn rpc_max_request_size(&self) -> Result<u32> {
Ok(Default::default())
}
/// Get maximum RPC response payload size.
fn rpc_max_response_size(&self) -> Result<Option<usize>> {
Ok(None)
fn rpc_max_response_size(&self) -> Result<u32> {
Ok(Default::default())
}
/// Get maximum number of subscriptions per connection.
fn rpc_max_subscriptions_per_connection(&self) -> Result<Option<usize>> {
Ok(None)
}
/// Get maximum WS output buffer capacity.
fn ws_max_out_buffer_capacity(&self) -> Result<Option<usize>> {
Ok(None)
fn rpc_max_subscriptions_per_connection(&self) -> Result<u32> {
Ok(Default::default())
}
/// Get the prometheus configuration (`None` if disabled)
@@ -532,18 +497,14 @@ pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
wasm_method: self.wasm_method()?,
wasm_runtime_overrides: self.wasm_runtime_overrides(),
execution_strategies: self.execution_strategies(is_dev, is_validator)?,
rpc_http: self.rpc_http(DCV::rpc_http_listen_port())?,
rpc_ws: self.rpc_ws(DCV::rpc_ws_listen_port())?,
rpc_ipc: self.rpc_ipc()?,
rpc_addr: self.rpc_addr(DCV::rpc_listen_port())?,
rpc_methods: self.rpc_methods()?,
rpc_ws_max_connections: self.rpc_ws_max_connections()?,
rpc_max_connections: self.rpc_max_connections()?,
rpc_cors: self.rpc_cors(is_dev)?,
rpc_max_payload: self.rpc_max_payload()?,
rpc_max_request_size: self.rpc_max_request_size()?,
rpc_max_response_size: self.rpc_max_response_size()?,
rpc_id_provider: None,
rpc_max_subs_per_conn: self.rpc_max_subscriptions_per_connection()?,
ws_max_out_buffer_capacity: self.ws_max_out_buffer_capacity()?,
prometheus_config: self
.prometheus_config(DCV::prometheus_listen_port(), &chain_spec)?,
telemetry_endpoints,
+6 -10
View File
@@ -287,18 +287,14 @@ mod tests {
wasm_method: Default::default(),
wasm_runtime_overrides: None,
execution_strategies: Default::default(),
rpc_http: None,
rpc_ws: None,
rpc_ipc: None,
rpc_ws_max_connections: None,
rpc_addr: None,
rpc_max_connections: Default::default(),
rpc_cors: None,
rpc_methods: Default::default(),
rpc_max_payload: None,
rpc_max_request_size: None,
rpc_max_response_size: None,
rpc_id_provider: None,
rpc_max_subs_per_conn: None,
ws_max_out_buffer_capacity: None,
rpc_max_request_size: Default::default(),
rpc_max_response_size: Default::default(),
rpc_id_provider: Default::default(),
rpc_max_subs_per_conn: Default::default(),
prometheus_config: None,
telemetry_endpoints: None,
default_heap_pages: None,
+59 -117
View File
@@ -20,6 +20,9 @@
#![warn(missing_docs)]
pub mod middleware;
use http::header::HeaderValue;
use jsonrpsee::{
server::{
middleware::proxy_get_request::ProxyGetRequestLayer, AllowHosts, ServerBuilder,
@@ -28,119 +31,62 @@ use jsonrpsee::{
RpcModule,
};
use std::{error::Error as StdError, net::SocketAddr};
use tower_http::cors::{AllowOrigin, CorsLayer};
pub use crate::middleware::RpcMetrics;
use http::header::HeaderValue;
pub use jsonrpsee::core::{
id_providers::{RandomIntegerIdProvider, RandomStringIdProvider},
traits::IdProvider,
};
use tower_http::cors::{AllowOrigin, CorsLayer};
const MEGABYTE: usize = 1024 * 1024;
const MEGABYTE: u32 = 1024 * 1024;
/// Maximal payload accepted by RPC servers.
pub const RPC_MAX_PAYLOAD_DEFAULT: usize = 15 * MEGABYTE;
/// Default maximum number of connections for WS RPC servers.
const WS_MAX_CONNECTIONS: usize = 100;
/// Default maximum number subscriptions per connection for WS RPC servers.
const WS_MAX_SUBS_PER_CONN: usize = 1024;
pub mod middleware;
/// Type alias JSON-RPC server
/// Type alias for the JSON-RPC server.
pub type Server = ServerHandle;
/// Server config.
#[derive(Debug, Clone)]
pub struct WsConfig {
/// RPC server configuration.
#[derive(Debug)]
pub struct Config<'a, M: Send + Sync + 'static> {
/// Socket addresses.
pub addrs: [SocketAddr; 2],
/// CORS.
pub cors: Option<&'a Vec<String>>,
/// Maximum connections.
pub max_connections: Option<usize>,
pub max_connections: u32,
/// Maximum subscriptions per connection.
pub max_subs_per_conn: Option<usize>,
pub max_subs_per_conn: u32,
/// Maximum rpc request payload size.
pub max_payload_in_mb: Option<usize>,
pub max_payload_in_mb: u32,
/// Maximum rpc response payload size.
pub max_payload_out_mb: Option<usize>,
pub max_payload_out_mb: u32,
/// Metrics.
pub metrics: Option<RpcMetrics>,
/// RPC API.
pub rpc_api: RpcModule<M>,
/// Subscription ID provider.
pub id_provider: Option<Box<dyn IdProvider>>,
/// Tokio runtime handle.
pub tokio_handle: tokio::runtime::Handle,
}
impl WsConfig {
// Deconstructs the config to get the finalized inner values.
//
// `Payload size` or `max subs per connection` bigger than u32::MAX will be truncated.
fn deconstruct(self) -> (u32, u32, u32, u32) {
let max_conns = self.max_connections.unwrap_or(WS_MAX_CONNECTIONS) as u32;
let max_payload_in_mb = payload_size_or_default(self.max_payload_in_mb) as u32;
let max_payload_out_mb = payload_size_or_default(self.max_payload_out_mb) as u32;
let max_subs_per_conn = self.max_subs_per_conn.unwrap_or(WS_MAX_SUBS_PER_CONN) as u32;
(max_payload_in_mb, max_payload_out_mb, max_conns, max_subs_per_conn)
}
}
/// Start HTTP server listening on given address.
pub async fn start_http<M: Send + Sync + 'static>(
addrs: [SocketAddr; 2],
cors: Option<&Vec<String>>,
max_payload_in_mb: Option<usize>,
max_payload_out_mb: Option<usize>,
metrics: Option<RpcMetrics>,
rpc_api: RpcModule<M>,
rt: tokio::runtime::Handle,
/// Start RPC server listening on given address.
pub async fn start_server<M: Send + Sync + 'static>(
config: Config<'_, M>,
) -> Result<ServerHandle, Box<dyn StdError + Send + Sync>> {
let max_payload_in = payload_size_or_default(max_payload_in_mb) as u32;
let max_payload_out = payload_size_or_default(max_payload_out_mb) as u32;
let host_filter = hosts_filter(cors.is_some(), &addrs);
let Config {
addrs,
cors,
max_payload_in_mb,
max_payload_out_mb,
max_connections,
max_subs_per_conn,
metrics,
id_provider,
tokio_handle,
rpc_api,
} = config;
let middleware = tower::ServiceBuilder::new()
// Proxy `GET /health` requests to internal `system_health` method.
.layer(ProxyGetRequestLayer::new("/health", "system_health")?)
.layer(try_into_cors(cors)?);
let builder = ServerBuilder::new()
.max_request_body_size(max_payload_in)
.max_response_body_size(max_payload_out)
.set_host_filtering(host_filter)
.set_middleware(middleware)
.custom_tokio_runtime(rt)
.http_only();
let rpc_api = build_rpc_api(rpc_api);
let (handle, addr) = if let Some(metrics) = metrics {
let server = builder.set_logger(metrics).build(&addrs[..]).await?;
let addr = server.local_addr();
(server.start(rpc_api)?, addr)
} else {
let server = builder.build(&addrs[..]).await?;
let addr = server.local_addr();
(server.start(rpc_api)?, addr)
};
log::info!(
"Running JSON-RPC HTTP server: addr={}, allowed origins={}",
addr.map_or_else(|_| "unknown".to_string(), |a| a.to_string()),
format_cors(cors)
);
Ok(handle)
}
/// Start a JSON-RPC server listening on given address that supports both HTTP and WS.
pub async fn start<M: Send + Sync + 'static>(
addrs: [SocketAddr; 2],
cors: Option<&Vec<String>>,
ws_config: WsConfig,
metrics: Option<RpcMetrics>,
rpc_api: RpcModule<M>,
rt: tokio::runtime::Handle,
id_provider: Option<Box<dyn IdProvider>>,
) -> Result<ServerHandle, Box<dyn StdError + Send + Sync>> {
let (max_payload_in, max_payload_out, max_connections, max_subs_per_conn) =
ws_config.deconstruct();
let host_filter = hosts_filter(cors.is_some(), &addrs);
let host_filter = hosts_filtering(cors.is_some(), &addrs);
let middleware = tower::ServiceBuilder::new()
// Proxy `GET /health` requests to internal `system_health` method.
@@ -148,14 +94,14 @@ pub async fn start<M: Send + Sync + 'static>(
.layer(try_into_cors(cors)?);
let mut builder = ServerBuilder::new()
.max_request_body_size(max_payload_in)
.max_response_body_size(max_payload_out)
.max_request_body_size(max_payload_in_mb.saturating_mul(MEGABYTE))
.max_response_body_size(max_payload_out_mb.saturating_mul(MEGABYTE))
.max_connections(max_connections)
.max_subscriptions_per_connection(max_subs_per_conn)
.ping_interval(std::time::Duration::from_secs(30))
.set_host_filtering(host_filter)
.set_middleware(middleware)
.custom_tokio_runtime(rt);
.custom_tokio_runtime(tokio_handle);
if let Some(provider) = id_provider {
builder = builder.set_id_provider(provider);
@@ -175,7 +121,7 @@ pub async fn start<M: Send + Sync + 'static>(
};
log::info!(
"Running JSON-RPC WS server: addr={}, allowed origins={}",
"Running JSON-RPC server: addr={}, allowed origins={}",
addr.map_or_else(|_| "unknown".to_string(), |a| a.to_string()),
format_cors(cors)
);
@@ -183,6 +129,20 @@ pub async fn start<M: Send + Sync + 'static>(
Ok(handle)
}
fn hosts_filtering(enabled: bool, addrs: &[SocketAddr]) -> AllowHosts {
if enabled {
// NOTE The listening addresses are whitelisted by default.
let mut hosts = Vec::with_capacity(addrs.len() * 2);
for addr in addrs {
hosts.push(format!("localhost:{}", addr.port()).into());
hosts.push(format!("127.0.0.1:{}", addr.port()).into());
}
AllowHosts::Only(hosts)
} else {
AllowHosts::Any
}
}
fn build_rpc_api<M: Send + Sync + 'static>(mut rpc_api: RpcModule<M>) -> RpcModule<M> {
let mut available_methods = rpc_api.method_names().collect::<Vec<_>>();
available_methods.sort();
@@ -198,24 +158,6 @@ fn build_rpc_api<M: Send + Sync + 'static>(mut rpc_api: RpcModule<M>) -> RpcModu
rpc_api
}
fn payload_size_or_default(size_mb: Option<usize>) -> usize {
size_mb.map_or(RPC_MAX_PAYLOAD_DEFAULT, |mb| mb.saturating_mul(MEGABYTE))
}
fn hosts_filter(enabled: bool, addrs: &[SocketAddr]) -> AllowHosts {
if enabled {
// NOTE The listening addresses are whitelisted by default.
let mut hosts = Vec::with_capacity(addrs.len() * 2);
for addr in addrs {
hosts.push(format!("localhost:{}", addr.port()).into());
hosts.push(format!("127.0.0.1:{}", addr.port()).into());
}
AllowHosts::Only(hosts)
} else {
AllowHosts::Any
}
}
fn try_into_cors(
maybe_cors: Option<&Vec<String>>,
) -> Result<CorsLayer, Box<dyn StdError + Send + Sync>> {
+8 -18
View File
@@ -83,34 +83,24 @@ pub struct Configuration {
pub wasm_runtime_overrides: Option<PathBuf>,
/// Execution strategies.
pub execution_strategies: ExecutionStrategies,
/// RPC over HTTP binding address. `None` if disabled.
pub rpc_http: Option<SocketAddr>,
/// RPC over Websockets binding address. `None` if disabled.
pub rpc_ws: Option<SocketAddr>,
/// RPC over IPC binding path. `None` if disabled.
pub rpc_ipc: Option<String>,
/// Maximum number of connections for WebSockets RPC server. `None` if default.
pub rpc_ws_max_connections: Option<usize>,
/// JSON-RPC server binding address.
pub rpc_addr: Option<SocketAddr>,
/// Maximum number of connections for JSON-RPC server.
pub rpc_max_connections: u32,
/// CORS settings for HTTP & WS servers. `None` if all origins are allowed.
pub rpc_cors: Option<Vec<String>>,
/// RPC methods to expose (by default only a safe subset or all of them).
pub rpc_methods: RpcMethods,
/// Maximum payload of rpc request/responses.
pub rpc_max_payload: Option<usize>,
/// Maximum payload of a rpc request
pub rpc_max_request_size: Option<usize>,
/// Maximum payload of a rpc request
pub rpc_max_response_size: Option<usize>,
pub rpc_max_request_size: u32,
/// Maximum payload of a rpc response.
pub rpc_max_response_size: u32,
/// Custom JSON-RPC subscription ID provider.
///
/// Default: [`crate::RandomStringSubscriptionId`].
pub rpc_id_provider: Option<Box<dyn crate::RpcSubscriptionIdProvider>>,
/// Maximum allowed subscriptions per rpc connection
///
/// Default: 1024.
pub rpc_max_subs_per_conn: Option<usize>,
/// Maximum size of the output buffer capacity for websocket connections.
pub ws_max_out_buffer_capacity: Option<usize>,
pub rpc_max_subs_per_conn: u32,
/// Prometheus endpoint configuration. `None` if disabled.
pub prometheus_config: Option<PrometheusConfig>,
/// Telemetry service URL. `None` if disabled.
+20 -85
View File
@@ -380,57 +380,37 @@ where
}
}
let (max_request_size, ws_max_response_size, http_max_response_size) =
legacy_cli_parsing(config);
let random_port = |mut addr: SocketAddr| {
// if binding the specified port failed then a random port is assigned by the OS.
let backup_port = |mut addr: SocketAddr| {
addr.set_port(0);
addr
};
let ws_addr = config
.rpc_ws
.unwrap_or_else(|| "127.0.0.1:9944".parse().expect("valid sockaddr; qed"));
let ws_addr2 = random_port(ws_addr);
let http_addr = config
.rpc_http
.unwrap_or_else(|| "127.0.0.1:9933".parse().expect("valid sockaddr; qed"));
let http_addr2 = random_port(http_addr);
let addr = config.rpc_addr.unwrap_or(([127, 0, 0, 1], 9944).into());
let backup_addr = backup_port(addr);
let metrics = sc_rpc_server::RpcMetrics::new(config.prometheus_registry())?;
let server_config = sc_rpc_server::WsConfig {
max_connections: config.rpc_ws_max_connections,
max_payload_in_mb: max_request_size,
max_payload_out_mb: ws_max_response_size,
let server_config = sc_rpc_server::Config {
addrs: [addr, backup_addr],
max_connections: config.rpc_max_connections,
max_payload_in_mb: config.rpc_max_request_size,
max_payload_out_mb: config.rpc_max_response_size,
max_subs_per_conn: config.rpc_max_subs_per_conn,
rpc_api: gen_rpc_module(deny_unsafe(addr, &config.rpc_methods))?,
metrics,
id_provider: rpc_id_provider,
cors: config.rpc_cors.as_ref(),
tokio_handle: config.tokio_handle.clone(),
};
let http_fut = sc_rpc_server::start_http(
[http_addr, http_addr2],
config.rpc_cors.as_ref(),
max_request_size,
http_max_response_size,
metrics.clone(),
gen_rpc_module(deny_unsafe(http_addr, &config.rpc_methods))?,
config.tokio_handle.clone(),
);
let ws_fut = sc_rpc_server::start(
[ws_addr, ws_addr2],
config.rpc_cors.as_ref(),
server_config.clone(),
metrics.clone(),
gen_rpc_module(deny_unsafe(ws_addr, &config.rpc_methods))?,
config.tokio_handle.clone(),
rpc_id_provider,
);
// TODO: https://github.com/paritytech/substrate/issues/13773
//
// `block_in_place` is a hack to allow callers to call `block_on` prior to
// calling `start_rpc_servers`.
match tokio::task::block_in_place(|| {
config.tokio_handle.block_on(futures::future::try_join(http_fut, ws_fut))
config.tokio_handle.block_on(sc_rpc_server::start_server(server_config))
}) {
Ok((http, ws)) => Ok(Box::new((waiting::Server(Some(http)), waiting::Server(Some(ws))))),
Ok(server) => Ok(Box::new(waiting::Server(Some(server)))),
Err(e) => Err(Error::Application(e)),
}
}
@@ -534,51 +514,6 @@ where
}
}
fn legacy_cli_parsing(config: &Configuration) -> (Option<usize>, Option<usize>, Option<usize>) {
let ws_max_response_size = match (
config.ws_max_out_buffer_capacity,
config.rpc_max_response_size,
) {
(Some(legacy_max), max) => {
eprintln!("DEPRECATED: `--ws_max_out_buffer_capacity` has been removed; use `rpc-max-response-size or rpc-max-request-size` instead");
eprintln!("Setting WS `rpc-max-response-size` to `max(ws_max_out_buffer_capacity, rpc_max_response_size)`");
Some(std::cmp::max(legacy_max, max.unwrap_or(0)))
},
(None, Some(m)) => Some(m),
(None, None) => None,
};
let max_request_size = match (config.rpc_max_payload, config.rpc_max_request_size) {
(Some(legacy_max), max) => {
eprintln!("DEPRECATED: `--rpc_max_payload` has been removed use `rpc-max-response-size or rpc-max-request-size` instead");
eprintln!(
"Setting `rpc-max-response-size` to `max(rpc_max_payload, rpc_max_request_size)`"
);
Some(std::cmp::max(legacy_max, max.unwrap_or(0)))
},
(None, Some(max)) => Some(max),
(None, None) => None,
};
let http_max_response_size = match (config.rpc_max_payload, config.rpc_max_response_size) {
(Some(legacy_max), max) => {
eprintln!("DEPRECATED: `--rpc_max_payload` has been removed use `rpc-max-response-size or rpc-max-request-size` instead");
eprintln!(
"Setting HTTP `rpc-max-response-size` to `max(rpc_max_payload, rpc_max_response_size)`"
);
Some(std::cmp::max(legacy_max, max.unwrap_or(0)))
},
(None, Some(max)) => Some(max),
(None, None) => None,
};
if config.rpc_ipc.is_some() {
eprintln!("DEPRECATED: `--ipc-path` has no effect anymore IPC support has been removed");
}
(max_request_size, ws_max_response_size, http_max_response_size)
}
#[cfg(test)]
mod tests {
use super::*;
+6 -10
View File
@@ -246,18 +246,14 @@ fn node_config<
wasm_method: Default::default(),
wasm_runtime_overrides: Default::default(),
execution_strategies: Default::default(),
rpc_http: None,
rpc_ipc: None,
rpc_ws: None,
rpc_ws_max_connections: None,
rpc_addr: Default::default(),
rpc_max_connections: Default::default(),
rpc_cors: None,
rpc_methods: Default::default(),
rpc_max_payload: None,
rpc_max_request_size: None,
rpc_max_response_size: None,
rpc_id_provider: None,
rpc_max_subs_per_conn: None,
ws_max_out_buffer_capacity: None,
rpc_max_request_size: Default::default(),
rpc_max_response_size: Default::default(),
rpc_id_provider: Default::default(),
rpc_max_subs_per_conn: Default::default(),
prometheus_config: None,
telemetry_endpoints: None,
default_heap_pages: None,
+1 -1
View File
@@ -282,7 +282,7 @@ pub fn extract_info_from_output(read: impl Read + Send) -> (NodeInfo, String) {
data.push_str("\n");
// does the line contain our port (we expect this specific output from substrate).
let sock_addr = match line.split_once("Running JSON-RPC WS server: addr=") {
let sock_addr = match line.split_once("Running JSON-RPC server: addr=") {
None => return None,
Some((_, after)) => after.split_once(",").unwrap().0,
};