mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-30 11:13:34 +00:00
Hold HeadTracker lock until persisting to disk (#5084)
* Fix head tracker drop order on un-ordered shutdown * lint --------- Co-authored-by: Michael Sproul <michael@sigmaprime.io>
This commit is contained in:
@@ -30,7 +30,7 @@ use crate::eth1_finalization_cache::{Eth1FinalizationCache, Eth1FinalizationData
|
||||
use crate::events::ServerSentEventHandler;
|
||||
use crate::execution_payload::{get_execution_payload, NotifyExecutionLayer, PreparePayloadHandle};
|
||||
use crate::fork_choice_signal::{ForkChoiceSignalRx, ForkChoiceSignalTx, ForkChoiceWaitResult};
|
||||
use crate::head_tracker::HeadTracker;
|
||||
use crate::head_tracker::{HeadTracker, HeadTrackerReader, SszHeadTracker};
|
||||
use crate::historical_blocks::HistoricalBlockError;
|
||||
use crate::light_client_finality_update_verification::{
|
||||
Error as LightClientFinalityUpdateError, VerifiedLightClientFinalityUpdate,
|
||||
@@ -610,12 +610,19 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
let mut batch = vec![];
|
||||
|
||||
let _head_timer = metrics::start_timer(&metrics::PERSIST_HEAD);
|
||||
batch.push(self.persist_head_in_batch());
|
||||
|
||||
// Hold a lock to head_tracker until it has been persisted to disk. Otherwise there's a race
|
||||
// condition with the pruning thread which can result in a block present in the head tracker
|
||||
// but absent in the DB. This inconsistency halts pruning and dramastically increases disk
|
||||
// size. Ref: https://github.com/sigp/lighthouse/issues/4773
|
||||
let head_tracker = self.head_tracker.0.read();
|
||||
batch.push(self.persist_head_in_batch(&head_tracker));
|
||||
|
||||
let _fork_choice_timer = metrics::start_timer(&metrics::PERSIST_FORK_CHOICE);
|
||||
batch.push(self.persist_fork_choice_in_batch());
|
||||
|
||||
self.store.hot_db.do_atomically(batch)?;
|
||||
drop(head_tracker);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -623,25 +630,28 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
/// Return a `PersistedBeaconChain` without reference to a `BeaconChain`.
|
||||
pub fn make_persisted_head(
|
||||
genesis_block_root: Hash256,
|
||||
head_tracker: &HeadTracker,
|
||||
head_tracker_reader: &HeadTrackerReader,
|
||||
) -> PersistedBeaconChain {
|
||||
PersistedBeaconChain {
|
||||
_canonical_head_block_root: DUMMY_CANONICAL_HEAD_BLOCK_ROOT,
|
||||
genesis_block_root,
|
||||
ssz_head_tracker: head_tracker.to_ssz_container(),
|
||||
ssz_head_tracker: SszHeadTracker::from_map(head_tracker_reader),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a database operation for writing the beacon chain head to disk.
|
||||
pub fn persist_head_in_batch(&self) -> KeyValueStoreOp {
|
||||
Self::persist_head_in_batch_standalone(self.genesis_block_root, &self.head_tracker)
|
||||
pub fn persist_head_in_batch(
|
||||
&self,
|
||||
head_tracker_reader: &HeadTrackerReader,
|
||||
) -> KeyValueStoreOp {
|
||||
Self::persist_head_in_batch_standalone(self.genesis_block_root, head_tracker_reader)
|
||||
}
|
||||
|
||||
pub fn persist_head_in_batch_standalone(
|
||||
genesis_block_root: Hash256,
|
||||
head_tracker: &HeadTracker,
|
||||
head_tracker_reader: &HeadTrackerReader,
|
||||
) -> KeyValueStoreOp {
|
||||
Self::make_persisted_head(genesis_block_root, head_tracker)
|
||||
Self::make_persisted_head(genesis_block_root, head_tracker_reader)
|
||||
.as_kv_store_op(BEACON_CHAIN_DB_KEY)
|
||||
}
|
||||
|
||||
@@ -1341,6 +1351,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
self.head_tracker.heads()
|
||||
}
|
||||
|
||||
/// Only used in tests.
|
||||
pub fn knows_head(&self, block_hash: &SignedBeaconBlockHash) -> bool {
|
||||
self.head_tracker.contains_head((*block_hash).into())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user