Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manual finalization endpoint #7059

Merged

Conversation

eserilev
Copy link
Collaborator

Introduce a new lighthouse endpoint that allows a user to force a manual finalization. This migrates data to the freezer db and prunes sidechains which may help reduce disk space issues on holesky at the moment.

@eserilev eserilev requested a review from jxs as a code owner February 28, 2025 19:45
@michaelsproul michaelsproul added the v7.0.0-beta.2 Second hacky Holesky rescue release label Feb 28, 2025
@eserilev
Copy link
Collaborator Author

eserilev commented Mar 1, 2025

one quick and dirty thing we might be able to try

// add some for loop here so we only fetch at most one state per roots iterator
for {
    let state_roots = RootsIterator::new(&store, finalized_state)
        .take_while(|result| match result {
            Ok((_, _, slot)) => *slot >= current_split_slot,
            Err(_) => true,
        })
        .collect::<Result<Vec<_>, _>>()?;
    // do the hot db -> cold db migration + pruning
 }

@michaelsproul
Copy link
Member

I think the RootsIterator is already inside a loop, so there should only be one at a time:

for (head_hash, head_slot) in heads {
// Load head block. If it fails with a decode error, it's likely a reverted block,
// so delete it from the head tracker but leave it and its states in the database
// This is suboptimal as it wastes disk space, but it's difficult to fix. A re-sync
// can be used to reclaim the space.
let head_state_root = match store.get_blinded_block(&head_hash) {
Ok(Some(block)) => block.state_root(),
Ok(None) => {
return Err(BeaconStateError::MissingBeaconBlock(head_hash.into()).into())
}
Err(Error::SszDecodeError(e)) => {
warn!(
log,
"Forgetting invalid head block";
"block_root" => ?head_hash,
"error" => ?e,
);
abandoned_heads.insert(head_hash);
continue;
}
Err(e) => return Err(e.into()),
};
let mut potentially_abandoned_head = Some(head_hash);
let mut potentially_abandoned_blocks = vec![];
// Iterate backwards from this head, staging blocks and states for deletion.
let iter = std::iter::once(Ok((head_hash, head_state_root, head_slot)))
.chain(RootsIterator::from_block(&store, head_hash)?);

Similarly the RootsIterator itself jumps back over states one at a time too.

The only thing I can think is that we're putting these states in the cache, and that's enough to cause an OOM with --state-cache-size 32

@@ -190,6 +198,10 @@ impl<E: EthSpec, Hot: ItemStore<E>, Cold: ItemStore<E>> BackgroundMigrator<E, Ho
Ok(())
}

pub fn process_manual_finalization(&self, notif: ManualFinalizationNotification) {
let _ = self.send_background_notification(Notification::ManualFinalization(notif));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we ever run store migrator in the foreground other than testing, but probably should support it given we do it for all 3 other notifications, and if we want to test this with BeaconChainHarness, it won't be immediately obvious why this doesn't get run.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. We should do this for the clean version of this PR

@michaelsproul michaelsproul merged commit 8f43cb9 into sigp:holesky-rescue Mar 3, 2025
16 of 29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
v7.0.0-beta.2 Second hacky Holesky rescue release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants