diff --git a/fork_choice_control/src/mutator.rs b/fork_choice_control/src/mutator.rs index db066f5b..9a448d98 100644 --- a/fork_choice_control/src/mutator.rs +++ b/fork_choice_control/src/mutator.rs @@ -441,7 +441,7 @@ where if self.store.is_forward_synced() && misc::slots_since_epoch_start::
(tick.slot) == 0 { if tick.kind == TickKind::AttestFourth { - self.prune_old_blob_sidecars()?; + self.prune_old_records()?; } if let Some(metrics) = self.metrics.as_ref() { @@ -2336,27 +2336,50 @@ where Ok(()) } - fn prune_old_blob_sidecars(&self) -> Result<()> { + fn prune_old_records(&self) -> Result<()> { let storage = self.storage.clone_arc(); - let current_epoch = misc::compute_epoch_at_slot::
(self.store.slot()); - let up_to_epoch = current_epoch.saturating_sub( - self.store - .chain_config() - .min_epochs_for_blob_sidecars_requests, - ); - let up_to_slot = misc::compute_start_slot_at_epoch::
(up_to_epoch); + let blobs_up_to_epoch = self.store.min_checked_data_availability_epoch(); + let blobs_up_to_slot = misc::compute_start_slot_at_epoch::
(blobs_up_to_epoch); + let blocks_up_to_epoch = self.store.min_checked_block_availability_epoch(); + let blocks_up_to_slot = misc::compute_start_slot_at_epoch::
(blocks_up_to_epoch);
Builder::new()
- .name("old-blob-pruner".to_owned())
+ .name("old-data-pruner".to_owned())
.spawn(move || {
- debug!("pruning old blob sidecards from storage up to slot {up_to_slot}…");
+ debug!("pruning old blob sidecars from storage up to slot {blobs_up_to_slot}…");
+
+ match storage.prune_old_blob_sidecars(blobs_up_to_slot) {
+ Ok(()) => {
+ debug!(
+ "pruned old blob sidecars from storage up to slot {blobs_up_to_slot}"
+ );
+ }
+ Err(error) => {
+ error!("pruning old blob sidecars from storage failed: {error:?}")
+ }
+ }
+
+ debug!("pruning old blocks and states from storage up to slot {blocks_up_to_slot}…");
+
+ match storage.prune_old_blocks_and_states(blocks_up_to_slot) {
+ Ok(()) => {
+ debug!(
+ "pruned old blocks and states from storage up to slot {blocks_up_to_slot}"
+ );
+ }
+ Err(error) => {
+ error!("pruning old blocks and states from storage failed: {error:?}")
+ }
+ }
+
+ debug!("pruning old state roots from storage up to slot {blocks_up_to_slot}…");
- match storage.prune_old_blob_sidecars(up_to_slot) {
+ match storage.prune_old_state_roots(blocks_up_to_slot) {
Ok(()) => {
- debug!("pruned old blob sidecards from storage up to slot {up_to_slot}");
+ debug!("pruned old state roots from storage up to slot {blocks_up_to_slot}");
}
Err(error) => {
- error!("pruning old blob sidecards from storage failed: {error:?}")
+ error!("pruning old state roots from storage failed: {error:?}")
}
}
})?;
diff --git a/fork_choice_control/src/queries.rs b/fork_choice_control/src/queries.rs
index 1b35ef28..bac7e082 100644
--- a/fork_choice_control/src/queries.rs
+++ b/fork_choice_control/src/queries.rs
@@ -554,6 +554,14 @@ where
storage: self.storage(),
}
}
+
+ pub fn min_checked_block_availability_epoch(&self) -> Epoch {
+ self.store_snapshot().min_checked_block_availability_epoch()
+ }
+
+ pub fn min_checked_data_availability_epoch(&self) -> Epoch {
+ self.store_snapshot().min_checked_data_availability_epoch()
+ }
}
#[cfg(test)]
diff --git a/fork_choice_control/src/storage.rs b/fork_choice_control/src/storage.rs
index f4a0c947..3fbf78ab 100644
--- a/fork_choice_control/src/storage.rs
+++ b/fork_choice_control/src/storage.rs
@@ -397,6 +397,71 @@ impl {
Ok(())
}
+ pub(crate) fn prune_old_blocks_and_states(&self, up_to_slot: Slot) -> Result<()> {
+ let mut block_roots_to_remove = vec![];
+ let mut keys_to_remove = vec![];
+
+ let results = self
+ .database
+ .iterator_descending(..=BlockRootBySlot(up_to_slot.saturating_sub(1)).to_string())?;
+
+ for result in results {
+ let (key_bytes, value_bytes) = result?;
+
+ if !BlockRootBySlot::has_prefix(&key_bytes) {
+ break;
+ }
+
+ block_roots_to_remove.push(H256::from_ssz_default(value_bytes)?);
+ keys_to_remove.push(key_bytes.into_owned());
+ }
+
+ for block_root in block_roots_to_remove {
+ let key = FinalizedBlockByRoot(block_root).to_string();
+ self.database.delete(key)?;
+
+ let key = UnfinalizedBlockByRoot(block_root).to_string();
+ self.database.delete(key)?;
+
+ let key = StateByBlockRoot(block_root).to_string();
+ self.database.delete(key)?;
+ }
+
+ for key in keys_to_remove {
+ self.database.delete(key)?;
+ }
+
+ Ok(())
+ }
+
+ pub(crate) fn prune_old_state_roots(&self, up_to_slot: Slot) -> Result<()> {
+ let mut keys_to_remove = vec![];
+
+ let results = self
+ .database
+ .iterator_ascending(SlotByStateRoot(H256::zero()).to_string()..)?;
+
+ for result in results {
+ let (key_bytes, value_bytes) = result?;
+
+ if !SlotByStateRoot::has_prefix(&key_bytes) {
+ break;
+ }
+
+ let slot = Slot::from_ssz_default(value_bytes)?;
+
+ if slot < up_to_slot {
+ keys_to_remove.push(key_bytes.into_owned());
+ }
+ }
+
+ for key in keys_to_remove {
+ self.database.delete(key)?;
+ }
+
+ Ok(())
+ }
+
pub(crate) fn checkpoint_state_slot(&self) -> Result