mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-30 16:37:57 +00:00
Implement change trie for child trie. (#3122)
* Initial implementation, some redundancy is awkward and there is some useless computation (but there is a pending pr for that). Next are tests. * Minimal tests and fix extend child. * implement iterator for change child trie. * prune child trie. * Fix pruning test. * bump spec version. * Avoid empty child trie (could also be checked before) * tabs. * Fix child digest overriding each others. * Restore doc deleted on merge. * Check correct child value on extrinsics build. * Revert runtime version update.
This commit is contained in:
committed by
Svyatoslav Nikolsky
parent
06658e0c3c
commit
e3d0c60a31
@@ -535,6 +535,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
&self,
|
||||
first: NumberFor<Block>,
|
||||
last: BlockId<Block>,
|
||||
storage_key: Option<&StorageKey>,
|
||||
key: &StorageKey
|
||||
) -> error::Result<Vec<(NumberFor<Block>, u32)>> {
|
||||
let (config, storage) = self.require_changes_trie()?;
|
||||
@@ -557,6 +558,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
number: last_number,
|
||||
},
|
||||
self.backend.blockchain().info().best_number,
|
||||
storage_key.as_ref().map(|sk| sk.0.as_slice()),
|
||||
&key.0)
|
||||
.and_then(|r| r.map(|r| r.map(|(block, tx)| (block, tx))).collect::<Result<_, _>>())
|
||||
.map_err(|err| error::Error::ChangesTrieAccessFailed(err))
|
||||
@@ -574,13 +576,15 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
last: Block::Hash,
|
||||
min: Block::Hash,
|
||||
max: Block::Hash,
|
||||
key: &StorageKey
|
||||
storage_key: Option<&StorageKey>,
|
||||
key: &StorageKey,
|
||||
) -> error::Result<ChangesProof<Block::Header>> {
|
||||
self.key_changes_proof_with_cht_size(
|
||||
first,
|
||||
last,
|
||||
min,
|
||||
max,
|
||||
storage_key,
|
||||
key,
|
||||
cht::size(),
|
||||
)
|
||||
@@ -593,6 +597,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
last: Block::Hash,
|
||||
min: Block::Hash,
|
||||
max: Block::Hash,
|
||||
storage_key: Option<&StorageKey>,
|
||||
key: &StorageKey,
|
||||
cht_size: NumberFor<Block>,
|
||||
) -> error::Result<ChangesProof<Block::Header>> {
|
||||
@@ -670,7 +675,8 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
number: last_number,
|
||||
},
|
||||
max_number,
|
||||
&key.0
|
||||
storage_key.as_ref().map(|sk| sk.0.as_slice()),
|
||||
&key.0,
|
||||
)
|
||||
.map_err(|err| error::Error::from(error::Error::ChangesTrieAccessFailed(err)))?;
|
||||
|
||||
@@ -2580,7 +2586,12 @@ pub(crate) mod tests {
|
||||
|
||||
for (index, (begin, end, key, expected_result)) in test_cases.into_iter().enumerate() {
|
||||
let end = client.block_hash(end).unwrap().unwrap();
|
||||
let actual_result = client.key_changes(begin, BlockId::Hash(end), &StorageKey(key)).unwrap();
|
||||
let actual_result = client.key_changes(
|
||||
begin,
|
||||
BlockId::Hash(end),
|
||||
None,
|
||||
&StorageKey(key),
|
||||
).unwrap();
|
||||
match actual_result == expected_result {
|
||||
true => (),
|
||||
false => panic!(format!("Failed test {}: actual = {:?}, expected = {:?}",
|
||||
|
||||
@@ -381,6 +381,10 @@ where
|
||||
// whole state is not available on light node
|
||||
}
|
||||
|
||||
fn for_key_values_with_prefix<A: FnMut(&[u8], &[u8])>(&self, _prefix: &[u8], _action: A) {
|
||||
// whole state is not available on light node
|
||||
}
|
||||
|
||||
fn for_keys_in_child_storage<A: FnMut(&[u8])>(&self, _storage_key: &[u8], _action: A) {
|
||||
// whole state is not available on light node
|
||||
}
|
||||
@@ -461,6 +465,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn for_key_values_with_prefix<A: FnMut(&[u8], &[u8])>(&self, prefix: &[u8], action: A) {
|
||||
match *self {
|
||||
OnDemandOrGenesisState::OnDemand(ref state) =>
|
||||
StateBackend::<H>::for_key_values_with_prefix(state, prefix, action),
|
||||
OnDemandOrGenesisState::Genesis(ref state) => state.for_key_values_with_prefix(prefix, action),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn for_keys_in_child_storage<A: FnMut(&[u8])>(&self, storage_key: &[u8], action: A) {
|
||||
match *self {
|
||||
OnDemandOrGenesisState::OnDemand(ref state) =>
|
||||
|
||||
@@ -110,6 +110,8 @@ pub struct RemoteChangesRequest<Header: HeaderT> {
|
||||
/// Known changes trie roots for the range of blocks [tries_roots.0..max_block].
|
||||
/// Proofs for roots of ascendants of tries_roots.0 are provided by the remote node.
|
||||
pub tries_roots: (Header::Number, Header::Hash, Vec<Header::Hash>),
|
||||
/// Optional Child Storage key to read.
|
||||
pub storage_key: Option<Vec<u8>>,
|
||||
/// Storage key to read.
|
||||
pub key: Vec<u8>,
|
||||
/// Number of times to retry request. None means that default RETRY_COUNT is used.
|
||||
@@ -307,6 +309,7 @@ impl<E, H, B: BlockT, S: BlockchainStorage<B>, F> LightDataChecker<E, H, B, S, F
|
||||
number: request.last_block.0,
|
||||
},
|
||||
remote_max_block,
|
||||
request.storage_key.as_ref().map(Vec::as_slice),
|
||||
&request.key)
|
||||
.map_err(|err| ClientError::ChangesTrieAccessFailed(err))
|
||||
}
|
||||
@@ -749,7 +752,7 @@ pub mod tests {
|
||||
// 'fetch' changes proof from remote node
|
||||
let key = StorageKey(key);
|
||||
let remote_proof = remote_client.key_changes_proof(
|
||||
begin_hash, end_hash, begin_hash, max_hash, &key
|
||||
begin_hash, end_hash, begin_hash, max_hash, None, &key
|
||||
).unwrap();
|
||||
|
||||
// check proof on local client
|
||||
@@ -761,6 +764,7 @@ pub mod tests {
|
||||
max_block: (max, max_hash),
|
||||
tries_roots: (begin, begin_hash, local_roots_range),
|
||||
key: key.0,
|
||||
storage_key: None,
|
||||
retry_count: None,
|
||||
};
|
||||
let local_result = local_checker.check_changes_proof(&request, ChangesProof {
|
||||
@@ -795,7 +799,7 @@ pub mod tests {
|
||||
let b3 = remote_client.block_hash_from_id(&BlockId::Number(3)).unwrap().unwrap();
|
||||
let b4 = remote_client.block_hash_from_id(&BlockId::Number(4)).unwrap().unwrap();
|
||||
let remote_proof = remote_client.key_changes_proof_with_cht_size(
|
||||
b1, b4, b3, b4, &dave, 4
|
||||
b1, b4, b3, b4, None, &dave, 4
|
||||
).unwrap();
|
||||
|
||||
// prepare local checker, having a root of changes trie CHT#0
|
||||
@@ -814,6 +818,7 @@ pub mod tests {
|
||||
last_block: (4, b4),
|
||||
max_block: (4, b4),
|
||||
tries_roots: (3, b3, vec![remote_roots[2].clone(), remote_roots[3].clone()]),
|
||||
storage_key: None,
|
||||
key: dave.0,
|
||||
retry_count: None,
|
||||
};
|
||||
@@ -845,7 +850,7 @@ pub mod tests {
|
||||
// 'fetch' changes proof from remote node
|
||||
let key = StorageKey(key);
|
||||
let remote_proof = remote_client.key_changes_proof(
|
||||
begin_hash, end_hash, begin_hash, max_hash, &key).unwrap();
|
||||
begin_hash, end_hash, begin_hash, max_hash, None, &key).unwrap();
|
||||
|
||||
let local_roots_range = local_roots.clone()[(begin - 1) as usize..].to_vec();
|
||||
let request = RemoteChangesRequest::<Header> {
|
||||
@@ -854,6 +859,7 @@ pub mod tests {
|
||||
last_block: (end, end_hash),
|
||||
max_block: (max, max_hash),
|
||||
tries_roots: (begin, begin_hash, local_roots_range.clone()),
|
||||
storage_key: None,
|
||||
key: key.0,
|
||||
retry_count: None,
|
||||
};
|
||||
@@ -907,7 +913,7 @@ pub mod tests {
|
||||
let b3 = remote_client.block_hash_from_id(&BlockId::Number(3)).unwrap().unwrap();
|
||||
let b4 = remote_client.block_hash_from_id(&BlockId::Number(4)).unwrap().unwrap();
|
||||
let remote_proof = remote_client.key_changes_proof_with_cht_size(
|
||||
b1, b4, b3, b4, &dave, 4
|
||||
b1, b4, b3, b4, None, &dave, 4
|
||||
).unwrap();
|
||||
|
||||
// fails when changes trie CHT is missing from the local db
|
||||
|
||||
Reference in New Issue
Block a user