mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-09 20:11:09 +00:00
Added client function to delete a recent block (#8533)
* Implemented recent block removal * Apply suggestions from code review Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
@@ -623,6 +623,7 @@ impl<Block: BlockT> HeaderMetadata<Block> for BlockchainDb<Block> {
|
||||
}
|
||||
|
||||
fn remove_header_metadata(&self, hash: Block::Hash) {
|
||||
self.header_cache.lock().remove(&hash);
|
||||
self.header_metadata_cache.remove_header_metadata(hash);
|
||||
}
|
||||
}
|
||||
@@ -1972,6 +1973,59 @@ impl<Block: BlockT> sc_client_api::backend::Backend<Block> for Backend<Block> {
|
||||
Ok((reverted, reverted_finalized))
|
||||
}
|
||||
|
||||
fn remove_leaf_block(
|
||||
&self,
|
||||
hash: &Block::Hash,
|
||||
) -> ClientResult<()> {
|
||||
let best_hash = self.blockchain.info().best_hash;
|
||||
|
||||
if best_hash == *hash {
|
||||
return Err(
|
||||
sp_blockchain::Error::Backend(
|
||||
format!("Can't remove best block {:?}", hash)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
let hdr = self.blockchain.header_metadata(hash.clone())?;
|
||||
if !self.have_state_at(&hash, hdr.number) {
|
||||
return Err(
|
||||
sp_blockchain::Error::UnknownBlock(
|
||||
format!("State already discarded for {:?}", hash)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
let mut leaves = self.blockchain.leaves.write();
|
||||
if !leaves.contains(hdr.number, *hash) {
|
||||
return Err(
|
||||
sp_blockchain::Error::Backend(
|
||||
format!("Can't remove non-leaf block {:?}", hash)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
let mut transaction = Transaction::new();
|
||||
if let Some(commit) = self.storage.state_db.remove(hash) {
|
||||
apply_state_commit(&mut transaction, commit);
|
||||
}
|
||||
transaction.remove(columns::KEY_LOOKUP, hash.as_ref());
|
||||
let changes_trie_cache_ops = self.changes_tries_storage.revert(
|
||||
&mut transaction,
|
||||
&cache::ComplexBlockId::new(
|
||||
*hash,
|
||||
hdr.number,
|
||||
),
|
||||
)?;
|
||||
|
||||
self.changes_tries_storage.post_commit(Some(changes_trie_cache_ops));
|
||||
leaves.revert(hash.clone(), hdr.number);
|
||||
leaves.prepare_transaction(&mut transaction, columns::META, meta_keys::LEAF_PREFIX);
|
||||
self.storage.db.commit(transaction)?;
|
||||
self.blockchain().remove_header_metadata(*hash);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn blockchain(&self) -> &BlockchainDb<Block> {
|
||||
&self.blockchain
|
||||
}
|
||||
@@ -3008,4 +3062,36 @@ pub(crate) mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_leaf_block_works() {
|
||||
let backend = Backend::<Block>::new_test_with_tx_storage(
|
||||
2,
|
||||
10,
|
||||
TransactionStorageMode::StorageChain
|
||||
);
|
||||
let mut blocks = Vec::new();
|
||||
let mut prev_hash = Default::default();
|
||||
for i in 0 .. 2 {
|
||||
let hash = insert_block(&backend, i, prev_hash, None, Default::default(), vec![i.into()], None);
|
||||
blocks.push(hash);
|
||||
prev_hash = hash;
|
||||
}
|
||||
|
||||
// insert a fork at block 2, which becomes best block
|
||||
let best_hash = insert_block(
|
||||
&backend,
|
||||
1,
|
||||
blocks[0],
|
||||
None,
|
||||
sp_core::H256::random(),
|
||||
vec![42.into()],
|
||||
None
|
||||
);
|
||||
assert!(backend.remove_leaf_block(&best_hash).is_err());
|
||||
assert!(backend.have_state_at(&prev_hash, 1));
|
||||
backend.remove_leaf_block(&prev_hash).unwrap();
|
||||
assert_eq!(None, backend.blockchain().header(BlockId::hash(prev_hash.clone())).unwrap());
|
||||
assert!(!backend.have_state_at(&prev_hash, 1));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user