fix: batch pre-Boole sync contribution proofs - #1201
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## unstable #1201 +/- ##
============================================
+ Coverage 62.98% 64.82% +1.84%
============================================
Files 162 163 +1
Lines 27235 27785 +550
============================================
+ Hits 17154 18013 +859
+ Misses 10081 9772 -309
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Preserve raw sync committee position multiplicity and eagerly admit one complete ContributionProofs envelope per validator and slot.
defbdda to
2ef996a
Compare
|
@claude, please take a look |
|
Claude finished @shane-moore's task in 11m 7s —— View job Code Review: PR #1201
Overall this is a well-designed, well-documented, and well-tested fix. The ownership split (ValidatorStore derives Ethereum facts/roots; SignatureCollector owns envelope construction + admission + retry + cleanup) is clean, and the Correctness — verified sound
Optional observations (non-blocking)
Note on local verificationI reviewed statically. I was unable to run |
|
@claude Thanks for the review. I checked the optional observations against the current head and am not changing #1201:
No changes are needed for these non-blocking observations. |
|
Claude finished @shane-moore's task in 38s —— View job Re: optional observationsAcknowledged — all three are reasonable to defer, and I agree no changes are needed for #1201.
Nothing blocking here. Closing these out — the deferrals to #1208 are well-scoped. |
|
Queued — the merge queue status continues in this comment ↓. |
Merge Queue Status
This pull request spent 31 minutes 56 seconds in the queue, including 29 minutes 15 seconds running CI. Required conditions to merge
|
Closes #1050.
Problem, Evidence, and Context
Ethereum sync committees are position-based, so the same validator may occupy positions on multiple subnets or appear more than once within one subnet. For example, positions
[0, 1, 128]map to subnet 0 twice and subnet 1 once. Lighthouse therefore calls Anchor once per unique subnet, two callbacks in this example, while the deployed SSV shape used by go-ssv and ssv-spec requires oneContributionProofsenvelope per validator and slot with one entry per raw position, three entries here. Anchor instead sent one envelope per callback, causingInvalidPartialSignatureTypeCountand wrong-root-count errors.This is especially visible on concentrated devnets and testnets. Although Boole bypasses this path, Anchor's built-in mainnet, Hoodi, and Holesky schedules currently have no Boole activation configured, so hardening the Alan producer remains useful.
Change Overview
Pending | Admittedrecord.Runtime behavior changes only for pre-Boole sync committee contribution selection proofs. Regular sync committee messages, other duties, Boole committee batching, public wire types, and inbound validation behavior are unchanged.
Design Choice
We considered an all-callback accumulator, buffering in ValidatorStore or the generic sender, and a broader Lighthouse batch API. Accepting one envelope per subnet was rejected because it preserves a wire shape that diverges from go-ssv and ssv-spec.
The eager full descriptor keeps ownership aligned: ValidatorStore derives Ethereum duty facts and roots, while the signature collector owns SSV envelope construction, admission, retry, and cleanup. Any usable callback can admit the complete envelope, avoiding an all-callback barrier and allowing a sibling to retry synchronous admission failure.
Risks, Trade-offs, and Mitigations
The blast radius is intentionally narrow. The new mutex covers only bounded synchronous signing, SSZ construction, and nonblocking queue admission, with no await or blocking send while held. Descriptor, retry, cleanup, mismatch, multiplicity, and concurrency tests cover the new state.
Validation
Before the standalone rebase:
git diff --checkmake cargo-fmt-checksignature_collector,anchor_validator_store,message_validator, andssv_typesmake lintmake testAfter replaying the #1050 commit onto current
unstable:git range-diffconfirmed the rebased commit preserves the original patch identitygit diff --checkmake cargo-fmt-checkcargo test --release -p signature_collector, 20 passedcargo test --release -p anchor_validator_store, 40 passedcargo test --release -p message_validator, 57 passedA mixed pre-Boole ssv-mini run used three candidate Anchor operators and one go-ssv operator. Ten validators each held seven raw positions across four unique subnets.
Rollback
Revert the #1050 commit. There are no configuration, storage, migration, or wire-format changes.
Dependencies
#1198 has merged. This branch has been replayed onto current
unstableand now contains one standalone #1050 commit with only this PR's diff. There are no remaining open PR dependencies.Additional Info / Next Steps
The ssv-mini run also exposed a separate pre-existing post-consensus multi-root batching issue. It is intentionally out of scope here. The owned descriptor and eager
Pending | Admittedadmission model can be extended with a phase-aware key, or a separate post-consensus record, to address that path next.