Chapter 39: Consensus and staking signatures
A consensus signature authenticates a validator’s vote on a block at the chain’s heartbeat: every slot, every epoch. Ethereum’s beacon chain runs BLS signatures on the BLS12-381 pairing-friendly curve (Boneh et al., 2022; Ethereum Foundation, 2024). The construction has one architectural property the post-quantum candidates do not match: pairing-based aggregation collapses partial signatures from validators to one 96-byte aggregate that any verifier can check against the aggregated public key. The post-quantum lattice and hash-based candidates produce independent signatures per attestation set. The per-set byte budget scales linearly in rather than sitting flat.
Covered in Ch 37 and Ch 38: the per-spend transaction surface (BIP-360 P2MR on Bitcoin, ERC-4337 on Ethereum) and the wallet-and-derivation surface (BIP-32 redesign under post-quantum primitives). The consensus surface from the Ch 36 surface taxonomy is this chapter’s target. The wallet-vendor migration timeline from Ch 38 is independent of the chain-level consensus migration here. The wallet migrates on its custody-vendor cadence and the chain protocol migrates on a hard-fork cadence.
A Strand consensus surface migrating from BLS-BLS12-381 to ML-DSA-65
Section titled “A Strand consensus surface migrating from BLS-BLS12-381 to ML-DSA-65”The Strand consensus surface from the Ch 36 fixture deploys BLS-BLS12-381 per-slot at years (validator-key reuse window) and year (consensus-signature rollout window). Ethereum processes validator activations, exits, and committee reshuffling at epoch boundaries: 32 slots of 12 seconds gives a 6.4-minute epoch. Committees reshuffle every epoch, but validator registry membership changes only through the activation and exit queues, which Ethereum has metered in ETH rather than in validators since the Electra fork. The per-epoch activation and exit churn is min(MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT, get_balance_churn_limit(state)), floored at 128 ETH and capped at 256 ETH. Mainnet has sat at the 256 ETH cap since Electra activated, because roughly 42.4 million ETH of total stake (per the beaconcha.in-fed dashboard at validatorqueue.com, read 25 August 2026) puts the balance-derived term far above the ceiling (validatorqueue.com, 2026). At Strand’s scale of 100 thousand validators holding 32 ETH each, the 128 ETH floor binds instead, which is 4 validators per epoch. Strand parameterizes its churn limit at 8 validators per epoch, a chain-specific ceiling at twice that floor.
A migration of the consensus signature requires a hard fork because the BeaconBlock and Attestation data structures, the SimpleSerialize (SSZ) encoding those structures use, the verifier-set logic, and the slashing conditions all change.
The byte-budget framing throughout this chapter is a normalized per-validator-set comparison, not a literal Ethereum per-block estimate. Assume validators sign one consensus message and the protocol must represent all contributions in one payload. Ethereum’s actual beacon-chain attestations are split by slot, committee, subnet, and aggregation structure. The current Electra Attestation carries aggregation_bits, data, signature, and committee_bits, so the per-slot block payload at any moment is a fraction of the per-validator-set total. The normalized model isolates the cryptographic aggregation effect. The architectural property at issue (aggregation collapses to one signature vs post-quantum produces signatures) holds at any subset. For the non-aggregating candidates the normalized figure is also the deployment total, because splitting the set across committees leaves the same signatures in smaller parcels. For the aggregating candidates it is a single-payload floor rather than a total, and how many payloads a deployment pays is a protocol choice. At one million validators Ethereum’s committee formula caps at 64 committees per slot across 32 slots, 2,048 per epoch, and since Electra (7 May 2025) EIP-7549 keeps the committee index out of the signed AttestationData, so equal votes across committees aggregate into one signature and BLS does not pay one per committee (dapplion & Kalinin, 2023; Ethereum Foundation, 2024). A comparison imposed at one signature per committee puts threshold ML-DSA at roughly signature bytes plus the bitmap, near 6.9 MB per epoch, beside roughly 322 KB for BLS priced the same way: a factor of about 21 rather than the normalized 1.03, for that imposed shape and not for Ethereum’s current aggregation, whose real payloads depend on how many distinct attestation data are cast and included. Where a figure below is this floor rather than a deployment price, the surrounding text says so.
The motivating example: 100 validators sign an attestation under both BLS-BLS12-381 and ML-DSA-65, and the per-validator-set byte budget compares as follows. Under BLS, the 100 partial signatures aggregate to one 96-byte signature plus a 13-byte participation bitmap (one bit per validator, rounded up to the byte), totaling 109 bytes. Under ML-DSA-65 the 100 partial signatures ship independently at 3309 bytes each, totaling 330 900 bytes. The byte-budget factor against the BLS aggregate is 3036 to one. At the Ethereum mainnet round-figure anchor of one million active validators, the same factor sits at 26 452 to one. The consensus-signature migration imposes a per-validator-set byte tax that has no on-chain mitigation short of a SNARK-based aggregation wrapper (an open-research direction at chain-tip 2026).
The four-part operator playbook translates this byte-budget figure into four decisions: pick the candidate per the byte budget, decide between threshold and per-validator signing, plan the validator-key rotation cadence, and choreograph the hard-fork rollout.
BLS signatures, aggregation, and the discrete-log reduction
Section titled “BLS signatures, aggregation, and the discrete-log reduction”BLS signatures on a pairing-friendly curve implement the Boneh-Lynn-Shacham construction (Boneh et al., 2004). The signing key is a scalar ; the public key is the point on the curve where is a fixed generator and is the curve order. The signature on a message is the point where is a hash-to-curve function targeting (the order- subgroup of ). Verification computes the pairing on one side and on the other. The signature verifies if and only if the two pairings are equal.
The Ethereum consensus-specs fix the canonical signature form at 96 bytes (the compressed point) and the canonical public-key form at 48 bytes (the compressed point) (Boneh et al., 2022; Ethereum Foundation, 2024). These sizes record as named constants in the package. A future revision can update one number rather than recompute every figure.
The aggregation property is structural to the pairing. Given signatures on the same message from public keys , the aggregate signature is the group product on (Boneh et al., 2003). Verification of the aggregate against the aggregated public key on requires one pairing on each side, regardless of (same-message fast aggregate verification). Multi-message aggregates require one pairing per distinct message. The same-message aggregate-verification path is safe only under a rogue-key mitigation: Ethereum’s validator registration includes a BLS proof-of-possession verified by is_valid_deposit_signature before the public key is added to the validator registry by add_validator_to_registry (Ethereum Foundation, 2024).
What aggregation buys is therefore narrower than it first looks. BLS makes the cryptographic signature component constant in : same-message signatures collapse to one 96-byte aggregate. The full on-chain payload is not constant, because the chain still carries one participation bit per validator. In the normalized all-validator-set model the total is bytes, with the bitmap growing linearly in . That second term is the one the rest of this chapter keeps running into: it survives every candidate swap, and at one million validators it is three orders of magnitude larger than the signature it accompanies.
The security of BLS reduces to the computational co-Diffie-Hellman assumption on the pairing-friendly curve (Boneh et al., 2004). The discrete-log problem on (or ) is the underlying hard problem. An algorithm that solves discrete logs on either curve breaks BLS. Shor’s algorithm (Shor, 1994) solves discrete logs in polynomial time on a sufficiently large quantum computer, breaking BLS at every active validator’s public key once a CRQC arrives (Aggarwal et al., 2018; Babbush et al., 2026). The first-wave exposure for the consensus surface is the validator-set registry: every registered validator’s public key sits in BeaconState.validators[].pubkey from deposit processing onward (Ethereum Foundation, 2024), regardless of whether the validator has been activated or has signed any specific slot. A CRQC running Shor against any registered recovers the signing scalar in polynomial time.
The post-quantum candidates do not aggregate trivially. ML-DSA-65 (National Institute of Standards and Technology, 2024) is a Fiat-Shamir lattice signature with no group homomorphism on signatures. The verification equation checks a norm bound on the response vector and a hash equality against the commitment, neither of which is preserved under addition of signatures, and the signer’s rejection-sampling loop (Ch 12) leaves no algebraic structure for a combiner to exploit. SLH-DSA-128s (National Institute of Standards and Technology, 2024b) signs the message digest with a few-time FORS key and authenticates that key with a hypertree of XMSS signatures, each a WOTS+ signature plus a Merkle authentication path (Ch 17). A signature therefore carries signer-specific signature material as well as authentication nodes, and neither part combines across signers, so aggregation reduces no bytes. FN-DSA-512 (Perlner, 2025) is a NTRU-based Gaussian-sampling signature whose signature carries a short vector that does not concatenate. Its 666-byte signature and 897-byte public key are Falcon-512’s figures from the round-3 submission (Fouque et al., 2020). FIPS 206 has published no document to take them from.
Threshold constructions are the one direction that would restore something like aggregation, and they are not evenly developed across the candidate set. ML-DSA is an active research and standardization area for threshold variants in which cosigners produce one verifier-compatible ML-DSA-65 signature via a multi-round combine protocol off-chain. NIST’s 2026 Multi-Party Threshold Schemes workshop tracks proposals along these lines. Quorus is the model this chapter prices (Bienstock et al., 2025). Its distributed key generation jointly produces one fixed ML-DSA public key plus secret shares, and any authorized subset then produces one standard FIPS 204 signature under that joint key. An SLH-DSA threshold combiner remains an open research problem at chain-tip 2026, because the hypertree authentication path resists the standard threshold-protocol techniques. FALCON’s Gaussian-sampling step resisted them too until Garg, Escudero, Polychroniadou, Takahashi and Wang (June 2026, revised July) ran the sampler inside a multi-party computation and presented what they call the first threshold protocol whose signatures verify under the unmodified FALCON verification algorithm, implemented and benchmarked in an N-party and a three-party setting (Garg et al., 2026). Whether it aligns with the final FN-DSA standard and whether it suits a consensus deployment are questions the paper does not settle. A deployable threshold-PQ protocol on the consensus surface still ships a per-validator participation bitmap on-chain alongside the combined signature, analogous in format to the BLS bitmap, to record which validators earn attestation rewards. Unlike the BLS bitmap, it is not an input to verification: one standard verification against the joint key proves that an authorized threshold signed and identifies no cosigner. Rewards and slashing therefore need a separate accountability mechanism (attributable partial signatures in the combine transcript, or an accountable-threshold extension), and this chapter’s byte figures do not price it.
The four-part consensus migration playbook
Section titled “The four-part consensus migration playbook”Pick the candidate per validator-set byte budget
Section titled “Pick the candidate per validator-set byte budget”The Strand operator picks one primitive based on the per-validator-set byte budget against the five-candidate set. The first inline block walks the byte arithmetic. The function below is a pedagogical slice of consensus_staking.aggregation_overhead.evaluate over the five primitives at one million validators.
# Block 1: pedagogical slice of consensus_staking.aggregation_overhead# (stdlib only).N = 1_000_000 # Ethereum mainnet round-figure anchor.BLS_AGG_BYTES = 96 # canonical G2 aggregate signature size.
CANDIDATES = { "BLS-BLS12-381": {"sig_bytes": 96, "aggregates": True}, "ML-DSA-65": {"sig_bytes": 3309, "aggregates": False}, "SLH-DSA-128s": {"sig_bytes": 7856, "aggregates": False}, "FN-DSA-512": {"sig_bytes": 666, "aggregates": False}, "threshold-ML-DSA": {"sig_bytes": 3309, "aggregates": True},}
def per_set_bytes(primitive, N): spec = CANDIDATES[primitive] bitmap_bytes = (N + 7) // 8 # one bit per validator, byte-aligned. if primitive == "BLS-BLS12-381": return BLS_AGG_BYTES + bitmap_bytes if primitive == "threshold-ML-DSA": # One combined ML-DSA-65 signature plus the per-validator # participation bitmap the chain records for rewards. Unlike # BLS's bitmap it is not an input to verification. return spec["sig_bytes"] + bitmap_bytes return N * spec["sig_bytes"]
baseline = per_set_bytes("BLS-BLS12-381", N)print(f"{'primitive':<19} {'per-set bytes':>15} {'factor vs BLS':>15}")for primitive in CANDIDATES: total = per_set_bytes(primitive, N) factor = total / baseline print(f"{primitive:<19} {total:>15,} {factor:>15.2f}")# ==> primitive per-set bytes factor vs BLS# ==> BLS-BLS12-381 125,096 1.00# ==> ML-DSA-65 3,309,000,000 26451.69# ==> SLH-DSA-128s 7,856,000,000 62799.77# ==> FN-DSA-512 666,000,000 5323.91# ==> threshold-ML-DSA 128,309 1.03Every Python block this chapter prints is also a standalone file in the companion repository, under chapter-code/ch39/, one file per block. Appendix C covers the clone and the environment they run on.
The BLS aggregate at one million validators carries 96 bytes of signature plus 125 000 bytes of participation bitmap, totaling 125 096 bytes. The participation bitmap dominates the BLS payload; the 96-byte aggregate signature is a rounding error against the bitmap at this scale. ML-DSA-65 produces 3.3 GB of signature per attestation set, a factor of 26 452 against the BLS baseline. SLH-DSA-128s produces 7.86 GB, a factor of 62 800. FN-DSA-512 produces 666 MB, a factor of 5324 (the smallest of the three plain post-quantum candidates because the NTRU-based signature is the most compact). Threshold ML-DSA carries 3 309 bytes of combined signature plus the same 125 000-byte participation bitmap that BLS ships, totaling 128 309 bytes per attestation set. The factor against the BLS aggregate is 1.03. The threshold-PQ payload is approximately the same size as the BLS aggregate at one million validators because the bitmap dominates both. The parity is a payload-size parity only: the BLS bitmap selects the public keys the aggregate verifies against, while the threshold bitmap rides beside a signature that verifies without it. It is also a normalized floor rather than a deployment price: a per-committee deployment pays one 3 309-byte combined signature per committee against 96 bytes for BLS. At Ethereum’s 2 048 committees per epoch the two totals (signatures plus the participation bitmap) sit near 6.9 MB and 322 KB, a factor of about 21.
Figure 39.1 below compares BLS aggregation against post-quantum non-aggregation under validators.
The threshold-ML-DSA byte budget covers the on-chain payload (combined signature plus participation bitmap); it excludes whatever accountability evidence a real protocol would add to make the bitmap enforceable for rewards and slashing. The combine protocol that produces the single signature runs off-chain across a participating subset of validators. The combine round carries multi-round message-passing overhead that scales in the number of cosigners. The package records the off-chain combine overhead as a flag rather than as a byte count, since the off-chain bytes do not ship in the BeaconBlock.
The conservative-assumption preference moves SLH-DSA-128s to the top of any long-lived validator-set key. The hash-only security argument depends on the pseudorandomness of the underlying PRF and on preimage resistance and related properties of the underlying hash function, SHA-2 or SHAKE (National Institute of Standards and Technology, 2024b). Chapter 18 names the hypothesis set the current tight proof rests on. It does not depend on a structured-lattice assumption. The byte-budget preference moves FN-DSA-512 to the top among plain, non-aggregating post-quantum signatures if FIPS 206 lands as a final standard before the consensus-migration hard fork. The aggregation-density preference moves threshold-ML-DSA to the top if the threshold construction reaches a deployable status, which it has not at chain-tip 2026.
Decide between threshold and per-validator signing
Section titled “Decide between threshold and per-validator signing”The threshold-versus-per-validator decision sits orthogonal to the candidate decision. The second inline block walks the threshold-scheme by candidate support matrix. The function below is a pedagogical slice of consensus_staking.threshold_compare.lookup over the five primitives and the three threshold-protocol roles.
# Block 2: pedagogical slice of consensus_staking.threshold_compare# (stdlib only).PRIMITIVES = ( "BLS-BLS12-381", "ML-DSA-65", "SLH-DSA-128s", "FN-DSA-512", "threshold-ML-DSA",)
# Each cell records the deployment status at chain-tip 2026 across# three threshold-protocol roles. ``--`` means the cell is not a# candidate for the operator (incompatible primitive plus role).MATRIX = { "BLS-BLS12-381": ("production", "classical-only", "--"), "ML-DSA-65": ("fips-final", "--", "research"), "SLH-DSA-128s": ("fips-final", "--", "research-early"), "FN-DSA-512": ("pre-draft", "--", "research-early"), "threshold-ML-DSA": ("research", "--", "research"),}
ROLES = ("no-threshold", "classical-FROST", "threshold-PQ")
print(f"{'primitive':<19} {'no-thr':<14} {'FROST':<16} threshold-PQ")for primitive in PRIMITIVES: a, b, c = MATRIX[primitive] print(f"{primitive:<19} {a:<14} {b:<16} {c}")# ==> primitive no-thr FROST threshold-PQ# ==> BLS-BLS12-381 production classical-only --# ==> ML-DSA-65 fips-final -- research# ==> SLH-DSA-128s fips-final -- research-early# ==> FN-DSA-512 pre-draft -- research-early# ==> threshold-ML-DSA research -- researchOnly one cell records a deployed primitive on a live chain: BLS at no-threshold. Of the four post-quantum rows in that column, the three plain signature candidates sit at a NIST-finalized standard or in the NIST standardization pipeline. The fourth, threshold-ML-DSA, reads research in that column too. An operator can deploy ML-DSA-65 or SLH-DSA-128s today, and FN-DSA-512 once FIPS 206 reaches a final standard. FIPS 206 is under development, with no Initial Public Draft yet released for public comment (Perlner, 2025). Every post-quantum threshold cell sits at a research stage. An operator who wants threshold post-quantum signatures has no chain-deployable option at chain-tip 2026.
The classical-FROST cell is included to be excluded. FROST, Flexible Round-Optimized Schnorr Threshold signatures (Komlo & Goldberg, 2020), is a threshold-Schnorr scheme over a discrete-log-based curve. It is Shor-vulnerable and not a post-quantum migration target. The matrix records FROST to make explicit the distinction between threshold-on-classical (FROST is implemented in some Bitcoin custody products, but Shor-vulnerable) and threshold-on-post-quantum (every variant remains a research direction).
The operator’s decision under a Mosca breach: deploy a no-threshold post-quantum candidate today, accept the per-validator-set byte tax, and revisit threshold-PQ once a candidate reaches a chain-deployable status. The validator-set rotation cadence against the Mosca window (next subsection) determines how aggressive the no-threshold deployment must be.
Plan the validator-key rotation cadence
Section titled “Plan the validator-key rotation cadence”The validator-key rotation cadence is the operator’s response to the Mosca window for the consensus surface. The Strand consensus surface from Ch 36 sits at and . The cadence functions below work with the signed margin . Ch 36’s exposure window is its positive part, so a negative margin is years of clearance, not a breach. All three of Ch 36’s planning scenarios clear the Mosca window for this surface. The two 2035 policy dates (NCSC and NSM-10) both sit at , giving a margin of years (cleared by six) with a safe window of 8. The hypothetical mid-arrival scenario at gives . This chapter therefore adds a scenario of its own, an aggressive arrival forecast included for pedagogical purposes, because none of Ch 36’s three puts the consensus surface under any pressure at all. It breaches by 1 year with a safe window of 1 year, which is the only setting in which the fixed-interval cadence below has anything to decide.
The third inline block runs the recommendation function over four scenarios spanning the three cadence regimes.
# Block 3: pedagogical slice of consensus_staking.consensus_mosca# (stdlib only).def breach_years(X, Y, Z): return X + Y - Z
def recommend(X, Y, Z): breach = breach_years(X, Y, Z) safe_window = max(0, Z - Y) if breach <= 0: return ("per-epoch", 0) if safe_window >= 1: return ("every-N-epochs", safe_window) return ("hard-fork-trigger", 0)
# Strand consensus surface from Ch 36: X=2, Y=1.X, Y = 2, 1SCENARIOS = ( ("aggressive Z=0", 0), ("narrow Z=2", 2), ("ncsc-2035 Z=9", 9), ("mid-2040 Z=14", 14),)for label, Z in SCENARIOS: cadence, N = recommend(X, Y, Z) breach = breach_years(X, Y, Z) print(f"{label}: breach={breach:>4}y -> {cadence}, N={N}y")# ==> aggressive Z=0: breach= 3y -> hard-fork-trigger, N=0y# ==> narrow Z=2: breach= 1y -> every-N-epochs, N=1y# ==> ncsc-2035 Z=9: breach= -6y -> per-epoch, N=0y# ==> mid-2040 Z=14: breach= -11y -> per-epoch, N=0yUnder the aggressive scenario, leaves no safe window for a fixed-interval rotation. The recommendation falls back to hard-fork-trigger. The operator coordinates a rotation at a named hard-fork event (CRQC arrival rumor, jurisdictional mandate, post-quantum activation fork). Under the narrow scenario, admits a one-year rotation interval, which brings effective key reuse to 1 and closes the arithmetic, on three conditions the arithmetic does not state. The interval counts down to the absolute arrival date, so it shrinks as does rather than resetting at each rotation. The post-quantum consensus-signature rollout completes inside , before that date, and every key issued after it is a post-quantum key. And every classical key retires within one year of issue, so that none is still trusted when the CRQC arrives. Rotating one classical key for another does nothing against Shor once the machine exists, because the newly active public key is as recoverable as the old one. What a shorter interval buys is a shorter tail of legacy keys still valid past the cutover, and that is the whole of its benefit.
Under both of the distinct Z values Ch 36’s planning scenarios use, no breach exists, so no emergency validator signing-key rotation is required. The operator continues normal validator lifecycle management (activations and exits through the chain’s churn-limited queues) and prepares for the post-quantum registration window introduced by the migration fork. Under today’s Ethereum protocol, a forced signing-key rotation in place requires exit and re-entry rather than a single in-protocol key-change call. A future hard fork could add an explicit validator key-change mechanism, after which the cadence would be bounded by the Mosca window.
The every-N-validator-rotations cadence is the operator’s contingency for a protocol that does add explicit key-change. Ethereum’s churn limit caps activations and exits per epoch in ETH terms, at most 256 ETH per epoch under Electra, and it is a ceiling on turnover rather than a source of it: a validator may stay active indefinitely, committee reshuffling does not rotate its BLS key, and no half-life follows from the cap (Ethereum Foundation, 2024). A saturated exit queue would need at least epochs’ worth of days, about 368 days, to move half of the 42.4 million ETH staked at the 25 August 2026 snapshot, and that is a throughput floor on a stated assumption rather than an observed turnover rate. An operator who wants to align an explicit key-change cadence with validator-set attrition rather than calendar time picks every-N-validator-rotations. The package returns it as a runner-up rather than as the recommendation because the calendar-time framing is sharper for the Mosca arithmetic.
The Ethereum hard-fork choreography
Section titled “The Ethereum hard-fork choreography”The hard-fork choreography for the consensus signature touches many more parts of the protocol than the signature field alone. The migration is not a field-size replacement; it is a packing, verification, gossip, and slashing-format redesign, and the table below is the change list an implementer works from.
The Attestation container changes in two different ways depending on the migration design, and it is the entry the rest of the list hangs off. In a threshold-PQ design the existing aggregate-attestation shape mostly survives (the Electra Attestation with its committee_bits, while the hypothetical design in D39 prices one per committee), and the single signature field changes from a 96-byte BLSSignature to a 3,309-byte combined ML-DSA-65 signature. In a no-threshold design the protocol must represent one signature per participating validator. The container becomes closer to a list of SingleAttestation-style records (with committee_index, attester_index, data, and per-validator signature), or a packed vector of validator-index plus signature pairs (Ethereum Foundation, 2024). The signature size class widens with the candidate: 666 bytes (FN-DSA-512), 3,309 bytes (ML-DSA-65 or threshold-ML-DSA), or 7,856 bytes (SLH-DSA-128s) per signature, multiplied by the validator count in the no-threshold case.
| Protocol area | What the fork changes | Why it cannot be deferred |
|---|---|---|
| BeaconBlock and Attestation SSZ | signature field size, and the container shape itself under no-threshold | the wire format is consensus-critical |
| Validator registry | adds a post-quantum public key or credential alongside the legacy BLS key | the verifier needs both during the transition |
| Domain separation | a post-quantum domain tag on the signing root | BLS and post-quantum signatures over the same AttestationData must not be interchangeable |
| Verifier-set logic | pairing verification replaced by the candidate’s verification routine | per-slot verification is the feasibility bound |
| Gossip validation | subnets accept the new attestation type, reject mismatched primitive and domain pairs | propagation rules gate what reaches a proposer |
| Aggregation and packing | under no-threshold, a list of per-validator signatures rather than one aggregate | block-body packing efficiency changes with it |
| Slashing evidence | the two-conflicting-attestation intersection rule survives per-validator signing; a joint-key threshold design needs attributable partials or an accountable-threshold extension | equivocation detection may need different logic |
| Fork choice | updates if the candidate changes the per-slot verification budget | verification times differ by orders of magnitude across the set |
| Light client and sync committee | proof size grows in committee size without BLS aggregation | both rely on aggregation for compact proofs |
| Validator client and remote signer | APIs expose the post-quantum signing call | the operator cannot sign otherwise |
| Builder, relay, and the MEV-boost block-building middleware | compatibility follows the attestation format | builders consume and republish attestations |
| Rollback semantics | states whether registered post-quantum key material is retained or zeroed | a second fork back to BLS leaves it exposed but no longer relied on |
The cutover-and-rollback procedure runs as a coordinated activation block. Before the activation block, validators register a post-quantum public key alongside their existing BLS public key during a registration window. The protocol enforces the registration window’s end as a hard deadline. Validators that have not registered a post-quantum public key by the end of the window are treated as inactive at activation. At the activation block, the consensus rule changes from BLS verification to post-quantum verification. BLS attestations after the activation block are invalid. The rollback path is a second hard fork that returns to BLS verification if the post-quantum implementation produces a runtime failure across a critical mass of validator clients.
The work-stream owner per the Ch 30 framework is the consensus-client team for each major Ethereum consensus client (Lighthouse, Prysm, Teku, Nimbus, Lodestar). The validator-coordinator owner per the same framework is the validator-set operator (staking pool, solo validator, custody platform) running the candidate-key registration. The chain governance owner per Ch 41 is the All Core Devs forum coordinating the hard-fork activation block. The Ch 30 four-phase program runs the migration through discovery (validator-key registration window), first-wave (early-adopter clients deploy the post-quantum verifier), broad-rollout (mainnet activation block), and end-of-migration (BLS-key registration window closes for any new validators).
Cryptanalysis: three consensus-surface attack categories
Section titled “Cryptanalysis: three consensus-surface attack categories”Three attack categories specific to the consensus surface beyond the generic Shor break covered in Ch 04 and the per-output-type framing covered in Ch 37.
The first is aggregator equivocation and invalid aggregate construction under BLS. In Ethereum’s BLS attestation flow, an aggregator is a validator selected by the protocol’s BLS selection-proof mechanism (the is_aggregator() check and the SignedAggregateAndProof broadcast with a selection proof) to collect committee signatures from a subnet and broadcast a single aggregate (Ethereum Foundation, 2024). There is no separate long-lived aggregator key. The aggregator role attaches to the validator’s ordinary BLS signing key for the slot it is selected. A malicious aggregator can omit contributions, delay propagation, or publish an invalid aggregate. What it cannot do under honest BLS is cryptographically claim participation from validators whose signatures it does not possess: the aggregate verification fails against the claimed participant set unless the aggregator actually holds the matching partial signatures.
Under a Shor-capable adversary, the threat changes qualitatively. Registered BLS public keys become sufficient targets for discrete-log recovery, so an adversary that recovers any subset of validator signing keys can forge signatures for those validators and assemble aggregates whose participation bitmap matches the forged subset. The mitigation is the primitive swap (BLS to a post-quantum candidate) rather than rotating a notional aggregator key. The post-quantum candidates eliminate the aggregator role entirely at the no-threshold candidates because every validator’s signature ships independently; threshold-ML-DSA reintroduces a combine-round coordinator analogous to the aggregator role, with the partial-leakage exposure documented in the third attack category below. The coordinator’s bitmap is also weaker evidence than the BLS aggregator’s: the combined signature verifies against the fixed joint key whatever the bitmap claims. A threshold-sized coalition can therefore sign an attribution the named validators never made, and per-validator rewards and slashing need accountability evidence beyond the signature itself.
The second is registered-validator Shor against on-chain pubkeys. Every registered validator’s public key sits in BeaconState.validators[].pubkey from deposit processing onward (Ethereum Foundation, 2024), regardless of whether the validator has been activated or has signed any specific slot. The verifier needs every registered validator’s to compute aggregated during attestation verification. A CRQC running Shor against any registered recovers the signing scalar in polynomial time (Shor, 1994). The exposure horizon is from-deposit-to-rotation: every validator whose public key has been registered on chain since chain-tip 2026 has its key recoverable once the CRQC arrives. The mitigation is the primitive swap (BLS to a post-quantum candidate). The rotation cadence and the protocol’s key-change mechanism determine how stale the legacy keys can be without breaching the Mosca window.
The third is threshold-signature attack surfaces absent from the single-signer setting. A threshold-PQ scheme that allows cosigners out of to produce one verifier-compatible signature introduces attack surfaces a single-signer scheme does not face. These include nonce-generation failures across the cosigner set, abort-round leakage from aborted protocol executions, coordinator trust assumptions, transcript leakage from the multi-round combine protocol, side channels in partial-signature generation, key-share compromise, and threshold-specific cryptanalysis. These are protocol-specific risk classes rather than a generic break of every threshold-PQ proposal. Individual schemes will have different exposure profiles depending on their construction.
At chain-tip 2026, threshold ML-DSA is an active research and standardization area (NIST’s 2026 Multi-Party Threshold Schemes workshop tracks proposals along these lines (Bienstock et al., 2025)) rather than a NIST-final, multi-client, consensus-deployed primitive. The conservative operator defers threshold-PQ deployment until a candidate has public specifications, security proofs, interoperable implementations, and several years of cryptanalysis. The conservative-assumption preference for the consensus surface therefore moves to a no-threshold post-quantum candidate during the cutover and revisits threshold-PQ once a candidate reaches a chain-deployable status.
Tradeoffs
Section titled “Tradeoffs”The five candidates trade off on five axes. The security-category column distinguishes assumption class and NIST category so the byte and timing numbers are not read as an equal-security comparison.
| Candidate | Category / assumption | Aggregation | Per-set byte cost (1M validators) | Signing time class | Deployment status (chain-tip 2026) |
|---|---|---|---|---|---|
| BLS-BLS12-381 | classical pairing (Shor-vulnerable) | yes (G2 product) | 125 KB | fast | deployed on Ethereum mainnet |
| ML-DSA-65 | lattice, NIST category 3 | none | 3.3 GB | fast | FIPS 204 final |
| SLH-DSA-128s | hash-based, NIST category 1 | none | 7.86 GB | slow | FIPS 205 final |
| FN-DSA-512 | NTRU lattice, NIST category 1 | none | 666 MB | moderate | FIPS 206 under development |
| threshold-ML-DSA | lattice threshold, research | T-of-N combine | 128 KB on-chain | moderate (combine round) | research |
The two aggregation rows are normalized single-payload figures. Priced at one signature per committee, BLS’s 125 KB grows to roughly 322 KB and threshold-ML-DSA’s 128 KB to roughly 6.9 MB per epoch. Ethereum’s own BLS payload since Electra aggregates equal votes across committees and is smaller than that imposed figure.
The signing-time tiers in the table are qualitative. The fast cells correspond to microsecond-scale signing on a server-class CPU (BLS and ML-DSA-65). The moderate cells correspond to low-millisecond signing (FN-DSA-512 carries a Gaussian-sampling step; threshold-ML-DSA adds the combine round). The slow cells correspond to signing in the range of hundreds of milliseconds or longer (SLH-DSA-128s pays for the hypertree authentication path). A primary-source benchmark is the operator’s responsibility before locking the candidate.
An operator who weighs the prospect of a structural attack on the lattice problems takes the conservative-assumption preference: deploy SLH-DSA-128s for the long-lived validator-set key, accept the longer signing time per attestation, and pay the 7.86 GB per-validator-set byte budget. The byte-budget preference favors FN-DSA-512 once FIPS 206 reaches a final standard. FN-DSA-512 produces the smallest plain post-quantum signature at 666 bytes. The aggregation-density preference favors threshold-ML-DSA once the construction reaches a chain-deployable status.
The deployment-status axis is the binding constraint for any candidate selected at chain-tip 2026. Threshold-ML-DSA and threshold-SLH-DSA sit at the research stage with no NIST standard and no multi-year cryptanalysis history. An operator who deploys either accepts the protocol-specific risk classes documented in the threshold partial-leakage section above. FN-DSA-512 sits at FIPS 206 under development, with no Initial Public Draft yet released for public comment (Perlner, 2025). An operator who deploys it before FIPS 206 reaches a final standard accepts that the parameter set may change at finalization. ML-DSA-65 and SLH-DSA-128s are both NIST-finalized. An operator who deploys either has the strongest standards footing among the post-quantum options.
Figure 39.2 below is the five-by-four candidate-axis matrix. Rows are the five candidates; columns are aggregation property, per-set byte cost class, signing-time class, and deployment status. Cells encode the decision with a label plus a redundant non-color marker, mirroring the Ch 38 Figure 38.2 convention.
The per-validator-set byte tax against the BLS aggregate is the constraint the consensus migration is planned around. BLS at one million validators carries 125 096 bytes of aggregate-plus-bitmap; ML-DSA-65 at the same validator count carries 3.3 billion bytes of independent signatures, a factor of 26 452. No SNARK-based aggregation wrapper is chain-deployed at chain-tip 2026. The per-validator-set byte tax is the binding constraint until either a SNARK aggregator reaches a deployable stage or threshold-PQ does.
Exercises
Section titled “Exercises”-
Normalized per-validator-set byte budget at one million validators. Compute the normalized per-attestation-set byte budget under each of the five candidates (BLS-BLS12-381, ML-DSA-65, SLH-DSA-128s, FN-DSA-512, threshold-ML-DSA) at active validators, where the protocol must represent all contributions in one payload. Report the multiplicative factor against the BLS aggregate baseline. State which candidate carries the smallest per-set byte budget and which carries the largest. Note that this is not a literal Ethereum per-block estimate: Ethereum splits the validator set across slots, committees, and subnets.
-
BeaconBlock SSZ change for post-quantum attestations. Ethereum’s
AttestationSSZ container currently carriesaggregation_bits,data,signature(a 96-byteBLSSignature), andcommittee_bits. Sketch two SSZ designs for switching the consensus signature off BLS:- A naive per-validator ML-DSA-65 attestation design: one
Attestationper signing validator, no committee-level aggregate. Identify which fields collapse, what new fields appear (validator index, signature), and what the new per-attestation byte count is. - A hypothetical threshold-ML-DSA design assuming a deployable combine protocol: one combined ML-DSA-65 signature per committee plus a participation bitmap that keeps the
aggregation_bitsformat. Identify which fields change size, which retain their BLS-era shape, and which lose their role in verification. For each design, state the new verification rule the verifier-set must implement.
- A naive per-validator ML-DSA-65 attestation design: one
-
Open-ended: surface taxonomy on a proof-of-authority chain. Apply the Ch 36 surface taxonomy to a proof-of-authority chain with a fixed validator set of 21 validators. State which surfaces are present (transaction, consensus, wallet, on-chain-verifier, governance) and which differ from the Ethereum proof-of-stake setting. For the consensus surface, pick a candidate from the chapter’s matrix and justify the decision against the chain’s constraints (small fixed validator set, no churn, governance via off-chain coordination).
-
Strand validator-key rotation cadence under . Strand has 100 thousand active validators. Each validator-key rotation costs the operator 5 minutes of operational work (stop signing under the old key, register the new key, resume signing). Assume Strand parameterizes its churn limit at 8 validators per epoch (a Strand-specific ceiling at twice the 4 validators per epoch that Ethereum’s 128 ETH Electra churn floor permits at this validator count and balance). Justify a validator-key rotation cadence under . Compute the wall-clock time to rotate the full validator set once at the chain’s churn limit. Compare against the chapter’s framing that no emergency signing-key rotation is required under .
-
Open-ended: map to the Ch 30 four-phase program. Map the consensus migration to the Ch 30 four-phase program (discovery, first-wave, broad-rollout, end-of-migration). For each phase, name the validator-coordinator work-stream owner per the same Ch 30 framework (consensus-client team, validator-set operator, chain governance forum, slashing-monitor service). Justify each mapping in one sentence.
Solutions to Exercises 1, 2, and 4 are in Appendix D, Chapter 39; Exercises 3 and 5 are open-ended and have editorial-note treatments rather than worked answers. A separate track, for rebuilding rather than reading: the package exercises/ch39-consensus-staking has every function the chapter teaches replaced by a stub. Run PQC_IMPL=exercises pytest tests/ch39 to grade your version against the suite that proves the reference one.
References
Section titled “References”Last updated: