1mod state_full;
22mod utils;
23
24#[cfg(test)]
25mod tests;
26
27use crate::SubscriptionTaskExecutor;
28use jsonrpsee::{core::async_trait, Extensions, PendingSubscriptionSink};
29use sc_client_api::{
30 Backend, BlockBackend, BlockchainEvents, ExecutorProvider, ProofProvider, StorageProvider,
31};
32use sc_rpc_api::{check_if_safe, DenyUnsafe};
33use sp_api::{CallApiAt, Metadata, ProvideRuntimeApi};
34use sp_blockchain::{HeaderBackend, HeaderMetadata};
35use sp_core::{
36 storage::{PrefixedStorageKey, StorageChangeSet, StorageData, StorageKey},
37 Bytes,
38};
39use sp_runtime::traits::Block as BlockT;
40use sp_version::RuntimeVersion;
41use std::sync::Arc;
42
43pub use sc_rpc_api::{child_state::*, state::*};
44
45const STORAGE_KEYS_PAGED_MAX_COUNT: u32 = 1000;
46
47#[async_trait]
49pub trait StateBackend<Block: BlockT, Client>: Send + Sync + 'static
50where
51 Block: BlockT + 'static,
52 Client: Send + Sync + 'static,
53{
54 fn call(
56 &self,
57 block: Option<Block::Hash>,
58 method: String,
59 call_data: Bytes,
60 ) -> Result<Bytes, Error>;
61
62 fn storage_keys(
64 &self,
65 block: Option<Block::Hash>,
66 prefix: StorageKey,
67 ) -> Result<Vec<StorageKey>, Error>;
68
69 fn storage_pairs(
71 &self,
72 block: Option<Block::Hash>,
73 prefix: StorageKey,
74 ) -> Result<Vec<(StorageKey, StorageData)>, Error>;
75
76 fn storage_keys_paged(
78 &self,
79 block: Option<Block::Hash>,
80 prefix: Option<StorageKey>,
81 count: u32,
82 start_key: Option<StorageKey>,
83 ) -> Result<Vec<StorageKey>, Error>;
84
85 fn storage(
87 &self,
88 block: Option<Block::Hash>,
89 key: StorageKey,
90 ) -> Result<Option<StorageData>, Error>;
91
92 fn storage_hash(
94 &self,
95 block: Option<Block::Hash>,
96 key: StorageKey,
97 ) -> Result<Option<Block::Hash>, Error>;
98
99 async fn storage_size(
104 &self,
105 block: Option<Block::Hash>,
106 key: StorageKey,
107 deny_unsafe: DenyUnsafe,
108 ) -> Result<Option<u64>, Error>;
109
110 fn metadata(&self, block: Option<Block::Hash>) -> Result<Bytes, Error>;
112
113 fn runtime_version(&self, block: Option<Block::Hash>) -> Result<RuntimeVersion, Error>;
115
116 fn query_storage(
122 &self,
123 from: Block::Hash,
124 to: Option<Block::Hash>,
125 keys: Vec<StorageKey>,
126 ) -> Result<Vec<StorageChangeSet<Block::Hash>>, Error>;
127
128 fn query_storage_at(
130 &self,
131 keys: Vec<StorageKey>,
132 at: Option<Block::Hash>,
133 ) -> Result<Vec<StorageChangeSet<Block::Hash>>, Error>;
134
135 fn read_proof(
137 &self,
138 block: Option<Block::Hash>,
139 keys: Vec<StorageKey>,
140 ) -> Result<ReadProof<Block::Hash>, Error>;
141
142 fn trace_block(
144 &self,
145 block: Block::Hash,
146 targets: Option<String>,
147 storage_keys: Option<String>,
148 methods: Option<String>,
149 ) -> Result<sp_rpc::tracing::TraceBlockResponse, Error>;
150
151 fn subscribe_runtime_version(&self, pending: PendingSubscriptionSink);
153
154 fn subscribe_storage(
156 &self,
157 pending: PendingSubscriptionSink,
158 keys: Option<Vec<StorageKey>>,
159 deny_unsafe: DenyUnsafe,
160 );
161}
162
163pub fn new_full<BE, Block: BlockT, Client>(
165 client: Arc<Client>,
166 executor: SubscriptionTaskExecutor,
167) -> (State<Block, Client>, ChildState<Block, Client>)
168where
169 Block: BlockT + 'static,
170 Block::Hash: Unpin,
171 BE: Backend<Block> + 'static,
172 Client: ExecutorProvider<Block>
173 + StorageProvider<Block, BE>
174 + ProofProvider<Block>
175 + HeaderMetadata<Block, Error = sp_blockchain::Error>
176 + BlockchainEvents<Block>
177 + CallApiAt<Block>
178 + HeaderBackend<Block>
179 + BlockBackend<Block>
180 + ProvideRuntimeApi<Block>
181 + Send
182 + Sync
183 + 'static,
184 Client::Api: Metadata<Block>,
185{
186 let child_backend =
187 Box::new(self::state_full::FullState::new(client.clone(), executor.clone()));
188 let backend = Box::new(self::state_full::FullState::new(client, executor));
189 (State { backend }, ChildState { backend: child_backend })
190}
191
192pub struct State<Block, Client> {
194 backend: Box<dyn StateBackend<Block, Client>>,
195}
196
197#[async_trait]
198impl<Block, Client> StateApiServer<Block::Hash> for State<Block, Client>
199where
200 Block: BlockT + 'static,
201 Client: Send + Sync + 'static,
202{
203 fn call(
204 &self,
205 method: String,
206 data: Bytes,
207 block: Option<Block::Hash>,
208 ) -> Result<Bytes, Error> {
209 self.backend.call(block, method, data).map_err(Into::into)
210 }
211
212 fn storage_keys(
213 &self,
214 key_prefix: StorageKey,
215 block: Option<Block::Hash>,
216 ) -> Result<Vec<StorageKey>, Error> {
217 self.backend.storage_keys(block, key_prefix).map_err(Into::into)
218 }
219
220 fn storage_pairs(
221 &self,
222 ext: &Extensions,
223 key_prefix: StorageKey,
224 block: Option<Block::Hash>,
225 ) -> Result<Vec<(StorageKey, StorageData)>, Error> {
226 check_if_safe(ext)?;
227 self.backend.storage_pairs(block, key_prefix).map_err(Into::into)
228 }
229
230 fn storage_keys_paged(
231 &self,
232 prefix: Option<StorageKey>,
233 count: u32,
234 start_key: Option<StorageKey>,
235 block: Option<Block::Hash>,
236 ) -> Result<Vec<StorageKey>, Error> {
237 if count > STORAGE_KEYS_PAGED_MAX_COUNT {
238 return Err(Error::InvalidCount { value: count, max: STORAGE_KEYS_PAGED_MAX_COUNT })
239 }
240 self.backend
241 .storage_keys_paged(block, prefix, count, start_key)
242 .map_err(Into::into)
243 }
244
245 fn storage(
246 &self,
247 key: StorageKey,
248 block: Option<Block::Hash>,
249 ) -> Result<Option<StorageData>, Error> {
250 self.backend.storage(block, key).map_err(Into::into)
251 }
252
253 fn storage_hash(
254 &self,
255 key: StorageKey,
256 block: Option<Block::Hash>,
257 ) -> Result<Option<Block::Hash>, Error> {
258 self.backend.storage_hash(block, key).map_err(Into::into)
259 }
260
261 async fn storage_size(
262 &self,
263 ext: &Extensions,
264 key: StorageKey,
265 block: Option<Block::Hash>,
266 ) -> Result<Option<u64>, Error> {
267 let deny_unsafe = ext
268 .get::<DenyUnsafe>()
269 .cloned()
270 .expect("DenyUnsafe extension is always set by the substrate rpc server; qed");
271 self.backend.storage_size(block, key, deny_unsafe).await.map_err(Into::into)
272 }
273
274 fn metadata(&self, block: Option<Block::Hash>) -> Result<Bytes, Error> {
275 self.backend.metadata(block).map_err(Into::into)
276 }
277
278 fn runtime_version(&self, at: Option<Block::Hash>) -> Result<RuntimeVersion, Error> {
279 self.backend.runtime_version(at).map_err(Into::into)
280 }
281
282 fn query_storage(
283 &self,
284 ext: &Extensions,
285 keys: Vec<StorageKey>,
286 from: Block::Hash,
287 to: Option<Block::Hash>,
288 ) -> Result<Vec<StorageChangeSet<Block::Hash>>, Error> {
289 check_if_safe(ext)?;
290 self.backend.query_storage(from, to, keys).map_err(Into::into)
291 }
292
293 fn query_storage_at(
294 &self,
295 keys: Vec<StorageKey>,
296 at: Option<Block::Hash>,
297 ) -> Result<Vec<StorageChangeSet<Block::Hash>>, Error> {
298 self.backend.query_storage_at(keys, at).map_err(Into::into)
299 }
300
301 fn read_proof(
302 &self,
303 keys: Vec<StorageKey>,
304 block: Option<Block::Hash>,
305 ) -> Result<ReadProof<Block::Hash>, Error> {
306 self.backend.read_proof(block, keys).map_err(Into::into)
307 }
308
309 fn trace_block(
315 &self,
316 ext: &Extensions,
317 block: Block::Hash,
318 targets: Option<String>,
319 storage_keys: Option<String>,
320 methods: Option<String>,
321 ) -> Result<sp_rpc::tracing::TraceBlockResponse, Error> {
322 check_if_safe(ext)?;
323 self.backend
324 .trace_block(block, targets, storage_keys, methods)
325 .map_err(Into::into)
326 }
327
328 fn subscribe_runtime_version(&self, pending: PendingSubscriptionSink) {
329 self.backend.subscribe_runtime_version(pending)
330 }
331
332 fn subscribe_storage(
333 &self,
334 pending: PendingSubscriptionSink,
335 ext: &Extensions,
336 keys: Option<Vec<StorageKey>>,
337 ) {
338 let deny_unsafe = ext
339 .get::<DenyUnsafe>()
340 .cloned()
341 .expect("DenyUnsafe extension is always set by the substrate rpc server; qed");
342 self.backend.subscribe_storage(pending, keys, deny_unsafe)
343 }
344}
345
346pub trait ChildStateBackend<Block: BlockT, Client>: Send + Sync + 'static
348where
349 Block: BlockT + 'static,
350 Client: Send + Sync + 'static,
351{
352 fn read_child_proof(
354 &self,
355 block: Option<Block::Hash>,
356 storage_key: PrefixedStorageKey,
357 keys: Vec<StorageKey>,
358 ) -> Result<ReadProof<Block::Hash>, Error>;
359
360 fn storage_keys(
363 &self,
364 block: Option<Block::Hash>,
365 storage_key: PrefixedStorageKey,
366 prefix: StorageKey,
367 ) -> Result<Vec<StorageKey>, Error>;
368
369 fn storage_keys_paged(
371 &self,
372 block: Option<Block::Hash>,
373 storage_key: PrefixedStorageKey,
374 prefix: Option<StorageKey>,
375 count: u32,
376 start_key: Option<StorageKey>,
377 ) -> Result<Vec<StorageKey>, Error>;
378
379 fn storage(
381 &self,
382 block: Option<Block::Hash>,
383 storage_key: PrefixedStorageKey,
384 key: StorageKey,
385 ) -> Result<Option<StorageData>, Error>;
386
387 fn storage_entries(
389 &self,
390 block: Option<Block::Hash>,
391 storage_key: PrefixedStorageKey,
392 keys: Vec<StorageKey>,
393 ) -> Result<Vec<Option<StorageData>>, Error>;
394
395 fn storage_hash(
397 &self,
398 block: Option<Block::Hash>,
399 storage_key: PrefixedStorageKey,
400 key: StorageKey,
401 ) -> Result<Option<Block::Hash>, Error>;
402
403 fn storage_size(
405 &self,
406 block: Option<Block::Hash>,
407 storage_key: PrefixedStorageKey,
408 key: StorageKey,
409 ) -> Result<Option<u64>, Error> {
410 self.storage(block, storage_key, key).map(|x| x.map(|x| x.0.len() as u64))
411 }
412}
413
414pub struct ChildState<Block, Client> {
416 backend: Box<dyn ChildStateBackend<Block, Client>>,
417}
418
419impl<Block, Client> ChildStateApiServer<Block::Hash> for ChildState<Block, Client>
420where
421 Block: BlockT + 'static,
422 Client: Send + Sync + 'static,
423{
424 fn storage_keys(
425 &self,
426 storage_key: PrefixedStorageKey,
427 key_prefix: StorageKey,
428 block: Option<Block::Hash>,
429 ) -> Result<Vec<StorageKey>, Error> {
430 self.backend.storage_keys(block, storage_key, key_prefix).map_err(Into::into)
431 }
432
433 fn storage_keys_paged(
434 &self,
435 storage_key: PrefixedStorageKey,
436 prefix: Option<StorageKey>,
437 count: u32,
438 start_key: Option<StorageKey>,
439 block: Option<Block::Hash>,
440 ) -> Result<Vec<StorageKey>, Error> {
441 self.backend
442 .storage_keys_paged(block, storage_key, prefix, count, start_key)
443 .map_err(Into::into)
444 }
445
446 fn storage(
447 &self,
448 storage_key: PrefixedStorageKey,
449 key: StorageKey,
450 block: Option<Block::Hash>,
451 ) -> Result<Option<StorageData>, Error> {
452 self.backend.storage(block, storage_key, key).map_err(Into::into)
453 }
454
455 fn storage_entries(
456 &self,
457 storage_key: PrefixedStorageKey,
458 keys: Vec<StorageKey>,
459 block: Option<Block::Hash>,
460 ) -> Result<Vec<Option<StorageData>>, Error> {
461 self.backend.storage_entries(block, storage_key, keys).map_err(Into::into)
462 }
463
464 fn storage_hash(
465 &self,
466 storage_key: PrefixedStorageKey,
467 key: StorageKey,
468 block: Option<Block::Hash>,
469 ) -> Result<Option<Block::Hash>, Error> {
470 self.backend.storage_hash(block, storage_key, key).map_err(Into::into)
471 }
472
473 fn storage_size(
474 &self,
475 storage_key: PrefixedStorageKey,
476 key: StorageKey,
477 block: Option<Block::Hash>,
478 ) -> Result<Option<u64>, Error> {
479 self.backend.storage_size(block, storage_key, key).map_err(Into::into)
480 }
481
482 fn read_child_proof(
483 &self,
484 child_storage_key: PrefixedStorageKey,
485 keys: Vec<StorageKey>,
486 block: Option<Block::Hash>,
487 ) -> Result<ReadProof<Block::Hash>, Error> {
488 self.backend
489 .read_child_proof(block, child_storage_key, keys)
490 .map_err(Into::into)
491 }
492}
493
494fn client_err(err: sp_blockchain::Error) -> Error {
495 Error::Client(Box::new(err))
496}