diff --git a/Cargo.lock b/Cargo.lock index ba2946d462368..5b01481eaaa72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2781,7 +2781,7 @@ dependencies = [ [[package]] name = "jsonrpsee" version = "0.3.0" -source = "git+https://github.com/paritytech/jsonrpsee?branch=master#932304c4c8aa8b06e9ba18c6b3b95b6fa83cd94c" +source = "git+https://github.com/paritytech/jsonrpsee?branch=master#c13f97ba8bb5a5862dd0372053f5d9aa56531c3b" dependencies = [ "jsonrpsee-http-client", "jsonrpsee-http-server", @@ -2795,7 +2795,7 @@ dependencies = [ [[package]] name = "jsonrpsee-http-client" version = "0.3.0" -source = "git+https://github.com/paritytech/jsonrpsee?branch=master#932304c4c8aa8b06e9ba18c6b3b95b6fa83cd94c" +source = "git+https://github.com/paritytech/jsonrpsee?branch=master#c13f97ba8bb5a5862dd0372053f5d9aa56531c3b" dependencies = [ "async-trait", "fnv", @@ -2815,7 +2815,7 @@ dependencies = [ [[package]] name = "jsonrpsee-http-server" version = "0.3.0" -source = "git+https://github.com/paritytech/jsonrpsee?branch=master#932304c4c8aa8b06e9ba18c6b3b95b6fa83cd94c" +source = "git+https://github.com/paritytech/jsonrpsee?branch=master#c13f97ba8bb5a5862dd0372053f5d9aa56531c3b" dependencies = [ "futures-channel", "futures-util", @@ -2850,10 +2850,11 @@ dependencies = [ [[package]] name = "jsonrpsee-proc-macros" version = "0.3.0" -source = "git+https://github.com/paritytech/jsonrpsee?branch=master#932304c4c8aa8b06e9ba18c6b3b95b6fa83cd94c" +source = "git+https://github.com/paritytech/jsonrpsee?branch=master#c13f97ba8bb5a5862dd0372053f5d9aa56531c3b" dependencies = [ "Inflector", "bae", + "log", "proc-macro-crate", "proc-macro2", "quote", @@ -2881,7 +2882,7 @@ dependencies = [ [[package]] name = "jsonrpsee-types" version = "0.3.0" -source = "git+https://github.com/paritytech/jsonrpsee?branch=master#932304c4c8aa8b06e9ba18c6b3b95b6fa83cd94c" +source = "git+https://github.com/paritytech/jsonrpsee?branch=master#c13f97ba8bb5a5862dd0372053f5d9aa56531c3b" dependencies = [ "anyhow", "async-trait", @@ -2899,7 +2900,7 @@ dependencies = [ [[package]] name = "jsonrpsee-utils" version = "0.3.0" -source = "git+https://github.com/paritytech/jsonrpsee?branch=master#932304c4c8aa8b06e9ba18c6b3b95b6fa83cd94c" +source = "git+https://github.com/paritytech/jsonrpsee?branch=master#c13f97ba8bb5a5862dd0372053f5d9aa56531c3b" dependencies = [ "beef", "futures-channel", @@ -2942,7 +2943,7 @@ dependencies = [ [[package]] name = "jsonrpsee-ws-client" version = "0.3.0" -source = "git+https://github.com/paritytech/jsonrpsee?branch=master#932304c4c8aa8b06e9ba18c6b3b95b6fa83cd94c" +source = "git+https://github.com/paritytech/jsonrpsee?branch=master#c13f97ba8bb5a5862dd0372053f5d9aa56531c3b" dependencies = [ "async-trait", "fnv", @@ -2965,7 +2966,7 @@ dependencies = [ [[package]] name = "jsonrpsee-ws-server" version = "0.3.0" -source = "git+https://github.com/paritytech/jsonrpsee?branch=master#932304c4c8aa8b06e9ba18c6b3b95b6fa83cd94c" +source = "git+https://github.com/paritytech/jsonrpsee?branch=master#c13f97ba8bb5a5862dd0372053f5d9aa56531c3b" dependencies = [ "futures-channel", "futures-util", @@ -4850,6 +4851,7 @@ name = "pallet-contracts-rpc" version = "4.0.0-dev" dependencies = [ "jsonrpsee", + "log", "pallet-contracts-primitives", "pallet-contracts-rpc-runtime-api", "parity-scale-codec", @@ -5159,6 +5161,7 @@ name = "pallet-mmr-rpc" version = "3.0.0" dependencies = [ "jsonrpsee", + "log", "pallet-mmr-primitives", "parity-scale-codec", "serde", @@ -5513,7 +5516,9 @@ dependencies = [ name = "pallet-transaction-payment-rpc" version = "4.0.0-dev" dependencies = [ + "anyhow", "jsonrpsee", + "log", "pallet-transaction-payment-rpc-runtime-api", "parity-scale-codec", "sp-api", @@ -7734,6 +7739,7 @@ version = "0.10.0-dev" dependencies = [ "anyhow", "jsonrpsee", + "log", "parity-scale-codec", "sc-chain-spec", "sc-client-api", diff --git a/client/rpc-api/src/lib.rs b/client/rpc-api/src/lib.rs index 4b165867c83e1..ca0bd78467b3d 100644 --- a/client/rpc-api/src/lib.rs +++ b/client/rpc-api/src/lib.rs @@ -28,6 +28,7 @@ pub use policy::DenyUnsafe; pub mod author; pub mod chain; +/// Child state API pub mod child_state; pub mod offchain; pub mod state; diff --git a/client/rpc-servers/src/lib.rs b/client/rpc-servers/src/lib.rs index 38056ce9f56a2..9e03400f833fa 100644 --- a/client/rpc-servers/src/lib.rs +++ b/client/rpc-servers/src/lib.rs @@ -21,7 +21,7 @@ #![warn(missing_docs)] use jsonrpsee::{ - http_server::{HttpServerBuilder, HttpStopHandle}, + http_server::{AccessControlBuilder, Host, HttpServerBuilder, HttpStopHandle}, ws_server::{WsServerBuilder, WsStopHandle}, RpcModule, }; @@ -90,7 +90,7 @@ pub type WsServer = WsStopHandle; /// Start HTTP server listening on given address. pub fn start_http( addr: std::net::SocketAddr, - _cors: Option<&Vec>, + cors: Option<&Vec>, maybe_max_payload_mb: Option, module: RpcModule, rt: tokio::runtime::Handle, @@ -99,8 +99,26 @@ pub fn start_http( .map(|mb| mb.saturating_mul(MEGABYTE)) .unwrap_or(RPC_MAX_PAYLOAD_DEFAULT); + let mut acl = AccessControlBuilder::new(); + + log::info!("Starting JSONRPC HTTP server: addr={}, allowed origins={:?}", addr, cors); + + if let Some(cors) = cors { + // Whitelist listening address. + let host = Host::parse(&format!("localhost:{}", addr.port())); + acl = acl.allow_host(host); + let host = Host::parse(&format!("127.0.0.1:{}", addr.port())); + acl = acl.allow_host(host); + + // Set allowed origins. + for origin in cors { + acl = acl.cors_allow_origin(origin.into()); + } + }; + let server = HttpServerBuilder::default() .max_request_body_size(max_request_body_size as u32) + .set_access_control(acl.build()) .build(addr)?; let handle = server.stop_handle(); @@ -117,7 +135,7 @@ pub fn start_http( pub fn start_ws( addr: std::net::SocketAddr, max_connections: Option, - _cors: Option<&Vec>, + cors: Option<&Vec>, maybe_max_payload_mb: Option, module: RpcModule, rt: tokio::runtime::Handle, @@ -127,14 +145,24 @@ pub fn start_ws( .unwrap_or(RPC_MAX_PAYLOAD_DEFAULT); let max_connections = max_connections.unwrap_or(WS_MAX_CONNECTIONS); - let server = tokio::task::block_in_place(|| { - rt.block_on( - WsServerBuilder::default() - .max_request_body_size(max_request_body_size as u32) - .max_connections(max_connections as u64) - .build(addr), - ) - })?; + let mut builder = WsServerBuilder::default() + .max_request_body_size(max_request_body_size as u32) + .max_connections(max_connections as u64); + + log::info!("Starting JSONRPC WS server: addr={}, allowed origins={:?}", addr, cors); + + if let Some(cors) = cors { + // Whitelist listening address. + builder = builder.set_allowed_hosts([ + format!("localhost:{}", addr.port()), + format!("127.0.0.1:{}", addr.port()), + ])?; + + // Set allowed origins. + builder = builder.set_allowed_origins(cors)?; + } + + let server = tokio::task::block_in_place(|| rt.block_on(builder.build(addr)))?; let handle = server.stop_handle(); let rpc_api = build_rpc_api(module); diff --git a/client/rpc/src/offchain/mod.rs b/client/rpc/src/offchain/mod.rs index 72519f14e0320..63fc0e48a6be4 100644 --- a/client/rpc/src/offchain/mod.rs +++ b/client/rpc/src/offchain/mod.rs @@ -51,6 +51,8 @@ impl Offchain { #[async_trait] impl OffchainApiServer for Offchain { fn set_local_storage(&self, kind: StorageKind, key: Bytes, value: Bytes) -> JsonRpcResult<()> { + self.deny_unsafe.check_if_safe()?; + let prefix = match kind { StorageKind::PERSISTENT => sp_offchain::STORAGE_PREFIX, StorageKind::LOCAL => @@ -61,13 +63,14 @@ impl OffchainApiServer for Offchain { } fn get_local_storage(&self, kind: StorageKind, key: Bytes) -> JsonRpcResult> { + self.deny_unsafe.check_if_safe()?; + let prefix = match kind { StorageKind::PERSISTENT => sp_offchain::STORAGE_PREFIX, StorageKind::LOCAL => return Err(JsonRpseeError::to_call_error(Error::UnavailableStorageKind)), }; - let bytes: Option = self.storage.read().get(prefix, &*key).map(Into::into); - Ok(bytes) + Ok(self.storage.read().get(prefix, &*key).map(Into::into)) } } diff --git a/client/rpc/src/state/mod.rs b/client/rpc/src/state/mod.rs index 88f0e70f6d4c8..702b851e354e4 100644 --- a/client/rpc/src/state/mod.rs +++ b/client/rpc/src/state/mod.rs @@ -296,7 +296,7 @@ where return Err(JsonRpseeError::to_call_error(Error::InvalidCount { value: count, max: STORAGE_KEYS_PAGED_MAX_COUNT, - })) + })); } self.backend .storage_keys_paged(block, prefix, count, start_key) @@ -342,7 +342,6 @@ where } async fn runtime_version(&self, at: Option) -> JsonRpcResult { - self.deny_unsafe.check_if_safe()?; self.backend .runtime_version(at) .await @@ -367,7 +366,6 @@ where keys: Vec, at: Option, ) -> JsonRpcResult>> { - self.deny_unsafe.check_if_safe()?; self.backend .query_storage_at(keys, at) .await @@ -379,7 +377,6 @@ where keys: Vec, block: Option, ) -> JsonRpcResult> { - self.deny_unsafe.check_if_safe()?; self.backend .read_proof(block, keys) .await diff --git a/client/rpc/src/system/mod.rs b/client/rpc/src/system/mod.rs index 95345e74709fb..94f7e63dfa287 100644 --- a/client/rpc/src/system/mod.rs +++ b/client/rpc/src/system/mod.rs @@ -164,14 +164,12 @@ impl SystemApiServer::Number> } async fn system_node_roles(&self) -> JsonRpcResult> { - self.deny_unsafe.check_if_safe()?; let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::NodeRoles(tx)); rx.await.map_err(|e| JsonRpseeError::to_call_error(e)) } async fn system_sync_state(&self) -> JsonRpcResult::Number>> { - self.deny_unsafe.check_if_safe()?; let (tx, rx) = oneshot::channel(); let _ = self.send_back.unbounded_send(Request::SyncState(tx)); rx.await.map_err(|e| JsonRpseeError::to_call_error(e)) diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index c2ebaf9ece83d..2a5f59b1e3590 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -592,8 +592,6 @@ where ), ); - // NOTE(niklasad1): we spawn jsonrpsee in seperate thread now. - // this will not shutdown the server. task_manager.keep_alive((config.base_path, rpc)); Ok(()) @@ -656,7 +654,7 @@ fn init_telemetry>( // Maciej: This is very WIP, mocking the original `gen_handler`. All of the `jsonrpsee` // specific logic should be merged back to `gen_handler` down the road. fn gen_rpc_module( - _deny_unsafe: DenyUnsafe, + deny_unsafe: DenyUnsafe, spawn_handle: SpawnTaskHandle, client: Arc, on_demand: Option>>, @@ -690,9 +688,6 @@ where { const UNIQUE_METHOD_NAMES_PROOF: &str = "Method names are unique; qed"; - // TODO(niklasad1): fix CORS. - let deny_unsafe = DenyUnsafe::No; - let system_info = sc_rpc::system::SystemInfo { chain_name: config.chain_spec.name().into(), impl_name: config.impl_name.clone(), diff --git a/client/sync-state-rpc/Cargo.toml b/client/sync-state-rpc/Cargo.toml index 4a1a7946add19..1ab8f539768c9 100644 --- a/client/sync-state-rpc/Cargo.toml +++ b/client/sync-state-rpc/Cargo.toml @@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] thiserror = "1.0.21" anyhow = "1" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", branch = "master", features = ["server"] } +log = "0.4" sc-chain-spec = { version = "4.0.0-dev", path = "../chain-spec" } sc-client-api = { version = "4.0.0-dev", path = "../api" } diff --git a/frame/contracts/rpc/Cargo.toml b/frame/contracts/rpc/Cargo.toml index 856062029a2c7..477c5ad55ebb1 100644 --- a/frame/contracts/rpc/Cargo.toml +++ b/frame/contracts/rpc/Cargo.toml @@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2" } jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", branch = "master", features = ["server"] } +log = "0.4" serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/frame/merkle-mountain-range/rpc/Cargo.toml b/frame/merkle-mountain-range/rpc/Cargo.toml index d988b3de7d637..c05329715a720 100644 --- a/frame/merkle-mountain-range/rpc/Cargo.toml +++ b/frame/merkle-mountain-range/rpc/Cargo.toml @@ -17,6 +17,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0" } jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", branch = "master", features = ["server"] } serde_json = "1" serde = { version = "1.0.126", features = ["derive"] } +log = "0.4" sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } diff --git a/frame/transaction-payment/rpc/Cargo.toml b/frame/transaction-payment/rpc/Cargo.toml index 0600c0f226200..b3463eaa9e578 100644 --- a/frame/transaction-payment/rpc/Cargo.toml +++ b/frame/transaction-payment/rpc/Cargo.toml @@ -13,9 +13,11 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] +anyhow = "1" codec = { package = "parity-scale-codec", version = "2.0.0" } jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", branch = "master", features = ["server"] } +log = "0.4" sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" } diff --git a/frame/transaction-payment/rpc/src/lib.rs b/frame/transaction-payment/rpc/src/lib.rs index ee9c500ffc55f..9b1b85887ea91 100644 --- a/frame/transaction-payment/rpc/src/lib.rs +++ b/frame/transaction-payment/rpc/src/lib.rs @@ -19,6 +19,7 @@ use std::{convert::TryInto, sync::Arc}; +use anyhow::anyhow; use codec::{Codec, Decode}; use jsonrpsee::{ proc_macros::rpc, @@ -28,7 +29,6 @@ use jsonrpsee::{ JsonRpcResult, }, }; -pub use pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi as TransactionPaymentRuntimeApi; use pallet_transaction_payment_rpc_runtime_api::{FeeDetails, InclusionFee, RuntimeDispatchInfo}; use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; @@ -39,6 +39,8 @@ use sp_runtime::{ traits::{Block as BlockT, MaybeDisplay}, }; +pub use pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi as TransactionPaymentRuntimeApi; + #[rpc(client, server, namespace = "payment")] pub trait TransactionPaymentApi { #[method(name = "queryInfo")] @@ -109,8 +111,11 @@ where .query_fee_details(&at, uxt, encoded_len) .map_err(|api_err| CallError::from_std_error(api_err))?; - let try_into_rpc_balance = - |value: Balance| value.try_into().map_err(|_try_err| CallError::InvalidParams); + let try_into_rpc_balance = |value: Balance| { + value + .try_into() + .map_err(|_| anyhow!("{} doesn't fit in NumberOrHex representation", value)) + }; Ok(FeeDetails { inclusion_fee: if let Some(inclusion_fee) = fee_details.inclusion_fee {