@@ -1709,15 +1709,22 @@ impl<Block: BlockT> Backend<Block> {
17091709 }
17101710
17111711 let new_displaced = self . blockchain . leaves . write ( ) . finalize_height ( f_num) ;
1712- self . prune_blocks ( transaction, f_num, & new_displaced) ?;
1712+ self . prune_blocks (
1713+ transaction,
1714+ f_num,
1715+ f_hash,
1716+ & new_displaced,
1717+ current_transaction_justifications,
1718+ ) ?;
17131719
17141720 Ok ( ( ) )
17151721 }
17161722
17171723 fn prune_blocks (
17181724 & self ,
17191725 transaction : & mut Transaction < DbHash > ,
1720- finalized : NumberFor < Block > ,
1726+ finalized_number : NumberFor < Block > ,
1727+ finalized_hash : Block :: Hash ,
17211728 displaced : & FinalizationOutcome < Block :: Hash , NumberFor < Block > > ,
17221729 ) -> ClientResult < ( ) > {
17231730 match self . blocks_pruning {
@@ -1729,10 +1736,10 @@ impl<Block: BlockT> Backend<Block> {
17291736 let number = finalized. saturating_sub ( keep. into ( ) ) ;
17301737 self . prune_block ( transaction, BlockId :: < Block > :: number ( number) ) ?;
17311738 }
1732- self . prune_displaced_branches ( transaction, finalized , displaced) ?;
1739+ self . prune_displaced_branches ( transaction, finalized_hash , displaced) ?;
17331740 } ,
17341741 BlocksPruning :: KeepFinalized => {
1735- self . prune_displaced_branches ( transaction, finalized , displaced) ?;
1742+ self . prune_displaced_branches ( transaction, finalized_hash , displaced) ?;
17361743 } ,
17371744 }
17381745 Ok ( ( ) )
@@ -1741,26 +1748,21 @@ impl<Block: BlockT> Backend<Block> {
17411748 fn prune_displaced_branches (
17421749 & self ,
17431750 transaction : & mut Transaction < DbHash > ,
1744- finalized : NumberFor < Block > ,
1751+ finalized : Block :: Hash ,
17451752 displaced : & FinalizationOutcome < Block :: Hash , NumberFor < Block > > ,
17461753 ) -> ClientResult < ( ) > {
17471754 // Discard all blocks from displaced branches
17481755 for h in displaced. leaves ( ) {
1749- let mut number = finalized;
1750- let mut hash = * h;
1751- // Follow displaced chains back until we reach a finalized block.
1752- // Since leaves are discarded due to finality, they can't have parents
1753- // that are canonical, but not yet finalized. So we stop deleting as soon as
1754- // we reach canonical chain.
1755- while self . blockchain . hash ( number) ? != Some ( hash) {
1756- match self . blockchain . header ( hash) ? {
1757- Some ( header) => {
1758- self . prune_block ( transaction, BlockId :: < Block > :: hash ( hash) ) ?;
1759- number = header. number ( ) . saturating_sub ( One :: one ( ) ) ;
1760- hash = * header. parent_hash ( ) ;
1756+ match sp_blockchain:: tree_route ( & self . blockchain , * h, finalized) {
1757+ Ok ( tree_route) =>
1758+ for r in tree_route. retracted ( ) {
1759+ self . blockchain . insert_persisted_body_if_pinned ( r. hash ) ?;
1760+ self . prune_block ( transaction, BlockId :: < Block > :: hash ( r. hash ) ) ?;
17611761 } ,
1762- None => break ,
1763- }
1762+ Err ( sp_blockchain:: Error :: UnknownBlock ( _) ) => {
1763+ // Sometimes routes can't be calculated. E.g. after warp sync.
1764+ } ,
1765+ Err ( e) => Err ( e) ?,
17641766 }
17651767 }
17661768 Ok ( ( ) )
@@ -3407,6 +3409,50 @@ pub(crate) mod tests {
34073409 assert_eq ! ( Some ( vec![ 4 . into( ) ] ) , bc. body( blocks[ 4 ] ) . unwrap( ) ) ;
34083410 }
34093411
3412+ #[ test]
3413+ fn prune_blocks_on_finalize_and_reorg ( ) {
3414+ // 0 - 1b
3415+ // \ - 1a - 2a - 3a
3416+ // \ - 2b
3417+
3418+ let backend = Backend :: < Block > :: new_test_with_tx_storage ( BlocksPruning :: Some ( 10 ) , 10 ) ;
3419+
3420+ let make_block = |index, parent, val : u64 | {
3421+ insert_block ( & backend, index, parent, None , H256 :: random ( ) , vec ! [ val. into( ) ] , None )
3422+ . unwrap ( )
3423+ } ;
3424+
3425+ let block_0 = make_block ( 0 , Default :: default ( ) , 0x00 ) ;
3426+ let block_1a = make_block ( 1 , block_0, 0x1a ) ;
3427+ let block_1b = make_block ( 1 , block_0, 0x1b ) ;
3428+ let block_2a = make_block ( 2 , block_1a, 0x2a ) ;
3429+ let block_2b = make_block ( 2 , block_1a, 0x2b ) ;
3430+ let block_3a = make_block ( 3 , block_2a, 0x3a ) ;
3431+
3432+ // Make sure 1b is head
3433+ let mut op = backend. begin_operation ( ) . unwrap ( ) ;
3434+ backend. begin_state_operation ( & mut op, block_0) . unwrap ( ) ;
3435+ op. mark_head ( block_1b) . unwrap ( ) ;
3436+ backend. commit_operation ( op) . unwrap ( ) ;
3437+
3438+ // Finalize 3a
3439+ let mut op = backend. begin_operation ( ) . unwrap ( ) ;
3440+ backend. begin_state_operation ( & mut op, block_0) . unwrap ( ) ;
3441+ op. mark_head ( block_3a) . unwrap ( ) ;
3442+ op. mark_finalized ( block_1a, None ) . unwrap ( ) ;
3443+ op. mark_finalized ( block_2a, None ) . unwrap ( ) ;
3444+ op. mark_finalized ( block_3a, None ) . unwrap ( ) ;
3445+ backend. commit_operation ( op) . unwrap ( ) ;
3446+
3447+ let bc = backend. blockchain ( ) ;
3448+ assert_eq ! ( None , bc. body( block_1b) . unwrap( ) ) ;
3449+ assert_eq ! ( None , bc. body( block_2b) . unwrap( ) ) ;
3450+ assert_eq ! ( Some ( vec![ 0x00 . into( ) ] ) , bc. body( block_0) . unwrap( ) ) ;
3451+ assert_eq ! ( Some ( vec![ 0x1a . into( ) ] ) , bc. body( block_1a) . unwrap( ) ) ;
3452+ assert_eq ! ( Some ( vec![ 0x2a . into( ) ] ) , bc. body( block_2a) . unwrap( ) ) ;
3453+ assert_eq ! ( Some ( vec![ 0x3a . into( ) ] ) , bc. body( block_3a) . unwrap( ) ) ;
3454+ }
3455+
34103456 #[ test]
34113457 fn indexed_data_block_body ( ) {
34123458 let backend = Backend :: < Block > :: new_test_with_tx_storage ( BlocksPruning :: Some ( 1 ) , 10 ) ;
0 commit comments