EIP-8321 Hash-chain RANDAO

Hegota Declined for Inclusion · Consensus & staking · EIP status Draft · created 2026-07-05

Replaces RANDAO's BLS-signature-based randomness contribution with a quantum-resistant hash-chain commit-reveal scheme. A validator registers a hash chain in advance and reveals it one step backward at each block proposal.

Why it is needed

Today, the beacon chain's randomness (RANDAO) works by having the block proposer contribute a BLS signature over the epoch number. Once the message and public key are fixed, a BLS signature has exactly one valid value. This uniqueness prevents the proposer from grinding, that is, choosing their own contribution at will. However, BLS is not quantum-resistant. A sufficiently strong quantum computer (CRQC) can recover the secret key from the public key, and an attacker could then compute validators' future contributions and the proposer order far ahead. Once prediction is possible, the existing "reveal or withhold" bias attack also becomes stronger. Today an attacker must hold k consecutive slots at the end of an epoch to choose among 2^k candidates, but an attacker who predicts all honest contributions needs only any k slots within the mixing window. Moreover, the hash-based signatures planned for the consensus layer (lean signatures, the XMSS family) use a salt and so lack uniqueness, and using them directly in RANDAO would allow grinding. A hash chain removes the signature itself and cuts this dependency.

What changes

Today

After EIP-8321

Who is affected

In depth

Hash chain construction and the no-zero rule

The validator draws a random 32-byte secret c_0, builds a chain of length n with c_i = blake3(HASH_CHAIN_RANDAO_DST + c_{i-1}), and registers the end value c_n as the commitment. HASH_CHAIN_RANDAO_DST (b'HASH_CHAIN_RANDAO') is a domain-separation prefix that keeps this hash from colliding with other hashes in the protocol, and it does not contain a per-link index, so the validator only needs to store the chain values. Reveals go in reverse order: the first reveal is c_{n-1}, the next is c_{n-2}. Because the revealed value is stored as the new commitment, the protocol does not need to know n or the current position. A chain value cannot be the zero word. This is because 0 is used to mark an unregistered validator, and if any link is 0, the chain must be regenerated. An n of 2^16 or more is recommended, generation takes milliseconds, and total storage is about 2MB. A chain cannot be extended in place, so it is exhausted once c_0 is used, but even under aggressive assumptions a validator proposes about 100 times a year, so the recommended length is hundreds of years' worth. If the chain is exhausted or the secret is lost, exiting and re-entering is the only means of recovery.

The two paths of process_randao and the hash accumulator

process_randao takes the hash-chain path if the stored commitment is not 0. It checks that hash_chain_reveal is not 0, that blake3(HASH_CHAIN_RANDAO_DST + reveal) equals the stored commitment, and that randao_reveal is G2_POINT_AT_INFINITY. It then accumulates mix = blake3(existing mix + reveal) and stores the revealed value as the new commitment. If the commitment is 0, it verifies the BLS signature as before and mixes with xor. The hash-chain path uses a hash accumulator instead of xor because of the commitment-copying attack. A commitment carries no identity, so someone can copy another validator's current commitment to create a valid registration, and with a linear xor accumulator they could cancel the victim's contribution by inserting the same value again. A hash has no efficient inverse operation, so inserting the same value again just yields an unrelated new mix, and this attack is blocked at the root. That is why the raw reveal value can be mixed in without per-validator personalization. The assertion that rejects a 0 reveal protects the invariant that 0 means unregistered.

The registration operation and the 3-epoch activation delay

Registration is a one-time operation in which RandaoCommitmentRegistration(validator_index, commitment) is signed with the validator's BLS key and included in a block. The signing domain DOMAIN_RANDAO_COMMITMENT_REGISTRATION (0x0F000000) is computed with the genesis fork version, so like BLSToExecutionChange it remains valid across forks. Up to MAX_RANDAO_COMMITMENT_REGISTRATIONS = 128 can be included per block, so all roughly one million validators can register within two days, and there is no deadline. A registration is valid only when the stored commitment is 0, and only one pending registration is allowed per validator, so both reuse and queue stuffing are blocked. Activation is at N + COMMITMENT_REGISTRATION_DELAY (= 3), where N is the inclusion epoch. The proposer-selection seed for epoch E is fixed at the end of E - MIN_SEED_LOOKAHEAD - 1, but the seed for N + 3 is fixed at the end of N + 1, which is after inclusion, so at registration time a validator cannot even know whether it will propose in the activation epoch. This is why reactive grinding, computing a favorable candidate chain and registering it, is impossible, and this lower bound is MIN_SEED_LOOKAHEAD + 2.

State, gossip, and fork transition

Two fields are added to BeaconState. randao_commitments is a List[Bytes32, VALIDATOR_REGISTRY_LIMIT] indexed by validator index, where 0 means unregistered and the legacy path is used. pending_randao_commitments is a ProgressiveList from EIP-7916. It is almost always empty, and even the worst normal state holds only about 12,300 entries, so it avoids the hashing cost of a large fixed-limit list. Pending commitments are applied in process_pending_randao_commitments, which runs right after process_registry_updates every epoch, once the activation epoch is reached. Gossip gains a global topic, randao_commitment_registration. Because a validator registers only once, duplicates are filtered by forwarding only the first message per validator, as with bls_to_execution_change. A message is REJECTed if the commitment is 0 or the index does not exist, IGNOREd if the validator has already been seen or has a pending registration, and REJECTed if the validator is already registered or the signature is invalid. At the fork, randao_commitments is initialized to zeros for the current number of validators, and add_validator_to_registry then appends a zero entry for each new validator, which keeps the list length invariant.

Security analysis: bias, theft, orphaned blocks, DoS

The potential for bias is the same as today. The whole chain is fixed before the commitment time, that is, before the proposal slot is known, so the proposer's options are the same as today: reveal, or withhold and give up the block and its reward. If the chain secret is stolen, an attacker can predict that validator's future contributions but cannot choose them. This is strictly less damaging than today's signing key theft, where a stolen key gives the attacker the power to sign as well as predict. Even so, the secret must be stored with the same care as a signing key, and because reaching the end of the chain reveals the seed, the chain must not be derived from the signing key. A reveal included in an orphaned block exposes that validator's future mandatory contributions in advance, but a predictable contribution is no worse than a withheld one, and RANDAO needs only one honest contributor in the mixing window, so there is no practical harm. Possession of the preimage cannot be verified at registration, and a wrong commitment cannot be fixed in place, so clients must walk back through the entire chain to check it before registering. Registration spam is bounded at every level: blocks (limit of 128), gossip (one verification per validator), and state (the one-pending rule and the cap of about 12,300).

Limits of scope, Draft status and call decisions

This EIP alone does not make beacon chain randomness quantum-resistant end to end. Block signatures and the signature on the registration operation are still BLS, and the legacy BLS reveal path remains during the transition. It is designed so that a later quantum-resistant fork can set the initial commitment at deposit time and change the signature scheme, removing the randao_reveal field and the registration operation together. The source is in Draft status, so the specification may still change. On the core developer calls, it was accepted as a Hegota candidate (PFI) at ACDC #183 on 07.23, but objections grew that an iterative quantum-resistant approach is premature, so the discussion will continue in the post-quantum Discord channel. At ACDC #187 on 09.17, seven items including EIP-8321 were removed from the Hegota candidates (DFI). Quantum-resistance work, including the hash-chain RANDAO, continues informally during the Hegota period.

Original EIP · ← EIPs