mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 06:31:09 +00:00
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:
@@ -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,
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>> {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user