@@ -11,7 +11,7 @@ use std::sync::{mpsc, Arc};
11
11
use std:: thread;
12
12
use std:: time:: { Duration , SystemTime , UNIX_EPOCH } ;
13
13
use store:: hot_cold_store:: { migrate_database, HotColdDBError } ;
14
- use store:: iter:: StateRootsIterator ;
14
+ use store:: iter:: { BlockRootsIterator , StateRootsIterator } ;
15
15
use store:: { DBColumn , Error , HotStateSummary , ItemStore , StoreItem , StoreOp } ;
16
16
pub use store:: { HotColdDB , MemoryStore } ;
17
17
use types:: {
@@ -514,23 +514,13 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> BackgroundMigrator<E, Ho
514
514
"new_finalized_epoch" => new_finalized_checkpoint. epoch,
515
515
) ;
516
516
517
- let mut hot_db_ops = vec ! [ ] ;
518
- // TODO(hdiff): iterate blocks from finalized block up to old_finalized_slot
519
- let finalized_blocks = vec ! [ ] ;
520
- Self :: prune_non_checkpoint_sync_committee_branches ( & finalized_blocks, & mut hot_db_ops) ;
521
- // if store.config.prune_payloads {
522
- Self :: prune_finalized_payloads ( & finalized_blocks, & mut hot_db_ops) ;
523
- // }
524
-
525
517
debug ! (
526
518
log,
527
519
"Extra pruning information" ;
528
520
"old_finalized_root" => format!( "{:?}" , old_finalized_checkpoint. root) ,
529
521
"new_finalized_root" => format!( "{:?}" , new_finalized_checkpoint. root) ,
530
522
) ;
531
523
532
- /////
533
-
534
524
let summaries_dag = {
535
525
let state_summaries = store
536
526
. hot_db
@@ -568,26 +558,26 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> BackgroundMigrator<E, Ho
568
558
summaries_dag. descendant_block_roots_of ( & new_finalized_checkpoint. root ) ?;
569
559
570
560
// TODO(hdiff): Could re-use the summaries dag
571
- let newly_finalized_chain =
572
- std:: iter:: once ( Ok ( ( new_finalized_slot, new_finalized_state_hash) ) )
573
- . chain (
574
- StateRootsIterator :: new ( & store, new_finalized_state)
575
- . map ( |res| res. map ( |( state_root, slot) | ( slot, state_root) ) ) ,
576
- )
561
+ let newly_finalized_state_roots =
562
+ std:: iter:: once ( Ok ( ( new_finalized_state_hash, new_finalized_slot) ) )
563
+ . chain ( StateRootsIterator :: new ( & store, new_finalized_state) )
577
564
. take_while ( |res| {
578
565
res. as_ref ( )
579
- . map_or ( true , |( slot , _ ) | * slot >= old_finalized_slot)
566
+ . map_or ( true , |( _ , slot ) | * slot >= old_finalized_slot)
580
567
} )
581
- . map ( |res| res. map ( |( _, state_root) | state_root) )
582
- . collect :: < Result < Vec < Hash256 > , _ > > ( ) ?;
568
+ . map ( |res| res. map ( |( state_root, _) | state_root) )
569
+ . collect :: < Result < HashSet < Hash256 > , _ > > ( ) ?;
570
+
571
+ // TODO(hdiff): Could re-use the summaries dag
572
+ let newly_finalized_blocks = BlockRootsIterator :: new ( & store, new_finalized_state)
573
+ . take_while ( |res| {
574
+ res. as_ref ( )
575
+ . map_or ( true , |( _, slot) | * slot >= old_finalized_slot)
576
+ } )
577
+ . collect :: < Result < Vec < ( Hash256 , Slot ) > , _ > > ( ) ?;
583
578
584
579
// Compute the set of finalized state roots that we must keep to make the dynamic HDiff system
585
580
// work.
586
- // TODO(hdiff): must not delete *all* finalized hdiffs. Instead, keep
587
- // the more recent diff of each layer including the snapshot.
588
- // Implement a routine somewhere to figure out which diffs should be kept
589
- // Given a start slot, and the current finalized state:
590
- // - iterate each hdiff layer and compute the most recent point <= finalized slot
591
581
let required_finalized_diff_state_slots =
592
582
store. hierarchy_hot . closest_layer_points ( new_finalized_slot) ;
593
583
@@ -601,23 +591,21 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> BackgroundMigrator<E, Ho
601
591
if block_roots_descendant_of_finalized. contains ( & summary. latest_block_root ) {
602
592
// Keep this state is the post state of a viable head, or a state advance from a
603
593
// viable head.
604
- } else if newly_finalized_chain . contains ( & state_root)
594
+ } else if newly_finalized_state_roots . contains ( & state_root)
605
595
&& required_finalized_diff_state_slots. contains ( & slot)
606
596
{
607
597
// Keep this state and diff as it's necessary for the finalized portion of the
608
- // HDiff links
598
+ // HDiff links. `required_finalized_diff_state_slots` tracks the set of slots on
599
+ // each diff layer, and by checking `newly_finalized_state_roots` which only
600
+ // keep those on the finalized canonical chain. Note that there may be lingering
601
+ // forks.
609
602
} else {
610
- // TODO(hdiff) compute the root of the hdiffs to keep, else prune
611
603
abandoned_blocks. insert ( SignedBeaconBlockHash :: from ( summary. latest_block_root ) ) ;
612
604
abandoned_states. insert ( ( slot, BeaconStateHash :: from ( state_root) ) ) ;
613
605
}
614
606
}
615
607
}
616
608
617
- // TODO(hdiff): Update the headtracker or remove it
618
-
619
- /////
620
-
621
609
let mut batch: Vec < StoreOp < E > > = abandoned_blocks
622
610
. into_iter ( )
623
611
. map ( Into :: into)
@@ -650,11 +638,13 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> BackgroundMigrator<E, Ho
650
638
store. pruning_checkpoint_store_op ( new_finalized_checkpoint) ,
651
639
) ) ;
652
640
653
- store. do_atomically_with_block_and_blobs_cache ( batch) ?;
641
+ Self :: prune_non_checkpoint_sync_committee_branches ( & newly_finalized_blocks, & mut batch) ;
642
+ // TODO(hdiff): access store config here
643
+ // if store.config.prune_payloads {
644
+ Self :: prune_finalized_payloads ( & newly_finalized_blocks, & mut batch) ;
645
+ // }
654
646
655
- // Do a quick separate pass to delete obsoleted hot states, usually pre-states from the state
656
- // advance which are not canonical due to blocks being applied on top.
657
- store. prune_old_hot_states ( ) ?;
647
+ store. do_atomically_with_block_and_blobs_cache ( batch) ?;
658
648
659
649
debug ! ( log, "Database pruning complete" ) ;
660
650
@@ -664,10 +654,10 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> BackgroundMigrator<E, Ho
664
654
}
665
655
666
656
fn prune_finalized_payloads (
667
- finalized_blocks : & [ ( Slot , Hash256 ) ] ,
657
+ finalized_blocks : & [ ( Hash256 , Slot ) ] ,
668
658
hot_db_ops : & mut Vec < StoreOp < E > > ,
669
659
) {
670
- for ( _ , block_root ) in finalized_blocks {
660
+ for ( block_root , _ ) in finalized_blocks {
671
661
// Delete the execution payload if payload pruning is enabled. At a skipped slot we may
672
662
// delete the payload for the finalized block itself, but that's OK as we only guarantee
673
663
// that payloads are present for slots >= the split slot. The payload fetching code is also
@@ -677,14 +667,14 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> BackgroundMigrator<E, Ho
677
667
}
678
668
679
669
fn prune_non_checkpoint_sync_committee_branches (
680
- finalized_blocks : & [ ( Slot , Hash256 ) ] ,
670
+ finalized_blocks : & [ ( Hash256 , Slot ) ] ,
681
671
hot_db_ops : & mut Vec < StoreOp < E > > ,
682
672
) {
683
673
let mut epoch_boundary_blocks = HashSet :: new ( ) ;
684
674
let mut non_checkpoint_block_roots = HashSet :: new ( ) ;
685
675
686
676
// Then, iterate states in slot ascending order, as they are stored wrt previous states.
687
- for ( slot , block_root ) in finalized_blocks {
677
+ for ( block_root , slot ) in finalized_blocks {
688
678
// At a missed slot, `state_root_iter` will return the block root
689
679
// from the previous non-missed slot. This ensures that the block root at an
690
680
// epoch boundary is always a checkpoint block root. We keep track of block roots
0 commit comments