@@ -41,7 +41,7 @@ use crate::light_client_optimistic_update_verification::{
4141 Error as LightClientOptimisticUpdateError , VerifiedLightClientOptimisticUpdate ,
4242} ;
4343use crate :: light_client_server_cache:: LightClientServerCache ;
44- use crate :: migrate:: BackgroundMigrator ;
44+ use crate :: migrate:: { BackgroundMigrator , ManualFinalizationNotification } ;
4545use crate :: naive_aggregation_pool:: {
4646 AggregatedAttestationMap , Error as NaiveAggregationError , NaiveAggregationPool ,
4747 SyncContributionAggregateMap ,
@@ -117,8 +117,8 @@ use std::sync::Arc;
117117use std:: time:: Duration ;
118118use store:: iter:: { BlockRootsIterator , ParentRootBlockIterator , StateRootsIterator } ;
119119use store:: {
120- BlobSidecarListFromRoot , DatabaseBlock , Error as DBError , HotColdDB , KeyValueStore ,
121- KeyValueStoreOp , StoreItem , StoreOp ,
120+ BlobSidecarListFromRoot , DatabaseBlock , Error as DBError , HotColdDB , HotStateSummary ,
121+ KeyValueStore , KeyValueStoreOp , StoreItem , StoreOp ,
122122} ;
123123use task_executor:: { ShutdownReason , TaskExecutor } ;
124124use tokio:: sync:: oneshot;
@@ -691,7 +691,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
691691 ///
692692 /// - `slot` always increases by `1`.
693693 /// - Skipped slots contain the root of the closest prior
694- /// non-skipped slot (identical to the way they are stored in `state.block_roots`).
694+ /// non-skipped slot (identical to the way they are stored in `state.block_roots`).
695695 /// - Iterator returns `(Hash256, Slot)`.
696696 ///
697697 /// Will return a `BlockOutOfRange` error if the requested start slot is before the period of
@@ -755,7 +755,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
755755 ///
756756 /// - `slot` always decreases by `1`.
757757 /// - Skipped slots contain the root of the closest prior
758- /// non-skipped slot (identical to the way they are stored in `state.block_roots`) .
758+ /// non-skipped slot (identical to the way they are stored in `state.block_roots`) .
759759 /// - Iterator returns `(Hash256, Slot)`.
760760 /// - The provided `block_root` is included as the first item in the iterator.
761761 pub fn rev_iter_block_roots_from (
@@ -765,8 +765,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
765765 let block = self
766766 . get_blinded_block ( & block_root) ?
767767 . ok_or ( Error :: MissingBeaconBlock ( block_root) ) ?;
768+ // This method is only used in tests, so we may as well cache states to make CI go brr.
769+ // TODO(release-v7) move this method out of beacon chain and into `store_tests`` or something equivalent.
768770 let state = self
769- . get_state ( & block. state_root ( ) , Some ( block. slot ( ) ) ) ?
771+ . get_state ( & block. state_root ( ) , Some ( block. slot ( ) ) , true ) ?
770772 . ok_or_else ( || Error :: MissingBeaconState ( block. state_root ( ) ) ) ?;
771773 let iter = BlockRootsIterator :: owned ( & self . store , state) ;
772774 Ok ( std:: iter:: once ( Ok ( ( block_root, block. slot ( ) ) ) )
@@ -782,7 +784,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
782784 /// - `slot` always decreases by `1`.
783785 /// - Iterator returns `(Hash256, Slot)`.
784786 /// - As this iterator starts at the `head` of the chain (viz., the best block), the first slot
785- /// returned may be earlier than the wall-clock slot.
787+ /// returned may be earlier than the wall-clock slot.
786788 pub fn rev_iter_state_roots_from < ' a > (
787789 & ' a self ,
788790 state_root : Hash256 ,
@@ -1292,8 +1294,9 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
12921294 & self ,
12931295 state_root : & Hash256 ,
12941296 slot : Option < Slot > ,
1297+ update_cache : bool ,
12951298 ) -> Result < Option < BeaconState < T :: EthSpec > > , Error > {
1296- Ok ( self . store . get_state ( state_root, slot) ?)
1299+ Ok ( self . store . get_state ( state_root, slot, update_cache ) ?)
12971300 }
12981301
12991302 /// Return the sync committee at `slot + 1` from the canonical chain.
@@ -1466,8 +1469,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
14661469 } ) ?
14671470 . ok_or ( Error :: NoStateForSlot ( slot) ) ?;
14681471
1472+ // This branch is mostly reached from the HTTP API when doing analysis, or in niche
1473+ // situations when producing a block. In the HTTP API case we assume the user wants
1474+ // to cache states so that future calls are faster, and that if the cache is
1475+ // struggling due to non-finality that they will dial down inessential calls. In the
1476+ // block proposal case we want to cache the state so that we can process the block
1477+ // quickly after it has been signed.
14691478 Ok ( self
1470- . get_state ( & state_root, Some ( slot) ) ?
1479+ . get_state ( & state_root, Some ( slot) , true ) ?
14711480 . ok_or ( Error :: NoStateForSlot ( slot) ) ?)
14721481 }
14731482 }
@@ -1649,6 +1658,43 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
16491658 }
16501659 }
16511660
1661+ pub fn manually_compact_database ( & self ) {
1662+ self . store_migrator . process_manual_compaction ( ) ;
1663+ }
1664+
1665+ pub fn manually_finalize_state (
1666+ & self ,
1667+ state_root : Hash256 ,
1668+ checkpoint : Checkpoint ,
1669+ ) -> Result < ( ) , Error > {
1670+ let HotStateSummary {
1671+ slot,
1672+ latest_block_root,
1673+ ..
1674+ } = self
1675+ . store
1676+ . load_hot_state_summary ( & state_root)
1677+ . map_err ( BeaconChainError :: DBError ) ?
1678+ . ok_or ( BeaconChainError :: MissingHotStateSummary ( state_root) ) ?;
1679+
1680+ if slot != checkpoint. epoch . start_slot ( T :: EthSpec :: slots_per_epoch ( ) )
1681+ || latest_block_root != * checkpoint. root
1682+ {
1683+ return Err ( BeaconChainError :: InvalidCheckpoint {
1684+ state_root,
1685+ checkpoint,
1686+ } ) ;
1687+ }
1688+
1689+ let notif = ManualFinalizationNotification {
1690+ state_root : state_root. into ( ) ,
1691+ checkpoint,
1692+ } ;
1693+
1694+ self . store_migrator . process_manual_finalization ( notif) ;
1695+ Ok ( ( ) )
1696+ }
1697+
16521698 /// Returns an aggregated `Attestation`, if any, that has a matching `attestation.data`.
16531699 ///
16541700 /// The attestation will be obtained from `self.naive_aggregation_pool`.
@@ -2793,6 +2839,15 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
27932839 chain_segment : Vec < RpcBlock < T :: EthSpec > > ,
27942840 notify_execution_layer : NotifyExecutionLayer ,
27952841 ) -> ChainSegmentResult {
2842+ for block in chain_segment. iter ( ) {
2843+ if let Err ( error) = self . check_invalid_block_roots ( block. block_root ( ) ) {
2844+ return ChainSegmentResult :: Failed {
2845+ imported_blocks : vec ! [ ] ,
2846+ error,
2847+ } ;
2848+ }
2849+ }
2850+
27962851 let mut imported_blocks = vec ! [ ] ;
27972852
27982853 // Filter uninteresting blocks from the chain segment in a blocking task.
@@ -2928,6 +2983,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
29282983 pub async fn verify_block_for_gossip (
29292984 self : & Arc < Self > ,
29302985 block : Arc < SignedBeaconBlock < T :: EthSpec > > ,
2986+ custody_columns_count : usize ,
29312987 ) -> Result < GossipVerifiedBlock < T > , BlockError > {
29322988 let chain = self . clone ( ) ;
29332989 self . task_executor
@@ -2937,7 +2993,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
29372993 let slot = block. slot ( ) ;
29382994 let graffiti_string = block. message ( ) . body ( ) . graffiti ( ) . as_utf8_lossy ( ) ;
29392995
2940- match GossipVerifiedBlock :: new ( block, & chain) {
2996+ match GossipVerifiedBlock :: new ( block, & chain, custody_columns_count ) {
29412997 Ok ( verified) => {
29422998 let commitments_formatted = verified. block . commitments_formatted ( ) ;
29432999 debug ! (
@@ -3284,6 +3340,15 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
32843340 self . remove_notified ( & block_root, r)
32853341 }
32863342
3343+ /// Check for known and configured invalid block roots before processing.
3344+ pub fn check_invalid_block_roots ( & self , block_root : Hash256 ) -> Result < ( ) , BlockError > {
3345+ if self . config . invalid_block_roots . contains ( & block_root) {
3346+ Err ( BlockError :: KnownInvalidExecutionPayload ( block_root) )
3347+ } else {
3348+ Ok ( ( ) )
3349+ }
3350+ }
3351+
32873352 /// Returns `Ok(block_root)` if the given `unverified_block` was successfully verified and
32883353 /// imported into the chain.
32893354 ///
@@ -6715,9 +6780,11 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
67156780 } ) ?;
67166781 let beacon_state_root = beacon_block. state_root ( ) ;
67176782
6783+ // This branch is reached from the HTTP API. We assume the user wants
6784+ // to cache states so that future calls are faster.
67186785 let mut beacon_state = self
67196786 . store
6720- . get_state ( & beacon_state_root, Some ( beacon_block. slot ( ) ) ) ?
6787+ . get_state ( & beacon_state_root, Some ( beacon_block. slot ( ) ) , true ) ?
67216788 . ok_or_else ( || {
67226789 Error :: DBInconsistent ( format ! ( "Missing state {:?}" , beacon_state_root) )
67236790 } ) ?;
@@ -6869,8 +6936,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
68696936
68706937 if signed_beacon_block. slot ( ) % T :: EthSpec :: slots_per_epoch ( ) == 0 {
68716938 let block = self . get_blinded_block ( & block_hash) . unwrap ( ) . unwrap ( ) ;
6939+ // This branch is reached from the HTTP API. We assume the user wants
6940+ // to cache states so that future calls are faster.
68726941 let state = self
6873- . get_state ( & block. state_root ( ) , Some ( block. slot ( ) ) )
6942+ . get_state ( & block. state_root ( ) , Some ( block. slot ( ) ) , true )
68746943 . unwrap ( )
68756944 . unwrap ( ) ;
68766945 finalized_blocks. insert ( state. finalized_checkpoint ( ) . root ) ;
@@ -7031,10 +7100,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
70317100 block_root : Hash256 ,
70327101 block_data : AvailableBlockData < T :: EthSpec > ,
70337102 ) -> Result < Option < StoreOp < T :: EthSpec > > , String > {
7034- // TODO(das) we currently store all subnet sampled columns. Tracking issue to exclude non
7035- // custody columns: https://github.com/sigp/lighthouse/issues/6465
7036- let _custody_columns_count = self . data_availability_checker . get_sampling_column_count ( ) ;
7037-
70387103 match block_data {
70397104 AvailableBlockData :: NoData => Ok ( None ) ,
70407105 AvailableBlockData :: Blobs ( blobs) => {
0 commit comments