Skip to content

Commit a5d9d56

Browse files
arkparark0f
authored andcommitted
Fix block pruning (paritytech#13323)
1 parent 4a85d19 commit a5d9d56

File tree

1 file changed

+64
-20
lines changed

1 file changed

+64
-20
lines changed

client/db/src/lib.rs

Lines changed: 64 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1806,7 +1806,13 @@ impl<Block: BlockT> Backend<Block> {
18061806
}
18071807

18081808
let new_displaced = self.blockchain.leaves.write().finalize_height(f_num);
1809-
self.prune_blocks(transaction, f_num, &new_displaced, current_transaction_justifications)?;
1809+
self.prune_blocks(
1810+
transaction,
1811+
f_num,
1812+
f_hash,
1813+
&new_displaced,
1814+
current_transaction_justifications,
1815+
)?;
18101816

18111817
Ok(())
18121818
}
@@ -1815,6 +1821,7 @@ impl<Block: BlockT> Backend<Block> {
18151821
&self,
18161822
transaction: &mut Transaction<DbHash>,
18171823
finalized_number: NumberFor<Block>,
1824+
finalized_hash: Block::Hash,
18181825
displaced: &FinalizationOutcome<Block::Hash, NumberFor<Block>>,
18191826
current_transaction_justifications: &mut HashMap<Block::Hash, Justification>,
18201827
) -> ClientResult<()> {
@@ -1843,10 +1850,10 @@ impl<Block: BlockT> Backend<Block> {
18431850

18441851
self.prune_block(transaction, BlockId::<Block>::number(number))?;
18451852
}
1846-
self.prune_displaced_branches(transaction, finalized_number, displaced)?;
1853+
self.prune_displaced_branches(transaction, finalized_hash, displaced)?;
18471854
},
18481855
BlocksPruning::KeepFinalized => {
1849-
self.prune_displaced_branches(transaction, finalized_number, displaced)?;
1856+
self.prune_displaced_branches(transaction, finalized_hash, displaced)?;
18501857
},
18511858
}
18521859
Ok(())
@@ -1855,28 +1862,21 @@ impl<Block: BlockT> Backend<Block> {
18551862
fn prune_displaced_branches(
18561863
&self,
18571864
transaction: &mut Transaction<DbHash>,
1858-
finalized: NumberFor<Block>,
1865+
finalized: Block::Hash,
18591866
displaced: &FinalizationOutcome<Block::Hash, NumberFor<Block>>,
18601867
) -> ClientResult<()> {
18611868
// Discard all blocks from displaced branches
18621869
for h in displaced.leaves() {
1863-
let mut number = finalized;
1864-
let mut hash = *h;
1865-
// Follow displaced chains back until we reach a finalized block.
1866-
// Since leaves are discarded due to finality, they can't have parents
1867-
// that are canonical, but not yet finalized. So we stop deleting as soon as
1868-
// we reach canonical chain.
1869-
while self.blockchain.hash(number)? != Some(hash) {
1870-
match self.blockchain.header(hash)? {
1871-
Some(header) => {
1872-
self.blockchain.insert_persisted_body_if_pinned(hash)?;
1873-
1874-
self.prune_block(transaction, BlockId::<Block>::hash(hash))?;
1875-
number = header.number().saturating_sub(One::one());
1876-
hash = *header.parent_hash();
1870+
match sp_blockchain::tree_route(&self.blockchain, *h, finalized) {
1871+
Ok(tree_route) =>
1872+
for r in tree_route.retracted() {
1873+
self.blockchain.insert_persisted_body_if_pinned(r.hash)?;
1874+
self.prune_block(transaction, BlockId::<Block>::hash(r.hash))?;
18771875
},
1878-
None => break,
1879-
}
1876+
Err(sp_blockchain::Error::UnknownBlock(_)) => {
1877+
// Sometimes routes can't be calculated. E.g. after warp sync.
1878+
},
1879+
Err(e) => Err(e)?,
18801880
}
18811881
}
18821882
Ok(())
@@ -3569,6 +3569,50 @@ pub(crate) mod tests {
35693569
assert_eq!(Some(vec![4.into()]), bc.body(blocks[4]).unwrap());
35703570
}
35713571

3572+
#[test]
3573+
fn prune_blocks_on_finalize_and_reorg() {
3574+
// 0 - 1b
3575+
// \ - 1a - 2a - 3a
3576+
// \ - 2b
3577+
3578+
let backend = Backend::<Block>::new_test_with_tx_storage(BlocksPruning::Some(10), 10);
3579+
3580+
let make_block = |index, parent, val: u64| {
3581+
insert_block(&backend, index, parent, None, H256::random(), vec![val.into()], None)
3582+
.unwrap()
3583+
};
3584+
3585+
let block_0 = make_block(0, Default::default(), 0x00);
3586+
let block_1a = make_block(1, block_0, 0x1a);
3587+
let block_1b = make_block(1, block_0, 0x1b);
3588+
let block_2a = make_block(2, block_1a, 0x2a);
3589+
let block_2b = make_block(2, block_1a, 0x2b);
3590+
let block_3a = make_block(3, block_2a, 0x3a);
3591+
3592+
// Make sure 1b is head
3593+
let mut op = backend.begin_operation().unwrap();
3594+
backend.begin_state_operation(&mut op, block_0).unwrap();
3595+
op.mark_head(block_1b).unwrap();
3596+
backend.commit_operation(op).unwrap();
3597+
3598+
// Finalize 3a
3599+
let mut op = backend.begin_operation().unwrap();
3600+
backend.begin_state_operation(&mut op, block_0).unwrap();
3601+
op.mark_head(block_3a).unwrap();
3602+
op.mark_finalized(block_1a, None).unwrap();
3603+
op.mark_finalized(block_2a, None).unwrap();
3604+
op.mark_finalized(block_3a, None).unwrap();
3605+
backend.commit_operation(op).unwrap();
3606+
3607+
let bc = backend.blockchain();
3608+
assert_eq!(None, bc.body(block_1b).unwrap());
3609+
assert_eq!(None, bc.body(block_2b).unwrap());
3610+
assert_eq!(Some(vec![0x00.into()]), bc.body(block_0).unwrap());
3611+
assert_eq!(Some(vec![0x1a.into()]), bc.body(block_1a).unwrap());
3612+
assert_eq!(Some(vec![0x2a.into()]), bc.body(block_2a).unwrap());
3613+
assert_eq!(Some(vec![0x3a.into()]), bc.body(block_3a).unwrap());
3614+
}
3615+
35723616
#[test]
35733617
fn indexed_data_block_body() {
35743618
let backend = Backend::<Block>::new_test_with_tx_storage(BlocksPruning::Some(1), 10);

0 commit comments

Comments
 (0)