Gloas payload attestation consensus (#8827)

- Implement `process_payload_attestation`
- Implement EF tests for payload attestations (allows simplification of handler now that we support all `operations` tests).
- Update the `BlockSignatureVerifier` to signature-verify payload attestations


Co-Authored-By: Michael Sproul <michael@sigmaprime.io>
This commit is contained in:
Michael Sproul
2026-02-17 16:50:44 +11:00
committed by GitHub
parent eec0700f94
commit 67b9673191
14 changed files with 378 additions and 34 deletions

View File

@@ -47,8 +47,6 @@ excluded_paths = [
"bls12-381-tests/hash_to_G2",
"tests/.*/eip7732",
"tests/.*/eip7805",
# TODO(gloas): remove these ignores as more Gloas operations are implemented
"tests/.*/gloas/operations/payload_attestation/.*",
# TODO(gloas): remove these ignores as Gloas consensus is implemented
"tests/.*/gloas/fork/.*",
"tests/.*/gloas/fork_choice/.*",

View File

@@ -21,7 +21,7 @@ use state_processing::{
process_operations::{
altair_deneb, base, gloas, process_attester_slashings,
process_bls_to_execution_changes, process_deposits, process_exits,
process_proposer_slashings,
process_payload_attestation, process_proposer_slashings,
},
process_sync_aggregate, withdrawals,
},
@@ -31,8 +31,9 @@ use types::{
Attestation, AttesterSlashing, BeaconBlock, BeaconBlockBody, BeaconBlockBodyBellatrix,
BeaconBlockBodyCapella, BeaconBlockBodyDeneb, BeaconBlockBodyElectra, BeaconBlockBodyFulu,
BeaconState, BlindedPayload, ConsolidationRequest, Deposit, DepositRequest, ExecutionPayload,
ForkVersionDecode, FullPayload, ProposerSlashing, SignedBlsToExecutionChange,
SignedExecutionPayloadEnvelope, SignedVoluntaryExit, SyncAggregate, WithdrawalRequest,
ForkVersionDecode, FullPayload, PayloadAttestation, ProposerSlashing,
SignedBlsToExecutionChange, SignedExecutionPayloadEnvelope, SignedVoluntaryExit, SyncAggregate,
WithdrawalRequest,
};
#[derive(Debug, Clone, Default, Deserialize)]
@@ -667,6 +668,32 @@ impl<E: EthSpec> Operation<E> for ConsolidationRequest {
}
}
impl<E: EthSpec> Operation<E> for PayloadAttestation<E> {
type Error = BlockProcessingError;
fn handler_name() -> String {
"payload_attestation".into()
}
fn is_enabled_for_fork(fork_name: ForkName) -> bool {
fork_name.gloas_enabled()
}
fn decode(path: &Path, _fork_name: ForkName, _spec: &ChainSpec) -> Result<Self, Error> {
ssz_decode_file(path)
}
fn apply_to(
&self,
state: &mut BeaconState<E>,
spec: &ChainSpec,
_extra: &Operations<E, Self>,
) -> Result<(), BlockProcessingError> {
let mut ctxt = ConsensusContext::new(state.slot());
process_payload_attestation(state, self, 0, VerifySignatures::True, &mut ctxt, spec)
}
}
impl<E: EthSpec, O: Operation<E>> LoadCase for Operations<E, O> {
fn load_from_dir(path: &Path, fork_name: ForkName) -> Result<Self, Error> {
let spec = &testing_spec::<E>(fork_name);

View File

@@ -1177,25 +1177,6 @@ impl<E: EthSpec + TypeName, O: Operation<E>> Handler for OperationsHandler<E, O>
fn handler_name(&self) -> String {
O::handler_name()
}
fn is_enabled_for_fork(&self, fork_name: ForkName) -> bool {
Self::Case::is_enabled_for_fork(fork_name)
&& (!fork_name.gloas_enabled()
|| self.handler_name() == "attestation"
|| self.handler_name() == "attester_slashing"
|| self.handler_name() == "block_header"
|| self.handler_name() == "bls_to_execution_change"
|| self.handler_name() == "consolidation_request"
|| self.handler_name() == "deposit_request"
|| self.handler_name() == "deposit"
|| self.handler_name() == "execution_payload"
|| self.handler_name() == "execution_payload_bid"
|| self.handler_name() == "proposer_slashing"
|| self.handler_name() == "sync_aggregate"
|| self.handler_name() == "withdrawal_request"
|| self.handler_name() == "withdrawals"
|| self.handler_name() == "voluntary_exit")
}
}
#[derive(Educe)]

View File

@@ -99,6 +99,12 @@ fn operations_execution_payload_bid() {
OperationsHandler::<MainnetEthSpec, ExecutionPayloadBidBlock<_>>::default().run();
}
#[test]
fn operations_payload_attestation() {
OperationsHandler::<MinimalEthSpec, PayloadAttestation<_>>::default().run();
OperationsHandler::<MainnetEthSpec, PayloadAttestation<_>>::default().run();
}
#[test]
fn operations_withdrawals() {
OperationsHandler::<MinimalEthSpec, WithdrawalsPayload<_>>::default().run();