Block proposal optimisations (#8156)

Closes:

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

This should reduce Lighthouse's block proposal times on Holesky and prevent us getting reorged.


  - [x] Allow the head state to be advanced further than 1 slot. This lets us avoid epoch processing on hot paths including block production, by having new epoch boundaries pre-computed and available in the state cache.
- [x] Use the finalized state to prune the op pool. We were previously using the head state and trying to infer slashing/exit relevance based on `exit_epoch`. However some exit epochs are far in the future, despite occurring recently.


Co-Authored-By: Michael Sproul <michael@sigmaprime.io>
This commit is contained in:
Michael Sproul
2025-10-08 17:09:12 +11:00
committed by GitHub
parent 2a433bc406
commit 13dfa9200f
4 changed files with 53 additions and 72 deletions

View File

@@ -33,7 +33,7 @@ use types::{AttestationShufflingId, BeaconStateError, EthSpec, Hash256, Relative
///
/// This avoids doing unnecessary work whilst the node is syncing or has perhaps been put to sleep
/// for some period of time.
const MAX_ADVANCE_DISTANCE: u64 = 4;
const MAX_ADVANCE_DISTANCE: u64 = 256;
/// Similarly for fork choice: avoid the fork choice lookahead during sync.
///
@@ -49,17 +49,7 @@ enum Error {
HeadMissingFromSnapshotCache(#[allow(dead_code)] Hash256),
BeaconState(#[allow(dead_code)] BeaconStateError),
Store(#[allow(dead_code)] store::Error),
MaxDistanceExceeded {
current_slot: Slot,
head_slot: Slot,
},
StateAlreadyAdvanced {
block_root: Hash256,
},
BadStateSlot {
_state_slot: Slot,
_block_slot: Slot,
},
MaxDistanceExceeded { current_slot: Slot, head_slot: Slot },
}
impl From<BeaconChainError> for Error {
@@ -180,9 +170,6 @@ async fn state_advance_timer<T: BeaconChainTypes>(
error = ?e,
"Failed to advance head state"
),
Err(Error::StateAlreadyAdvanced { block_root }) => {
debug!(?block_root, "State already advanced on slot")
}
Err(Error::MaxDistanceExceeded {
current_slot,
head_slot,
@@ -295,25 +282,6 @@ fn advance_head<T: BeaconChainTypes>(beacon_chain: &Arc<BeaconChain<T>>) -> Resu
.get_advanced_hot_state(head_block_root, current_slot, head_block_state_root)?
.ok_or(Error::HeadMissingFromSnapshotCache(head_block_root))?;
// Protect against advancing a state more than a single slot.
//
// Advancing more than one slot without storing the intermediate state would corrupt the
// database. Future works might store intermediate states inside this function.
match state.slot().cmp(&state.latest_block_header().slot) {
std::cmp::Ordering::Equal => (),
std::cmp::Ordering::Greater => {
return Err(Error::StateAlreadyAdvanced {
block_root: head_block_root,
});
}
std::cmp::Ordering::Less => {
return Err(Error::BadStateSlot {
_block_slot: state.latest_block_header().slot,
_state_slot: state.slot(),
});
}
}
let initial_slot = state.slot();
let initial_epoch = state.current_epoch();