mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 08:51:09 +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
@@ -31,15 +31,16 @@ use trie_backend_essence::{TrieBackendEssence};
|
||||
|
||||
/// Return changes of given key at given blocks range.
|
||||
/// `max` is the number of best known block.
|
||||
pub fn key_changes<S: Storage<H>, H: Hasher>(
|
||||
config: &Configuration,
|
||||
storage: &S,
|
||||
/// Changes are returned in descending order (i.e. last block comes first).
|
||||
pub fn key_changes<'a, S: Storage<H>, H: Hasher>(
|
||||
config: &'a Configuration,
|
||||
storage: &'a S,
|
||||
begin: u64,
|
||||
end: &AnchorBlockId<H::Out>,
|
||||
end: &'a AnchorBlockId<H::Out>,
|
||||
max: u64,
|
||||
key: &[u8],
|
||||
) -> Result<Vec<(u64, u32)>, String> where H::Out: HeapSizeOf {
|
||||
DrilldownIterator {
|
||||
key: &'a [u8],
|
||||
) -> Result<DrilldownIterator<'a, S, S, H>, String> where H::Out: HeapSizeOf {
|
||||
Ok(DrilldownIterator {
|
||||
essence: DrilldownIteratorEssence {
|
||||
key,
|
||||
roots_storage: storage,
|
||||
@@ -53,7 +54,7 @@ pub fn key_changes<S: Storage<H>, H: Hasher>(
|
||||
|
||||
_hasher: ::std::marker::PhantomData::<H>::default(),
|
||||
},
|
||||
}.collect()
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns proof of changes of given key at given blocks range.
|
||||
@@ -93,6 +94,7 @@ pub fn key_changes_proof<S: Storage<H>, H: Hasher>(
|
||||
|
||||
/// Check key changes proog and return changes of the key at given blocks range.
|
||||
/// `max` is the number of best known block.
|
||||
/// Changes are returned in descending order (i.e. last block comes first).
|
||||
pub fn key_changes_proof_check<S: RootsStorage<H>, H: Hasher>(
|
||||
config: &Configuration,
|
||||
roots_storage: &S,
|
||||
@@ -261,7 +263,7 @@ impl<'a, RS: 'a + RootsStorage<H>, S: Storage<H>, H: Hasher> DrilldownIteratorEs
|
||||
}
|
||||
|
||||
/// Exploring drilldown operator.
|
||||
struct DrilldownIterator<'a, RS: 'a + RootsStorage<H>, S: 'a + Storage<H>, H: Hasher> where H::Out: 'a {
|
||||
pub struct DrilldownIterator<'a, RS: 'a + RootsStorage<H>, S: 'a + Storage<H>, H: Hasher> where H::Out: 'a {
|
||||
essence: DrilldownIteratorEssence<'a, RS, S, H>,
|
||||
}
|
||||
|
||||
@@ -379,6 +381,7 @@ fn lower_bound_max_digest(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::iter::FromIterator;
|
||||
use primitives::Blake2Hasher;
|
||||
use changes_trie::input::InputPair;
|
||||
use changes_trie::storage::InMemoryStorage;
|
||||
@@ -427,23 +430,28 @@ mod tests {
|
||||
fn drilldown_iterator_works() {
|
||||
let (config, storage) = prepare_for_drilldown();
|
||||
let drilldown_result = key_changes::<InMemoryStorage<Blake2Hasher>, Blake2Hasher>(
|
||||
&config, &storage, 0, &AnchorBlockId { hash: Default::default(), number: 16 }, 16, &[42]);
|
||||
&config, &storage, 0, &AnchorBlockId { hash: Default::default(), number: 16 }, 16, &[42])
|
||||
.and_then(Result::from_iter);
|
||||
assert_eq!(drilldown_result, Ok(vec![(8, 2), (8, 1), (6, 3), (3, 0)]));
|
||||
|
||||
let drilldown_result = key_changes::<InMemoryStorage<Blake2Hasher>, Blake2Hasher>(
|
||||
&config, &storage, 0, &AnchorBlockId { hash: Default::default(), number: 2 }, 4, &[42]);
|
||||
&config, &storage, 0, &AnchorBlockId { hash: Default::default(), number: 2 }, 4, &[42])
|
||||
.and_then(Result::from_iter);
|
||||
assert_eq!(drilldown_result, Ok(vec![]));
|
||||
|
||||
let drilldown_result = key_changes::<InMemoryStorage<Blake2Hasher>, Blake2Hasher>(
|
||||
&config, &storage, 0, &AnchorBlockId { hash: Default::default(), number: 3 }, 4, &[42]);
|
||||
&config, &storage, 0, &AnchorBlockId { hash: Default::default(), number: 3 }, 4, &[42])
|
||||
.and_then(Result::from_iter);
|
||||
assert_eq!(drilldown_result, Ok(vec![(3, 0)]));
|
||||
|
||||
let drilldown_result = key_changes::<InMemoryStorage<Blake2Hasher>, Blake2Hasher>(
|
||||
&config, &storage, 7, &AnchorBlockId { hash: Default::default(), number: 8 }, 8, &[42]);
|
||||
&config, &storage, 7, &AnchorBlockId { hash: Default::default(), number: 8 }, 8, &[42])
|
||||
.and_then(Result::from_iter);
|
||||
assert_eq!(drilldown_result, Ok(vec![(8, 2), (8, 1)]));
|
||||
|
||||
let drilldown_result = key_changes::<InMemoryStorage<Blake2Hasher>, Blake2Hasher>(
|
||||
&config, &storage, 5, &AnchorBlockId { hash: Default::default(), number: 7 }, 8, &[42]);
|
||||
&config, &storage, 5, &AnchorBlockId { hash: Default::default(), number: 7 }, 8, &[42])
|
||||
.and_then(Result::from_iter);
|
||||
assert_eq!(drilldown_result, Ok(vec![(6, 3)]));
|
||||
}
|
||||
|
||||
@@ -453,7 +461,8 @@ mod tests {
|
||||
storage.clear_storage();
|
||||
|
||||
assert!(key_changes::<InMemoryStorage<Blake2Hasher>, Blake2Hasher>(
|
||||
&config, &storage, 0, &AnchorBlockId { hash: Default::default(), number: 100 }, 1000, &[42]).is_err());
|
||||
&config, &storage, 0, &AnchorBlockId { hash: Default::default(), number: 100 }, 1000, &[42])
|
||||
.and_then(|i| i.collect::<Result<Vec<_>, _>>()).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -44,7 +44,7 @@ mod storage;
|
||||
|
||||
pub use self::storage::InMemoryStorage;
|
||||
pub use self::changes_iterator::{key_changes, key_changes_proof, key_changes_proof_check};
|
||||
pub use self::prune::prune;
|
||||
pub use self::prune::{prune, oldest_non_pruned_trie};
|
||||
|
||||
use hash_db::Hasher;
|
||||
use heapsize::HeapSizeOf;
|
||||
|
||||
@@ -24,6 +24,22 @@ use trie_backend_essence::TrieBackendEssence;
|
||||
use changes_trie::{AnchorBlockId, Configuration, Storage};
|
||||
use changes_trie::storage::TrieBackendAdapter;
|
||||
|
||||
/// Get number of oldest block for which changes trie is not pruned
|
||||
/// given changes trie configuration, pruning parameter and number of
|
||||
/// best finalized block.
|
||||
pub fn oldest_non_pruned_trie(
|
||||
config: &Configuration,
|
||||
min_blocks_to_keep: u64,
|
||||
best_finalized_block: u64,
|
||||
) -> u64 {
|
||||
let max_digest_interval = config.max_digest_interval();
|
||||
let max_digest_block = best_finalized_block - best_finalized_block % max_digest_interval;
|
||||
match pruning_range(config, min_blocks_to_keep, max_digest_block) {
|
||||
Some((_, last_pruned_block)) => last_pruned_block + 1,
|
||||
None => 1,
|
||||
}
|
||||
}
|
||||
|
||||
/// Prune obslete changes tries. Puning happens at the same block, where highest
|
||||
/// level digest is created. Pruning guarantees to save changes tries for last
|
||||
/// `min_blocks_to_keep` blocks. We only prune changes tries at `max_digest_iterval`
|
||||
@@ -268,4 +284,23 @@ mod tests {
|
||||
assert_eq!(max_digest_intervals_to_keep(1024, 511), 2);
|
||||
assert_eq!(max_digest_intervals_to_keep(1024, 100), 10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn oldest_non_pruned_trie_works() {
|
||||
// when digests are not created at all
|
||||
assert_eq!(oldest_non_pruned_trie(&config(0, 0), 100, 10), 1);
|
||||
assert_eq!(oldest_non_pruned_trie(&config(0, 0), 100, 110), 11);
|
||||
|
||||
// when only l1 digests are created
|
||||
assert_eq!(oldest_non_pruned_trie(&config(100, 1), 100, 50), 1);
|
||||
assert_eq!(oldest_non_pruned_trie(&config(100, 1), 100, 110), 1);
|
||||
assert_eq!(oldest_non_pruned_trie(&config(100, 1), 100, 210), 101);
|
||||
|
||||
// when l2 digests are created
|
||||
assert_eq!(oldest_non_pruned_trie(&config(100, 2), 100, 50), 1);
|
||||
assert_eq!(oldest_non_pruned_trie(&config(100, 2), 100, 110), 1);
|
||||
assert_eq!(oldest_non_pruned_trie(&config(100, 2), 100, 210), 1);
|
||||
assert_eq!(oldest_non_pruned_trie(&config(100, 2), 100, 10110), 1);
|
||||
assert_eq!(oldest_non_pruned_trie(&config(100, 2), 100, 20110), 10001);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user