@@ -4166,21 +4166,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
41664166 ( re_org_state. pre_state , re_org_state. state_root )
41674167 }
41684168 // Normal case: proposing a block atop the current head using the cache.
4169- else if let Some ( ( _, cached_state) ) = self
4170- . block_production_state
4171- . lock ( )
4172- . take ( )
4173- . filter ( |( cached_block_root, _) | * cached_block_root == head_block_root)
4169+ else if let Some ( ( _, cached_state) ) =
4170+ self . get_state_from_block_production_cache ( head_block_root)
41744171 {
41754172 ( cached_state. pre_state , cached_state. state_root )
41764173 }
41774174 // Fall back to a direct read of the snapshot cache.
4178- else if let Some ( pre_state) = self
4179- . snapshot_cache
4180- . try_read_for ( BLOCK_PROCESSING_CACHE_LOCK_TIMEOUT )
4181- . and_then ( |snapshot_cache| {
4182- snapshot_cache. get_state_for_block_production ( head_block_root)
4183- } )
4175+ else if let Some ( pre_state) =
4176+ self . get_state_from_snapshot_cache_for_block_production ( head_block_root)
41844177 {
41854178 warn ! (
41864179 self . log,
@@ -4221,6 +4214,40 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
42214214 Ok ( ( state, state_root_opt) )
42224215 }
42234216
4217+ /// Get the state cached for block production *if* it matches `head_block_root`.
4218+ ///
4219+ /// This will clear the cache regardless of whether the block root matches, so only call this if
4220+ /// you think the `head_block_root` is likely to match!
4221+ fn get_state_from_block_production_cache (
4222+ & self ,
4223+ head_block_root : Hash256 ,
4224+ ) -> Option < ( Hash256 , BlockProductionPreState < T :: EthSpec > ) > {
4225+ // Take care to drop the lock as quickly as possible.
4226+ let mut lock = self . block_production_state . lock ( ) ;
4227+ let result = lock
4228+ . take ( )
4229+ . filter ( |( cached_block_root, _) | * cached_block_root == head_block_root) ;
4230+ drop ( lock) ;
4231+ result
4232+ }
4233+
4234+ /// Get a state for block production from the snapshot cache.
4235+ fn get_state_from_snapshot_cache_for_block_production (
4236+ & self ,
4237+ head_block_root : Hash256 ,
4238+ ) -> Option < BlockProductionPreState < T :: EthSpec > > {
4239+ if let Some ( lock) = self
4240+ . snapshot_cache
4241+ . try_read_for ( BLOCK_PROCESSING_CACHE_LOCK_TIMEOUT )
4242+ {
4243+ let result = lock. get_state_for_block_production ( head_block_root) ;
4244+ drop ( lock) ;
4245+ result
4246+ } else {
4247+ None
4248+ }
4249+ }
4250+
42244251 /// Fetch the beacon state to use for producing a block if a 1-slot proposer re-org is viable.
42254252 ///
42264253 /// This function will return `None` if proposer re-orgs are disabled.
@@ -4313,12 +4340,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
43134340
43144341 // Only attempt a re-org if we hit the block production cache or snapshot cache.
43154342 let pre_state = self
4316- . block_production_state
4317- . lock ( )
4318- . take ( )
4319- . and_then ( |( cached_block_root, state) | {
4320- ( cached_block_root == re_org_parent_block) . then_some ( state)
4321- } )
4343+ . get_state_from_block_production_cache ( re_org_parent_block)
4344+ . map ( |( _, state) | state)
43224345 . or_else ( || {
43234346 warn ! (
43244347 self . log,
@@ -4327,11 +4350,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
43274350 "slot" => slot,
43284351 "block_root" => ?re_org_parent_block
43294352 ) ;
4330- self . snapshot_cache
4331- . try_read_for ( BLOCK_PROCESSING_CACHE_LOCK_TIMEOUT )
4332- . and_then ( |snapshot_cache| {
4333- snapshot_cache. get_state_for_block_production ( re_org_parent_block)
4334- } )
4353+ self . get_state_from_snapshot_cache_for_block_production ( re_org_parent_block)
43354354 } )
43364355 . or_else ( || {
43374356 debug ! (
0 commit comments