@@ -1806,7 +1806,13 @@ impl<Block: BlockT> Backend<Block> {
1806
1806
}
1807
1807
1808
1808
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
+ ) ?;
1810
1816
1811
1817
Ok ( ( ) )
1812
1818
}
@@ -1815,6 +1821,7 @@ impl<Block: BlockT> Backend<Block> {
1815
1821
& self ,
1816
1822
transaction : & mut Transaction < DbHash > ,
1817
1823
finalized_number : NumberFor < Block > ,
1824
+ finalized_hash : Block :: Hash ,
1818
1825
displaced : & FinalizationOutcome < Block :: Hash , NumberFor < Block > > ,
1819
1826
current_transaction_justifications : & mut HashMap < Block :: Hash , Justification > ,
1820
1827
) -> ClientResult < ( ) > {
@@ -1843,10 +1850,10 @@ impl<Block: BlockT> Backend<Block> {
1843
1850
1844
1851
self . prune_block ( transaction, BlockId :: < Block > :: number ( number) ) ?;
1845
1852
}
1846
- self . prune_displaced_branches ( transaction, finalized_number , displaced) ?;
1853
+ self . prune_displaced_branches ( transaction, finalized_hash , displaced) ?;
1847
1854
} ,
1848
1855
BlocksPruning :: KeepFinalized => {
1849
- self . prune_displaced_branches ( transaction, finalized_number , displaced) ?;
1856
+ self . prune_displaced_branches ( transaction, finalized_hash , displaced) ?;
1850
1857
} ,
1851
1858
}
1852
1859
Ok ( ( ) )
@@ -1855,28 +1862,21 @@ impl<Block: BlockT> Backend<Block> {
1855
1862
fn prune_displaced_branches (
1856
1863
& self ,
1857
1864
transaction : & mut Transaction < DbHash > ,
1858
- finalized : NumberFor < Block > ,
1865
+ finalized : Block :: Hash ,
1859
1866
displaced : & FinalizationOutcome < Block :: Hash , NumberFor < Block > > ,
1860
1867
) -> ClientResult < ( ) > {
1861
1868
// Discard all blocks from displaced branches
1862
1869
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 ) ) ?;
1877
1875
} ,
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) ?,
1880
1880
}
1881
1881
}
1882
1882
Ok ( ( ) )
@@ -3569,6 +3569,50 @@ pub(crate) mod tests {
3569
3569
assert_eq ! ( Some ( vec![ 4 . into( ) ] ) , bc. body( blocks[ 4 ] ) . unwrap( ) ) ;
3570
3570
}
3571
3571
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
+
3572
3616
#[ test]
3573
3617
fn indexed_data_block_body ( ) {
3574
3618
let backend = Backend :: < Block > :: new_test_with_tx_storage ( BlocksPruning :: Some ( 1 ) , 10 ) ;
0 commit comments