diff --git a/packages/beacon-node/src/chain/errors/attestationError.ts b/packages/beacon-node/src/chain/errors/attestationError.ts index f904721c58d0..94cfde56b852 100644 --- a/packages/beacon-node/src/chain/errors/attestationError.ts +++ b/packages/beacon-node/src/chain/errors/attestationError.ts @@ -147,6 +147,10 @@ export enum AttestationErrorCode { * Gloas: Current slot attestation is marking payload as present */ PREMATURELY_INDICATED_PAYLOAD_PRESENT = "ATTESTATION_ERROR_PREMATURELY_INDICATED_PAYLOAD_PRESENT", + /** + * Gloas: index-1 attestation but the execution payload has not been seen yet + */ + EXECUTION_PAYLOAD_NOT_SEEN = "ATTESTATION_ERROR_EXECUTION_PAYLOAD_NOT_SEEN", } export type AttestationErrorType = @@ -185,7 +189,8 @@ export type AttestationErrorType = | {code: AttestationErrorCode.NON_ZERO_ATTESTATION_DATA_INDEX} | {code: AttestationErrorCode.ATTESTER_NOT_IN_COMMITTEE} | {code: AttestationErrorCode.INVALID_PAYLOAD_STATUS_VALUE; attDataIndex: number} - | {code: AttestationErrorCode.PREMATURELY_INDICATED_PAYLOAD_PRESENT}; + | {code: AttestationErrorCode.PREMATURELY_INDICATED_PAYLOAD_PRESENT} + | {code: AttestationErrorCode.EXECUTION_PAYLOAD_NOT_SEEN; beaconBlockRoot: RootHex}; export class AttestationError extends GossipActionError { getMetadata(): Record { diff --git a/packages/beacon-node/src/chain/validation/aggregateAndProof.ts b/packages/beacon-node/src/chain/validation/aggregateAndProof.ts index 6956e62ed392..25cb272cb8fa 100644 --- a/packages/beacon-node/src/chain/validation/aggregateAndProof.ts +++ b/packages/beacon-node/src/chain/validation/aggregateAndProof.ts @@ -90,6 +90,19 @@ async function validateAggregateAndProof( }); } + // [REJECT] If `aggregate.data.index == 1` (payload present for a past + // block), the execution payload for `block` passes validation. + // [IGNORE] When `aggregate.data.index == 1` (payload present for a past block), + // the corresponding execution payload for `block` has been seen (a client MAY queue + // attestations for processing once the payload is retrieved and SHOULD request the + // payload envelope via `ExecutionPayloadEnvelopesByRoot`). + if (block !== null && attData.index === 1 && !chain.seenPayloadEnvelope(toRootHex(attData.beaconBlockRoot))) { + throw new AttestationError(GossipAction.IGNORE, { + code: AttestationErrorCode.EXECUTION_PAYLOAD_NOT_SEEN, + beaconBlockRoot: toRootHex(attData.beaconBlockRoot), + }); + } + // [REJECT] len(committee_indices) == 1, where committee_indices = get_committee_indices(aggregate) committeeIndex = (aggregate as electra.Attestation).committeeBits.getSingleTrueBit(); if (committeeIndex === null) { diff --git a/packages/beacon-node/src/chain/validation/attestation.ts b/packages/beacon-node/src/chain/validation/attestation.ts index d410469ed1c6..f3b7b8863f57 100644 --- a/packages/beacon-node/src/chain/validation/attestation.ts +++ b/packages/beacon-node/src/chain/validation/attestation.ts @@ -315,6 +315,19 @@ async function validateAttestationNoSignatureCheck( code: AttestationErrorCode.PREMATURELY_INDICATED_PAYLOAD_PRESENT, }); } + + // [REJECT] If `attestation.data.index == 1` (payload present for a past + // block), the execution payload for `block` passes validation. + // [IGNORE] When `attestation.data.index == 1` (payload present for a past block), + // the corresponding execution payload for `block` has been seen (a client MAY queue + // attestations for processing once the payload is retrieved and SHOULD request the + // payload envelope via `ExecutionPayloadEnvelopesByRoot`). + if (block !== null && attData.index === 1 && !chain.seenPayloadEnvelope(toRootHex(attData.beaconBlockRoot))) { + throw new AttestationError(GossipAction.IGNORE, { + code: AttestationErrorCode.EXECUTION_PAYLOAD_NOT_SEEN, + beaconBlockRoot: toRootHex(attData.beaconBlockRoot), + }); + } } else { // [REJECT] attestation.data.index == 0 if (attData.index !== 0) { diff --git a/packages/beacon-node/src/chain/validation/executionPayloadEnvelope.ts b/packages/beacon-node/src/chain/validation/executionPayloadEnvelope.ts index b9cec7f702f7..a4334ef71621 100644 --- a/packages/beacon-node/src/chain/validation/executionPayloadEnvelope.ts +++ b/packages/beacon-node/src/chain/validation/executionPayloadEnvelope.ts @@ -32,7 +32,7 @@ async function validateExecutionPayloadEnvelope( const {payload} = envelope; const blockRootHex = toRootHex(envelope.beaconBlockRoot); - // [IGNORE] The envelope's block root `envelope.block_root` has been seen (via + // [IGNORE] The envelope's block root `envelope.beacon_block_root` has been seen (via // gossip or non-gossip sources) (a client MAY queue payload for processing once // the block is retrieved). // TODO GLOAS: Need to review this, we should queue the envelope for later