aere-research/aips/AIP-22.md

67 KiB

AIP-22: Post-Quantum-Only Finality (Chained Quorum Certificates, PQ Validator Identity, ECDSA Demoted to Compatibility)

Preamble

Field Value
AIP 22
Title Post-Quantum-Only Finality (Chained Quorum Certificates, PQ Validator Identity, ECDSA Demoted to Compatibility)
Author Aere Network Foundation
Type Standards Track
Category Core
Status Draft (design only; nothing described here is implemented or deployed at the Created date)
Created 2026-09-23
Requires AIP-15 (anchor certificate under the block hash), AIP-21 (per-block seal record), the per-message post-quantum enforcement of SPEC section 2.6 (in force on chain 2800 since block 17,700,000), AIP-19 (the acceptance process)
Supersedes None
Superseded-By None
Ratification Not ratified; testnet-gated (chain 28001 first, both clients), second-client-gated (both clients accept and refuse the same headers), founder-gated per activation height (AIP-19), external-audit gated before the canonical rule (section 4 of the Specification) is armed on chain 2800 (the gate AIP-15 already names)

Abstract

This AIP makes the finality of every block of an Aere QBFT chain a post-quantum property: a node that syncs from genesis establishes, for every block, that a quorum of validators sealed it with post-quantum signatures, without relying on any secp256k1 ECDSA signature. It does so with four changes, each activated by height and each a coordinated fork: (1) the anchor certificate's per-scheme seal count is raised from the current six of ten to Q, the QBFT quorum (seven of ten); (2) a Falcon-512 certificate is carried every 32nd block and the SLH-DSA-SHA2-128s certificate every 128th, so every block is covered, through the parent-hash chain, within 32 blocks by Q Falcon-512 seals (a single lattice assumption) and within 128 blocks also by Q SLH-DSA seals (a second, hash-based assumption); (3) validator identity becomes an address derived from the validator's post-quantum key, bound to all its keys by a versioned registry, so the validator set, the proposer rotation and message authorship no longer name an ECDSA key; (4) ECDSA commit seals and message signatures stop being validity criteria and remain only as a compatibility envelope on the wire, then leave the header. The design rejects a per-block certificate (259 to 370 GB per node per year at ten validators, measured cost basis), a per-block hash-based certificate (3.07 TB per year and seconds of signing per block, measured), STARK aggregation as the finality proof (the Falcon arithmetization is not measured; the proof is a history-compression layer, not a finality proof) and threshold Falcon (no standard, no audited implementation). Every quantity below carries its provenance; what is not measured is marked.

Motivation

Chain 2800 today has the following measured shape (sources in the Specification): every QBFT message on the hot path (proposal, prepare, commit, round-change) is refused unless it carries a valid Falcon-512 seal bound to its author, since block 17,700,000 on both clients; every 128th block carries a hybrid Falcon-512 + SLH-DSA-SHA2-128s certificate over its parent under the block hash, with at least six valid seals per scheme of the ten validators; and aere_getPqFinality returns, on every validator, the Falcon seals it heard for a recent block, re-verified (ten of ten on 2026-09-22). A validator that is online therefore finalizes nothing without post-quantum seals.

What remains classical is exactly what a node that is NOT online, one that syncs the history, is asked to believe:

  1. Between two anchors, the header of a block carries only ECDSA commit seals. A syncing node checks those and nothing post-quantum for up to 127 blocks (about 72 seconds at the measured block period). Its post-quantum assurance for those blocks arrives only with the next anchor, and the anchor's certificate is bound to the parent hash, so the assurance is real but delayed, and it is not stated as a rule anywhere.
  2. The certificate threshold is six of ten (schedule step 14961456:6), which is f + 3 at N = 10 and below the QBFT quorum of seven (recorded in the repository's findings register on 2026-09-11). A hostile reader is right to say: the certificate proves that six validators signed, it does not prove that consensus was reached.
  3. Validator identity is an ECDSA address: the validator list in extraData, the proposer rotation, the coinbase, the vote recipient, the registry's claim, and the peer-forwarding predicate of the Besu-derived client (it forwards Istanbul messages only to peers whose node-key address is in the set, measured 2026-09-02) all name secp256k1 keys. The Falcon registry binds an index to that address; the address itself is classical.
  4. The ECDSA signature of every consensus message and the ECDSA commit seals in every header are still validity criteria. The live security is therefore "ECDSA AND Falcon" for an online node, which is stronger than either alone, and "ECDSA, then Falcon at the next anchor" for a syncing one.

The Foundation's stated goal, restated on 2026-09-22, is a consensus whose safety and finality do not depend on ECDSA at all. This AIP is the path from the measured state above to that goal, with the cost of each step in bytes, disk, bandwidth and latency, and with the founder decisions it needs named.

Specification

Notation: N the validator set size at a height, f = floor((N - 1) / 3), Q = ceil(2N / 3) the QBFT commit quorum (Besu BftHelpers.calculateRequiredValidatorQuorum; 7 at N = 10, 14 at N = 21). hash(B) is the on-chain block hash (round forced to zero, commit seals and certificate excluded, SPEC section 2.3). M(B) = keccak256(RLP["AERE-PQ-COMMIT-1", chainId, number(B), hash(B)]) is the commit-seal message already in force (SPEC section 3.3). Scheme wire identifiers are those of the v2 certificate: 1 = Falcon-512, 2 = SLH-DSA-SHA2-128s.

Measured constants used throughout, with source:

Quantity Value Provenance
block period 0.565 s (band 0.56 to 0.63 s across September) measured 2026-08-24 over 2,000 blocks (strategie/agregare-pq/CIFRE-MASURATE.md #4); band from the operating notes of 2026-09-11 and 2026-09-22
blocks per year at 0.565 s 55,854,159 derived from the above (STUDIU-2026-08-24.md, section 2 conventions)
blocks per day ~152,900 derived (CIFRE #4)
Falcon-512 seal in extraData, with index and RLP wrapper 663 B (field 648 to 660 B, mean 655.1) measured on 178 seals of 20 live anchors (CIFRE #1)
SLH-DSA-SHA2-128s signature 7,856 B (+5 B wrapper, estimate) spec FIPS 205 (CIFRE #2)
ECDSA commit seal 65 B measured (CIFRE #8)
live hybrid anchor certificate at nine Falcon + nine SLH-DSA seals 77,386 B measured 2026-09-05 on anchor 17,184,144 (operating notes)
ordinary header at N = 9 1,259 B (extraData 634 B) measured 2026-09-04 on block 17,047,599 (consensus-pqc/COSTUL-DISCULUI-HIBRID-2026-09-04.md); 634 B from CIFRE #1
total database growth per validator 58 to 71 GB per year, headers about 95% of disk measured on the fleet in August 2026 as size divided by height (operating notes; STUDIU-2026-08-24.md section 1)
Falcon-512 verify 0.068 ms median (Bouncy Castle, validator-class host); 0.092 ms median, 0.215 ms p95 (rehearsal host) measured (audit-package-pq-consensus/evidence/EVIDENCE-INDEX.md, falconbench-bouncycastle.txt; consensus-pqc/ancora-v2/README.md)
Falcon-512 sign 0.60 ms median measured (same evidence index)
SLH-DSA-SHA2-128s sign on the consensus thread 0.3 to 0.7 s per signature with the JDK digest (1.4 to 2.7 s before) measured 2026-09-04 on chain 2800 (findings register)
SLH-DSA-SHA2-128s verify 0.669 ms median, 1.494 ms p95 on a 2-vCPU reader host with the fleet's jars (Falcon-512 on the same host and path: 0.367 ms median, ratio 1.8); 0.966 ms median on a laptop (ratio 2.9); the gas proxy (350,000 against 40,000, ratio 8.75) is not a time proxy on the consensus path measured 2026-09-22 (consensus-pqc/aip22-treapta0/REZULTATE.md, SealSchemeBench.java on SealSchemes, negative control 30 of 30 refused)
from-genesis import rate with ten peers ~1,300 blocks per second measured 2026-09-11 (findings register)
anchor cycle on the live chain (anchor parent + anchor) 1.33 to 2.00 s against 0.565 s for an ordinary block measured 2026-09-04 and 2026-09-05 (findings register)
FRI proof, production parameters (log_blowup 1, 100 queries, 2^20 rows) 639,032 B content, 655,044 B on disk; generation 6.1 to 7.1 s single thread on a laptop; verification 80 to 91 ms measured 2026-08-25 (strategie/agregare-pq/DOVADA-FRI-MASURATA-2026-08-24.md); the FRI component only, not a Falcon arithmetization

1. The target, stated exactly

Definition (post-quantum finality of a block). From the activation height H_fin (section 4), a block B of the canonical chain is post-quantum final when there exists a canonical anchor block A with number(A) > number(B) whose certificate carries, for every scheme the scheme-interval schedule requires at number(A), at least Q(number(A) - 1) valid seals of distinct validator indexes over M(parent(A)), verified against the registry epoch bound at number(A) - 1, and the parent-hash chain from parent(A) down to B is valid. The finality is single-assumption when the covering anchor carries only the Falcon-512 certificate and dual-assumption when it also carries the SLH-DSA-SHA2-128s certificate.

What the definition rests on. Two cryptographic assumptions and nothing else: the unforgeability of the scheme(s) in the covering certificate, and the collision resistance of keccak-256, which is what makes hash(parent(A)) a commitment to every ancestor. Keccak-256 is a hash function; the relevant quantum collision attack (Brassard, Hoyer, Tapp) is about 2^85 operations with impractical memory, and Grover's preimage attack leaves about 2^128, so 256-bit output holds under current public knowledge (STUDIU-2026-08-24.md, section 6). No ECDSA signature appears in the definition.

Bounded delay. With the Falcon certificate every I_F = 32 blocks and the SLH-DSA certificate every I_S = 128 blocks (section 2), every block becomes single-assumption post-quantum final within at most 32 blocks (about 18.1 s at 0.565 s, estimate from the measured period) and dual-assumption final within at most 128 blocks (about 72.3 s). Before that, an online validator already holds at least Q Falcon commit seals for the block, because a commit has counted only with a valid seal since block 17,250,000 (AIP-21 exposes them, re-verified, through aere_getPqFinality); that record is the zero-delay, verifiable, non-canonical proof, and the anchor is the canonical, permanent one. The two are the same claim at two ages, exactly as AIP-21 states for the anchor today.

The transition principle. ECDSA is not removed from the wire in one step. It is first demoted from a validity criterion to a compatibility envelope (section 4), then removed from the header (section 5). At no activation height does a node accept a block on ECDSA alone that it would have refused before; every step only tightens what a syncing node requires.

2. Per-block proof: the options, with cost, and the choice

Costs are the post-quantum overhead per block, over the ECDSA baseline that remains until section 5, as in the sizing study. "All N" attaches every heard seal (K is a floor: measured 8 to 9 of 9 attached at N = 9, cap 9 today per the findings register of 2026-09-11); "Q only" caps the proposer at the quorum.

Option Bytes per block, N = 10 (Q = 7) GB per node per year, N = 10 N = 21 (Q = 14) Bandwidth per event, serial to N-1 peers at 100 Mbps (hypothesis of the study, not measured) Latency Verdict
(1) Falcon quorum certificate in every header (over the parent) 4,641 (Q only) to 6,630 (all 10) 259.2 to 370.3 9,282 to 13,923 B per block, 518.4 to 777.7 GB 4.8 ms at N = 10, 22.3 ms at N = 21: holds 7 verifies 0.5 ms, sign 0.6 ms: negligible rejected on disk: 4 to 6 times the whole measured growth of a node today; AIP-21 rejected the same family on 2026-09-17 at 247 GB to 2.9 TB
(2) SLH-DSA quorum certificate in every header 55,027 (Q only) to 78,610 (all 10) 3,073 to 4,391 110,054 to 165,081 B per block 56.6 ms at N = 10 for 78,610 B: just above the rule; 264 ms at N = 21: violated signing 0.3 to 0.7 s per validator per block on the consensus thread (measured); per-commit SLH-DSA took testnet 28001 to 4 s per block on 2026-09-03 (testnet record) rejected twice: disk and block period
(3a) Per-block certificate written k blocks later same bytes as (1) same same same delay k buys the proposer gathering time, nothing else rejected: the delay does not reduce the bytes
(3b) Chained quorum certificate on a grid (this AIP): anchor A carries the certificate over parent(A); the parent-hash chain extends it to every block below Falcon all 10 at I_F = 32: 207.2; SLH-DSA all 10 at I_S = 128: 614.1; total 821.3 11.6 + 34.3 = 45.9 (Q only: 8.1 + 24.0 = 32.1) Falcon all 21 at 32: 435.1 B, 24.3 GB; SLH-DSA all 21 at 128: 1,289.7 B, 72.0 GB; total 96.3 GB Falcon anchor 6,630 B: 4.8 ms (N = 10), 22.3 ms (N = 21): holds; hybrid anchor 85,240 B at N = 10: 61.4 ms, just above the 56.5 ms rule (the live anchor cycle, 1.33 to 2.00 s measured, is the binding constraint today, not propagation); at N = 21 the SLH-DSA anchor (165 KB) takes 264 ms: violated at 100 Mbps, 26.4 ms at 1 Gbps Falcon: negligible; SLH-DSA anchor cycle 1.33 to 2.00 s measured today, unchanged by this AIP chosen; delta against today's live cost (ten plus ten seals at 128: 37.2 GB) is +8.7 GB per node per year
(4) STARK proof per epoch that "Q seals verify" 639,032 B (FRI component only, full proof larger and [NOT MEASURED]) per epoch: 4,992 B per block at epoch 128, 624 B at 1,024, 4.2 B at one proof per day 278.8 at epoch 128; 34.9 at 1,024; 0.23 at one per day constant in N (that is its only advantage) 460 ms at N = 10, 1,022 ms at N = 21: violated at every N if the proof is in the block's critical path generation 6.1 to 7.1 s single thread for the FRI component; the Falcon arithmetization and its trace height are [NOT MEASURED]; if the trace needs 2^22 rows, 21 to 27 s (extrapolation) not the finality proof: it is asynchronous by necessity, it is larger than a Falcon certificate at any epoch under 108 anchors, and its cost is unmeasured where it matters; it is the history-compression layer of section 7
(5) Threshold or aggregate Falcon not applicable excluded: no NIST standard aggregates Falcon (FIPS 206 draft standardizes single signatures), Falcon signatures are Gaussian samples on an NTRU lattice and do not add across keys, and no audited implementation exists; the chain's crypto-agility (section 4) lets it be adopted if that changes

Derivations, so they can be checked: GB per year = bytes per block x 55,854,159 / 10^9. Falcon all 10 = 10 x 663 = 6,630 B; Q only = 7 x 663 = 4,641 B. SLH-DSA all 10 = 10 x 7,861 = 78,610 B; Q only = 55,027 B. Live today: 9 + 9 seals at 128 = 77,386 B measured = 604.6 B per block = 33.8 GB; ten plus ten = 85,240 B = 666 B per block = 37.2 GB. Serial propagation time = bytes x 8 x (N - 1) / 10^8 s; the 56.5 ms rule is 10% of the block period, the sizing study's house rule. The bandwidth between validators has never been measured; the 100 Mbps figure is the study's named hypothesis.

Why (3b) and why these intervals. The anchor already is a chained quorum proof in everything but threshold and statement: its certificate signs M(parent(A)), and hash(parent(A)) commits to every earlier block. Making it the finality criterion costs no new format (the v2 certificate is already scheme-tagged) and no new gathering mechanism (the proposer of A finalized parent(A) by hearing at least Q sealed commits, since block 17,250,000). I_F = 32 is the grid the chain ran on from 13,014,000 to 17,225,968 at N = 9 without a rate change (measured 0.565 s across that period), so its cost and liveness are not an estimate; I_S = 128 is the grid in force today and keeps the SLH-DSA cost at its measured level. The Falcon-only intermediate anchors add 3 x 6,630 / 128 = 155.4 B per block, that is +8.7 GB per node per year, and bring single-assumption finality from 72 s to 18 s. A smaller I_F (16: +23.1 GB total Falcon, 9 s; 8: +46.3 GB, 4.5 s) is a founder choice with the table above; this AIP recommends 32.

Certificate at a Falcon-only anchor. The v2 encoding, unchanged: RLP[2, [[1, index, signature], ...]] under domain AERE-PQ-ANCHOR-2, digest in vanityData as today. A scheme-interval schedule (section 2.1) states which schemes are required at which anchor heights; the minimum applies per scheme, as today. A certificate that carries an SLH-DSA row at a height where the schedule does not require it is still verified and still counted for that scheme, exactly as any surplus seal is today; a certificate that lacks a required scheme's quorum is invalid.

2.1 Parameters

Property (Besu-derived; Nethermind-derived twin in parentheses) Meaning Value proposed for chain 2800
aere.pq.anchorMinSeals step (AERE_PQ_ANCHOR_MIN_SEALS) per-scheme minimum, floor semantics, existing property <H_K>:7 appended; at N = 21 a further step :14 in the epoch that admits the eleventh validator
aere.pq.anchor.maxSeals (AERE_PQ_ANCHOR_MAX_SEALS) proposer cap, existing 10 (raised from today's 9), then N
aere.pq.schemeIntervalSchedule (AERE_PQ_SCHEME_INTERVAL_SCHEDULE), new from height h, scheme s is required at anchor heights a with (a - H_grid) mod I_s == 0; I_s MUST be a multiple of the base anchor interval; the anchor grid itself becomes the finest interval named <H_I>:falcon-512/32+slh-dsa-sha2-128s/128
public verifier SCHEME_INTERVAL_SCHEDULE the same rule in tools/verify-anchor.mjs same

The threshold guard (PqAnchorThresholdGuard, doctrine of 2026-08-20) refuses a step above N - f and warns at or above Q; at N = 10, Q = N - f = 7, so K = 7 is configurable today and starts under the guard's "liveness tax" warning. The warning's arithmetic is the honest statement of the cost: with f = 3 validators down, an anchor needs every one of the remaining seven seals. QBFT itself needs those same seven to commit any block in that state, so the new condition is not a new fault tolerance, it is a timing condition on the anchor's proposer, bounded by a round change (section 8, Liveness).

3. Validator identity from the post-quantum key

3.1 The identifier

From the epoch activation height H_id, a validator is identified by

id = keccak256(0x50 || 0x20 || falcon512_public_key)[12:32]

where falcon512_public_key is the standard 897-byte encoding (header byte 0x09 followed by the 896-byte h polynomial; the registries of today store the 896-byte polynomial without the header, SPEC section 3.5, and implementations MUST prepend it before hashing). This is exactly the sender derivation of AIP-20 with the identifier that AIP-20 reserves for Falcon-512 (alg_id 0x20), so that when a later AIP activates Falcon-512 transactions, the validator's coinbase proceeds are spendable by the validator's own consensus key with no classical key. Until such an AIP, the id receives whatever the fee rules route to coinbase and cannot spend it; this is stated, not hidden.

The id is assigned at the validator's first registration under registry v3 and is retained through key rotations (section 3.2): it is a label after that, not a live derivation. A hostile reader should note the consequence: if Falcon-512 falls, the label's account is as exposed as any Falcon account; the consensus is not, because the hybrid rule requires the SLH-DSA seal of the same index and the registry binds both keys to the id.

3.2 Registry v3

A registry epoch is a JSON manifest with rows keyed "0".."count-1", formatVersion 3, chainId, bindHeight, count, and per row:

Field Content Status
id 20 bytes, section 3.1 required
keys map scheme name to public key: falcon-512 (897 B standard encoding), slh-dsa-sha2-128s (32 B); further schemes as the scheme registry admits them required, at least the schemes the scheme-interval schedule names
pop map scheme name to a possession proof by that key over `"AERE-PQ-POP-3"
rotation when a row changes any key against the previous epoch's row of the same id: a signature by EACH of the previous epoch's keys of that id over the new row hash, domain AERE-PQ-ROTATE-3 required on a changed row, absent otherwise
ecdsa { addr, claim }: the validator's classical address and an EIP-191 claim by that key over the row hash in the AERE-PQ-CLAIM-1 context of today required in the epoch that performs the switch at H_id (it is the verifiable link from the old set to the new one), optional afterwards
transport { secp256k1Address }: the address of the node key the validator's client uses on RLPx optional; see 3.4

Row hash: keccak256("AERE-PQ-ROW-3" || canonical serialization of the row without rotationandecdsa). Registry hash: the root of a keccak-256 binary Merkle tree over the row hashes in index order (odd node duplicated), domain-separated as keccak256("AERE-PQ-REGISTRY-3" || uint64be(chainId) || uint64be(bindHeight) || uint32be(count) || root). The Merkle form exists so that a row's membership can be proven on chain with ceil(log2(count)) hashes (section 6); the v1 and v2 pre-images are flat and cost the whole registry as calldata. The v3 hash is pinned exactly as today: slot 0 of a new immutable anchor contract for a live chain (AIP-15, exercised on chain 2800 at 13,889,290, 13,600,000 and 18,082,816), or pqRegistryHash in the genesis config for a new chain (SPEC section 1.5). The domain change guarantees that no v1 or v2 file can satisfy a v3 schedule entry.

Loading is strict, as today: count present, indices exactly 0..count-1, every required scheme present with a verifying pop, every changed row carrying verifying rotation signatures by all previous keys, an ambiguous file refuses rather than hashes.

3.3 What changes in QBFT

Where Today From H_id
extraData element 1, the validator list 20-byte ECDSA addresses 20-byte ids; at exactly H_id the list is the registry's ids in the order of the registry index of each validator of the set at H_id - 1, obtained through each row's ecdsa.addr; a set member without a v3 row at H_id is a configuration fault that refuses startup on every node, never a silent drop
extraData element 2, the vote recipient is an ECDSA address recipient is an id; a vote for an id with no row in the head registry is invalid
coinbase the proposer's ECDSA address, checked against the expected proposer the proposer's id, same check
proposer selection upstream round-robin over the ordered validator list the same upstream rule over the list of ids; both clients MUST order identically (the list as carried in the parent's extraData) [NOT MEASURED: the upstream selector is outside the Aere overlay; the conformance vector of section 9 pins the order]
message authorship (proposal, prepare, commit, round-change) the ECDSA-recovered address, which MUST be the address the registry binds to the seal's index (SPEC 2.6, rule 2) the registry row of the seal's index; row.id MUST be in the validator set of the height; the upstream ECDSA signature stays on the wire (the envelope is unchanged) and its recovered address MUST equal row.ecdsa.addr while that field exists in the head registry, and is not examined once it does not (section 4)
anchor rule R2, step 8 (SPEC 3.4) index resolves to an address that must be in the parent's validator set index resolves to an id that must be in the parent's validator set; two indices resolving to one id reject, as today
genesis of a new chain validators are ECDSA addresses validators are ids and pqRegistryHash names a v3 registry with bindHeight 0; the genesis set is then post-quantum from block 0 and the ecdsa field is never needed
history a from-genesis node judges sets below H_id by addresses and above it by ids, with the registry history list (never pruned, SPEC 3.2) providing every epoch

3.4 Peer forwarding

The Besu-derived client forwards Istanbul messages only to peers whose RLPx node-key address is in the validator set (measured 2026-09-02 on testnet 28001: a validator whose node key differed from its validator key received no consensus messages). With ids in the set, that predicate has no ECDSA address to match. From H_id a client MUST forward to every peer that (a) has negotiated the Istanbul capability and (b) either presents a node-key address listed as transport.secp256k1Address in a row of the head registry whose id is in the set, or, when no row lists a transport address, is any connected peer with the capability. Node identity on RLPx remains secp256k1 ECDSA; this AIP does not change the transport (Security Considerations).

4. ECDSA demoted: the canonical finality rule

From H_fin (a height at or above H_id), on every node that validates or reads blocks:

  1. The certificate chain is required for canonicality. A chain is canonical only if every anchor height at or above H_fin carries a certificate satisfying section 1 for every scheme the schedule requires there. A missing or short certificate at an anchor height is an invalid block, as today; in addition, a node MUST NOT extend its canonical head more than I_F blocks past the last anchor it has verified, so a fork that cannot produce certificates cannot be followed beyond one Falcon interval.
  2. ECDSA commit seals are not a validity criterion. The rule that a header carries at least Q ECDSA committed seals of the parent's set is no longer applied to headers at or above H_fin; the element MAY be present and MAY be empty. Between anchors a header is admitted on the basis of the hash chain, the proposer check and, until section 5, the ECDSA seals as an anti-spam admission filter whose failure is a refusal but whose success proves nothing about finality. The finality of the block is established only by the covering anchor (section 1).
  3. The ECDSA signature of a consensus message is not a validity criterion. The message counts as a vote iff its post-quantum seal(s) verify and bind to an id in the set (section 3.3). The envelope is kept because the upstream wire format carries it and because the second client's decoder expects it; a validator MAY sign it with any secp256k1 key. Precisely: a proposal, prepare or round-change has an author at all only once its seal verifies under the key of its index's row over the message of its own domain (a round-change in the form its prepared claim names), because the author also decides whether a message is relayed, and the relay happens before the vote is judged; a commit's author is its index's id only when that id is the commit seal signer's, and its seal is judged by the commit layer. A node refuses to start with H_fin set if any of the four seal layers is not armed at or below H_fin (AERE-PQC-FIN-02), and a validator refuses if it would not seal all four messages from H_fin (AERE-PQC-FIN-03): an unsealed message has no author, so such a validator would be silent from H_fin while looking healthy.
  4. Provisional tail and rollback. A block imported between anchors is provisional until its covering anchor is imported. A node that receives a valid anchor whose parent chain differs from its provisional tail MUST reorganize to the anchored chain; the depth of such a reorganization is at most I_F (32) blocks by rule 1. This is new behaviour for a QBFT client, whose head has been final on import until now, and it is a testnet gate (section 9, Stage 4) with the explicit negative control: a reader node fed a classical-only fork of up to 31 blocks rolls back to the honest anchor within one interval, in both clients.
  5. Weak subjectivity, named. A node that syncs from genesis with no other knowledge can be served, by an eclipsing peer, a fork that ends before the first enforced anchor (block 13,034,000, where the certificate schedule first required a seal); such a fork can never carry a later certificate and so can never reach the height of the honest chain, but an eclipsed node does not know that height. A syncing node therefore SHOULD be given a recent anchor (height and hash) out of band, from the published registry epoch or from the operator, and MUST refuse to consider a chain canonical that does not reach it with valid certificates. This is the same requirement every finality-gadget chain has, and it is the honest replacement for the statement "history below H is protected by ECDSA only": with the checkpoint, a rewrite at any height, including below 13,014,000, would have to reproduce every certificate above it, and the strongest of those requires Q post-quantum keys.
  6. Fallback and crypto-agility. The schemes required at an anchor are named by the scheme-interval schedule, by height; the keys are bound by the registry epoch, by height; the on-chain scheme registry (CryptoRegistry, AIP-4 and AIP-7) names what verifiers exist. Retiring a scheme, adding one (ML-DSA-65 keys would be a founder ceremony: new keys), or changing an interval is a schedule step at a future height on every node that judges headers, the procedure the fleet has executed for the base-fee floor, the seal threshold, the hybrid, the interval and the four message layers. Because the hybrid rule is a conjunction, a scheme that is broken does not weaken the certificate (the adversary still needs the other); a scheme whose implementation stops producing seals halts anchors, and the answer is a uniform schedule step or the existing uniform emergency options, never a single node's setting.

5. ECDSA out of the header

From H_hdr (at or above H_fin), extraData gains element 6, proposerSeal = [index, signature], a Falcon-512 seal by the proposer over the message the proposal already signs, keccak256(RLP["AERE-PQ-PROPOSAL-1", chainId, height, round, proposalDigest]), where proposalDigest is the QBFT proposal digest recomputable from the stored header (the round is element 3 of the stored extraData; the digest is the EXCLUDE_COMMIT_SEALS encoding hash, SPEC 2.3). Element 6 is outside the hash (like the commit seals and the certificate), present only when non-empty, and subject to the strict codec. From H_hdr a header is admitted between anchors iff the proposer seal verifies for the coinbase id at that height, and the ECDSA committed seals element MUST be empty. Cost: +663 B and -455 B (7 x 65) per block at N = 10, net +208 B, that is +11.6 GB per node per year (208 x 55,854,159 / 10^9). After H_hdr no ECDSA signature appears in any header or is examined in any consensus message; the last classical use is the RLPx transport.

6. Equivocation evidence and consequences without stake

Evidence object. PqEquivocation = [type, height, round, payloadA, sealA, payloadB, sealB, registryProof] where type is one of the four message domains, the two payloads are the upstream RLP payloads of two messages of that type at the same height and round with different digests (for round-change, different prepared digest at the same target round), the seals are the two Falcon-512 seals of the same index over the respective pre-images of SPEC 2.6, and registryProof is the v3 Merkle path of that index's row in the epoch bound at height. The object is valid iff both seals verify under the row's Falcon key, the index is the same, and the digests differ. A second form, PqConflictingAnchors = [anchorHeaderA, anchorHeaderB, registryProofs], two anchor headers at the same height with different parent hashes and each with a valid certificate of at least Q seals: by the quorum-intersection bound proved for all N in formal-consensus/qbft_safety_smt.py (L1: 2Q - N >= f + 1), the two certificates share at least f + 1 = 4 indexes at N = 10, each of which double-signed. This is accountable safety: a finality violation names its authors by their post-quantum seals, and it needs K = Q (section 2), which is one more reason for that step.

On-chain verification. An immutable, ownerless contract PqEquivocationEvidence accepts the object, verifies each seal with the live Falcon-512 precompile at 0x0AE1 (40,000 gas flat per verification, input framing of SPEC 4.2, live since block 9,189,161) and the SLH-DSA precompile at 0x0AE4 for a hybrid seal, verifies the Merkle path against the registry hash pinned in slot 0 of the epoch's anchor contract, and records (index, id, height, type) permanently. Gas per submission: 2 verifications plus calldata of roughly 2 x 663 B plus two payloads plus a Merkle path (estimate: under 300,000 gas; to be measured on the reference implementation).

Consequence. The set is permissioned and unstaked, so the only on-chain consequence available is removal: the remaining validators vote the id out with the QBFT vote element, and a client MAY refuse to count further messages from an index that a verified evidence record names, only from a height at which every node has the record (a schedule step, never a local decision, for the same reason as every other parameter here). A future AIP that introduces a bond can slash against the same record without a new evidence format. Stated plainly: on chain 2800 today all ten validators are operated by the Foundation, so "the remaining validators vote" is one party voting; the evidence record is nevertheless a public, independently verifiable fact, which is what this section is for.

7. History compression (research track, not a finality mechanism)

Once every anchor is a quorum certificate, a proof that "every anchor in [a, b] carried a valid certificate of at least Q seals under the registry epoch in force" lets a node prune the SLH-DSA seals of that range and keep the proof. The sizing study's arithmetic stands: at one proof per day the stored cost is 0.23 GB per node per year at any N (measured FRI size, one proof per 152,900 blocks), against 34.3 GB for the SLH-DSA seals themselves at N = 10. Admissibility criterion, from the study and binding here: the proof system's soundness MUST reduce to a plausibly post-quantum assumption (hash-based, FRI); a Groth16, PLONK or KZG proof on an elliptic-curve pairing is excluded because its soundness falls to Shor, and the adversary would forge the aggregation proof rather than a single seal. What is measured: the FRI component at production parameters (639,032 B, 6.1 to 7.1 s single thread, 80 to 91 ms verification, on a laptop). What is not: the arithmetization of Q Falcon-512 verifications (the AIR), its trace height (2^20 is an unverified assumption; 2^22 would give 773,496 B and 21 to 27 s by the measured slope), the same for SLH-DSA (a hash tower, much larger), generation on validator hardware, and multi-thread scaling. A node that syncs after pruning trusts the proof verifier and the registry binding instead of the seals; the STARK-verify precompile of AIP-16 is a skeleton that verifies nothing. Nothing in this section is on the activation path of sections 2 to 5.

8. Sync: what a from-genesis node verifies, and the cost

Per block: the hash chain (one keccak of the header, already done), the proposer check, and after H_hdr one Falcon verification (0.068 to 0.092 ms median measured on validator-class hosts in July, 0.215 ms p95; 0.367 ms median on a 2-vCPU reader host on 2026-09-22). Per Falcon anchor (every 32 blocks): up to N Falcon verifications, 0.7 ms median to 3.7 ms at N = 10 depending on the host; per hybrid anchor (every 128): additionally up to N SLH-DSA verifications, measured 2026-09-22 at 0.669 ms median (1.494 ms p95) each on the 2-vCPU reader host with the fleet's jars, so about 6.7 ms per hybrid anchor. Amortized per block: about 0.02 to 0.12 ms (Falcon at 32) plus about 0.05 ms (SLH-DSA at 128), against a measured import budget of about 0.77 ms per block (1,300 blocks per second with ten peers, 2026-09-11); the post-quantum verification is therefore under 10% of import time on the measured host. The earlier gas-proxy estimate (8.75 x Falcon) overstated the ratio: on the consensus path (JDK digest) SLH-DSA verification costs 1.8 times a Falcon verification on the same host. The whole history's anchors have been walked once by the independent Nethermind-derived watcher (134,954 anchors, 2026-09-08, operating notes), so the verification of every certificate ever produced is a measured, repeatable operation, not a projection. Memory: the AIP-21 side store holds about 7 kB per block for ten seals over a 256-block window (AIP-21); a syncing reader does not need it.

Liveness at K = Q. A proposer builds the certificate for parent(A) from the commit seals it heard. A proposer that finalized parent(A) through its own QBFT round holds at least Q of them by construction (a commit counts only with a valid seal since 17,250,000). A proposer that imported parent(A) by block gossip or sync, or that restarted and lost its seal store (the store is node-local and volatile; findings register, 2026-09-03 and 2026-09-05), cannot build it and its round times out; the next proposer in rotation takes the anchor. Measured before this AIP, at K = 6 with 8 to 9 seals attached: 12 of 12 anchors at round 0 (2026-09-05); 10 of 10 Falcon seals verified on every validator's AIP-21 record (2026-09-22). The round-0 rate at K = Q is [NOT MEASURED] and is Stage 1's testnet gate.

9. Cross-client determinism and conformance

Both clients of chain 2800 MUST: compute the same id from the same key; load, hash and refuse the same v3 registries; translate the set identically at H_id; order the validator list identically; accept and refuse the same anchors under the same scheme-interval schedule and thresholds; roll back the same provisional tail on the same anchor; verify the same equivocation objects. Conformance vectors are published with the reference implementation: a v3 registry with rotation, a set translation at a fixed height, a Falcon-only anchor, a hybrid anchor, a short certificate, a certificate with a surplus scheme, a proposer seal, an equivocation pair, a classical-only fork of 31 blocks; each invalid vector is refused by both clients for its stated reason (the lesson of AIP-20: a negative vector differs from the valid one in exactly one field, and the refusal names the field).

Rationale

A chained certificate instead of a per-block one. The parent-hash chain is a commitment; a quorum certificate on it covers everything below. Writing the same seals in every header multiplies disk by the interval for no additional binding. The cost table is the argument: 45.9 GB against 259 to 370 GB per node per year.

Two intervals instead of one. Falcon seals are cheap to make (0.6 ms) and to store (663 B); SLH-DSA seals are expensive to make (0.3 to 0.7 s on the consensus thread) and to store (7,861 B). Coupling them at one interval forces the choice between a slow single-assumption finality (128 blocks) and an SLH-DSA disk bill four times today's. Decoupling gives 18 s single-assumption and 72 s dual-assumption finality for +8.7 GB.

K = Q instead of a threshold below it. Below the quorum the certificate proves participation, not consensus, and the accountable-safety bound of section 6 does not hold. The guard already permits 7 at N = 10; the cost is the liveness timing condition of section 8, bounded by a round change.

An address derived from the Falcon key, with the AIP-20 derivation. One derivation for accounts and validators removes a class of confusion and lets a validator spend its coinbase proceeds with its consensus key once Falcon transactions activate. A separate payout address was considered and rejected: it adds a field and a validation rule to every header for the sake of the transition period only.

Rotation chain instead of re-deriving the id at every epoch. A scheme rotation must not change the validator set; keys are what rotate, the identity is what persists, and the previous keys sign the hand-over.

Merkle registry hash. The flat pre-images of v1 and v2 were right for a fail-closed loader; on-chain evidence needs membership proofs, and the domain change makes the two forms unconfusable.

Not a STARK in the finality path. The measured FRI proof is 100 times a Falcon certificate at N = 10 and would violate the propagation rule at every N; the Falcon arithmetization is unmeasured; and an asynchronous proof cannot be a validity criterion for the block it attests. It is the right tool for pruning, later.

Not a hybrid-flag hard removal of ECDSA on day one. Every step here tightens what a syncing node requires and never loosens what an online node requires. Removing the envelope from the wire would change the upstream message format on both clients for no security gain; removing it from the validity rules is the security gain, and that is section 4.

Alternatives rejected, in one line each: per-block certificate (disk); per-block SLH-DSA (disk and period, measured); Merkle root plus sidecar for full nodes (saves nothing for a full node and moves light-client trust to data availability, study section 6; it remains the right tool for light clients and is not excluded for them); XMSS or other stateful hash-based signatures (a key exhausts in 6.9 days at the block rate and a restore from backup is a reuse, study section 2); elliptic-curve SNARK aggregation (soundness falls to Shor, study section 3); threshold Falcon (no standard).

Backwards Compatibility

Every activation height here is a coordinated fork: the same binary and the same schedule on every node that validates or reads blocks (the validators of both clients and every reader, whoever operates it), armed before the height, one node at a time with cooling between restarts (SPEC section 2.6 and the published activation procedure): a node that judges headers on a different binary or a different schedule diverges from the validators at the height, so readers are armed with the validators, never after them. Below each height nothing changes. Headers produced before H_hdr keep their ECDSA seals and remain valid at their heights; the strict codec round-trips them unchanged. The public verifier tools/verify-anchor.mjs needs the scheme-interval schedule (Stage 2), the v3 registry and ids (Stage 3), and the proposer seal (Stage 5), each published in the same hour as the fleet change (a registry epoch that the public verifier does not know makes it reject every anchor the new signer takes part in). The published follower configuration in RUN-A-NODE.md and the SPEC gain the new properties at each stage. The ZK light client contracts (AereZkQbftLightClient, canonical verifiers anchored to the seven-validator set; findings register, 2026-09-05 and 2026-09-11) verify ECDSA quorums with an elliptic-curve SNARK and cannot attest post-quantum finality; after H_fin a light client either verifies anchor certificates directly (the published verifier already does) or waits for a hash-based proof system (section 7). Integrators that read extraData element 1 as ECDSA addresses must read ids from H_id; eth_getBlockByNumber is otherwise unchanged; coinbase becomes an id.

Security Considerations

  • Threat model. An adversary who holds every classical validator key and no post-quantum key (the posterior-corruption, long-range rewrite; peer-reviewed treatment of the threat: Azouvi, Danezis, Nikolaenko, "Winkle", IACR 2019/1440, AFT 2020; the quantum framing and this defence are Aere's own). "Harvest now, decrypt later" does not apply to signatures and is not what this AIP defends against.
  • What this AIP achieves against that adversary, per height. Today: cannot finalize a block online (message seals); can serve a syncing node a tail of up to 127 blocks that the next anchor invalidates. After H_K and H_I: the same, with the tail bounded at 31 blocks and every covering certificate a quorum. After H_id: cannot name a validator, vote, or propose in any set, even for a syncing node. After H_fin: cannot cause any node to consider any block final. After H_hdr: cannot produce a header that any node admits at all.
  • What it does not achieve. Node-to-node transport (RLPx) is authenticated by secp256k1; an adversary with node keys can impersonate a peer, not a validator. A post-quantum handshake (ML-KEM) is a separate AIP. Nothing here is audited by a third party; AIP-15's external-audit gate applies before H_fin on chain 2800. The set is ten validators operated by one party; this AIP changes what a key can do, not who holds the keys.
  • Hybrid conjunction. A certificate is valid only with the quorum of every required scheme; forging it needs both a lattice break (Falcon-512) and a hash-function break (SLH-DSA-SHA2-128s) at dual-assumption anchors, and a lattice break alone at the intermediate Falcon anchors. The single-assumption window is at most 32 blocks by design, and the founder can shorten it at the cost in the table.
  • Liveness tax at K = Q. With f validators down, an anchor needs every remaining seal to reach its proposer in time; a proposer without them skips by round change. The measured pre-AIP rate is 12 of 12 anchors at round 0; the post-AIP rate is a testnet gate. The threshold guard's warning text is the operator's acknowledgment of this trade.
  • Rollback of a provisional tail. New behaviour for a QBFT client, bounded at 32 blocks, exercised on the testnet with a negative control before any mainnet height. A bug here is a liveness bug on readers, never a safety bug: nothing becomes final without a certificate.
  • Weak subjectivity. Section 4, rule 5. A node without a checkpoint can be eclipsed onto a fork that ends before 13,034,000; with one, it cannot be made to accept a rewrite at any height.
  • Identity derivation. Including the type byte and the algorithm identifier in the id pre-image (as AIP-20 does) closes "same bytes, different scheme" confusions; the id is not a proof of anything, the registry row is.
  • Registry writer. A registry epoch is produced by the Foundation and pinned on chain by a transaction from a Foundation key; a rogue epoch cannot bind a key to an existing id without that id's previous keys signing the rotation, and cannot add a row whose key does not prove possession. It can still add a new id with new keys, which is the power to add a validator, and that is the governance weakness the AIP-19 process names, unchanged here.
  • Denial of service by seals. Without the ECDSA authorship check, any connected peer can send messages that fail the Falcon check; each costs 0.068 ms to refuse and the per-peer limits of the client apply. This is the same surface the message layers already have since 17,700,000.

Reference Implementation and On-Chain Deployment

Nothing described here exists at the Created date. Planned artifacts, each landing as an exact delta over the production tree of the Besu-derived client (consensus-pqc/arbore-complet-2026-08-01/, the discipline of AIP-20 and AIP-21) and as anchored, idempotent patches for the Nethermind-derived client (nethermind-pqc/nethermind-intree/patches/), with a two-client conformance proof and a negative control in each client before any height is set:

  1. Stage 1, H_K: a schedule step <H_K>:7 and cap 10 on every node; the existing gate scripts/deschise/pragul-ancorei-e-cvorumul-setului.sh turns green; negative control: a certificate with six seals at or above H_K is refused by both clients; measured round-0 anchor rate at K = Q on testnet 28001 (four Besu-derived validators, one Nethermind-derived, Q = 4 at N = 5) and then on chain 2800.
  2. Stage 2, H_I: aere.pq.schemeIntervalSchedule in PqAnchorConfig and the producer, AERE_PQ_SCHEME_INTERVAL_SCHEDULE in the Nethermind engine and header validator, SCHEME_INTERVAL_SCHEDULE in the public verifier, the disk gate reading per-scheme intervals, the z3 model of the interval schedule extended to per-scheme grids; negative control: a hybrid-required anchor carrying only Falcon is refused, a Falcon-only anchor missing at a 32-grid height is refused.
  3. Stage 3, H_id: registry v3 (PqRegistryHash v3 pre-image and Merkle root, loader, PqRegistryBinding rotation and per-scheme possession proofs), id derivation, set translation at H_id, authorship by row, forwarding predicate, the formal-consensus registry models extended (registry_rotation_coverage_smt.py, registry_index_binding_smt.py) with the rotation chain; the v3 manifest tooling under chei-falcon/ producing the epoch from the keys already on the validators (no new key material); the public manifests index gains the v3 epoch in the same hour.
  4. Stage 4, H_fin: the canonical rule, the provisional tail and its rollback in both clients, the checkpoint option, the reader gossip of the AIP-21 record (optional sub-step, its own conformance test); external audit of stages 1 to 4 before the mainnet height.
  5. Stage 5, H_hdr: element 6 and the empty-commit-seals rule in the codec of both clients and in the public verifier.
  6. Section 6: PqEquivocationEvidence under contracts/, with the precompile framing conversion (registry public key to the 897-byte precompile input) tested against the live precompiles on testnet 28001.

Activation heights on chain 2800 are the founder's (AIP-19 acceptance per stage); the disk delta (+8.7 GB per node per year at Stage 2, +11.6 GB at Stage 5) is stated to the founder with the fleet's measured margin at that date; the SLH-DSA verification time, the round-0 rate at K = Q, the validator-to-validator bandwidth and the Falcon arithmetization are the measurements that precede, respectively, section 8's claim, Stage 1, any set growth beyond 21 with SLH-DSA in the header, and section 7.

Stage records (dated; the Status and Ratification rows above are unchanged by them)

2026-09-22, stage 0, measurement 1 (SLH-DSA verification time): see the constants table; recorded in the repository under consensus-pqc/aip22-treapta0/.

2026-09-22 22:48Z, stage 1 started on testnet 28001 (K = Q = 4 of 5): the step 2988864:4 was appended to the per-scheme minimum schedule of all six nodes that judge headers on chain 28001 (four Besu-derived validators and the read node on one host, the Nethermind-derived validator on another), one node at a time with at least 120 s and one anchor between restarts; every node caught the tip within about 20 s and carries the step in its live process environment. The Besu-derived client's threshold guard accepted the step with its quorum-or-above warning: "K reaches 4 at height 2988864; quorum for 5 validators is 4 and N - f is 4 ... the margin under the fault budget is 0", which is the liveness tax of section 8 stated by the code. Baseline before the step, measured the same hour on 40 anchors at K = 3: 40 of 40 at round 0, parent-to-anchor cycle 2.33 s mean (the testnet host is loaded; chain 2800 measured 1.80 s on 20 anchors in the same hour).

2026-09-22 23:21Z, stage 1 proven on testnet 28001 (K = Q = 4 of 5): over the seven anchors above H = 2,988,864, seven of seven were produced at round 0 (100%, parent-to-anchor cycle 2.29 s mean on the loaded host); the public verifier (verify-anchor.mjs, the tool this package ships) accepted all seven, each carrying 4 to 5 Falcon-512 and 4 to 5 SLH-DSA seals with one anchor carrying exactly the four-of-five minimum per scheme; a negative control that demanded six seals of five validators from H refused all seven; and both clients held identical hashes for all seven anchors (the Nethermind-derived validator on its local RPC and the Besu-derived nodes on the public door). Stage 2 (per-scheme intervals) is implemented in both clients with matched conformance vectors and negative controls; nothing here is on chain 2800.

2026-09-23 10:13Z, stage 2 armed on testnet 28001 for H_I = 3,070,656: all six nodes that judge headers carry 3070656:32 in the anchor-interval schedule and 3070656:falcon-512/32+slh-dsa-sha2-128s/128 in the scheme schedule, each switched in one restart with the house guards: the five Besu-derived nodes on a distribution built from the fleet's laboratory tree (the three consensus modules' regression 1,091 probes, 0 failed; against the live distribution exactly the seven stage-2 classes differ, none is missing), the Nethermind-derived validator on a binary built on its host (no type of the live binary missing). The public verifier reads the new grammar (a scheme named at the parent's step but off its own grid is surplus: verified, not required at K; a scheme not named at all is refused) and gave the same result as before on both chains ahead of H_I (20 of 20 on 2800, 6 of 6 on 28001).

2026-09-23 12:07Z, stage 2 proven on testnet 28001 (H_I = 3,070,656): over the 11 anchors from H_I to the tip (3,070,656 to 3,070,976), the three on the 128 grid (3,070,656, 3,070,784, 3,070,912) were hybrid (four Falcon-512 and four SLH-DSA-SHA2-128s seals each) and the eight between them Falcon-only (five Falcon-512 seals); eleven of eleven were produced at round 0 (parent-to-anchor cycle 1.00 s mean); the public verifier with the stage-2 schedule accepted all eleven; a negative control running the same verifier with the schedule in force before H_I (SLH-DSA required at every anchor) refused exactly the eight Falcon-only anchors ("missing scheme slh-dsa-sha2-128s") and accepted the three hybrid ones; the Nethermind-derived validator held identical hashes for all eleven; the block rhythm was unchanged (0.566 s before, 0.563 s after). Not measured, and stated: the behaviour of a node left without the stage at H_I (the testnet has none). The public verifier with per-scheme intervals and the stage-3 identity translation is published in the aere-node package and on the site the same hour; chain 2800 verifies 20 of 20 with it, unchanged. Nothing of stage 2 is on chain 2800.

2026-09-23 13:33:49Z, stage 3 rehearsed on testnet 28001 (H_id = 3,080,010), with two defects of the Nethermind-derived client found and repaired the same hour: the v3 epoch of the testnet (five rows, each binding exactly the Falcon-512 key, the SLH-DSA key and the address of the live key manifest, checked row by row; registry hash 0xd19eef4a..., pinned in every node's configuration) was published in the testnet's manifest index before H_id, and the public verifier finds it there, verifies it in full (every proof of possession, every ECDSA link, the Merkle registry hash) and requires its keys to equal the keys that sign. At H_id the validator list in extraData changed from the five ECDSA addresses (block 3,080,009) to the five post-quantum ids (block 3,080,010), and coinbase became an id. Defect 1, found by reading the code at 12:48Z, before H_id: the Nethermind-derived client's anchor rule and producer compared the registry's classical address of a seal's index with the parent's list, which holds ids from H_id, so it would have refused every anchor after H_id; repaired (the index's address translated into the identity of the parent's height, as the Besu-derived client does) and switched at 12:51Z. Defect 2, found on the chain: that client reset its message-author check at every height to the validator set of its environment, in addresses, so from H_id it dropped every Besu message as "not in the validator set", stopped sealing, and its round-0 slot expired at every rotation: 1.546 s per block from 13:34 to 13:48Z against 0.564 before (the proof over [H_id, H_id + 500] reports it: OPEN, four proposers, rhythm ratio 2.741, kept dated). Repaired (the environment set translated into ids from H_id) and switched at 13:48:50Z. After the repair, over [3,080,800, 3,081,300]: all five ids proposed exactly 100 blocks each, both clients held identical hashes for every block from H_id - 1 to 3,081,300 (1,292 of 1,292, the degraded window included), the rhythm ratio was 1.000, the public verifier run as a stranger (no variables) accepted 20 of 20 anchors with the v3 link, and the same verifier with the identity switched off refused all 20 ("keys not in validator set"). A vote carried an id: validator 0 proposed the removal of validator 3's id, block 3,082,048 carries [id, drop] in its vote element, the vote alone has no majority and the set stayed five ids, and after the vote was discarded the next block of validator 0 carries none; both clients agree on those blocks. Not measured, and stated: the behaviour of a node left without stage 3 at H_id. The Besu-derived client and the public verifier also carry stage 3b (the keys that seal read from the v3 epoch in force from a height H_k, with a startup continuity guard and the ECDSA link inherited by id), proven with the shared vectors and negative controls, deployed nowhere; the local signing key by height (stage 3b-ii) is next.

2026-09-23 16:37Z, stage 3b proven on testnet 28001: a validator's keys rotated under its id at B2 = 3,097,600. From H_k = 3,080,010 (the bindHeight of the switch epoch) the keys that seal are read from the v3 epoch in force, in both clients and in the public verifier; a startup guard in each client refuses to start unless the epoch at H_k carries exactly the keys of the existing registries (10 keys of 5 rows, verified on all six nodes), so the switch changed no key. A node's own signing key and index are derived the same way: a validator holds its current key and its NEXT keys as files, and from each height it signs with the key its row carries in the epoch in force there, at that row's index; a second startup guard refuses to start a validator registered in an epoch from H_k whose key it does not hold, because it would otherwise go silent at that epoch with every configuration check green. The rotation: a new PROBA key pair (Falcon-512 and SLH-DSA-SHA2-128s) for validator 2 was generated on its own host by the registry tool (owner-only files, nothing private printed); its row in the epoch bound at B2 keeps the id 0xe7e6b4d3..., carries the new keys with their proofs of possession, and carries a rotation signed by each previous key over the new row hash; the other four rows keep their keys, with possession re-proven for the new bindHeight. The epoch's registry hash 0xb5847f46... is identical in the Besu-derived strict loader and in the independent JavaScript implementation, which also refuses the same epoch without its predecessor (REG3-09, the rotated row then reads as a new id) and with the rotation signature corrupted (REG3-12). All six nodes were armed before B2 (five Besu-derived on a distribution that loses no class of the live one, the Nethermind-derived validator on a binary built on its host), validator 2 with its next keys; the epoch and the keysFrom mark were published in the testnet's manifest index the same hour. Over [B2 - 1, B2 + 500]: the validator set was the same five ids at B2 - 1, B2 and B2 + 500; both clients held identical hashes for all 502 blocks; the rhythm was 0.565 s per block before and 0.568 after; the public verifier run as a stranger (no variables) found the epoch and the mark in the published index and accepted 15 of 15 anchors; and the NEGATIVE CONTROL, the same verifier on a copy of the published manifests without the epoch bound at B2, refused validator 2's Falcon seal as invalid on 12 of the 15 anchors (the other three did not carry that validator's seal), so the seals after B2 are made with the rotated key and nothing else verifies them. Not measured, and stated: the behaviour of a node left without the epoch at B2 (the testnet has none), and a rotation on chain 2800, which means new keys and a founder decision.

2026-09-23 18:47-19:00Z, stage 4 (message authorship from verified seals) armed on testnet 28001 for H_fin = 3,117,000, and two holes found by reading the code before it. Reading both clients before any live step showed that "the author is the id of the seal's index" is only as good as the check that the seal verifies, and that the check was not where the author is decided: (a) the Nethermind-derived client verified the post-quantum seals of commits only; it counted a prepare, a proposal's implicit prepare and a round-change by their author alone, so an author read from an unverified index would have let anyone who can reach that node vote in any validator's name; (b) the Besu-derived client relays a message as soon as its author is in the set, before its seal layers judge it, so the same author would have let anyone make every validator relay messages in any validator's name, where until H_fin that required a validator's ECDSA key; and (c) in the Besu-derived client a seal layer whose property is unset verifies nothing. The form armed, in both clients: from H_fin a proposal, prepare or round-change has an author only once its Falcon-512 seal verifies under the key of its index's row in the v3 epoch in force, over the message of its own domain (a round-change in the form its prepared claim names), through the same verifier and message builder as the seal layers; a commit's author is its index's id only when that id is the commit seal signer's, and its seal is judged by the commit layer; a node refuses to start with H_fin set if a seal layer is not armed at or below it (AERE-PQC-FIN-02) and a validator refuses if it would not seal all four messages from H_fin (AERE-PQC-FIN-03, a node that would otherwise be silent at H_fin while looking healthy); AERE-PQC-FIN-01 requires the v3 keys at or below H_fin and the chain id. Probes: in the Besu-derived client the author with an injected verifier, the real payloads with real Falcon-512 keys and a foreign envelope key, and both guards (three modules 1,137 tests, 0 failures, with the application compiled; negative controls planted at run time "H_fin never active", "every seal verifies", "a commit binds to any signer", "FIN-02 never refuses", "FIN-03 never refuses", each turning its probes red); in the Nethermind-derived client the same cases on its wire codec with probe Falcon keys (34 tests, 35 with the shared vectors below; six negative controls red with the tests run). Shared vectors: seven real messages (prepare, commit, round-change) written by the Besu-derived client with a foreign envelope and real seals, each expected author asserted through its own decoding path, decode to the same author in the Nethermind-derived client, seven of seven, and the "every seal verifies" and "a commit binds to any signer" controls turn that probe red. Armed: the five Besu-derived nodes on a distribution built from the fleet laboratory that loses no class of the live one (six classes added), one at a time with cooling, each logging "H_fin armed at 3117000"; the Nethermind-derived validator on a binary built on its host that loses no module of the live one. Also in this stage and deployed with it, inert unless configured: the checkpoint option (aere.pq.checkpoint / AERE_PQ_CHECKPOINT, a header rule that refuses a header at a checkpoint height with another hash; not configured on the testnet) and, in the Nethermind-derived client, the sync-mode guard the Besu-derived client has had since 2026-08-02 (with the anchor armed, fast or snap sync refuses to start, proven at run time). Not in this stage on the testnet, and stated: rule 2 of section 4 (see the open question in the plan: whether ECDSA commit seals may be empty between anchors), a head rule for validators fed a classical-only fork (it needs a measurement with N >= 4), and the Nethermind-derived reader under attack (not measured).

2026-09-23 19:40Z, stage 4 proven on testnet 28001 (H_fin = 3,117,000). Over [H_fin - 1, H_fin + 500]: H_fin armed in the environment of all six nodes (five of five Besu-derived, one of one Nethermind-derived; positive control on the same read, the H_k property, five of five and one of one); both clients held identical hashes for all 502 blocks; all five ids proposed (101, 100, 100, 100, 100 blocks), so every validator's proposals and votes, the Nethermind-derived validator's included, have an author in the other client; the rhythm was 0.568 s per block before and 0.566 after (ratio 0.996); at the crossing itself the 60 blocks after H_fin took 33 s against 35 s for the 59 before. NEGATIVE CONTROL OF THE METHOD: the same measures on the known-bad window [3,080,010, 3,080,510] (the second defect at H_id, four proposers) come out red (four proposers, ratio 2.741), and the proof refuses to speak (NOT MEASURED) unless H_fin is armed on all six nodes, which it would otherwise have reported as proven on a window without the stage. Not measured, and stated: a forged message on the network (no testnet node can inject one; its refusal is proven by the probes and negative controls in both clients and by the shared vectors).

2026-09-23, stage 3 foundation: the registry v3 forms, pinned. Section 3.2 names a "canonical serialization"; the bytes are now fixed, identically, in the Besu-derived client (PqRegistryV3), the Nethermind-derived client (PqRegistryV3) and a third, independent JavaScript implementation, and pinned by 19 shared conformance vectors (two valid epochs, the second rotating one validator's keys under its id; seventeen refusals, each differing from a valid manifest in one field with the signatures re-made over that field, one per refusal code AERE-PQC-REG3-01 to -16):

row pre-image  = "AERE-PQ-ROW-3" || u8(3) || u64be(chainId) || u64be(bindHeight) || u32be(count)
                 || u32be(index) || id(20) || u8(nKeys)
                 || per key, ascending scheme wire id (falcon-512 = 1, slh-dsa-sha2-128s = 2):
                    u8(wireId) || u32be(len pk) || pk || u32be(len pop) || pop
                 || u8(hasTransport) [|| transport(20)]
row hash       = keccak256(row pre-image)                 (rotation and ecdsa are not part of it)
Merkle node    = keccak256(0x01 || left || right); an odd node is paired with itself
registry hash  = keccak256("AERE-PQ-REGISTRY-3" || u64be(chainId) || u64be(bindHeight) || u32be(count) || root)
pop message    = keccak256(the pre-image of section 3.2's pop row)   signed by that key
rotate message = keccak256("AERE-PQ-ROTATE-3" || new row hash)       signed by every previous key of the id
ecdsa claim    = keccak256(0x19 || 0x00 || low20(keccak256("AERE-PQ-CLAIM-1" || u64be(chainId))) || row hash)

Two refinements to the text above, recorded rather than silently applied: the Merkle inner node carries the tag byte 0x01, so an inner node can never be presented as a row hash; and a membership proof is valid only for an index below count, because with the odd node paired with itself the path of the last row of an odd-sized tree would otherwise also prove the index count (both clients and the JavaScript tool refuse it, and a probe in each asserts the refusal). Negative controls: in the Besu-derived client, removing the rotation rule, the id-derivation rule or the index bound each turns its probes red with the probes run (and the untouched source green); in the Nethermind-derived client, removing the rotation rule turns 2 of its 3 probes red and removing the index bound 1 of 3 (untouched: 3 of 3 green); in the JavaScript tool the same three plantings are caught by 2, 2 and 1 vectors. Nothing of stage 3 is wired into consensus yet: the set translation at H_id, authorship by row, coinbase and votes by id, and the forwarding predicate are the next parts, and the v3 epoch of testnet 28001 needs the PROBA keys on its hosts to sign possession, claim and rotation.

Errata

None.

Post-Acceptance Outcome Record

Not accepted; nothing to record.

Released to the public domain (CC0). No rights reserved.