From 62f80ad987190b3ac63a180e08eba82f86eb5f10 Mon Sep 17 00:00:00 2001 From: lodekeeper Date: Sun, 15 Mar 2026 12:25:09 +0000 Subject: [PATCH] feat: attestation index=1 requires FULL variant (consensus-specs#4918) Attestation with index=1 (full node) now requires the FULL variant to exist in the proto-array. Throws UNKNOWN_PAYLOAD_STATUS if payload has not been seen. --- packages/fork-choice/src/forkChoice/errors.ts | 7 ++++++- .../fork-choice/src/forkChoice/forkChoice.ts | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/fork-choice/src/forkChoice/errors.ts b/packages/fork-choice/src/forkChoice/errors.ts index c79309b17547..f97df72bf087 100644 --- a/packages/fork-choice/src/forkChoice/errors.ts +++ b/packages/fork-choice/src/forkChoice/errors.ts @@ -57,6 +57,10 @@ export enum InvalidAttestationCode { * The attestation data index is invalid for a Gloas block (must be 0 or 1). */ INVALID_DATA_INDEX = "INVALID_DATA_INDEX", + /** + * Attestation index=1 (full node) but the payload is not known/available. + */ + UNKNOWN_PAYLOAD_STATUS = "UNKNOWN_PAYLOAD_STATUS", } export type InvalidAttestation = @@ -69,7 +73,8 @@ export type InvalidAttestation = | {code: InvalidAttestationCode.INVALID_TARGET; attestation: RootHex; local: RootHex} | {code: InvalidAttestationCode.ATTESTS_TO_FUTURE_BLOCK; block: Slot; attestation: Slot} | {code: InvalidAttestationCode.FUTURE_SLOT; attestationSlot: Slot; latestPermissibleSlot: Slot} - | {code: InvalidAttestationCode.INVALID_DATA_INDEX; index: number}; + | {code: InvalidAttestationCode.INVALID_DATA_INDEX; index: number} + | {code: InvalidAttestationCode.UNKNOWN_PAYLOAD_STATUS; beaconBlockRoot: RootHex}; export enum ForkChoiceErrorCode { INVALID_ATTESTATION = "FORKCHOICE_ERROR_INVALID_ATTESTATION", diff --git a/packages/fork-choice/src/forkChoice/forkChoice.ts b/packages/fork-choice/src/forkChoice/forkChoice.ts index 2d0cef22540c..a54173709201 100644 --- a/packages/fork-choice/src/forkChoice/forkChoice.ts +++ b/packages/fork-choice/src/forkChoice/forkChoice.ts @@ -1673,6 +1673,22 @@ export class ForkChoice implements IForkChoice { }); } + // [New in Gloas:EIP7732] + // If attesting for a full node (index=1), the payload must be known (locally available) + // Spec: gloas/fork-choice.md#modified-validate_on_attestation + if (isGloasBlock(block) && attestationData.index === 1) { + const fullVariant = this.protoArray.getNodeIndexByRootAndStatus(beaconBlockRootHex, PayloadStatus.FULL); + if (fullVariant === undefined) { + throw new ForkChoiceError({ + code: ForkChoiceErrorCode.INVALID_ATTESTATION, + err: { + code: InvalidAttestationCode.UNKNOWN_PAYLOAD_STATUS, + beaconBlockRoot: beaconBlockRootHex, + }, + }); + } + } + this.validatedAttestationDatas.add(attDataRoot); }