Skip to content

Gloas: add an endpoint to retrieve the PTC (Payload Timeliness Committee) for a slot #623

Description

@iurii-ssv

Problem

In Gloas, on-chain PTC votes are recorded in block bodies as PayloadAttestation aggregates whose aggregation_bits: Bitvector[PTC_SIZE] are indexed by the PTC ordering — the proposer constructs them "with respect to the PTC that is obtained from get_ptc(state, Slot(block_slot - 1))" (validator.md).

No API surface exposes that ordering — and none would expose PTC membership to observers either, once the duties endpoint rework lands:

  • The current duties endpoint (POST /eth/v1/validator/duties/ptc/{epoch}, Standardized Epbs Beacon Api #552) returns membership for the requested validators only, with no position information (unlike AttesterDuty.validator_committee_index).
  • Update to handle non canonical ptc duties #619 replaces it with a per-slot GET returning {data, validator_indices} for validators the beacon node tracks — the right call for the VC flow (duties must exist per branch), but it removes the last way to query PTC membership in advance, historically, or for arbitrary validators.
  • GET /eth/v1/beacon/pool/payload_attestations (Standardized Epbs Beacon Api #552) exposes individual messages, but the pool is ephemeral — it cannot answer historical questions, while the durable on-chain record (the aggregates) is exactly what cannot be interpreted.
  • Both analogous on-chain participation bitfields have ordering endpoints today: attestation aggregation_bitsGET /eth/v1/beacon/states/{state_id}/committees, and sync_aggregate.sync_committee_bitsGET /eth/v1/beacon/states/{state_id}/sync_committees. The PTC is the one participation bitfield without one.

As a result, an external observer (staking operators' monitoring, block explorers, analytics, PTC-liveness research) cannot attribute on-chain payload attestations to validators — i.e. per-validator PTC participation cannot be computed the way attestation and sync participation are computed today.

Note that a position field on the duty object alone would not suffice: compute_ptc returns the committee "with possible duplicates", so one validator can hold several seats (bits). Sync committees share this property, and sync_committees solves it by returning the full ordered list.

Proposal

Mirror the existing committee endpoints:

GET /eth/v1/beacon/states/{state_id}/ptc?slot={slot}
  • slot optional, defaulting to the state's slot; must be within the range computable from the requested state (same semantics as committees?slot=).
  • data.validators: exactly PTC_SIZE validator indices, in get_ptc(state, slot) order, duplicates preserved.
{
  "execution_optimistic": false,
  "finalized": false,
  "data": { "validators": ["1021", "994", "1021", "..."] }
}

Serving cost is minimal for recent slots: state.ptc_window already caches the PTC for (2 + MIN_SEED_LOOKAHEAD) * SLOTS_PER_EPOCH slots, so this is a cache read; historical slots can be served from historical states exactly like /committees. And because it is state-scoped, it composes with the non-canonical-branch concern motivating #619: the PTC for a branch is queryable via that branch's state.

Alternative considered

A positions array on the duty object would be a smaller change, but it only helps callers that already know which validators to ask about, cannot answer historical queries, and #619's direction (BN-tracked validators, in-slot fetch) moves the duties endpoint further away from being an observer surface. Happy to go either way — and happy to follow up with the spec PR once there's agreement on the shape.

References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Gloasapi's needed in Gloas fork.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions