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:
Svyatoslav Nikolsky
2019-01-17 12:08:50 +03:00
committed by Bastian Köcher
parent eb000fb1ae
commit da1fb3f273
14 changed files with 443 additions and 190 deletions
@@ -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);
}
}