mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-09 20:11:09 +00:00
Adds state_queryStorageAt (#5362)
* adds state_queryStorageAt * make at param for query_storage_at optional * Update client/rpc/src/state/state_full.rs Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com> * adds query_storage_at to StateBackend Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
This commit is contained in:
@@ -163,6 +163,13 @@ pub trait StateBackend<Block: BlockT, Client>: Send + Sync + 'static
|
||||
keys: Vec<StorageKey>,
|
||||
) -> FutureResult<Vec<StorageChangeSet<Block::Hash>>>;
|
||||
|
||||
/// Query storage entries (by key) starting at block hash given as the second parameter.
|
||||
fn query_storage_at(
|
||||
&self,
|
||||
keys: Vec<StorageKey>,
|
||||
at: Option<Block::Hash>
|
||||
) -> FutureResult<Vec<StorageChangeSet<Block::Hash>>>;
|
||||
|
||||
/// New runtime version subscription
|
||||
fn subscribe_runtime_version(
|
||||
&self,
|
||||
@@ -357,6 +364,14 @@ impl<Block, Client> StateApi<Block::Hash> for State<Block, Client>
|
||||
self.backend.query_storage(from, to, keys)
|
||||
}
|
||||
|
||||
fn query_storage_at(
|
||||
&self,
|
||||
keys: Vec<StorageKey>,
|
||||
at: Option<Block::Hash>
|
||||
) -> FutureResult<Vec<StorageChangeSet<Block::Hash>>> {
|
||||
self.backend.query_storage_at(keys, at)
|
||||
}
|
||||
|
||||
fn subscribe_storage(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
|
||||
@@ -33,7 +33,7 @@ use sp_core::{
|
||||
};
|
||||
use sp_version::RuntimeVersion;
|
||||
use sp_runtime::{
|
||||
generic::BlockId, traits::{Block as BlockT, NumberFor, SaturatedConversion},
|
||||
generic::BlockId, traits::{Block as BlockT, NumberFor, SaturatedConversion, CheckedSub},
|
||||
};
|
||||
|
||||
use sp_api::{Metadata, ProvideRuntimeApi, CallApiAt};
|
||||
@@ -94,8 +94,8 @@ impl<BE, Block: BlockT, Client> FullState<BE, Block, Client>
|
||||
let from_meta = self.client.header_metadata(from).map_err(invalid_block_err)?;
|
||||
let to_meta = self.client.header_metadata(to).map_err(invalid_block_err)?;
|
||||
|
||||
if from_meta.number >= to_meta.number {
|
||||
return Err(invalid_block_range(&from_meta, &to_meta, "from number >= to number".to_owned()))
|
||||
if from_meta.number > to_meta.number {
|
||||
return Err(invalid_block_range(&from_meta, &to_meta, "from number > to number".to_owned()))
|
||||
}
|
||||
|
||||
// check if we can get from `to` to `from` by going through parent_hashes.
|
||||
@@ -122,7 +122,10 @@ impl<BE, Block: BlockT, Client> FullState<BE, Block, Client>
|
||||
.max_key_changes_range(from_number, BlockId::Hash(to_meta.hash))
|
||||
.map_err(client_err)?;
|
||||
let filtered_range_begin = changes_trie_range
|
||||
.map(|(begin, _)| (begin - from_number).saturated_into::<usize>());
|
||||
.and_then(|(begin, _)| {
|
||||
// avoids a corner case where begin < from_number (happens when querying genesis)
|
||||
begin.checked_sub(&from_number).map(|x| x.saturated_into::<usize>())
|
||||
});
|
||||
let (unfiltered_range, filtered_range) = split_range(hashes.len(), filtered_range_begin);
|
||||
|
||||
Ok(QueryStorageRange {
|
||||
@@ -398,6 +401,15 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
|
||||
Box::new(result(call_fn()))
|
||||
}
|
||||
|
||||
fn query_storage_at(
|
||||
&self,
|
||||
keys: Vec<StorageKey>,
|
||||
at: Option<Block::Hash>
|
||||
) -> FutureResult<Vec<StorageChangeSet<Block::Hash>>> {
|
||||
let at = at.unwrap_or_else(|| self.client.info().best_hash);
|
||||
self.query_storage(at, Some(at), keys)
|
||||
}
|
||||
|
||||
fn subscribe_runtime_version(
|
||||
&self,
|
||||
_meta: crate::metadata::Metadata,
|
||||
|
||||
@@ -331,6 +331,14 @@ impl<Block, F, Client> StateBackend<Block, Client> for LightState<Block, F, Clie
|
||||
Box::new(result(Err(client_err(ClientError::NotAvailableOnLightClient))))
|
||||
}
|
||||
|
||||
fn query_storage_at(
|
||||
&self,
|
||||
_keys: Vec<StorageKey>,
|
||||
_at: Option<Block::Hash>
|
||||
) -> FutureResult<Vec<StorageChangeSet<Block::Hash>>> {
|
||||
Box::new(result(Err(client_err(ClientError::NotAvailableOnLightClient))))
|
||||
}
|
||||
|
||||
fn subscribe_storage(
|
||||
&self,
|
||||
_meta: crate::metadata::Metadata,
|
||||
|
||||
@@ -30,6 +30,7 @@ use substrate_test_runtime_client::{
|
||||
sp_consensus::BlockOrigin,
|
||||
runtime,
|
||||
};
|
||||
use sp_runtime::generic::BlockId;
|
||||
|
||||
const CHILD_INFO: ChildInfo<'static> = ChildInfo::new_default(b"unique_id");
|
||||
|
||||
@@ -212,7 +213,7 @@ fn should_send_initial_storage_changes_and_notifications() {
|
||||
|
||||
#[test]
|
||||
fn should_query_storage() {
|
||||
fn run_tests(mut client: Arc<TestClient>) {
|
||||
fn run_tests(mut client: Arc<TestClient>, has_changes_trie_config: bool) {
|
||||
let core = tokio::runtime::Runtime::new().unwrap();
|
||||
let api = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor())));
|
||||
|
||||
@@ -237,6 +238,13 @@ fn should_query_storage() {
|
||||
let block2_hash = add_block(1);
|
||||
let genesis_hash = client.genesis_hash();
|
||||
|
||||
if has_changes_trie_config {
|
||||
assert_eq!(
|
||||
client.max_key_changes_range(1, BlockId::Hash(block1_hash)).unwrap(),
|
||||
Some((0, BlockId::Hash(block1_hash))),
|
||||
);
|
||||
}
|
||||
|
||||
let mut expected = vec![
|
||||
StorageChangeSet {
|
||||
block: genesis_hash,
|
||||
@@ -306,7 +314,7 @@ fn should_query_storage() {
|
||||
Err(Error::InvalidBlockRange {
|
||||
from: format!("1 ({:?})", block1_hash),
|
||||
to: format!("0 ({:?})", genesis_hash),
|
||||
details: "from number >= to number".to_owned(),
|
||||
details: "from number > to number".to_owned(),
|
||||
}).map_err(|e| e.to_string())
|
||||
);
|
||||
|
||||
@@ -376,12 +384,39 @@ fn should_query_storage() {
|
||||
details: format!("UnknownBlock: header not found in db: {}", random_hash1),
|
||||
}).map_err(|e| e.to_string()),
|
||||
);
|
||||
|
||||
// single block range
|
||||
let result = api.query_storage_at(
|
||||
keys.clone(),
|
||||
Some(block1_hash),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
result.wait().unwrap(),
|
||||
vec![
|
||||
StorageChangeSet {
|
||||
block: block1_hash,
|
||||
changes: vec![
|
||||
(StorageKey(vec![1_u8]), None),
|
||||
(StorageKey(vec![2_u8]), Some(StorageData(vec![2_u8]))),
|
||||
(StorageKey(vec![3_u8]), Some(StorageData(vec![3_u8]))),
|
||||
(StorageKey(vec![4_u8]), None),
|
||||
(StorageKey(vec![5_u8]), Some(StorageData(vec![0_u8]))),
|
||||
]
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
run_tests(Arc::new(substrate_test_runtime_client::new()));
|
||||
run_tests(Arc::new(TestClientBuilder::new()
|
||||
.changes_trie_config(Some(ChangesTrieConfiguration::new(4, 2)))
|
||||
.build()));
|
||||
run_tests(Arc::new(substrate_test_runtime_client::new()), false);
|
||||
run_tests(
|
||||
Arc::new(
|
||||
TestClientBuilder::new()
|
||||
.changes_trie_config(Some(ChangesTrieConfiguration::new(4, 2)))
|
||||
.build(),
|
||||
),
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user