This repository was archived by the owner on Nov 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Fix the storage_size/state_getStorageSize RPC call
#13154
Merged
paritytech-processbot
merged 8 commits into
paritytech:master
from
koute:master_storage_size_fix
Jan 18, 2023
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
c84d026
Have `KeyIterator` clone the `prefix` it receives
koute 83cd8e8
Stream keys in `storage_size` RPC and add a runtime limit
koute 027a718
Update client/rpc/Cargo.toml
koute b83d731
Update client/rpc/src/state/utils.rs
koute cdbb894
Rename the types to signify that the cancellation is due to a timeout
koute e3f6555
Move the test into a `mod tests`
koute 8ed99ed
Add a comment regarding `biased` in `tokio::select`
koute 2868c17
Make the `clone` explicit when calling `KeyIterator::{new, new_child}`
koute File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,17 +18,20 @@ | |
|
|
||
| //! State API backend for full nodes. | ||
|
|
||
| use std::{collections::HashMap, marker::PhantomData, sync::Arc}; | ||
| use std::{collections::HashMap, marker::PhantomData, sync::Arc, time::Duration}; | ||
|
|
||
| use super::{ | ||
| client_err, | ||
| error::{Error, Result}, | ||
| ChildStateBackend, StateBackend, | ||
| }; | ||
| use crate::SubscriptionTaskExecutor; | ||
| use crate::{DenyUnsafe, SubscriptionTaskExecutor}; | ||
|
|
||
| use futures::{future, stream, FutureExt, StreamExt}; | ||
| use jsonrpsee::{core::Error as JsonRpseeError, SubscriptionSink}; | ||
| use jsonrpsee::{ | ||
| core::{async_trait, Error as JsonRpseeError}, | ||
| SubscriptionSink, | ||
| }; | ||
| use sc_client_api::{ | ||
| Backend, BlockBackend, BlockchainEvents, CallExecutor, ExecutorProvider, ProofProvider, | ||
| StorageProvider, | ||
|
|
@@ -48,6 +51,9 @@ use sp_core::{ | |
| use sp_runtime::{generic::BlockId, traits::Block as BlockT}; | ||
| use sp_version::RuntimeVersion; | ||
|
|
||
| /// The maximum time allowed for an RPC call when running without unsafe RPC enabled. | ||
| const MAXIMUM_SAFE_RPC_CALL_TIMEOUT: Duration = Duration::from_secs(30); | ||
|
|
||
| /// Ranges to query in state_queryStorage. | ||
| struct QueryStorageRange<Block: BlockT> { | ||
| /// Hashes of all the blocks in the range. | ||
|
|
@@ -166,6 +172,7 @@ where | |
| } | ||
| } | ||
|
|
||
| #[async_trait] | ||
| impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Client> | ||
| where | ||
| Block: BlockT + 'static, | ||
|
|
@@ -251,33 +258,53 @@ where | |
| .map_err(client_err) | ||
| } | ||
|
|
||
| fn storage_size( | ||
| async fn storage_size( | ||
| &self, | ||
| block: Option<Block::Hash>, | ||
| key: StorageKey, | ||
| deny_unsafe: DenyUnsafe, | ||
| ) -> std::result::Result<Option<u64>, Error> { | ||
| let block = match self.block_or_best(block) { | ||
| Ok(b) => b, | ||
| Err(e) => return Err(client_err(e)), | ||
| }; | ||
|
|
||
| match self.client.storage(block, &key) { | ||
| Ok(Some(d)) => return Ok(Some(d.0.len() as u64)), | ||
| Err(e) => return Err(client_err(e)), | ||
| Ok(None) => {}, | ||
| } | ||
| let client = self.client.clone(); | ||
| let timeout = match deny_unsafe { | ||
| DenyUnsafe::Yes => Some(MAXIMUM_SAFE_RPC_CALL_TIMEOUT), | ||
| DenyUnsafe::No => None, | ||
| }; | ||
|
|
||
| self.client | ||
| .storage_pairs(block, &key) | ||
| .map(|kv| { | ||
| let item_sum = kv.iter().map(|(_, v)| v.0.len() as u64).sum::<u64>(); | ||
| if item_sum > 0 { | ||
| Some(item_sum) | ||
| } else { | ||
| None | ||
| } | ||
| }) | ||
| .map_err(client_err) | ||
| super::utils::spawn_blocking_with_timeout(timeout, move |is_timed_out| { | ||
| // Does the key point to a concrete entry in the database? | ||
| match client.storage(block, &key) { | ||
| Ok(Some(d)) => return Ok(Ok(Some(d.0.len() as u64))), | ||
| Err(e) => return Ok(Err(client_err(e))), | ||
| Ok(None) => {}, | ||
| } | ||
|
|
||
| // The key doesn't point to anything, so it's probably a prefix. | ||
| let iter = match client.storage_keys_iter(block, Some(&key), None).map_err(client_err) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I think we should. In the next PR I was planning on getting rid of all of the methods that return a |
||
| Ok(iter) => iter, | ||
| Err(e) => return Ok(Err(e)), | ||
| }; | ||
|
|
||
| let mut sum = 0; | ||
| for storage_key in iter { | ||
| let value = client.storage(block, &storage_key).ok().flatten().unwrap_or_default(); | ||
| sum += value.0.len() as u64; | ||
|
|
||
| is_timed_out.check_if_timed_out()?; | ||
| } | ||
|
|
||
| if sum > 0 { | ||
| Ok(Ok(Some(sum))) | ||
| } else { | ||
| Ok(Ok(None)) | ||
| } | ||
| }) | ||
| .await | ||
| .map_err(|error| Error::Client(Box::new(error)))? | ||
| } | ||
|
|
||
| fn storage_hash( | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is a bold take :P I would not want to rely on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's how the original RPC works. 🤷
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh fuck, I have overseen this :P Sorry 🙈 I should go back in time and add my comment there xD