Add early RANDAO pre-consensus emission SIP - #101
Conversation
iurii-ssv
left a comment
There was a problem hiding this comment.
LGTM overall, the suggestions below are mostly minor clarifications.
Found while implementing the receiver rules in Anchor: existing client pipelines run contextual checks before signature verification, and a strict signatures-first order would drop the duplicate-count shield in front of RSA. Structural and canonical-form checks now run first and define the Early RANDAO candidate; for candidates the signature-vs-contextual order is implementation-defined, short-circuiting only on non-retaining verdicts, and any outcome that retains, accepts, forwards, or mutates state requires a valid operator signature (invalid signature plus Unknown duty is a pinned REJECT). Checks are staged: RSA gates retention and forwarding, BLS gates consumption. Vectors added for the pinned and flexible cases.
Pins receiver-divergence points found while mapping the rules onto Anchor's duty tracker and quarantine design. Known now requires the epoch's complete fetched proposer schedule (a locally filtered subset is not Known, so an honest share cannot be IGNOREd as Known-unassigned by a partial view). Retention is admission-conditioned rather than unconditional; the byte-identical occupied-key case keeps the original entry, full-capacity eviction has the incoming candidate compete under an exact total order (the unreachable fourth tiebreak is dropped), and promotion is restated via promotion candidates so an entry cannot both promote and fail revalidation. Vectors added for each case.
The summary said the SIP activates at the Gloas-aligned SSV fork, but the ePBS SIP (ssvlabs#94, checked at d5197bc) defines no SSV-network fork; its validation rules gate on epoch(msg.slot) >= GLOAS_FORK_EPOCH. This SIP now matches that model explicitly: activation is Ethereum-gated by the epoch(S) >= GLOAS_FORK_EPOCH conjunct, the SSV fork-equality conjunct is window-boundary protection only (it keeps the 2-slot emission window from spanning any scheduled SSV fork), and a new S >= EARLY_RANDAO_LEAD conjunct resolves the genesis underflow normatively, surfaced by the slot-zero unit test in the Anchor implementation. Vectors spell out the boundary outcomes.
|
Pushed some commits tightening the validation contract, from some findings while implementing the receiver rules in anchor:
Test vectors added for each change. |
The predicate required the SSV fork at S - EARLY_RANDAO_LEAD to equal the SSV fork at S, making the first two slots of every SSV fork activation epoch ineligible. It protects against nothing. Every fork-sensitive artifact of a partial signature (gossip topic, domain, role gating) is derived from the message's stamped slot rather than from emission time, so a message emitted inside a window that spans a fork activation is published, validated, and consumed entirely under the fork active at S. The SIP already relied on this for the Ethereum boundary, where the first slot of GLOAS_FORK_EPOCH is eligible and its window starts pre-fork; forbidding the same thing for SSV forks was inconsistent. Eligibility is now S >= EARLY_RANDAO_LEAD and epoch(S) >= GLOAS_FORK_EPOCH, a pure function of the slot and the Ethereum fork schedule.
Operators may emit the existing Proposer-duty RANDAO partial signature up to 2 slots before the proposal slot, so clusters reconstruct
randao_revealbefore the slot starts instead of inside the post-Gloas ~3s block-production budget. No new duty, role, message kind, domain, topic, or container; changes are confined to message-validation timing rules plus a bounded receive-side buffer. Activates at the Gloas-aligned SSV fork.Rationale and design discussion: #100
Addresses: ssvlabs/ssv-spec#373