Skip to content

chore(deps): bump Lighthouse to unstable HEAD e58ec88fe and migrate sign_attestations to SingleAttestation #1214

Description

@shane-moore

Goal

Bump the Lighthouse pin on epbs from 81d576943 to unstable HEAD e58ec88fe and adapt Anchor so the workspace compiles and validator duties, including Gloas aggregation, work correctly against it.

Context and motivation

The 59-commit pin window contains three breaking interface changes and one behavioral one:

  1. Lighthouse #9578 reshaped the ValidatorStore attestation interface: AttestationToSign lost its generic and now carries attester_index, pubkey, committee_index, and bare AttestationData; sign_attestations now streams Vec<SingleAttestation>. Anchor's aggregation-bit plumbing (add_signature, validator_committee_index) has no counterpart in the new contract.
  2. The EIP-7688 head commit requires mirroring Lighthouse's six [patch.crates-io] git pins into Anchor's root workspace (patches only apply from the root) and adds an Attestation::Gloas variant that breaks one exhaustive match.
  3. Lighthouse #9573 added ForkName::Heze; #9580 renamed the EnrExt multiaddr accessors.
  4. EIP-7688 progressive types are serialization-compatible with their positional counterparts, but change signing-root derivation at Gloas. Anchor's aggregate decode sites branch only Base-vs-Electra; at Gloas slots they decode successfully but merkleize positionally, and the now-7688-aware beacon nodes reject the resulting SignedAggregateAndProof at publish. SIP-94 (as amended in ePBS (EIP-7732) Support ssvlabs/SIPs#94) requires decoding the aggregate as the Gloas type and computing the signing root under Gloas merkleization. The block path needs no work: decided blocks are already decoded as Gloas types, and progressive roots come with the Lighthouse types.

Suggested approach

  • Mirror Lighthouse's [patch.crates-io] entries with a sync-obligation comment; add the Heze DataVersion arms (value 9) and the EnrExt rename.
  • Migrate sign_committee_attestations to the new AttestationToSign: apply QBFT-decided mutations (root, source, target, and at Gloas the decided index) directly to data, build SingleAttestation at result assembly, retype slashing_protection_attestations.
  • Add identity consistency checks at assembly, post-collection: compare the duty's attester_index and committee_index against Anchor's own metadata; mismatches are marked non-publishable but still flow through slashing protection so every emitted signature is recorded. Do not filter before collection: the committee partial-signature batch size is declared from VotingAssignments and the collector sends only on an exact count, so pre-collection filtering stalls the committee.
  • Add two fork-aware decode helpers next to DataVersion (one for Attestation, one for AggregateAndProof) with an explicit match: Base, Electra, Gloas, and Heze fail-closed until a Heze wire shape is pinned upstream. Rewire the four aggregate decode sites through them and update the stale doc comment claiming bytes vary only Base/Electra.
  • Bind value.version to our_value.version in both aggregator data validators before decoding, mirroring the proposer duty-slot-fork check.
  • Single atomic commit for pin plus compile adaptations; decode helpers and tests may follow as separate review commits.

Acceptance criteria

  • Workspace compiles against e58ec88fe; make lint, make test (including ssv-spec fixtures), cargo check --workspace --locked, and make audit pass.
  • sign_attestations streams Vec<SingleAttestation> per committee batch; decided-index and pre-Electra index-passthrough semantics are unchanged and covered by tests.
  • An identity-mismatched duty reaches the slashing database but is absent from the returned batch, and the committee message still sends.
  • At version Gloas, decided aggregates decode as Gloas types and their AggregateAndProof signing roots use progressive merkleization (differing from the positional root on identical bytes).
  • Heze-version values and version mismatches against the local value are rejected.

Tests

  • Migrate testing/common.rs, testing/committee_attestation.rs (result alias), and testing/committee_attestation_gloas.rs.
  • A focused Signature to AggregateSignature conversion test with a real keypair (the harness mock returns infinity signatures).
  • Slashing-protection success, same-data, and conflicting-data cases for the migrated function.
  • Decoder root tests: Gloas-typed decode yields the progressive root, differing from the positional root on identical bytes; Heze rejection; version-binding mismatches; maximum-size Gloas aggregate against MaxAggregatedAttestationBytes.
  • The metadata-service test helper that labels an Electra-shaped attestation as Gloas becomes a real Attestation::Gloas.

Notes

  • Rollout: operators computing progressive signing roots and operators computing positional ones split threshold-signature reconstruction on identical decided bytes, so Gloas devnet fleets must upgrade in lockstep with their Lighthouse images. Pre-Gloas networks (mainnet, hoodi) are byte-identical and unaffected.
  • No cross-client impact today: go-ssv cannot represent DataVersion beyond Fulu; root derivation is now pinned in SIP-94.
  • Rejected alternatives: keeping an internal Attestation<E> and converting at the boundary (rebuilds deleted complexity); splitting metadata from data internally (churn with no consumer); erroring the whole committee on one identity mismatch (trades one bad duty for the committee's slot); filtering invalid duties pre-collection (stalls the exact-count collector); splitting the 7688 signing-root work into a follow-up PR (would leave Gloas aggregation broken against upgraded beacon nodes in between).
  • Out of scope: the local-testnet cl_image bump, the share-time slashing insert, mixed-slot/duplicate-batch defensive hardening.

Issues are directionally correct, not prescriptive; verify symbols at PR time.

Metadata

Metadata

Assignees

No one assigned

    Labels

    epbsePBS / EIP-7732 / Gloas implementation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions