AIPs: AIP-20 and AIP-21 status rows carry the chain-2800 deployment of 2026-09-22 (AIP-21 live on all ten validators, AIP-20 armed for block 19,900,000); AIP-22 (post-quantum-only finality) added as a design-only Draft; the index no longer describes the pre-September world (seven validators, one client, no AIP above 19) and states which post-quantum layers are live with their heights

This commit is contained in:
Aere Network 2026-09-23 01:30:13 +03:00
parent a2fe6c46ba
commit c94b3f5c06
4 changed files with 857 additions and 9 deletions

327
aips/AIP-20.md Normal file
View File

@ -0,0 +1,327 @@
# AIP-20: Native Post-Quantum Transactions (Type 0x50, ML-DSA Authorization)
## Preamble
| Field | Value |
| --- | --- |
| AIP | 20 |
| Title | Native Post-Quantum Transactions (Type 0x50, ML-DSA Authorization) |
| Author | Aere Network Foundation |
| Type | Standards Track |
| Category | Core |
| Status | Draft (specification only at the Created date, when no implementation existed; implemented in both clients and proven conformant 2026-09-17; live on testnet 28001 from block 2,212,000; on chain 2800 deployed on every node 2026-09-22 and armed for block 19,900,000, see the dated records at the end) |
| Created | 2026-09-17 |
| Requires | None (the ML-DSA-44 verify precompile at `0x0AE3` is reused only for conformance vectors, not on the transaction path) |
| Supersedes | None |
| Superseded-By | None |
| Ratification | Not ratified; testnet-gated (chain 28001 first), second-client-gated (both clients must pass the same vectors), founder gated for chain 2800 |
## Abstract
This AIP introduces an EIP-2718 typed transaction, type `0x50`, whose authorization is a
FIPS 204 **ML-DSA** signature instead of a secp256k1 ECDSA signature. The parameter set is
selected per transaction by an algorithm identifier (ML-DSA-44, ML-DSA-65 or ML-DSA-87), the
sender address is derived from the post-quantum public key, and no secp256k1 operation appears
anywhere in the validation of such a transaction. Accounts created this way hold no key that a
cryptographically relevant quantum computer could recover. The type is activated by block height,
uniformly on every node that validates or reads blocks, on the public testnet 28001 first and on
chain 2800 only through a founder-signed acceptance of this AIP (AIP-19 process).
## Motivation
Every externally owned account on chain 2800 is authorized today by a secp256k1 ECDSA signature,
whose security rests on the discrete logarithm problem, broken by Shor's algorithm. The chain's
consensus already requires post-quantum seals on every QBFT message (SPEC section 2.6, in force
since block 17,700,000) and binds every 128th block under a hybrid Falcon-512 + SLH-DSA-SHA2-128s
certificate; the accounts of users are the remaining classical layer.
Post-quantum contract accounts exist on 2800 (`AerePQCTxAccount`, `HybridAuthorizer`, the ERC-4337
threshold account), but they are second-class: the transaction that carries the post-quantum
authorization is itself an ECDSA transaction from a relayer, gas is paid by that relayer, and every
wallet needs a bundler. A native type makes a post-quantum account a first-class account: it pays
its own gas, appears in `eth_getTransactionByHash` like any other, and needs no classical key at
all. The Foundation's stated goal for this change is to move the network past ECDSA, not to add a
post-quantum option beside it.
## Specification
### Transaction envelope
```
TransactionType = 0x50
TransactionPayload = rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit,
to, value, data, access_list, alg_id, public_key, signature])
```
All fields up to and including `access_list` have the semantics of EIP-1559 (type `0x02`). The
three new fields are:
| Field | Type | Meaning |
| --- | --- | --- |
| `alg_id` | uint8 | the signature algorithm and parameter set, table below |
| `public_key` | bytes | the raw ML-DSA public key, exact length for `alg_id` |
| `signature` | bytes | the raw ML-DSA signature, exact length for `alg_id` |
| `alg_id` | Algorithm | Public key | Signature | NIST category | Status in this AIP |
| --- | --- | --- | --- | --- | --- |
| `0x01` | ML-DSA-44 (FIPS 204) | 1,312 B | 2,420 B | 2 | valid |
| `0x02` | ML-DSA-65 (FIPS 204) | 1,952 B | 3,309 B | 3 | valid, recommended default |
| `0x03` | ML-DSA-87 (FIPS 204) | 2,592 B | 4,627 B | 5 | valid, highest security |
| `0x10` | SLH-DSA-SHA2-128s (FIPS 205) | 32 B | 7,856 B | 1 | reserved for a later AIP |
| `0x20` | Falcon-512 (FN-DSA, FIPS 206 draft) | 897 B | variable | 1 | reserved for a later AIP |
| `0x80` | hybrid flag (classical + post-quantum, both required) | | | | reserved for a later AIP |
Any other `alg_id`, and any `public_key` or `signature` whose length is not exactly the length
of the table, makes the transaction invalid.
### Sender address
```
sender = keccak256(0x50 || alg_id || public_key)[12:32]
```
The type byte and the algorithm identifier are part of the pre-image so that the same key
material under a different algorithm, or a future type reusing ML-DSA keys, cannot claim the same
address.
### Signing hash and signature
```
signing_hash = keccak256(0x50 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas,
gas_limit, to, value, data, access_list, alg_id, public_key]))
signature = ML-DSA.Sign(secret_key, signing_hash, ctx = "")
```
Signing uses the FIPS 204 "pure" interface (Algorithm 2, `ML-DSA.Sign`) over the 32-byte
`signing_hash` with the empty context string. Both deterministic and hedged signing are
acceptable; verification is identical. The pre-hash variant (`HashML-DSA`) is not used.
A transaction is valid only if `ML-DSA.Verify(public_key, signing_hash, signature, ctx = "")`
returns true for the parameter set of `alg_id`.
### Transaction hash
As for every typed transaction: `keccak256(0x50 || TransactionPayload)`. The signature bytes are
part of the hash; two different valid signatures over the same payload are two transactions with
the same nonce, of which at most one can be included.
### Validity rules
A block is valid only if every type-`0x50` transaction it contains satisfies all of:
1. the block number is at or above the per-node activation height `aere.pqtx.forkBlock`, set
uniformly on every node (before that height the type is invalid in the transaction pool and in
blocks, so an un-upgraded fleet and an upgraded one behave identically below the height);
2. `alg_id` is `0x01`, `0x02` or `0x03` and the key and signature lengths match the table;
3. the ML-DSA verification above succeeds;
4. `chain_id` equals the chain identifier of the network;
5. with `sender` derived as above, the nonce, balance, gas and fee-market rules of type `0x02`
apply unchanged (`to` may be empty: contract creation is allowed, and the created address is
`keccak256(rlp([sender, nonce]))[12:32]` as usual).
### Gas
```
intrinsic_gas = 21,000
+ calldata_gas(data) (the calldata pricing active at that block)
+ access_list_gas(access_list)
+ 16 * (len(public_key) + len(signature))
+ PQ_VERIFY_GAS[alg_id]
```
The authorization bytes are transported in every block like calldata and are charged at the
non-zero calldata rate. `PQ_VERIFY_GAS` is the cost of the signature verification itself:
| `alg_id` | `PQ_VERIFY_GAS` (Draft values) |
| --- | --- |
| ML-DSA-44 | 55,000 (equal to the precompile `0x0AE3`) |
| ML-DSA-65 | 75,000 |
| ML-DSA-87 | 100,000 |
The Draft values are to be re-measured on the validator hardware, against `ecrecover` as the
reference, before this AIP leaves Draft; the measured table is part of the acceptance record.
Worked example, ML-DSA-65 transfer with empty calldata: 21,000 + 16 x 5,261 + 75,000 = 180,176
gas, that is about 8.6 times an ECDSA transfer.
### Receipts and JSON-RPC
The receipt uses the EIP-2718 envelope with type byte `0x50` and is otherwise a type-`0x02`
receipt. `eth_getTransactionByHash`, `eth_getTransactionByBlockNumberAndIndex` and the block
methods return `"type": "0x50"`, the fields `algId` (hex quantity), `pqPublicKey` and
`pqSignature` (hex data), and `from` as the derived sender; the fields `v`, `r`, `s` and `yParity`
are absent. `eth_sendRawTransaction` accepts the envelope. `eth_signTransaction` and `eth_sign` do
not support the type: keys are held by the client library, never by the node.
### Networking
The transaction is exchanged as an opaque typed transaction in `eth/68` `Transactions`,
`NewPooledTransactionHashes` and `PooledTransactions` messages, exactly as types `0x01` to `0x04`.
A peer that does not implement the type drops it, which is one reason the activation height is
set on every node of the network, readers included, before it is reached.
### Size
The largest authorization (ML-DSA-87) is 7,219 bytes; transactions remain subject to the
existing maximum encoded size of the pool and of the network layer.
### Migration
An account holding funds under an ECDSA key moves them to a post-quantum account with an ordinary
transfer to the derived address; nothing is converted automatically and no existing address
changes meaning. Contract-level migration helpers (`AereAccountMigrator`) may be used but are not
required.
### Cross-client determinism
Both clients of chain 2800 (the Besu-derived client and the Nethermind-derived client) MUST derive
the sender, compute the signing hash, charge gas and accept or reject a type-`0x50` transaction
identically. Conformance vectors (valid transactions for each `alg_id`, and invalid ones: wrong
length, wrong chain id, corrupted signature, wrong `alg_id`, below the activation height) are
published with the reference implementation and both clients must pass all of them before the
type is activated anywhere.
## Rationale
**Native instead of account abstraction.** ERC-4337 accounts on 2800 already verify post-quantum
signatures, but the outer transaction is ECDSA-signed by a relayer and the account cannot pay for
itself. A native type removes the relayer, the bundler and the last classical signature from the
path of a post-quantum user.
**ML-DSA first.** FIPS 204 is final (August 2024), is the NIST primary signature standard, and has
maintained implementations in the three ecosystems this network runs on: JavaScript
(`@noble/post-quantum`, already a dependency of this repository), Java (Bouncy Castle) and .NET.
Its three parameter sets give users a choice between size and security category; ML-DSA-65 is the
recommended default and ML-DSA-87 the highest category NIST defines. SLH-DSA (hash-based, the most
conservative assumption set) and Falcon-512 (the smallest signatures, and the scheme this
network's validators use for consensus) are reserved identifiers so that they can be added by a
later AIP without a new transaction type: this is the same crypto-agility principle the on-chain
`CryptoRegistry` follows.
**Hash-then-sign.** ML-DSA can sign arbitrary-length messages, but signing the 32-byte
`signing_hash` keeps the wallet flow identical to the existing typed transactions (the signer
never needs the full transaction), keeps hardware signers viable, and reuses the domain separation
that the type byte already provides.
**No hybrid classical + post-quantum in v1.** A mandatory ECDSA co-signature would keep exactly the
dependency this AIP removes. The `0x80` flag is reserved for users who want both signatures for a
transition period; it is a separate decision with its own AIP.
**Address includes type and algorithm.** It costs nothing and closes the class of "same bytes,
different scheme" confusions permanently.
## Backwards Compatibility
Purely additive for existing transaction types: nothing about types `0x00` to `0x04` changes. A
node without this implementation rejects any block containing a type-`0x50` transaction, so the
activation is a coordinated fork: the same binary and the same `aere.pqtx.forkBlock` on every
validator, every public read node, the archive and the second client, before the height is
reached. Below the height every node, upgraded or not, rejects the type, so setting the parameter
early is safe.
## Security Considerations
- **Quantum threat model.** An account authorized only by ML-DSA has no key recoverable by Shor's
algorithm. Consensus messages are post-quantum enforced (SPEC 2.6). Node-to-node transport (RLPx)
remains classical; it authenticates peers, not funds, and is out of scope here.
- **Denial of service.** ML-DSA verification is slower than ECDSA recovery. The cost is paid in gas
before execution, the pool verifies before storing, and pool admission is subject to the existing
per-peer limits; the verification cost is bounded and constant per `alg_id`.
- **Transaction size.** Up to 7,219 bytes of authorization per transaction; pool and block size
accounting count them like calldata (the gas charge above makes the economics explicit).
- **Signature non-uniqueness.** Hedged ML-DSA signing yields different signatures for the same
message; each is a distinct transaction hash with the same nonce, exactly as two ECDSA signatures
with different nonces `k` would be; nonce rules make at most one includable.
- **Replay.** `chain_id` is in the signing pre-image; the same key yields the same address on 28001
and 2800, as with ECDSA, and the chain id prevents cross-chain replay.
- **Implementation divergence.** Two clients, two ML-DSA implementations. The conformance vectors
(FIPS 204 known-answer tests plus the transaction vectors of this AIP) and a differential test
that feeds both clients the same blocks are acceptance conditions, not optional extras.
- **Key generation.** Clients generating ML-DSA keys MUST use a cryptographically secure random
source; the reference tooling uses the platform CSPRNG.
## Reference Implementation and On-Chain Deployment
Nothing described here exists at the Created date. This section is updated, dated, as each
artifact lands.
Planned artifacts, in order:
1. Besu-derived client (the Aere overlay): `TransactionType.AERE_PQ (0x50)`, a
`PqTransactionDecoder` / `PqTransactionEncoder` registered in `TransactionDecoder` and
`TransactionEncoder`, a post-quantum authorization on `Transaction` with sender derivation from
the public key, activation gating and ML-DSA verification in `MainnetTransactionValidator`,
intrinsic gas in the gas calculator, receipt and JSON-RPC result mappings, pool admission.
2. Nethermind-derived client: the same surface (`TxType`, decoder, validator, intrinsic gas,
signer abstraction, RPC models), with the decoder widened before any emission exists.
3. Reference tooling `tools/pqtx/` (key generation, signing, sending) on `@noble/post-quantum`, and
the conformance vectors `vectors/pqtx/`.
4. A conformance gate that runs the vectors through both clients and fails on any disagreement,
with negative controls (each invalid vector must be rejected by both).
5. Activation on the public testnet 28001 by height, with the second client validating; then the
founder-signed acceptance and the activation height on chain 2800.
**2026-09-17, artifacts 1 and 3 exist; nothing is deployed.** The Besu-derived implementation is
delivered as an exact delta over the production tree,
`consensus-pqc/arbore-complet-2026-08-01/petice-aip20/` (17 unified patches, 6 new files, applier
`APLICA-AIP20.sh` with `-F0`), proven to contain nothing but this AIP by reproducing the tree byte
for byte from the scripted edits; its conformance test (`AerePqTransactionTest`, 8 tests) passed
8 of 8 on the 14 vectors in `vectors/pqtx/` produced by `tools/pqtx/pqtx.mjs` on
`@noble/post-quantum`, so a JavaScript ML-DSA signature verifies under Bouncy Castle Java and every
negative vector is refused for its stated reason. Activation stays absent (`aere.pqtx.forkBlock`
unset means never). Not measured yet: a full distribution built with the delta, and the import of a
block carrying a type-`0x50` transaction on a network; that is the testnet step (artifacts 4 and 5).
Artifact 2 (the Nethermind-derived client) exists as an anchored, idempotent patch set
(`nethermind-pqc/nethermind-intree/patches/aip20-tranzactii-pq.sh`: 8 new files, 16 anchored edits,
the same 14 vectors under the test data); its conformance test (`AereAip20PqTransactionProofTests`,
9 tests) passed 9 of 9 on 2026-09-17 with Bouncy Castle C# ML-DSA, so both clients now derive the
same sender and hash, charge the same gas (180,176 for the ML-DSA-65 example) and refuse each negative
vector for its stated reason. The first run refused the corrupted ML-DSA-87 vector for gas instead of
for the signature: the reference tool gave negative vectors a flat gas limit; fixed and the vectors
regenerated the same day. Artifact 4, the two-client proof with a negative control in each client,
is `aips/aip20-conformitate/DOVEDESTE.sh`, recorded in `ULTIMA.txt` and watched by the fact
`F-AIP20-CONFORM`; first recorded 2026-09-17 19:51Z: CONFORM (Besu 8 of 8, Nethermind 9 of 9, the
planted "always valid" verification turned the corrupted-signature test red in both).
**2026-09-17, 21:14Z: artifact 5, first half, exists: the type is live on the public testnet 28001.**
All six nodes (four Besu validators and the public reader on the delta build `wt6ae52adb`, the
Nethermind validator on a binary built from the anchored patch set) were armed by height, H =
2,212,000, with the same transaction refused by every node before H (`Invalid transaction type` on an
armed Besu node, `Invalid params` on an unarmed one) and the same transaction included at block
2,212,032 after H (ML-DSA-65, `status 0x1`, 183,176 gas), returned identically by
`eth_getTransactionByHash` on both clients, the sender having no secp256k1 key at all. Under load,
50 further transactions from the same key were accepted and included 50 of 50 across 25 blocks at an
unchanged block rate. The negative controls after H found one gap: the Nethermind node imported and
served type-`0x50` transactions but refused every submission through its own RPC with the wallet
error `-32020`, because its sealer read "no ECDSA signature" as "sign it with the node's wallet"; a
17th anchored edit (`TxSealer.cs`) and a tenth test fixed it, the rebuilt binary was switched in on
the testnet at 21:29Z, and through Nethermind's RPC the corrupted signature is now refused as
`InvalidTxSignature`, the wrong chain as `InvalidTxChainId`, and a valid transaction was accepted and
included at block 2,213,784 as seen by both clients. Record: `aips/aip20-conformitate/TESTNET-28001-2026-09-17.md`.
Measured at 21:36Z the same day: ten type-`0x50` transactions submitted through the Nethermind
validator's RPC were all included in block 2,214,337, a block proposed by that Nethermind validator
itself and accepted by the Besu validators, so both clients receive, relay, propose and execute the
type in both directions. The second half of artifact 5, the founder-signed acceptance and the activation
height on chain 2800, is not done and is not the author's to do.
**2026-09-22, 21:45Z: artifact 5, second half, armed on chain 2800; activation height H = 19,900,000.** Under the
founder's general mandate of 2026-09-22 (given in chat; the AIP-19 signed acceptance is still to be produced, so the
ratification row above stays as it is), every node that validates or reads blocks on chain 2800 runs the same binary that
carries this type (distribution `wt3f12ef0d`, proven to be the live binary plus exactly AIP-20 and AIP-21, see AIP-21's
record of the same day) with the same `aere.pqtx.forkBlock=19900000` (Nethermind-derived client:
`AERE_PQTX_FORK_BLOCK=19900000`): nine Besu-derived validators, the Nethermind-derived validator, the two public readers,
and the archive unit (stopped for disk, prepared for when it restarts). Before H the binary behaves exactly as the old
one: a type-0x50 vector for chain 28001 sent through the public door is refused with `Wrong chainId` (a binary that knows
the type), where the old binary answered `Invalid params`. What is NOT yet measured on chain 2800: a block carrying a
type-0x50 transaction imported by every node after H; that is the next record, with the first such transaction.
## Errata
None.
## Post-Acceptance Outcome Record
Not accepted; nothing to record.
## Copyright
Released to the public domain (CC0). No rights reserved.

260
aips/AIP-21.md Normal file
View File

@ -0,0 +1,260 @@
# AIP-21: Verifiable Post-Quantum Finality per Block (Side Store, Proof RPC, Anchor as Permanent Record)
## Preamble
| Field | Value |
| --- | --- |
| AIP | 21 |
| Title | Verifiable Post-Quantum Finality per Block (Side Store, Proof RPC, Anchor as Permanent Record) |
| Author | Aere Network Foundation |
| Type | Standards Track |
| Category | Interface (non-consensus) |
| Status | Draft (first half implemented in the Besu-derived client on 2026-09-18, not yet on any network at the Created date; both halves in both clients on testnet 28001 the same day; on chain 2800 on all ten validators since 2026-09-22, see the dated records at the end) |
| Created | 2026-09-18 |
| Requires | AIP-15 (post-quantum anchor certificates), the per-Commit post-quantum seal enforced on chain 2800 since 2026-09-05 |
| Supersedes | None |
| Superseded-By | None |
| Ratification | Not ratified; testnet-gated (chain 28001 first), second-client-gated (both clients answer the same record for the same block), no activation height needed on chain 2800 because nothing here changes block validity |
## Abstract
Every block of an Aere QBFT chain is committed with a Falcon-512 seal on each Commit message, and
every validator already holds, for recent blocks, the seals it heard. Those seals never reach the
header: only every 128th block carries a certificate, over its parent, so the immediate post-quantum
finality of a block has been true and not observable. This AIP makes it observable without growing the
header: a bounded side store of heard seals per block hash, a JSON-RPC method `aere_getPqFinality`
that returns the seals of a block re-verified now against the anchored registry over the exact message
the validators signed, with the verdict "verified distinct signers ≥ the chain's commit quorum",
and the anchor certificate as the permanent record once the window has passed.
## Motivation
A user, an exchange or a bridge that asks "is this block final under post-quantum assumptions right
now?" could until now only be answered "yes, trust us" or "wait for the next anchor". The seals that
prove it exist on every validator and are thrown away after a few hundred blocks. Keeping them a
little longer and answering a query costs kilobytes, and turns a claim into a measurement that a
third party can repeat: fetch the record, verify each Falcon-512 seal against the published registry
epoch, count distinct signers, compare with the quorum. It also makes "immediate post-quantum
finality" a gate we can run against our own nodes, on the block of ten seconds ago, instead of a
sentence on a website.
## Specification
### The record
For a block `B` at height `h` with on-chain hash `H` (round forced to zero), a node answers:
```
blockNumber h
blockHash H
validators n, the size of the validator set that validated B
quorum the chain's commit quorum for n (Besu: ceil(2n/3))
sealForm "anchor" when the signed message is M = commitMessage(chainId, h, H) (AIP-15,
the form in force on every live network today), "commit-digest" below it
signedMessage M in hex, or null when it cannot be rebuilt from the header
falconSeals [{scheme:"falcon-512", index, verified, signature}] as heard, index-sorted
falconSealsHeard count
falconSealsVerified distinct validator indexes whose seal verifies NOW against the registry epoch
bound at height h (verifyAtHistoric)
verifiedIndexes that set
hybridSeals [{scheme, index, verified:null, signature}] heard extras (SLH-DSA on anchor
parents); listed, not verified by this method: the anchor certificate is theirs
finality "post-quantum" | "partial" | "none" | "unavailable" | "unverifiable-form"
retentionBlocks the node's window
note one sentence that says what the verdict rests on
```
`finality` is `post-quantum` iff `falconSealsVerified >= quorum > 0`; `partial` when at least one
seal verifies but fewer than the quorum; `none` when seals were heard and none verifies; `unavailable`
when no seal was heard (a reader node, or a block outside the window); `unverifiable-form` below the
anchor form. A method that cannot verify says so; it never counts an unverified seal.
### The side store
The existing per-node seal cache (keyed on the on-chain block hash, populated from Commit messages)
gains a configurable retention window, system property `aere.pq.finality.window` (blocks). The
consensus default stays the previous value (256); the value is per node and never a consensus value:
two nodes with different windows import the same chain. Memory cost is about 7 kB per block for ten
seals.
### The window on disk (second half, 2026-09-18)
The window survives a restart. Each client appends what it heard for a height to a journal when the NEXT
height begins, and reads the journal back at startup. Both clients write the SAME format, pinned by a byte
vector present literal for literal in both proof suites: one directory, segment files of 64 heights
(`w-<height / 64>.rlp`), each a sequence of frames `length(4, big endian) || payload || crc32(payload)(4, big
endian)`, the payload being the RLP list `["AERE-PQ-SEALWINDOW-1", chainId, blockNumber, blockHash,
[[index, signature], ...]]`. Frames are only appended; segments wholly below the window are deleted, so the
footprint is bounded by the window (a few megabytes at the default) whatever the age of the node. Writes are
best effort and unsynced: a disk fault costs the answer for those blocks after a restart, never the node.
Nothing read from the journal is believed. A seal is self-verifying: at startup every seal is verified again
against the registry epoch bound at its height, over the commit message rebuilt from the block hash, and what
does not verify is dropped. The Besu-derived client also drops, before looking at a signature, any frame whose
hash is not the canonical hash its own chain holds at that height; the Nethermind-derived client keeps the
hash beside each seal and applies the same canonical filter at query time. A forged journal obtains the empty
window an absent journal already gives. A torn tail (the node died mid-append) or a damaged frame costs that
frame and what follows it in the same segment, nothing else.
Switches, per node, never consensus values: Besu-derived client, system property `aere.pq.finality.persist`
(`false` turns the journal off; default on wherever the head-seal store is on), directory
`<data>/aere-pq-seal-window`; Nethermind-derived client, environment variable `AERE_PQ_FINALITY_DIR` (unset
= off). What is NOT persisted: the hybrid extras (SLH-DSA seals on anchor parents); after a restart they are
listed only for blocks heard since, and the anchor certificate remains their permanent record.
### The method
`aere_getPqFinality([blockParameter])`, `blockParameter` a number, `latest` or `pending`; default
`latest`. Registered in the QBFT API group. Returns the record above, or `null` for an unknown block.
### Who can answer
Seals travel on Commit messages between validators, so only validators hear them. A public reader
node answers `unavailable` honestly. A network that wants the record public exposes a read-only door
that accepts only this method and asks a validator: on testnet 28001 that door is
`https://testnet-rpc.aere.network/finality`, a proxy that tries the four Besu validators in turn and
refuses every other method.
### The permanent record
Once the block leaves every node's window, its post-quantum finality is recorded by the next anchor
certificate (AIP-15), which is verifiable forever with the published verifier. The two are the same
claim at two ages: the seals prove it in the second, the certificate proves it for the life of the
chain.
## Rationale
Growing the header with a post-quantum seal per validator per block was measured at 247 GB to 2.9 TB
per node per year on 2026-09-17 and rejected; anchors every 128 blocks cost about 32 GB per year. A
side store that keeps what validators already hold, for a bounded window, costs kilobytes and changes
nothing about validity, so it needs no coordination, no fork and no signature to deploy.
## Backwards Compatibility
None affected. Nodes with and without the method import the same chain.
## Security Considerations
The record is only as strong as its verification: a seal is counted only if it verifies now against
the registry epoch bound at that height, over the message rebuilt from the header this node holds. A
node lying about the record can be caught by any second node or by the anchor certificate. The record
exposes no secret: seals are already broadcast to every validator.
## Reference Implementation
Besu-derived client, `consensus-pqc/arbore-complet-2026-08-01/petice-aip21/`: the method
`AereGetPqFinality` (consensus/qbft), its test `AereGetPqFinalityTest` (7 cases, each with its negative
pair: a signer short of quorum, nothing verifying, nothing heard, a form that cannot be rebuilt, an
unknown block), the retention window in `PqSealCache`, three anchored edits (`aip21-aplica.py`). The
Nethermind port, the testnet deployment and the public door are recorded here, dated, as they land.
**Testnet 28001 deployment, 2026-09-18 02:35Z.** The five Besu nodes of the public testnet (four validators and the
reader) run the AIP-21 distribution `besu-aip21-26.4.0-aere.1-d203201-wt5fda18a0`, switched one at a time with a
130 s cooling window between restarts (`testnet-public/84-comuta-toate-f2.sh` over `83-binar-nod-f2.sh`, each node
back at the tip before the next). Public door: `https://testnet-rpc.aere.network/finality` (`finalitate-proxy.mjs`,
unit `aere-testnet-finalitate`; accepts only `aere_getPqFinality` and `eth_blockNumber`, asks the four validators in
turn and names which one answered). First public record: block 2,244,964, quorum 4, 5 of 5 seals verified,
`post-quantum`; after the full switch, block 2,246,017, quorum 4, 5 of 5, `post-quantum`. Aere Cloud relays it as
`GET /v1/pq/finality/{block}?network=testnet`.
**Nethermind port, written 2026-09-18** (`nethermind-pqc/nethermind-intree/`): `Nethermind.AerePqc/Consensus/Finality/AerePqFinality.cs`
(the query; the same record, the same five verdicts and notes as the Besu method), `patches/AereRpcModule.cs`
(JSON-RPC module `Aere`, `aere_getPqFinality`, enabled per endpoint like every module), `patches/aip21-finalitate-nm.py`
(anchored, idempotent: retention window `AERE_PQ_FINALITY_WINDOW`, default 256, in place of the previous fixed 8
heights; each heard seal remembers the digest of the proposal it was heard for, because this engine keys its store
on the height, so a seal of a losing proposal at the same height is never listed for the block that won; snapshots
under the engine lock for the RPC thread), `patches/AereAip21PqFinalityProofTests.cs` (10 cases, each with its
negative pair; 10 of 10 green, negative control: with verification planted to 'always true' 5 of 10 go red).
**Nethermind testnet deployment, 2026-09-18 03:18Z.** The Nethermind validator of testnet 28001 runs
build `client2-aip21-2026-09-18` (built on its host from the same overlay, 185 assemblies, nothing lost against the
previous live binary), switched by `testnet-public/88-aip21-nm-binar-nou.sh` with the `Aere` module enabled in its
JSON-RPC configuration. Functional proof on the node: `latest` (block 2,250,690) `post-quantum`, 5 of 5 seals verified,
quorum 4, `retentionBlocks` 256; `latest-64` (2,250,626) `post-quantum`; an unknown block returns `null`, a block from
before the restart returns `unavailable`, an unknown method of the module returns -32601. Public door:
`https://client2.aere.network/testnet/finality` (`89-finalitate-usa-client2.sh`, unit `aere-testnet-finalitate-nm`,
`answeredBy: nethermind@8651`; nginx location in `deploy/client2/nginx-client2-rpc.conf`).
**Two-client conformance, 2026-09-18 03:21Z** (`aips/aip21-conformitate/DOVEDESTE.sh`, repeatable, writes `ULTIMA.txt`):
block 2,250,809 asked to both doors: hash `0xab55016e3b3b5397abd6bfd8e86299f7105e95af8c9675979d4240ffe9293451` on both,
`post-quantum` on both, quorum 4, verified indexes [0,1,2,3,4] on both; negative controls: the hash of block N-1 from
Nethermind differs from the hash of N from Besu (the comparison can fail), a block outside the Nethermind window is
`unavailable` there (no invented agreement), both doors refuse every other method. Aere Cloud:
`GET /v1/pq/finality/{block}?network=testnet&client=besu|nethermind|both`; with `both` the response carries the two
records, `agreement` and `postQuantumConfirmedByBoth`. Record: `aips/aip21-conformitate/TESTNET-28001-2026-09-18.md`.
**Correction, 2026-09-18 08:17Z (Nethermind-derived client, found on testnet, fixed the same morning).** The first form of
the port remembered each heard seal under the QBFT *message* digest. That digest keeps the round; the on-chain hash zeroes
it. They coincide in round 0 and differ for any block finalised in a round above zero, which every validator restart
produces; the Falcon commit seal signs the on-chain hash. So for those blocks the client answered `unavailable` while
holding five valid seals, and the window restore dropped them. Measured on block 2,282,930 (round 1): Besu-derived
`post-quantum`, Nethermind-derived `unavailable`; `DOVEDESTE.sh` reported NECONFORM. Fixed by remembering seals under the
on-chain hash (`CurrentOnchainHash()`), pinned by a proof (round 0 equal, round 1 different, the query under each key), and
the conformance proof now looks for the newest round-above-zero block and demands agreement on it. Implementers: the key
under which anything about a BLOCK is kept is the on-chain hash, never the message digest.
**Second half on testnet 28001, 2026-09-18 08:24Z to 08:49Z (both clients).** Besu-derived client: distribution
`besu-aip21b-26.4.0-aere.1-d203201-wt3f12ef0d` (33 proofs on the distribution tree, 9 of them the window persistence suite,
with a negative control that blinds the historic verification and turns the restore proof red) rolled onto the five nodes
one at a time with the host-clock cooling; a second restart of node 0 then restored `1284 verified seal(s) over 257
block(s)` from 257 frames, `0 not canonical`, `0 FAILED`, and block 2,284,257, heard before that restart, answered
`post-quantum` after it. Nethermind-derived client: build `client2-aip21c` (17 proofs, 6 of them the journal suite with the
shared byte vector; negative control on both the query and the journal verification), `AERE_PQ_FINALITY_DIR` set in the
unit's environment; after its second restart `1255 verified seal(s) over 251 block(s)` restored from 265 frames and block
2,285,317 (heard before it) stayed `post-quantum`, `0 FAILED`, while a block outside the window stayed `unavailable`.
**The round-above-zero case, measured live (08:48Z).** Block 2,285,333 was finalised in round 1. Both doors answer
`post-quantum` on the same hash (`0xcfecf9d0...8d2c3b`): the Besu-derived validator with signers `[0,1,2,3]`, the
Nethermind-derived validator with `[0,1,2,3,4]`, its own seal included (a validator finalises on quorum, so it may not
have heard the last Commit; the two counts legitimately differ, the verdict and the hash do not). The full
Nethermind-side record, signatures included, is kept in `aips/aip21-conformitate/runda1-bloc-2285333-nethermind.json`.
The same question on the first form of the port gave `unavailable` (the 08:17Z correction below). `DOVEDESTE.sh`:
CONFORM at 08:49:38Z, round-1 block included.
**Rebuild, 2026-09-18 11:54Z.** The Nethermind-derived testnet validator now runs build `client2-aip21d`: the same AIP-21
code, rebuilt after the host build script was found to copy only one of the five files of the consensus subprotocol from
the repository (the difference was one diagnostic line's log level; nothing functional). Switched with the same script and
proofs: window restored after the second restart (`1255 verified seal(s) over 251 block(s)`, 0 failed), round-1 block
2,305,309 `post-quantum` in both clients on the same hash, `DOVEDESTE.sh` CONFORM at 11:57Z.
**A probe that manufactures its own rare case measures its action, not the code (08:42Z).** The switch script first
looked for the round-above-zero block that ITS OWN restart of the validator produces, demanded `post-quantum` there, and
rolled a good binary back: the round had changed precisely because that validator was down, so it could not have heard
the seals of that block, and `unavailable` was the correct answer. A round-above-zero block says something about a client
only if the client answers for it, or if the OTHER client's record lists its seal index among the verified signers (then
it took part and must hold the record). Three cases, in the switch script and in `DOVEDESTE.sh`: answers `post-quantum`
on the same hash = measured; does not, but its index is in the other record = failure; does not, and its index is absent
= it was down, nothing measured.
**Interoperability note (measured 2026-09-18 03:16Z).** Send `blockParameter` as a hex string (`"0x2256b9"`), `latest`
or `pending`. The Besu-derived client also accepts a bare JSON number; the Nethermind-derived client rejects it with
`-32602 Invalid params` (`unknown block parameter type`). The public doors pass parameters through unchanged.
**Chain 2800 deployment, 2026-09-22 20:42Z to 21:45Z (both clients).** Under the founder's general mandate of
2026-09-22 (given in chat; the AIP-19 signed acceptance is still to be produced, so the ratification row above stays as
it is), the distribution `26.4.0-aere.1-d203201-wt3f12ef0d` was proven to be the live mainnet binary (`wtde7ea1c5`,
series d358) plus exactly AIP-20 and AIP-21: class by class in both directions (49,481 classes live, 49,492 new, 0 lost,
11 new, 46 with a different CRC of which 20 differ in code, all inside the patch footprint, and 21 identical in code,
line tables only). It was rolled onto the nine Besu-derived validators one at a time with the host-clock cooling (five
minutes and an anchor between restarts; every node returned `LATE-ANCHOR ACTIVATED`, kept pace, kept every property and
gained exactly `-Daere.pqtx.forkBlock=19900000`), then onto the two public readers and the (stopped) archive unit, and
the Nethermind-derived validator (the tenth) moved to a build made on its own host (`client2-aip2021-2026-09-22`,
nothing lost against the live binary, drop-in `zz-binar`, `AERE_PQ_FINALITY_DIR`, `AERE_PQTX_FORK_BLOCK=19900000`).
Measured at 21:45Z with `deploy/validators/aip2021-2026-09-22/dovedeste-aip2021-2800.sh`: every validator answers
`aere_getPqFinality` with `post-quantum`, 10 of 10 Falcon seals verified, quorum 7, `retentionBlocks` 256; the two
readers answer `unavailable` (they hear no seals, which is the honest answer); the Nethermind-derived validator agrees
with a Besu-derived one on the same block (same hash, same quorum, both `post-quantum`); all ten validators keep proposing
in rotation (20 of the last 200 blocks each). There is no public finality door on chain 2800 yet: the validators' RPCs are
local, so the record is read on the validator, or through Aere Cloud when that route is added.
## Errata
None.
## Post-Acceptance Outcome Record
Not accepted; nothing to record.
## Copyright
Copyright and related rights waived via CC0.

246
aips/AIP-22.md Normal file
View File

@ -0,0 +1,246 @@
# 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 | [NOT MEASURED in milliseconds in this repository]; gas proxy 350,000 against 40,000 for Falcon-512, ratio 8.75 | **spec** of the live precompiles (CIFRE #5) |
| 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" || uint8(3) || uint64be(chainId) || uint64be(bindHeight) || uint32be(count) || uint32be(index) || id(20) || uint8(schemeWireId) || uint32be(len(pk)) || pk` | required per key (today only the Falcon key carries a proof of possession; the SLH-DSA key gets one) |
| `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 `rotation` and `ecdsa`)`. 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 `id`s; at exactly `H_id` the list is the registry's `id`s 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 `id`s; 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 `id`s 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 `id`s, 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 `id`s 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.
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, 0.215 ms p95). Per Falcon anchor (every 32 blocks): up to N Falcon verifications, 0.7 ms median to 2.2 ms p95 at N = 10; per hybrid anchor (every 128): additionally up to N SLH-DSA verifications, [NOT MEASURED in ms; by the gas proxy about 8.75 x 0.068 = 0.6 ms each, 6 ms per anchor, **estimate**]. Amortized per block: about 0.02 ms (Falcon at 32) plus about 0.05 ms (SLH-DSA at 128, estimate), 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 by this estimate, and the SLH-DSA figure must be measured before the claim is repeated. 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 `id`s (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 `id`s 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.
## Errata
None.
## Post-Acceptance Outcome Record
Not accepted; nothing to record.
## Copyright
Released to the public domain (CC0). No rights reserved.

View File

@ -44,10 +44,13 @@ document is current.
| [17](./AIP-17.md) | One-Gwei EIP-1559 Base-Fee Floor | Standards Track / Core | Final | | | [17](./AIP-17.md) | One-Gwei EIP-1559 Base-Fee Floor | Standards Track / Core | Final | |
| [18](./AIP-18.md) | EIP-2935 on Chain 2800: Deviation from the Written Activation Schedule | Standards Track / Core | Final | | | [18](./AIP-18.md) | EIP-2935 on Chain 2800: Deviation from the Written Activation Schedule | Standards Track / Core | Final | |
| [19](./AIP-19.md) | AIP Process Hardening | Meta | **Review, not ratified** | | | [19](./AIP-19.md) | AIP Process Hardening | Meta | **Review, not ratified** | |
| [20](./AIP-20.md) | Native Post-Quantum Transactions (Type 0x50, ML-DSA Authorization) | Standards Track / Core | **Draft, not ratified; implemented in both clients and proven conformant on shared vectors (2026-09-17); live on testnet 28001 from block 2,212,000 (first type-0x50 transaction at 2,212,032, both clients); on chain 2800 the implementation runs on every node since 2026-09-22 and is armed, uniformly, for block 19,900,000 (per-node property, not a genesis change); no type-0x50 transaction on chain 2800 before that height** | |
| [21](./AIP-21.md) | Verifiable Post-Quantum Finality per Block (Side Store, Proof RPC, Anchor as Permanent Record) | Standards Track / Interface (non-consensus) | **Draft, not ratified; first half (retention window + `aere_getPqFinality`) implemented in the Besu-derived client with 7 tests and deployed on testnet 28001 (5 nodes, public door `testnet-rpc.aere.network/finality`) on 2026-09-18; Nethermind port the same day (10 tests) and deployed on the testnet Nethermind validator with its own public door; two-client conformance proven live (`aip21-conformitate/DOVEDESTE.sh`, CONFORM on block 2,250,809); second half (the window on disk, same journal format in both clients) deployed on all six testnet nodes the same day: the window survives a restart in both (1,284 and 1,255 seals re-verified, 0 failed), and a round-1 block is `post-quantum` in both on the same hash (CONFORM 08:49Z, block 2,285,481 and round-1 block 2,285,333); on chain 2800 since 2026-09-22 on all ten validators and both clients (`aere_getPqFinality` answers `post-quantum` with 10 of 10 seals re-verified; dated record at the end of AIP-21)** | |
| [22](./AIP-22.md) | Post-Quantum-Only Finality (Chained Quorum Certificates, PQ Validator Identity, ECDSA Demoted to Compatibility) | Standards Track / Core | **Draft, design only (2026-09-23): nothing implemented or deployed; every quantity carries its provenance or is marked not measured** | |
Numbers are permanent and are never reused, including for withdrawn proposals Numbers are permanent and are never reused, including for withdrawn proposals
(AIP-1 section 2). Numbering is contiguous from 1 to 19 with no gaps. No AIP (AIP-1 section 2). Numbering is contiguous from 1 to 22 with no gaps. No AIP
numbered 20 or higher exists in any Aere repository. numbered 23 or higher exists in any Aere repository.
## Which of these are live on chain 2800 ## Which of these are live on chain 2800
@ -59,17 +62,29 @@ AIP-3 (500 ms target, 516.4 ms measured), AIP-4, AIP-5, AIP-6, AIP-7
block 10,141,734), AIP-18 (EIP-2935 from block 9,189,161). AIP-9 through AIP-14 block 10,141,734), AIP-18 (EIP-2935 from block 9,189,161). AIP-9 through AIP-14
describe the decisions behind the live system. describe the decisions behind the live system.
**Not live:** AIP-8 (needs a hard fork), AIP-15 (isolated testnet only), AIP-16 **Post-quantum layers live on top of QBFT (see `SPEC.md` of the public node
(a skeleton that verifies nothing), AIP-19 (a process change under review). package for the exact rules and heights):** the anchor certificate under the block
hash (every 32nd block from 13,014,000, every 128th from 17,225,968; hybrid
Falcon-512 + SLH-DSA since 17,047,600; at least six valid seals per scheme of the ten
validators since 14,961,456), and the per-message Falcon-512 enforcement on every QBFT
message (heights 17,250,000 to 17,700,000, September 2026). AIP-21's record is live
on chain 2800 since 2026-09-22; AIP-20 is deployed and armed for 19,900,000.
**Never claimed:** post-quantum consensus. Aere consensus is classical secp256k1 **Not live:** AIP-8 (needs a hard fork), AIP-15 as written (its testnet R&D form;
ECDSA QBFT at N = 7. Post-quantum applies to signatures, accounts and what is live is the dated list above), AIP-16 (a skeleton that verifies nothing),
applications only. The precompiles `0x0AE6` and `0x0AE7` are testnet-only. AIP-19 (a process change under review), AIP-22 (design only).
**Not claimed:** consensus whose safety does not depend on ECDSA. Aere consensus is
QBFT in which classical secp256k1 ECDSA is still a validity criterion on every block
and every message, with the post-quantum layers above added to it (hybrid, never
"post-quantum only"); AIP-22 is the design for removing that dependence and nothing
in it is implemented. The precompiles `0x0AE6` and `0x0AE7` are testnet-only.
## Governance, stated plainly ## Governance, stated plainly
Aere is not yet trustlessly governed. Seven validators, all Foundation-operated, Aere is not yet trustlessly governed. Ten validators (since 2026-09-11), all
one live client, no external security audit, thin real usage. In that reality an Foundation-operated, two client implementations (one of each since 2026-09-11) but
one operator, no external security audit, thin real usage. In that reality an
AIP is not ratified by a vote of independent stakeholders. **The founder decides**, AIP is not ratified by a vote of independent stakeholders. **The founder decides**,
acting through the Foundation account acting through the Foundation account
`0x0243A4f47D44b40b65D33f20329dE20D00c6f3C3`, which is a single-key account and `0x0243A4f47D44b40b65D33f20329dE20D00c6f3C3`, which is a single-key account and