Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/beacon-node/src/chain/errors/attestationError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -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<AttestationErrorType> {
getMetadata(): Record<string, string | number | null> {
Expand Down
13 changes: 13 additions & 0 deletions packages/beacon-node/src/chain/validation/aggregateAndProof.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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))) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Retry API aggregates after payload envelope arrives

This new IGNORE branch introduces the same failure mode for publishAggregateAndProofsV2: index-1 aggregates now error out when the block is present but payload envelope import has not completed, yet the API retry path only handles unknown block roots and does not retry on EXECUTION_PAYLOAD_NOT_SEEN. As a result, valid aggregates from external/fallback beacon nodes can be rejected instead of being processed after envelope retrieval.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like both of these codex messages are saying that our queuing needs to handle these failed attestations / aggregates

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is out of the scope of this PR. Tracking this issue at #9224

throw new AttestationError(GossipAction.IGNORE, {
code: AttestationErrorCode.EXECUTION_PAYLOAD_NOT_SEEN,
Comment thread
ensi321 marked this conversation as resolved.
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) {
Expand Down
13 changes: 13 additions & 0 deletions packages/beacon-node/src/chain/validation/attestation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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))) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Retry API attestation after payload envelope arrives

Throwing EXECUTION_PAYLOAD_NOT_SEEN here causes submitPoolAttestationsV2 to fail index-1 submissions whenever the block is known but the payload envelope is still in flight, because its retry helper only catches UNKNOWN_OR_PREFINALIZED_BEACON_BLOCK_ROOT (validateGossipFnRetryUnknownRoot in network/processor/gossipHandlers.ts) and only waits for block availability. In fallback/DVT setups (multiple beacon nodes), this creates a regression where valid attestations are dropped instead of being retried once the envelope is imported.

Useful? React with 👍 / 👎.

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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading