State cache tweaks (#7095)

Backport of:

- https://github.com/sigp/lighthouse/pull/7067

For:

- https://github.com/sigp/lighthouse/issues/7039


  - Prevent writing to state cache when migrating the database
- Add `state-cache-headroom` flag to control pruning
- Prune old epoch boundary states ahead of mid-epoch states
- Never prune head block's state
- Avoid caching ancestor states unless they are on an epoch boundary
- Log when states enter/exit the cache

Co-authored-by: Eitan Seri-Levi <eserilev@ucsc.edu>
This commit is contained in:
Michael Sproul
2025-03-18 13:10:21 +11:00
committed by GitHub
parent 8ce9edc584
commit 4de062626b
29 changed files with 358 additions and 114 deletions

View File

@@ -126,8 +126,11 @@ pub fn get_attestation_performance<T: BeaconChainTypes>(
// Load state for block replay.
let state_root = prior_block.state_root();
// This branch is reached from the HTTP API. We assume the user wants
// to cache states so that future calls are faster.
let state = chain
.get_state(&state_root, Some(prior_slot))
.get_state(&state_root, Some(prior_slot), true)
.and_then(|maybe_state| maybe_state.ok_or(BeaconChainError::MissingBeaconState(state_root)))
.map_err(unhandled_error)?;

View File

@@ -285,8 +285,10 @@ pub fn get_block_packing_efficiency<T: BeaconChainTypes>(
// Load state for block replay.
let starting_state_root = first_block.state_root();
// This branch is reached from the HTTP API. We assume the user wants
// to cache states so that future calls are faster.
let starting_state = chain
.get_state(&starting_state_root, Some(prior_slot))
.get_state(&starting_state_root, Some(prior_slot), true)
.and_then(|maybe_state| {
maybe_state.ok_or(BeaconChainError::MissingBeaconState(starting_state_root))
})

View File

@@ -43,8 +43,10 @@ pub fn get_block_rewards<T: BeaconChainTypes>(
.map_err(unhandled_error)?
.ok_or_else(|| custom_bad_request(format!("prior state at slot {} unknown", prior_slot)))?;
// This branch is reached from the HTTP API. We assume the user wants
// to cache states so that future calls are faster.
let mut state = chain
.get_state(&state_root, Some(prior_slot))
.get_state(&state_root, Some(prior_slot), true)
.and_then(|maybe_state| maybe_state.ok_or(BeaconChainError::MissingBeaconState(state_root)))
.map_err(unhandled_error)?;
@@ -133,8 +135,10 @@ pub fn compute_block_rewards<T: BeaconChainTypes>(
))
})?;
// This branch is reached from the HTTP API. We assume the user wants
// to cache states so that future calls are faster.
let parent_state = chain
.get_state(&parent_block.state_root(), Some(parent_block.slot()))
.get_state(&parent_block.state_root(), Some(parent_block.slot()), true)
.map_err(unhandled_error)?
.ok_or_else(|| {
custom_bad_request(format!(

View File

@@ -189,8 +189,10 @@ impl StateId {
_ => (self.root(chain)?, None),
};
// This branch is reached from the HTTP API. We assume the user wants
// to cache states so that future calls are faster.
let state = chain
.get_state(&state_root, slot_opt)
.get_state(&state_root, slot_opt, true)
.map_err(warp_utils::reject::unhandled_error)
.and_then(|opt| {
opt.ok_or_else(|| {

View File

@@ -58,8 +58,10 @@ pub fn get_state_before_applying_block<T: BeaconChainTypes>(
})
.map_err(|e| custom_not_found(format!("Parent block is not available! {:?}", e)))?;
// We are about to apply a new block to the chain. It's parent state
// is a useful/recent state, we elect to cache it.
let parent_state = chain
.get_state(&parent_block.state_root(), Some(parent_block.slot()))
.get_state(&parent_block.state_root(), Some(parent_block.slot()), true)
.and_then(|maybe_state| {
maybe_state
.ok_or_else(|| BeaconChainError::MissingBeaconState(parent_block.state_root()))