Gloas payload bid consensus (#8801)

- [x] Consensus changes for execution payload bids
- [x] EF tests for bids (and `block_header` -- no changes required).


Co-Authored-By: Michael Sproul <michael@sigmaprime.io>
This commit is contained in:
Michael Sproul
2026-02-12 15:26:23 +11:00
committed by GitHub
parent 711971f269
commit b8072c5b77
10 changed files with 358 additions and 18 deletions

View File

@@ -9,11 +9,12 @@ use tree_hash::TreeHash;
use typenum::Unsigned;
use types::{
AbstractExecPayload, AttesterSlashingRef, BeaconBlockRef, BeaconState, BeaconStateError,
ChainSpec, DepositData, Domain, Epoch, EthSpec, Fork, Hash256, InconsistentFork,
BuilderIndex, ChainSpec, DepositData, Domain, Epoch, EthSpec, Fork, Hash256, InconsistentFork,
IndexedAttestation, IndexedAttestationRef, ProposerSlashing, SignedAggregateAndProof,
SignedBeaconBlock, SignedBeaconBlockHeader, SignedBlsToExecutionChange,
SignedContributionAndProof, SignedRoot, SignedVoluntaryExit, SigningData, Slot, SyncAggregate,
SyncAggregatorSelectionData,
SignedContributionAndProof, SignedExecutionPayloadBid, SignedRoot, SignedVoluntaryExit,
SigningData, Slot, SyncAggregate, SyncAggregatorSelectionData,
consts::gloas::BUILDER_INDEX_SELF_BUILD,
};
pub type Result<T> = std::result::Result<T, Error>;
@@ -28,6 +29,9 @@ pub enum Error {
/// Attempted to find the public key of a validator that does not exist. You cannot distinguish
/// between an error and an invalid block in this case.
ValidatorUnknown(u64),
/// Attempted to find the public key of a builder that does not exist. You cannot distinguish
/// between an error and an invalid block in this case.
BuilderUnknown(BuilderIndex),
/// Attempted to find the public key of a validator that does not exist. You cannot distinguish
/// between an error and an invalid block in this case.
ValidatorPubkeyUnknown(PublicKeyBytes),
@@ -53,7 +57,7 @@ impl From<BeaconStateError> for Error {
}
}
/// Helper function to get a public key from a `state`.
/// Helper function to get a validator public key from a `state`.
pub fn get_pubkey_from_state<E>(
state: &BeaconState<E>,
validator_index: usize,
@@ -71,6 +75,25 @@ where
.map(Cow::Owned)
}
/// Helper function to get a builder public key from a `state`.
pub fn get_builder_pubkey_from_state<E>(
state: &BeaconState<E>,
builder_index: BuilderIndex,
) -> Option<Cow<'_, PublicKey>>
where
E: EthSpec,
{
state
.builders()
.ok()?
.get(builder_index as usize)
.and_then(|b| {
let pk: Option<PublicKey> = b.pubkey.decompress().ok();
pk
})
.map(Cow::Owned)
}
/// A signature set that is valid if a block was signed by the expected block producer.
pub fn block_proposal_signature_set<'a, E, F, Payload: AbstractExecPayload<E>>(
state: &'a BeaconState<E>,
@@ -332,6 +355,41 @@ where
Ok(SignatureSet::multiple_pubkeys(signature, pubkeys, message))
}
pub fn execution_payload_bid_signature_set<'a, E, F>(
state: &'a BeaconState<E>,
get_builder_pubkey: F,
signed_execution_payload_bid: &'a SignedExecutionPayloadBid<E>,
spec: &'a ChainSpec,
) -> Result<Option<SignatureSet<'a>>>
where
E: EthSpec,
F: Fn(BuilderIndex) -> Option<Cow<'a, PublicKey>>,
{
let execution_payload_bid = &signed_execution_payload_bid.message;
let builder_index = execution_payload_bid.builder_index;
if builder_index == BUILDER_INDEX_SELF_BUILD {
// No signatures to verify in case of a self-build, but consensus code MUST check that
// the signature is the point at infinity.
// See `process_execution_payload_bid`.
return Ok(None);
}
let domain = spec.get_domain(
state.current_epoch(),
Domain::BeaconBuilder,
&state.fork(),
state.genesis_validators_root(),
);
let pubkey = get_builder_pubkey(builder_index).ok_or(Error::BuilderUnknown(builder_index))?;
let message = execution_payload_bid.signing_root(domain);
Ok(Some(SignatureSet::single_pubkey(
&signed_execution_payload_bid.signature,
pubkey,
message,
)))
}
/// Returns the signature set for the given `attester_slashing` and corresponding `pubkeys`.
pub fn attester_slashing_signature_sets<'a, E, F>(
state: &'a BeaconState<E>,