ChainSafe / ChainSafe/lodestar

getPoolAttestationsV2 omits unaggregated attestations — only exposes aggregatedAttestationPool

Open
#9,677 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
1.4k
Forks
483
Avg merge
1d 16h
Merged PRs (30d)
150

Description

Spun out from #9669 (per @markolazic01's [suggestion](https://github.com/ChainSafe/lodestar/issues/9669#issuecomment-5008095649)) so it isn't overlooked when the 500-vs-empty-array fix there lands.

## Summary

`GET /eth/v2/beacon/pool/attestations` only exposes `chain.aggregatedAttestationPool`, never `chain.attestationPool`. Aggregates are populated from `beacon_aggregate_and_proof` gossip at ~2/3 into the slot (~8s), so the endpoint reports an empty list for the first ~8s of every slot — even for slots the node has already seen unaggregated attestations for.

## Detail

The spec describes the endpoint as *"Retrieves attestations known by the node but not necessarily incorporated into any block."*

- The GET handler reads only the aggregated pool: `chain.aggregatedAttestationPool.getAll(slot)` — `packages/beacon-node/src/api/impl/beacon/pool/index.ts:41`.
- Unaggregated attestations arriving on `beacon_attestation_{subnet}` at ~4s go to a separate pool, `chain.attestationPool` (`chain/interface.ts:122`), which has its own `getAll(bySlot)` (`chain/opPools/attestationPool.ts:200`) that the API never calls.
- That pool is itself gated on `aggregatorTracker.shouldAggregate(subnet, slot)` before insert — on the gossip path (`network/processor/gossipHandlers.ts:1343`) and on the API submit path (`api/impl/beacon/pool/index.ts:102`). So it is a pre-aggregation buffer, not a general "everything the node has seen" pool.

## Consequence

Fixing the 500 in #9669 removes the error, but the endpoint still returns `data: []` for the first ~8s of every slot. This is the underlying reason the Vouch hot-standby use case described in #9669 fails — its primary-detection check at +5s lands inside the empty window — rather than the 500 itself.

## Decision needed

Whether returning only aggregated attestations matches the intended semantics of *"attestations known by the node"*. If not, options include surfacing `chain.attestationPool` alongside the aggregated pool and/or documenting the aggregated-only behavior explicitly.

Note: because of the `shouldAggregate` gating, even exposing `attestationPool` would surface only attestations in subnets the node is aggregating for that slot — not *every* seen attestation — so fully satisfying "known by the node" may need a broader buffer. Worth settling the intended contract first.

Related: #9669 (the 500-vs-empty-array bug this was split from).

🤖 Generated with AI assistance

Contributor guide

Open the contributing guide

Research direction

Read packages/beacon-node/src/api/impl/beacon/pool/index.ts, chain/interface.ts, chain/opPools/attestationPool.ts, and network/processor/gossipHandlers.ts to trace the endpoint and pool behavior. Review related issue #9669 and settle the intended contract for “attestations known by the node.” Done means the chosen behavior is implemented or the aggregated-only behavior is explicitly documented.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.