feat(validator_store): publish PTC validator set on VotingAssignments - #1053
feat(validator_store): publish PTC validator set on VotingAssignments#1053shane-moore wants to merge 3 commits into
Conversation
|
@claude, please take a look |
|
I'll analyze this and get back to you. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## epbs #1053 +/- ##
=======================================
Coverage ? 62.08%
=======================================
Files ? 156
Lines ? 26317
Branches ? 0
=======================================
Hits ? 16340
Misses ? 9977
Partials ? 0
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
I'll analyze this and get back to you. |
1 similar comment
|
I'll analyze this and get back to you. |
|
@claude, please take a look |
|
Claude finished @shane-moore's task in 3m 48s —— View job ReviewVerdict: LGTM with minor optional improvements. The change is tightly scoped, additive, and faithfully mirrors the existing
What's good
Minor suggestions (optional)
Non-issues I checked
RiskLow. Pre-CStar paths are bit-for-bit unchanged (the new branch returns |
|
@claude, thanks. On each: 1. Keeping 2. I don't think there's a real gap here. 3. No |
|
Claude finished @shane-moore's task in 1m 10s —— View job Acknowledged — all three points stand
1. 2. 3. Orchestrator-level coverage. Confirmed — every No changes requested. PR stands as-is from my side. |
|
closing for now since we're going to move to a non-qbft ptc approach |

Problem, Evidence, and Context
Closes #1036. Next ePBS milestone item after PR #1033 (
Role::PTCCommittee+ message-validator handling), alongside PR #1047 (PayloadAttestationVoteSSZ container).Per SIP-94 §3 and the Gloas validator spec, each PTC-assigned validator signs
PayloadAttestationDataunderDOMAIN_PTC_ATTESTER. In SSV, a cluster runs one QBFT instance per slot and each locally-assigned PTC validator contributes a partial signature on the decided data. The downstreamsign_payload_attestationpath (#1037) needs the per-cluster partial-signature batch size at signing time, mirroring howsign_committee_attestationsusesvoting_message_count_for_committeeat `lib.rs:1534-1537` for the attestation batch.This PR publishes that count input on `VotingAssignments` so #1037 can size its batch with the same closure-based filter pattern.
Change Overview
Additive change across four files, +122/-3. All work lives in `anchor/validator_store`.
Reading order: start at `validator_store/src/lib.rs` (new field + count helper on `VotingAssignments`); then `metadata_service.rs` (fork-gated lookup + the pure helper in the helper bay); unit tests in the existing `#[cfg(test)] mod tests` block mirror `test_aggregators_sorted_by_validator_index`.
Intentionally unchanged:
Risks, Trade-offs, and Mitigations
Slot-start lookup cost. Adds ~30 O(1) hashmap reads per slot for a typical operator (1-10 PTC duties, three `database.state()` reads each via `get_validator_and_cluster`). Cheaper than the per-validator `SyncSubnetId::compute_subnets_for_sync_committee::(...)` already running in Phase 1. The alternative (separate 9s-fraction fetch phase) was rejected because PTC duties are epoch-stable and the source is an in-memory `PtcMap` read.
Flat vec vs per-cluster grouping. `ptc_validators` is flat across clusters, mirroring `attesting_validators`. The attestation precedent at `lib.rs:1534-1537` shows the flat-vec + closure-filter pattern is sufficient for per-cluster batch sizing; #1037 mirrors it. If a non-count consumer ever emerges, a refactor is one field-shape change with the call site as the regression test.
Empty-assignments counter behavior. Tightening to include `ptc_count == 0` makes the counter strictly more accurate — it fires only when no duties exist at the slot. Not noisier during early CStar rollout; the prior condition would have falsely counted PTC-only slots as empty post-fork.
Validation
New test coverage (pure-helper tests, no tokio runtime, no `MetadataService` instance):
Rollback
Additive change on a metadata-only struct. Revert removes the field, helper method, fork-gated lookup, pure helper, gauge, and tests. Pre-CStar behavior is unchanged (empty vec until fork activation), so revert pre-CStar is a no-op. Post-CStar revert removes the input #1037 reads, but #1037 has not landed yet, so no downstream impact.
Blockers / Dependencies
None for merge. Downstream consumer (milestone #4):
Additional Info / Next Steps
N/A