Early RANDAO Pre-Consensus Emission #100
shane-moore
started this conversation in
SIP Discussions
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Normative text lives in PR #101; this post is rationale only. It covers the design choices reviewers are most likely to question, the gossip-layer findings that shaped them, and the alternatives we rejected. Follows up ssvlabs/ssv-spec#373 and the Discord thread that converged on
proposal_slot - 2.Why not a new duty
ProposerPreferences needed its own duty because its output must leave SSV before the slot and its content is mutable, so collection state has to exist per future slot. RANDAO has neither property: the reveal is a deterministic single root whose only consumer is the Proposer duty itself, at the slot. Early emission just needs the existing partial to travel earlier; the in-slot runner consumes it as usual. A dedicated duty would also still need the in-slot pre-consensus as its failure fallback, so we would ship two mechanisms to do one job, and one proposal's failure story would span two duties.
Why a 2-slot window, and why it is receiver-pinned but producer-free
The gossip wave needs well under a slot, so the window size is not about latency. Two slots buys a retry opportunity (a missed emission at S-2 leaves S-1) and keeps emission away from the epoch boundary. The receiver window is the fork-locked rule; when a producer emits inside it is policy. That split is deliberate: after the fork we can measure and narrow emission guidance freely, but widening the window would need another fork. Pinning the larger window keeps every later choice reversible. This also answers the "keep the timing open until we can test" position: it is open, on the producer side, permanently.
Epoch-start batching looks simpler and is not. It needs a ~32-slot earliness allowance, makes the slot-ordering exemption load-bearing for all proposer traffic instead of an edge case, turns the duty-knowledge race into the common case (emission at the exact moment every node fetches the new epoch's duties), widens reveal exposure ~16x, and lands on the busiest processing moment of the epoch. Same spec, bigger constants, rare paths promoted to hot paths.
What the gossip layer actually does with duplicates (this drove half the spec)
We verified the deduplication behavior in both stacks before writing the rules, and three facts turned out to be load-bearing:
Consequences, in order of how much spec they explain:
The ordering exemption's second direction came out of the same review: randao shares its MessageID with the proposal's consensus and post-consensus traffic, so an early partial for S+1 observed during slot S must not advance the high-water mark, or slot S's remaining messages get rejected as stale. The first direction (not being rejected below the mark) mirrors the ProposerPreferences precedent; the second is new because PP has its own MessageID and randao does not.
Other rejected options
Security reasoning beyond the SIP's conclusions
The widened reaction window is the design's real cost. Today an observer can reconstruct a cluster's reveal roughly 2-4s before the block publishes; early emission stretches that to up to 25s. What changes is not the proposer's grinding ability (unchanged in kind, one bit per slot) but third parties' time to act on it: compute the conditional effect of this slot's reveal, then bribe, censor, or DoS the four known operator endpoints if withholding favors them. We judged this acceptable because it is bounded by the existing single-proposal grinding bound, and because the producer-side timing freedom means the window can be operationally narrowed to near-today without a fork if it ever matters in practice.
Two properties worth knowing when reviewing the validation rules: seen-cache poisoning from deliberately mistimed emission is always self-inflicted (only the signer can produce the bytes, so an attacker can only starve its own share), and the retention buffer's worst case requires a committee operator sharing several hundred validators with the victim during a duty-fetch failure, for a payoff bounded at one evicted share and a round change.
Evidence and verification
Mechanics verified 2026-07-23 against go-ssv
pr-2901-epbs-gloas@ 90df7fa0 with go-libp2p-pubsub v0.15.0, and Anchorunstablewith its pinned rust-libp2p; ssv-spec main @ 5d11f26b confirmed no spec-repo changes are needed (the runner already stamps the duty slot; buffering and validation timing are node-side). The design went through an adversarial cross-model review that produced the ordering exemption's second direction, the retention redesign, and the per-duty fork predicate; the three residual risks it still flags are stated verbatim at the end of the SIP's Security Considerations.Open questions for this thread
All reactions