mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 19:21:13 +00:00
Use changes tries in query_storage RPC (#1082)
* use changes tries in query_storage RPC * let + match + return + call -> match
This commit is contained in:
committed by
Bastian Köcher
parent
eb000fb1ae
commit
da1fb3f273
@@ -42,7 +42,7 @@ use state_machine::{
|
||||
key_changes, key_changes_proof, OverlayedChanges
|
||||
};
|
||||
|
||||
use crate::backend::{self, BlockImportOperation};
|
||||
use crate::backend::{self, BlockImportOperation, PrunableStateChangesTrieStorage};
|
||||
use crate::blockchain::{self, Info as ChainInfo, Backend as ChainBackend, HeaderBackend as ChainHeaderBackend};
|
||||
use crate::call_executor::{CallExecutor, LocalCallExecutor};
|
||||
use executor::{RuntimeVersion, RuntimeInfo};
|
||||
@@ -355,35 +355,54 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
Ok((header, proof))
|
||||
}
|
||||
|
||||
/// Get longest range within [first; last] that is possible to use in `key_changes`
|
||||
/// and `key_changes_proof` calls.
|
||||
/// Range could be shortened from the beginning if some changes tries have been pruned.
|
||||
/// Returns Ok(None) if changes trues are not supported.
|
||||
pub fn max_key_changes_range(
|
||||
&self,
|
||||
first: NumberFor<Block>,
|
||||
last: BlockId<Block>,
|
||||
) -> error::Result<Option<(NumberFor<Block>, BlockId<Block>)>> {
|
||||
let (config, storage) = match self.require_changes_trie().ok() {
|
||||
Some((config, storage)) => (config, storage),
|
||||
None => return Ok(None),
|
||||
};
|
||||
let first = first.as_();
|
||||
let last_num = self.backend.blockchain().expect_block_number_from_id(&last)?.as_();
|
||||
if first > last_num {
|
||||
return Err(error::ErrorKind::ChangesTrieAccessFailed("Invalid changes trie range".into()).into());
|
||||
}
|
||||
let finalized_number = self.backend.blockchain().info()?.finalized_number;
|
||||
let oldest = storage.oldest_changes_trie_block(&config, finalized_number.as_());
|
||||
let first = As::sa(::std::cmp::max(first, oldest));
|
||||
Ok(Some((first, last)))
|
||||
}
|
||||
|
||||
/// Get pairs of (block, extrinsic) where key has been changed at given blocks range.
|
||||
/// Works only for runtimes that are supporting changes tries.
|
||||
pub fn key_changes(
|
||||
&self,
|
||||
first: Block::Hash,
|
||||
last: Block::Hash,
|
||||
key: &[u8]
|
||||
first: NumberFor<Block>,
|
||||
last: BlockId<Block>,
|
||||
key: &StorageKey
|
||||
) -> error::Result<Vec<(NumberFor<Block>, u32)>> {
|
||||
let config = self.changes_trie_config()?;
|
||||
let storage = self.backend.changes_trie_storage();
|
||||
let (config, storage) = match (config, storage) {
|
||||
(Some(config), Some(storage)) => (config, storage),
|
||||
_ => return Err(error::ErrorKind::ChangesTriesNotSupported.into()),
|
||||
};
|
||||
let (config, storage) = self.require_changes_trie()?;
|
||||
let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?.as_();
|
||||
let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?;
|
||||
|
||||
let first_number = self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(first))?.as_();
|
||||
let last_number = self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(last))?.as_();
|
||||
key_changes::<_, Blake2Hasher>(
|
||||
&config,
|
||||
storage,
|
||||
first_number,
|
||||
&*storage,
|
||||
first.as_(),
|
||||
&ChangesTrieAnchorBlockId {
|
||||
hash: convert_hash(&last),
|
||||
hash: convert_hash(&last_hash),
|
||||
number: last_number,
|
||||
},
|
||||
self.backend.blockchain().info()?.best_number.as_(),
|
||||
key)
|
||||
&key.0)
|
||||
.and_then(|r| r.map(|r| r.map(|(block, tx)| (As::sa(block), tx))).collect::<Result<_, _>>())
|
||||
.map_err(|err| error::ErrorKind::ChangesTrieAccessFailed(err).into())
|
||||
.map(|r| r.into_iter().map(|(b, e)| (As::sa(b), e)).collect())
|
||||
}
|
||||
|
||||
/// Get proof for computation of (block, extrinsic) pairs where key has been changed at given blocks range.
|
||||
@@ -398,7 +417,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
last: Block::Hash,
|
||||
min: Block::Hash,
|
||||
max: Block::Hash,
|
||||
key: &[u8]
|
||||
key: &StorageKey
|
||||
) -> error::Result<ChangesProof<Block::Header>> {
|
||||
self.key_changes_proof_with_cht_size(
|
||||
first,
|
||||
@@ -417,7 +436,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
last: Block::Hash,
|
||||
min: Block::Hash,
|
||||
max: Block::Hash,
|
||||
key: &[u8],
|
||||
key: &StorageKey,
|
||||
cht_size: u64,
|
||||
) -> error::Result<ChangesProof<Block::Header>> {
|
||||
struct AccessedRootsRecorder<'a, Block: BlockT> {
|
||||
@@ -447,14 +466,9 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
}
|
||||
}
|
||||
|
||||
let config = self.changes_trie_config()?;
|
||||
let storage = self.backend.changes_trie_storage();
|
||||
let (config, storage) = match (config, storage) {
|
||||
(Some(config), Some(storage)) => (config, storage),
|
||||
_ => return Err(error::ErrorKind::ChangesTriesNotSupported.into()),
|
||||
};
|
||||
|
||||
let (config, storage) = self.require_changes_trie()?;
|
||||
let min_number = self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(min))?;
|
||||
|
||||
let recording_storage = AccessedRootsRecorder::<Block> {
|
||||
storage,
|
||||
min: min_number.as_(),
|
||||
@@ -478,7 +492,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
number: last_number,
|
||||
},
|
||||
max_number.as_(),
|
||||
key
|
||||
&key.0
|
||||
)
|
||||
.map_err(|err| error::Error::from(error::ErrorKind::ChangesTrieAccessFailed(err)))?;
|
||||
|
||||
@@ -528,6 +542,16 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
Ok(proof)
|
||||
}
|
||||
|
||||
/// Returns changes trie configuration and storage or an error if it is not supported.
|
||||
fn require_changes_trie(&self) -> error::Result<(ChangesTrieConfiguration, &B::ChangesTrieStorage)> {
|
||||
let config = self.changes_trie_config()?;
|
||||
let storage = self.backend.changes_trie_storage();
|
||||
match (config, storage) {
|
||||
(Some(config), Some(storage)) => Ok((config, storage)),
|
||||
_ => Err(error::ErrorKind::ChangesTriesNotSupported.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new block, built on the head of the chain.
|
||||
pub fn new_block<InherentData>(
|
||||
&self
|
||||
@@ -1713,9 +1737,8 @@ pub(crate) mod tests {
|
||||
let (client, _, test_cases) = prepare_client_with_key_changes();
|
||||
|
||||
for (index, (begin, end, key, expected_result)) in test_cases.into_iter().enumerate() {
|
||||
let begin = client.block_hash(begin).unwrap().unwrap();
|
||||
let end = client.block_hash(end).unwrap().unwrap();
|
||||
let actual_result = client.key_changes(begin, end, &key).unwrap();
|
||||
let actual_result = client.key_changes(begin, BlockId::Hash(end), &StorageKey(key)).unwrap();
|
||||
match actual_result == expected_result {
|
||||
true => (),
|
||||
false => panic!(format!("Failed test {}: actual = {:?}, expected = {:?}",
|
||||
|
||||
Reference in New Issue
Block a user