mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 03:01:07 +00:00
Pruning changes trie without digests (#952)
* pruning changes tries without digests * u64::max_value()
This commit is contained in:
committed by
Gav Wood
parent
5b28147d27
commit
6f9a505fba
@@ -1277,63 +1277,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn changes_trie_storage_works_with_forks() {
|
||||
let backend = Backend::<Block>::new_test(1000, 100);
|
||||
|
||||
let changes0 = vec![(b"k0".to_vec(), b"v0".to_vec())];
|
||||
let changes1 = vec![(b"k1".to_vec(), b"v1".to_vec())];
|
||||
let changes2 = vec![(b"k2".to_vec(), b"v2".to_vec())];
|
||||
let block0 = insert_header(&backend, 0, Default::default(), changes0.clone(), Default::default());
|
||||
let block1 = insert_header(&backend, 1, block0, changes1.clone(), Default::default());
|
||||
let block2 = insert_header(&backend, 2, block1, changes2.clone(), Default::default());
|
||||
|
||||
let changes2_1_0 = vec![(b"k3".to_vec(), b"v3".to_vec())];
|
||||
let changes2_1_1 = vec![(b"k4".to_vec(), b"v4".to_vec())];
|
||||
let block2_1_0 = insert_header(&backend, 3, block2, changes2_1_0.clone(), Default::default());
|
||||
let block2_1_1 = insert_header(&backend, 4, block2_1_0, changes2_1_1.clone(), Default::default());
|
||||
|
||||
let changes2_2_0 = vec![(b"k5".to_vec(), b"v5".to_vec())];
|
||||
let changes2_2_1 = vec![(b"k6".to_vec(), b"v6".to_vec())];
|
||||
let block2_2_0 = insert_header(&backend, 3, block2, changes2_2_0.clone(), Default::default());
|
||||
let block2_2_1 = insert_header(&backend, 4, block2_2_0, changes2_2_1.clone(), Default::default());
|
||||
|
||||
// finalize block1
|
||||
backend.changes_tries_storage.meta.write().finalized_number = 1;
|
||||
|
||||
// branch1: when asking for finalized block hash
|
||||
let (changes1_root, _) = prepare_changes(changes1);
|
||||
let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block2_1_1, number: 4 };
|
||||
assert_eq!(backend.changes_tries_storage.root(&anchor, 1), Ok(Some(changes1_root)));
|
||||
|
||||
// branch2: when asking for finalized block hash
|
||||
let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block2_2_1, number: 4 };
|
||||
assert_eq!(backend.changes_tries_storage.root(&anchor, 1), Ok(Some(changes1_root)));
|
||||
|
||||
// branch1: when asking for non-finalized block hash (search by traversal)
|
||||
let (changes2_1_0_root, _) = prepare_changes(changes2_1_0);
|
||||
let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block2_1_1, number: 4 };
|
||||
assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_1_0_root)));
|
||||
|
||||
// branch2: when asking for non-finalized block hash (search using canonicalized hint)
|
||||
let (changes2_2_0_root, _) = prepare_changes(changes2_2_0);
|
||||
let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block2_2_1, number: 4 };
|
||||
assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_2_0_root)));
|
||||
|
||||
// finalize first block of branch2 (block2_2_0)
|
||||
backend.changes_tries_storage.meta.write().finalized_number = 3;
|
||||
|
||||
// branch2: when asking for finalized block of this branch
|
||||
assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_2_0_root)));
|
||||
|
||||
// branch1: when asking for finalized block of other branch
|
||||
// => result is incorrect (returned for the block of branch1), but this is expected,
|
||||
// because the other fork is abandoned (forked before finalized header)
|
||||
let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block2_1_1, number: 4 };
|
||||
assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_2_0_root)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn changes_tries_are_pruned_on_finalization() {
|
||||
fn changes_tries_with_digest_are_pruned_on_finalization() {
|
||||
let mut backend = Backend::<Block>::new_test(1000, 100);
|
||||
backend.changes_tries_storage.meta.write().finalized_number = 1000;
|
||||
backend.changes_tries_storage.min_blocks_to_keep = Some(8);
|
||||
@@ -1410,6 +1354,108 @@ mod tests {
|
||||
assert!(backend.changes_tries_storage.get(&root12).unwrap().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn changes_tries_without_digest_are_pruned_on_finalization() {
|
||||
let mut backend = Backend::<Block>::new_test(1000, 100);
|
||||
backend.changes_tries_storage.min_blocks_to_keep = Some(4);
|
||||
let config = ChangesTrieConfiguration {
|
||||
digest_interval: 0,
|
||||
digest_levels: 0,
|
||||
};
|
||||
|
||||
// insert some blocks
|
||||
let block0 = insert_header(&backend, 0, Default::default(), vec![(b"key_at_0".to_vec(), b"val_at_0".to_vec())], Default::default());
|
||||
let block1 = insert_header(&backend, 1, block0, vec![(b"key_at_1".to_vec(), b"val_at_1".to_vec())], Default::default());
|
||||
let block2 = insert_header(&backend, 2, block1, vec![(b"key_at_2".to_vec(), b"val_at_2".to_vec())], Default::default());
|
||||
let block3 = insert_header(&backend, 3, block2, vec![(b"key_at_3".to_vec(), b"val_at_3".to_vec())], Default::default());
|
||||
let block4 = insert_header(&backend, 4, block3, vec![(b"key_at_4".to_vec(), b"val_at_4".to_vec())], Default::default());
|
||||
let block5 = insert_header(&backend, 5, block4, vec![(b"key_at_5".to_vec(), b"val_at_5".to_vec())], Default::default());
|
||||
let block6 = insert_header(&backend, 6, block5, vec![(b"key_at_6".to_vec(), b"val_at_6".to_vec())], Default::default());
|
||||
|
||||
// check that roots of all tries are in the columns::CHANGES_TRIE
|
||||
let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block6, number: 6 };
|
||||
fn read_changes_trie_root(backend: &Backend<Block>, num: u64) -> H256 {
|
||||
backend.blockchain().header(BlockId::Number(num)).unwrap().unwrap().digest().logs().iter()
|
||||
.find(|i| i.as_changes_trie_root().is_some()).unwrap().as_changes_trie_root().unwrap().clone()
|
||||
}
|
||||
let root1 = read_changes_trie_root(&backend, 1); assert_eq!(backend.changes_tries_storage.root(&anchor, 1).unwrap(), Some(root1));
|
||||
let root2 = read_changes_trie_root(&backend, 2); assert_eq!(backend.changes_tries_storage.root(&anchor, 2).unwrap(), Some(root2));
|
||||
let root3 = read_changes_trie_root(&backend, 3); assert_eq!(backend.changes_tries_storage.root(&anchor, 3).unwrap(), Some(root3));
|
||||
let root4 = read_changes_trie_root(&backend, 4); assert_eq!(backend.changes_tries_storage.root(&anchor, 4).unwrap(), Some(root4));
|
||||
let root5 = read_changes_trie_root(&backend, 5); assert_eq!(backend.changes_tries_storage.root(&anchor, 5).unwrap(), Some(root5));
|
||||
let root6 = read_changes_trie_root(&backend, 6); assert_eq!(backend.changes_tries_storage.root(&anchor, 6).unwrap(), Some(root6));
|
||||
|
||||
// now simulate finalization of block#5, causing prune of trie at #1
|
||||
let mut tx = DBTransaction::new();
|
||||
backend.changes_tries_storage.prune(Some(config.clone()), &mut tx, block5, 5);
|
||||
backend.storage.db.write(tx).unwrap();
|
||||
assert!(backend.changes_tries_storage.get(&root1).unwrap().is_none());
|
||||
assert!(backend.changes_tries_storage.get(&root2).unwrap().is_some());
|
||||
|
||||
// now simulate finalization of block#6, causing prune of tries at #2
|
||||
let mut tx = DBTransaction::new();
|
||||
backend.changes_tries_storage.prune(Some(config.clone()), &mut tx, block6, 6);
|
||||
backend.storage.db.write(tx).unwrap();
|
||||
assert!(backend.changes_tries_storage.get(&root2).unwrap().is_none());
|
||||
assert!(backend.changes_tries_storage.get(&root3).unwrap().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn changes_trie_storage_works_with_forks() {
|
||||
let backend = Backend::<Block>::new_test(1000, 100);
|
||||
|
||||
let changes0 = vec![(b"k0".to_vec(), b"v0".to_vec())];
|
||||
let changes1 = vec![(b"k1".to_vec(), b"v1".to_vec())];
|
||||
let changes2 = vec![(b"k2".to_vec(), b"v2".to_vec())];
|
||||
let block0 = insert_header(&backend, 0, Default::default(), changes0.clone(), Default::default());
|
||||
let block1 = insert_header(&backend, 1, block0, changes1.clone(), Default::default());
|
||||
let block2 = insert_header(&backend, 2, block1, changes2.clone(), Default::default());
|
||||
|
||||
let changes2_1_0 = vec![(b"k3".to_vec(), b"v3".to_vec())];
|
||||
let changes2_1_1 = vec![(b"k4".to_vec(), b"v4".to_vec())];
|
||||
let block2_1_0 = insert_header(&backend, 3, block2, changes2_1_0.clone(), Default::default());
|
||||
let block2_1_1 = insert_header(&backend, 4, block2_1_0, changes2_1_1.clone(), Default::default());
|
||||
|
||||
let changes2_2_0 = vec![(b"k5".to_vec(), b"v5".to_vec())];
|
||||
let changes2_2_1 = vec![(b"k6".to_vec(), b"v6".to_vec())];
|
||||
let block2_2_0 = insert_header(&backend, 3, block2, changes2_2_0.clone(), Default::default());
|
||||
let block2_2_1 = insert_header(&backend, 4, block2_2_0, changes2_2_1.clone(), Default::default());
|
||||
|
||||
// finalize block1
|
||||
backend.changes_tries_storage.meta.write().finalized_number = 1;
|
||||
|
||||
// branch1: when asking for finalized block hash
|
||||
let (changes1_root, _) = prepare_changes(changes1);
|
||||
let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block2_1_1, number: 4 };
|
||||
assert_eq!(backend.changes_tries_storage.root(&anchor, 1), Ok(Some(changes1_root)));
|
||||
|
||||
// branch2: when asking for finalized block hash
|
||||
let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block2_2_1, number: 4 };
|
||||
assert_eq!(backend.changes_tries_storage.root(&anchor, 1), Ok(Some(changes1_root)));
|
||||
|
||||
// branch1: when asking for non-finalized block hash (search by traversal)
|
||||
let (changes2_1_0_root, _) = prepare_changes(changes2_1_0);
|
||||
let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block2_1_1, number: 4 };
|
||||
assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_1_0_root)));
|
||||
|
||||
// branch2: when asking for non-finalized block hash (search using canonicalized hint)
|
||||
let (changes2_2_0_root, _) = prepare_changes(changes2_2_0);
|
||||
let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block2_2_1, number: 4 };
|
||||
assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_2_0_root)));
|
||||
|
||||
// finalize first block of branch2 (block2_2_0)
|
||||
backend.changes_tries_storage.meta.write().finalized_number = 3;
|
||||
|
||||
// branch2: when asking for finalized block of this branch
|
||||
assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_2_0_root)));
|
||||
|
||||
// branch1: when asking for finalized block of other branch
|
||||
// => result is incorrect (returned for the block of branch1), but this is expected,
|
||||
// because the other fork is abandoned (forked before finalized header)
|
||||
let anchor = state_machine::ChangesTrieAnchorBlockId { hash: block2_1_1, number: 4 };
|
||||
assert_eq!(backend.changes_tries_storage.root(&anchor, 3), Ok(Some(changes2_2_0_root)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tree_route_works() {
|
||||
let backend = Backend::<Block>::new_test(1000, 100);
|
||||
|
||||
@@ -465,20 +465,14 @@ macro_rules! impl_runtime_apis {
|
||||
)*
|
||||
}
|
||||
impl_runtime_apis! {
|
||||
@EXTEND_FUNCTIONS
|
||||
$runtime;
|
||||
;
|
||||
$trait_name;
|
||||
$( $( $generic ),* )*;
|
||||
{ $( $fn_name ( $( $arg_name: $arg_ty ),* ); )* }
|
||||
$( $fn_name ( $( $arg_name: $arg_ty ),* ); )*;
|
||||
$( $rest )*
|
||||
}
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$( $trait_name_parsed:ident $( < $( $parsed_generic:ident ),* > )*::$fn_name_parsed:ident (
|
||||
$( $arg_name_parsed:ident : $arg_ty_parsed:ty ),* );
|
||||
)*;
|
||||
$( $fn_name_parsed:ident ( $( $arg_name_parsed:ident : $arg_ty_parsed:ty ),* ); )*;
|
||||
impl $trait_name:ident $( < $( $generic:ident ),* > )* for $runtime_ignore:ident {
|
||||
$(
|
||||
fn $fn_name:ident ( $( $arg_name:ident : $arg_ty:ty ),* ) $( -> $return_ty:ty )* {
|
||||
@@ -496,73 +490,15 @@ macro_rules! impl_runtime_apis {
|
||||
)*
|
||||
}
|
||||
impl_runtime_apis! {
|
||||
@EXTEND_FUNCTIONS
|
||||
$runtime;
|
||||
$(
|
||||
$trait_name_parsed $( < $( $parsed_generic ),* > )*
|
||||
::$fn_name_parsed ( $( $arg_name_parsed: $arg_ty_parsed ),* );
|
||||
)*;
|
||||
$trait_name;
|
||||
$( $( $generic ),* )*;
|
||||
{ $( $fn_name ( $( $arg_name: $arg_ty ),* ); )* }
|
||||
$( $rest )*
|
||||
}
|
||||
};
|
||||
(@EXTEND_FUNCTIONS
|
||||
$runtime:ident;
|
||||
$( $trait_name_parsed:ident $( < $( $parsed_generic:ident ),* > )*::$fn_name_parsed:ident (
|
||||
$( $arg_name_parsed:ident : $arg_ty_parsed:ty ),* );
|
||||
)*;
|
||||
$trait_name:ident;
|
||||
$( $generic:ident ),*;
|
||||
{
|
||||
$fn_name_extend:ident ( $( $arg_name_extend:ident : $arg_ty_extend:ty ),* );
|
||||
$( $extend_rest:tt )*
|
||||
}
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
impl_runtime_apis! {
|
||||
@EXTEND_FUNCTIONS
|
||||
$runtime;
|
||||
$(
|
||||
$trait_name_parsed $( < $( $parsed_generic ),* > )*
|
||||
::$fn_name_parsed ( $( $arg_name_parsed: $arg_ty_parsed ),* );
|
||||
)*
|
||||
$trait_name < $( $generic ),* >
|
||||
::$fn_name_extend ( $( $arg_name_extend: $arg_ty_extend ),* );;
|
||||
$trait_name;
|
||||
$( $generic ),*;
|
||||
{
|
||||
$( $extend_rest )*
|
||||
}
|
||||
$( $rest )*
|
||||
}
|
||||
};
|
||||
(@EXTEND_FUNCTIONS
|
||||
$runtime:ident;
|
||||
$( $trait_name_parsed:ident $( < $( $parsed_generic:ident ),* > )*::$fn_name_parsed:ident (
|
||||
$( $arg_name_parsed:ident : $arg_ty_parsed:ty ),* );
|
||||
)*;
|
||||
$trait_name:ident;
|
||||
$( $generic:ident ),*;
|
||||
{}
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
impl_runtime_apis! {
|
||||
$runtime;
|
||||
$(
|
||||
$trait_name_parsed $( < $( $parsed_generic ),* > )*
|
||||
::$fn_name_parsed ( $( $arg_name_parsed: $arg_ty_parsed ),* );
|
||||
)*;
|
||||
$( $fn_name_parsed ( $( $arg_name_parsed: $arg_ty_parsed ),* ); )*
|
||||
$( $fn_name ( $( $arg_name: $arg_ty ),* ); )*;
|
||||
$( $rest )*
|
||||
}
|
||||
};
|
||||
(
|
||||
$runtime:ident;
|
||||
$(
|
||||
$trait_name:ident $( < $( $generic:ident ),* > )*
|
||||
::$fn_name:ident ( $( $arg_name:ident : $arg_ty:ty ),* );
|
||||
)*;
|
||||
$( $fn_name:ident ( $( $arg_name:ident : $arg_ty:ty ),* ); )*;
|
||||
) => {
|
||||
pub mod api {
|
||||
use super::*;
|
||||
@@ -575,7 +511,6 @@ macro_rules! impl_runtime_apis {
|
||||
Some({impl_runtime_apis! {
|
||||
@GENERATE_IMPL_CALL
|
||||
$runtime;
|
||||
$trait_name $( < $( $generic ),* > )*;
|
||||
$fn_name;
|
||||
$( $arg_name : $arg_ty ),*;
|
||||
data;
|
||||
@@ -601,7 +536,6 @@ macro_rules! impl_runtime_apis {
|
||||
let output = { impl_runtime_apis! {
|
||||
@GENERATE_IMPL_CALL
|
||||
$runtime;
|
||||
$trait_name $( < $( $generic ),* > )*;
|
||||
$fn_name;
|
||||
$( $arg_name : $arg_ty ),*;
|
||||
input;
|
||||
@@ -619,7 +553,6 @@ macro_rules! impl_runtime_apis {
|
||||
};
|
||||
(@GENERATE_IMPL_CALL
|
||||
$runtime:ident;
|
||||
$trait_name:ident $( < $( $generic:ident ),* > )*;
|
||||
$fn_name:ident;
|
||||
$arg_name:ident : $arg_ty:ty;
|
||||
$input:ident;
|
||||
@@ -629,12 +562,11 @@ macro_rules! impl_runtime_apis {
|
||||
None => panic!("Bad input data provided to {}", stringify!($fn_name)),
|
||||
};
|
||||
|
||||
let output = <$runtime as $trait_name $( < $( $generic ),* > )*>::$fn_name($arg_name);
|
||||
let output = $runtime::$fn_name($arg_name);
|
||||
$crate::runtime_api::Encode::encode(&output)
|
||||
};
|
||||
(@GENERATE_IMPL_CALL
|
||||
$runtime:ident;
|
||||
$trait_name:ident $( < $( $generic:ident ),* > )*;
|
||||
$fn_name:ident;
|
||||
$( $arg_name:ident : $arg_ty:ty ),*;
|
||||
$input:ident;
|
||||
@@ -644,7 +576,7 @@ macro_rules! impl_runtime_apis {
|
||||
None => panic!("Bad input data provided to {}", stringify!($fn_name)),
|
||||
};
|
||||
|
||||
let output = <$runtime as $trait_name $( < $( $generic ),* > )*>::$fn_name($( $arg_name ),*);
|
||||
let output = $runtime::$fn_name($( $arg_name ),*);
|
||||
$crate::runtime_api::Encode::encode(&output)
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user