Skip to content

research: end-to-end eager-attesting gap (head events not driving sign_attestations) #986

@shane-moore

Description

@shane-moore

Issue Addressed

Follow-up to #806 — the unresolved part of comment-3857920948
(#806 (comment)).
On a closer look the gap is broader than that comment described, so
filing it end-to-end.

This is a research ticket for someone to confirm the gap, validate
feasibility, and either spin out a follow-up implementation issue/PR
or document why we shouldn't do it.

Background

Lighthouse 8.1.0 (sigp/lighthouse#7892)
introduced "earlier attestation broadcasting": the validator
client's AttestationService races a beacon-node SSE head event
against the 1/3-slot timer and calls sign_attestations on
whichever fires first. Anchor's Lighthouse pin (4b3a9d3) includes
this code, but on Anchor it's compiled in and dormant.

Gap

There are three coupled reasons eager attesting doesn't reach the
wire on Anchor today.

First, Anchor never opts into the LH head-monitor wiring. In
anchor/client/src/lib.rs, BeaconNodeFallback is constructed
without set_head_send(...) and AttestationServiceBuilder
without head_monitor_rx(...). Both default to None upstream,
which means the SSE polling task is never spawned and the
eager-attest race in validator_services/src/attestation_service.rs
short-circuits to its timer-only branch. PR #813 was a clean
dependency bump and didn't pick up the small wiring patch LH 8.1.0
added in its own VC binary.

Second, MetadataService's Phase 2 — the step that produces
VotingContext from a fresh attestation_data fetch — runs on a
fixed 1/3-slot timer in anchor/validator_store/src/metadata_service.rs.
There is no head-event subscription anywhere in the metadata service.

Third, the two are intertwined. Even if the LH side were wired,
Anchor's sign_committee_attestations in
anchor/validator_store/src/lib.rs blocks on get_voting_context(slot)
before any signing work, and that watch channel is filled only by
Phase 2 at t ≈ 4 s. Fixing the LH side alone, or the MetadataService
side alone, doesn't move attestation publishing earlier.

Target behaviour

The eager-attest path should be live end-to-end. On a head event at
t < 1/3 slot, the LH AttestationService should fire
sign_attestations early — which means activating the head monitor
in anchor/client/src/lib.rs (mirroring LH's own VC wiring), likely
behind a --disable-beacon-head-monitor flag matching LH 8.1.0. At
the same time, MetadataService Phase 2 should produce VotingContext
from the same head event (falling back to the existing 1/3-slot
timer if no event arrives), so the watch channel is ready when
sign_committee_attestations reaches get_voting_context. With
both in place, Anchor's QBFT consensus and signing begin immediately
on a head event instead of at t = 4 s.

The pattern to mirror lives in LH at
validator_services/src/attestation_service.rs:186-193.

Why it matters

Spec-compliant attestation timing is the benefit LH 8.1.0 already
delivers for solo stakers. On SSV, QBFT round-trips sit on top of
LH's signing path, so any pre-QBFT delay compounds — operator
inclusion-distance scores on ssv.network depend on early publishing.

References

Metadata

Metadata

Assignees

Labels

clientresearchAnything with unclear path forward and likely needing Go-SSV involvement

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions