@@ -1709,15 +1709,22 @@ impl<Block: BlockT> Backend<Block> {
1709
1709
}
1710
1710
1711
1711
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
+ ) ?;
1713
1719
1714
1720
Ok ( ( ) )
1715
1721
}
1716
1722
1717
1723
fn prune_blocks (
1718
1724
& self ,
1719
1725
transaction : & mut Transaction < DbHash > ,
1720
- finalized : NumberFor < Block > ,
1726
+ finalized_number : NumberFor < Block > ,
1727
+ finalized_hash : Block :: Hash ,
1721
1728
displaced : & FinalizationOutcome < Block :: Hash , NumberFor < Block > > ,
1722
1729
) -> ClientResult < ( ) > {
1723
1730
match self . blocks_pruning {
@@ -1729,10 +1736,10 @@ impl<Block: BlockT> Backend<Block> {
1729
1736
let number = finalized. saturating_sub ( keep. into ( ) ) ;
1730
1737
self . prune_block ( transaction, BlockId :: < Block > :: number ( number) ) ?;
1731
1738
}
1732
- self . prune_displaced_branches ( transaction, finalized , displaced) ?;
1739
+ self . prune_displaced_branches ( transaction, finalized_hash , displaced) ?;
1733
1740
} ,
1734
1741
BlocksPruning :: KeepFinalized => {
1735
- self . prune_displaced_branches ( transaction, finalized , displaced) ?;
1742
+ self . prune_displaced_branches ( transaction, finalized_hash , displaced) ?;
1736
1743
} ,
1737
1744
}
1738
1745
Ok ( ( ) )
@@ -1741,26 +1748,21 @@ impl<Block: BlockT> Backend<Block> {
1741
1748
fn prune_displaced_branches (
1742
1749
& self ,
1743
1750
transaction : & mut Transaction < DbHash > ,
1744
- finalized : NumberFor < Block > ,
1751
+ finalized : Block :: Hash ,
1745
1752
displaced : & FinalizationOutcome < Block :: Hash , NumberFor < Block > > ,
1746
1753
) -> ClientResult < ( ) > {
1747
1754
// Discard all blocks from displaced branches
1748
1755
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 ) ) ?;
1761
1761
} ,
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) ?,
1764
1766
}
1765
1767
}
1766
1768
Ok ( ( ) )
@@ -3407,6 +3409,50 @@ pub(crate) mod tests {
3407
3409
assert_eq ! ( Some ( vec![ 4 . into( ) ] ) , bc. body( blocks[ 4 ] ) . unwrap( ) ) ;
3408
3410
}
3409
3411
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
+
3410
3456
#[ test]
3411
3457
fn indexed_data_block_body ( ) {
3412
3458
let backend = Backend :: < Block > :: new_test_with_tx_storage ( BlocksPruning :: Some ( 1 ) , 10 ) ;
0 commit comments