Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 6fdf3db

Browse files
authored
Make queryStorage and storagePairs unsafe RPC functions (#7342)
The RPC calls can be rather expensive and can easily bring a RPC node in some problems ;)
1 parent 900d034 commit 6fdf3db

File tree

4 files changed

+64
-12
lines changed

4 files changed

+64
-12
lines changed

client/rpc-api/src/state/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ pub enum Error {
5151
/// Maximum allowed value
5252
max: u32,
5353
},
54+
/// Call to an unsafe RPC was denied.
55+
UnsafeRpcCalled(crate::policy::UnsafeRpcError),
5456
}
5557

5658
impl std::error::Error for Error {

client/rpc/src/state/mod.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use std::sync::Arc;
2828
use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId, manager::SubscriptionManager};
2929
use rpc::{Result as RpcResult, futures::{Future, future::result}};
3030

31-
use sc_rpc_api::state::ReadProof;
31+
use sc_rpc_api::{DenyUnsafe, state::ReadProof};
3232
use sc_client_api::light::{RemoteBlockchain, Fetcher};
3333
use sp_core::{Bytes, storage::{StorageKey, PrefixedStorageKey, StorageData, StorageChangeSet}};
3434
use sp_version::RuntimeVersion;
@@ -171,6 +171,7 @@ pub trait StateBackend<Block: BlockT, Client>: Send + Sync + 'static
171171
pub fn new_full<BE, Block: BlockT, Client>(
172172
client: Arc<Client>,
173173
subscriptions: SubscriptionManager,
174+
deny_unsafe: DenyUnsafe,
174175
) -> (State<Block, Client>, ChildState<Block, Client>)
175176
where
176177
Block: BlockT + 'static,
@@ -185,7 +186,7 @@ pub fn new_full<BE, Block: BlockT, Client>(
185186
self::state_full::FullState::new(client.clone(), subscriptions.clone())
186187
);
187188
let backend = Box::new(self::state_full::FullState::new(client, subscriptions));
188-
(State { backend }, ChildState { backend: child_backend })
189+
(State { backend, deny_unsafe }, ChildState { backend: child_backend })
189190
}
190191

191192
/// Create new state API that works on light node.
@@ -194,6 +195,7 @@ pub fn new_light<BE, Block: BlockT, Client, F: Fetcher<Block>>(
194195
subscriptions: SubscriptionManager,
195196
remote_blockchain: Arc<dyn RemoteBlockchain<Block>>,
196197
fetcher: Arc<F>,
198+
deny_unsafe: DenyUnsafe,
197199
) -> (State<Block, Client>, ChildState<Block, Client>)
198200
where
199201
Block: BlockT + 'static,
@@ -217,12 +219,14 @@ pub fn new_light<BE, Block: BlockT, Client, F: Fetcher<Block>>(
217219
remote_blockchain,
218220
fetcher,
219221
));
220-
(State { backend }, ChildState { backend: child_backend })
222+
(State { backend, deny_unsafe }, ChildState { backend: child_backend })
221223
}
222224

223225
/// State API with subscriptions support.
224226
pub struct State<Block, Client> {
225227
backend: Box<dyn StateBackend<Block, Client>>,
228+
/// Whether to deny unsafe calls
229+
deny_unsafe: DenyUnsafe,
226230
}
227231

228232
impl<Block, Client> StateApi<Block::Hash> for State<Block, Client>
@@ -249,6 +253,10 @@ impl<Block, Client> StateApi<Block::Hash> for State<Block, Client>
249253
key_prefix: StorageKey,
250254
block: Option<Block::Hash>,
251255
) -> FutureResult<Vec<(StorageKey, StorageData)>> {
256+
if let Err(err) = self.deny_unsafe.check_if_safe() {
257+
return Box::new(result(Err(err.into())))
258+
}
259+
252260
self.backend.storage_pairs(block, key_prefix)
253261
}
254262

@@ -292,6 +300,10 @@ impl<Block, Client> StateApi<Block::Hash> for State<Block, Client>
292300
from: Block::Hash,
293301
to: Option<Block::Hash>
294302
) -> FutureResult<Vec<StorageChangeSet<Block::Hash>>> {
303+
if let Err(err) = self.deny_unsafe.check_if_safe() {
304+
return Box::new(result(Err(err.into())))
305+
}
306+
295307
self.backend.query_storage(from, to, keys)
296308
}
297309

client/rpc/src/state/tests.rs

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use substrate_test_runtime_client::{
3232
sp_consensus::BlockOrigin,
3333
runtime,
3434
};
35+
use sc_rpc_api::DenyUnsafe;
3536
use sp_runtime::generic::BlockId;
3637
use crate::testing::TaskExecutor;
3738
use futures::{executor, compat::Future01CompatExt};
@@ -58,7 +59,11 @@ fn should_return_storage() {
5859
.add_extra_storage(b":map:acc2".to_vec(), vec![1, 2, 3])
5960
.build();
6061
let genesis_hash = client.genesis_hash();
61-
let (client, child) = new_full(Arc::new(client), SubscriptionManager::new(Arc::new(TaskExecutor)));
62+
let (client, child) = new_full(
63+
Arc::new(client),
64+
SubscriptionManager::new(Arc::new(TaskExecutor)),
65+
DenyUnsafe::No,
66+
);
6267
let key = StorageKey(KEY.to_vec());
6368

6469
assert_eq!(
@@ -96,7 +101,11 @@ fn should_return_child_storage() {
96101
.add_child_storage(&child_info, "key", vec![42_u8])
97102
.build());
98103
let genesis_hash = client.genesis_hash();
99-
let (_client, child) = new_full(client, SubscriptionManager::new(Arc::new(TaskExecutor)));
104+
let (_client, child) = new_full(
105+
client,
106+
SubscriptionManager::new(Arc::new(TaskExecutor)),
107+
DenyUnsafe::No,
108+
);
100109
let child_key = prefixed_storage_key();
101110
let key = StorageKey(b"key".to_vec());
102111

@@ -131,7 +140,11 @@ fn should_return_child_storage() {
131140
fn should_call_contract() {
132141
let client = Arc::new(substrate_test_runtime_client::new());
133142
let genesis_hash = client.genesis_hash();
134-
let (client, _child) = new_full(client, SubscriptionManager::new(Arc::new(TaskExecutor)));
143+
let (client, _child) = new_full(
144+
client,
145+
SubscriptionManager::new(Arc::new(TaskExecutor)),
146+
DenyUnsafe::No,
147+
);
135148

136149
assert_matches!(
137150
client.call("balanceOf".into(), Bytes(vec![1,2,3]), Some(genesis_hash).into()).wait(),
@@ -145,7 +158,11 @@ fn should_notify_about_storage_changes() {
145158

146159
{
147160
let mut client = Arc::new(substrate_test_runtime_client::new());
148-
let (api, _child) = new_full(client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor)));
161+
let (api, _child) = new_full(
162+
client.clone(),
163+
SubscriptionManager::new(Arc::new(TaskExecutor)),
164+
DenyUnsafe::No,
165+
);
149166

150167
api.subscribe_storage(Default::default(), subscriber, None.into());
151168

@@ -179,7 +196,11 @@ fn should_send_initial_storage_changes_and_notifications() {
179196

180197
{
181198
let mut client = Arc::new(substrate_test_runtime_client::new());
182-
let (api, _child) = new_full(client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor)));
199+
let (api, _child) = new_full(
200+
client.clone(),
201+
SubscriptionManager::new(Arc::new(TaskExecutor)),
202+
DenyUnsafe::No,
203+
);
183204

184205
let alice_balance_key = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Alice.into()));
185206

@@ -217,7 +238,11 @@ fn should_send_initial_storage_changes_and_notifications() {
217238
#[test]
218239
fn should_query_storage() {
219240
fn run_tests(mut client: Arc<TestClient>, has_changes_trie_config: bool) {
220-
let (api, _child) = new_full(client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor)));
241+
let (api, _child) = new_full(
242+
client.clone(),
243+
SubscriptionManager::new(Arc::new(TaskExecutor)),
244+
DenyUnsafe::No,
245+
);
221246

222247
let mut add_block = |nonce| {
223248
let mut builder = client.new_block(Default::default()).unwrap();
@@ -434,7 +459,11 @@ fn should_split_ranges() {
434459
#[test]
435460
fn should_return_runtime_version() {
436461
let client = Arc::new(substrate_test_runtime_client::new());
437-
let (api, _child) = new_full(client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor)));
462+
let (api, _child) = new_full(
463+
client.clone(),
464+
SubscriptionManager::new(Arc::new(TaskExecutor)),
465+
DenyUnsafe::No,
466+
);
438467

439468
let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\
440469
\"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",3],\
@@ -457,7 +486,11 @@ fn should_notify_on_runtime_version_initially() {
457486

458487
{
459488
let client = Arc::new(substrate_test_runtime_client::new());
460-
let (api, _child) = new_full(client.clone(), SubscriptionManager::new(Arc::new(TaskExecutor)));
489+
let (api, _child) = new_full(
490+
client.clone(),
491+
SubscriptionManager::new(Arc::new(TaskExecutor)),
492+
DenyUnsafe::No,
493+
);
461494

462495
api.subscribe_runtime_version(Default::default(), subscriber);
463496

client/service/src/builder.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -753,13 +753,18 @@ fn gen_handler<TBl, TBackend, TExPool, TRpc, TCl>(
753753
subscriptions.clone(),
754754
remote_blockchain.clone(),
755755
on_demand,
756+
deny_unsafe,
756757
);
757758
(chain, state, child_state)
758759

759760
} else {
760761
// Full nodes
761762
let chain = sc_rpc::chain::new_full(client.clone(), subscriptions.clone());
762-
let (state, child_state) = sc_rpc::state::new_full(client.clone(), subscriptions.clone());
763+
let (state, child_state) = sc_rpc::state::new_full(
764+
client.clone(),
765+
subscriptions.clone(),
766+
deny_unsafe,
767+
);
763768
(chain, state, child_state)
764769
};
765770

0 commit comments

Comments
 (0)