{
None
}
+/// Get the `deny_unsafe` setting based on the address and the RPC methods exposed by the interface.
+pub fn deny_unsafe(addr: &SocketAddr, methods: &RpcMethods) -> DenyUnsafe {
+ match (addr.ip().is_loopback(), methods) {
+ | (_, RpcMethods::Unsafe) | (false, RpcMethods::Auto) => DenyUnsafe::No,
+ _ => DenyUnsafe::Yes,
+ }
+}
+
+pub(crate) fn format_listen_addrs(addr: &[SocketAddr]) -> String {
+ let mut s = String::new();
+
+ let mut it = addr.iter().peekable();
+
+ while let Some(addr) = it.next() {
+ s.push_str(&addr.to_string());
+
+ if it.peek().is_some() {
+ s.push(',');
+ }
+ }
+
+ if addr.len() == 1 {
+ s.push(',');
+ }
+
+ s
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/substrate/client/rpc-spec-v2/Cargo.toml b/substrate/client/rpc-spec-v2/Cargo.toml
index 1ec7895e3088..ae21895de38d 100644
--- a/substrate/client/rpc-spec-v2/Cargo.toml
+++ b/substrate/client/rpc-spec-v2/Cargo.toml
@@ -16,7 +16,7 @@ workspace = true
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
-jsonrpsee = { features = ["client-core", "macros", "server-core"], workspace = true }
+jsonrpsee = { workspace = true, features = ["client-core", "macros", "server-core"] }
# Internal chain structures for "chain_spec".
sc-chain-spec = { workspace = true, default-features = true }
# Pool for submitting extrinsics required by "transaction"
@@ -45,7 +45,7 @@ rand = { workspace = true, default-features = true }
schnellru = { workspace = true }
[dev-dependencies]
-jsonrpsee = { features = ["server", "ws-client"], workspace = true }
+jsonrpsee = { workspace = true, features = ["server", "ws-client"] }
serde_json = { workspace = true, default-features = true }
tokio = { features = ["macros"], workspace = true, default-features = true }
substrate-test-runtime-client = { workspace = true }
diff --git a/substrate/client/rpc/Cargo.toml b/substrate/client/rpc/Cargo.toml
index 4a8f4b3ec630..6fe28a3873e9 100644
--- a/substrate/client/rpc/Cargo.toml
+++ b/substrate/client/rpc/Cargo.toml
@@ -43,7 +43,6 @@ sp-statement-store = { workspace = true, default-features = true }
tokio = { workspace = true, default-features = true }
[dev-dependencies]
-sp-tracing = { workspace = true }
assert_matches = { workspace = true }
sc-block-builder = { workspace = true, default-features = true }
sc-network = { workspace = true, default-features = true }
@@ -55,7 +54,6 @@ tokio = { workspace = true, default-features = true }
sp-io = { workspace = true, default-features = true }
substrate-test-runtime-client = { workspace = true }
pretty_assertions = { workspace = true }
-tracing-subscriber = { features = ["env-filter"], workspace = true }
[features]
test-helpers = []
diff --git a/substrate/client/rpc/src/author/mod.rs b/substrate/client/rpc/src/author/mod.rs
index 2fc21a238bc9..731f4df2f6f3 100644
--- a/substrate/client/rpc/src/author/mod.rs
+++ b/substrate/client/rpc/src/author/mod.rs
@@ -30,8 +30,8 @@ use crate::{
use codec::{Decode, Encode};
use futures::TryFutureExt;
-use jsonrpsee::{core::async_trait, types::ErrorObject, PendingSubscriptionSink};
-use sc_rpc_api::DenyUnsafe;
+use jsonrpsee::{core::async_trait, types::ErrorObject, Extensions, PendingSubscriptionSink};
+use sc_rpc_api::check_if_safe;
use sc_transaction_pool_api::{
error::IntoPoolError, BlockHash, InPoolTransaction, TransactionFor, TransactionPool,
TransactionSource, TxHash,
@@ -55,8 +55,6 @@ pub struct Author {
pool: Arc
,
/// The key store.
keystore: KeystorePtr,
- /// Whether to deny unsafe calls
- deny_unsafe: DenyUnsafe,
/// Executor to spawn subscriptions.
executor: SubscriptionTaskExecutor,
}
@@ -67,10 +65,9 @@ impl
Author
{
client: Arc,
pool: Arc,
keystore: KeystorePtr,
- deny_unsafe: DenyUnsafe,
executor: SubscriptionTaskExecutor,
) -> Self {
- Author { client, pool, keystore, deny_unsafe, executor }
+ Author { client, pool, keystore, executor }
}
}
@@ -104,8 +101,14 @@ where
})
}
- fn insert_key(&self, key_type: String, suri: String, public: Bytes) -> Result<()> {
- self.deny_unsafe.check_if_safe()?;
+ fn insert_key(
+ &self,
+ ext: &Extensions,
+ key_type: String,
+ suri: String,
+ public: Bytes,
+ ) -> Result<()> {
+ check_if_safe(ext)?;
let key_type = key_type.as_str().try_into().map_err(|_| Error::BadKeyType)?;
self.keystore
@@ -114,8 +117,8 @@ where
Ok(())
}
- fn rotate_keys(&self) -> Result {
- self.deny_unsafe.check_if_safe()?;
+ fn rotate_keys(&self, ext: &Extensions) -> Result {
+ check_if_safe(ext)?;
let best_block_hash = self.client.info().best_hash;
let mut runtime_api = self.client.runtime_api();
@@ -128,8 +131,8 @@ where
.map_err(|api_err| Error::Client(Box::new(api_err)).into())
}
- fn has_session_keys(&self, session_keys: Bytes) -> Result {
- self.deny_unsafe.check_if_safe()?;
+ fn has_session_keys(&self, ext: &Extensions, session_keys: Bytes) -> Result {
+ check_if_safe(ext)?;
let best_block_hash = self.client.info().best_hash;
let keys = self
@@ -142,8 +145,8 @@ where
Ok(self.keystore.has_keys(&keys))
}
- fn has_key(&self, public_key: Bytes, key_type: String) -> Result {
- self.deny_unsafe.check_if_safe()?;
+ fn has_key(&self, ext: &Extensions, public_key: Bytes, key_type: String) -> Result {
+ check_if_safe(ext)?;
let key_type = key_type.as_str().try_into().map_err(|_| Error::BadKeyType)?;
Ok(self.keystore.has_keys(&[(public_key.to_vec(), key_type)]))
@@ -155,9 +158,10 @@ where
fn remove_extrinsic(
&self,
+ ext: &Extensions,
bytes_or_hash: Vec>>,
) -> Result>> {
- self.deny_unsafe.check_if_safe()?;
+ check_if_safe(ext)?;
let hashes = bytes_or_hash
.into_iter()
.map(|x| match x {
diff --git a/substrate/client/rpc/src/author/tests.rs b/substrate/client/rpc/src/author/tests.rs
index 6bcb3e7863c0..bde60960eaf4 100644
--- a/substrate/client/rpc/src/author/tests.rs
+++ b/substrate/client/rpc/src/author/tests.rs
@@ -22,6 +22,7 @@ use crate::testing::{test_executor, timeout_secs};
use assert_matches::assert_matches;
use codec::Encode;
use jsonrpsee::{core::EmptyServerParams as EmptyParams, MethodsError as RpcError, RpcModule};
+use sc_rpc_api::DenyUnsafe;
use sc_transaction_pool::{BasicPool, FullChainApi};
use sc_transaction_pool_api::TransactionStatus;
use sp_core::{
@@ -72,26 +73,27 @@ impl Default for TestSetup {
}
impl TestSetup {
- fn author(&self) -> Author> {
- Author {
+ fn to_rpc(&self) -> RpcModule>> {
+ let mut module = Author {
client: self.client.clone(),
pool: self.pool.clone(),
keystore: self.keystore.clone(),
- deny_unsafe: DenyUnsafe::No,
executor: test_executor(),
}
+ .into_rpc();
+ module.extensions_mut().insert(DenyUnsafe::No);
+ module
}
fn into_rpc() -> RpcModule>> {
- Self::default().author().into_rpc()
+ Self::default().to_rpc()
}
}
#[tokio::test]
async fn author_submit_transaction_should_not_cause_error() {
- sp_tracing::init_for_tests();
- let author = TestSetup::default().author();
- let api = author.into_rpc();
+ let api = TestSetup::into_rpc();
+
let xt: Bytes = uxt(AccountKeyring::Alice, 1).encode().into();
let extrinsic_hash: H256 = blake2_256(&xt).into();
let response: H256 = api.call("author_submitExtrinsic", [xt.clone()]).await.unwrap();
@@ -179,7 +181,7 @@ async fn author_should_return_pending_extrinsics() {
async fn author_should_remove_extrinsics() {
const METHOD: &'static str = "author_removeExtrinsic";
let setup = TestSetup::default();
- let api = setup.author().into_rpc();
+ let api = setup.to_rpc();
// Submit three extrinsics, then remove two of them (will cause the third to be removed as well,
// having a higher nonce)
@@ -214,7 +216,7 @@ async fn author_should_remove_extrinsics() {
#[tokio::test]
async fn author_should_insert_key() {
let setup = TestSetup::default();
- let api = setup.author().into_rpc();
+ let api = setup.to_rpc();
let suri = "//Alice";
let keypair = ed25519::Pair::from_string(suri, None).expect("generates keypair");
let params: (String, String, Bytes) = (
@@ -231,7 +233,7 @@ async fn author_should_insert_key() {
#[tokio::test]
async fn author_should_rotate_keys() {
let setup = TestSetup::default();
- let api = setup.author().into_rpc();
+ let api = setup.to_rpc();
let new_pubkeys: Bytes = api.call("author_rotateKeys", EmptyParams::new()).await.unwrap();
let session_keys =
@@ -244,7 +246,6 @@ async fn author_should_rotate_keys() {
#[tokio::test]
async fn author_has_session_keys() {
- // Setup
let api = TestSetup::into_rpc();
// Add a valid session key
@@ -255,7 +256,7 @@ async fn author_has_session_keys() {
// Add a session key in a different keystore
let non_existent_pubkeys: Bytes = {
- let api2 = TestSetup::default().author().into_rpc();
+ let api2 = TestSetup::into_rpc();
api2.call("author_rotateKeys", EmptyParams::new())
.await
.expect("Rotates the keys")
@@ -279,8 +280,6 @@ async fn author_has_session_keys() {
#[tokio::test]
async fn author_has_key() {
- sp_tracing::init_for_tests();
-
let api = TestSetup::into_rpc();
let suri = "//Alice";
let alice_keypair = ed25519::Pair::from_string(suri, None).expect("Generates keypair");
diff --git a/substrate/client/rpc/src/dev/mod.rs b/substrate/client/rpc/src/dev/mod.rs
index 424ef72b694e..3ccda760c3f5 100644
--- a/substrate/client/rpc/src/dev/mod.rs
+++ b/substrate/client/rpc/src/dev/mod.rs
@@ -22,8 +22,9 @@
#[cfg(test)]
mod tests;
+use jsonrpsee::Extensions;
use sc_client_api::{BlockBackend, HeaderBackend};
-use sc_rpc_api::{dev::error::Error, DenyUnsafe};
+use sc_rpc_api::{check_if_safe, dev::error::Error};
use sp_api::{ApiExt, Core, ProvideRuntimeApi};
use sp_core::Encode;
use sp_runtime::{
@@ -42,14 +43,13 @@ type HasherOf = <::Header as Header>::Hashing;
/// The Dev API. All methods are unsafe.
pub struct Dev {
client: Arc,
- deny_unsafe: DenyUnsafe,
_phantom: PhantomData,
}
impl Dev {
/// Create a new Dev API.
- pub fn new(client: Arc, deny_unsafe: DenyUnsafe) -> Self {
- Self { client, deny_unsafe, _phantom: PhantomData::default() }
+ pub fn new(client: Arc) -> Self {
+ Self { client, _phantom: PhantomData::default() }
}
}
@@ -64,8 +64,12 @@ where
+ 'static,
Client::Api: Core,
{
- fn block_stats(&self, hash: Block::Hash) -> Result