Use correct Fork in verify_header_signature (#8528)

Fix a bug in `verify_header_signature` which tripped up some Lighthouse nodes at the Fusaka fork. The bug was a latent bug in a function that has been present for a long time, but only used by slashers. With Fulu it entered the critical path of blob/column verification -- call stack:

- `FetchBlobsBeaconAdapter::process_engine_blobs`
- `BeaconChain::process_engine_blobs`
- `BeaconChain::check_engine_blobs_availability_and_import`
- `BeaconChain::check_blob_header_signature_and_slashability`
- `verify_header_signature`

Thanks @eserilev for quickly diagnosing the root cause.


  Change `verify_header_signature` to use `ChainSpec::fork_at_epoch` to compute the `Fork`, rather than using the head state's fork. At a fork boundary the head state's fork is stale and lacks the data for the new fork. Using `fork_at_epoch` ensures that we use the correct fork data and validate transition block's signature correctly.


Co-Authored-By: Michael Sproul <michael@sigmaprime.io>
This commit is contained in:
Michael Sproul
2025-12-04 20:56:48 +11:00
committed by GitHub
parent ced49dd265
commit 094c36db97
2 changed files with 97 additions and 2 deletions

View File

@@ -2122,11 +2122,13 @@ pub fn verify_header_signature<T: BeaconChainTypes, Err: BlockBlobError>(
.get(header.message.proposer_index as usize)
.cloned()
.ok_or(Err::unknown_validator_error(header.message.proposer_index))?;
let head_fork = chain.canonical_head.cached_head().head_fork();
let fork = chain
.spec
.fork_at_epoch(header.message.slot.epoch(T::EthSpec::slots_per_epoch()));
if header.verify_signature::<T::EthSpec>(
&proposer_pubkey,
&head_fork,
&fork,
chain.genesis_validators_root,
&chain.spec,
) {