aere-research/aips/AIP-21.md
Aere Network c9ba6d4bec AIP-21 erratum and AIP-23 note (2026-10-01), formal models annotated: the post-quantum commit seal carries no round
AIP-21: a record that reaches `post-quantum` shows that the commit quorum of distinct validators sealed the block
post-quantum in some round; it does not by itself prove that the block was decided (follows the AIP-22 erratum of the same
day). AIP-23: dated note on what the finality level rests on; level names unchanged. Three formal models carry a dated note
where they treated certificate uniqueness as a property of the code rather than of the model.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 17:10:21 +03:00

22 KiB

AIP-21: Verifiable Post-Quantum Finality per Block (Side Store, Proof RPC, Anchor as Permanent Record)

Note added 2026-09-30. Where this document says that only every 128th block carries a certificate, it describes chain 2800 from block 17,225,968 to block 20,746,736 (2026-09-05 to 2026-09-29). Since block 20,746,736 (AIP-22 stage 2) a Falcon-512 certificate is carried every 32nd block and SLH-DSA seals every 128th, with at least seven of ten seals per scheme since block 20,715,632 (AIP-22 stage 1).

Correction added 2026-10-01. The commit seal this record counts carries no round, and the store keeps seals by block hash across rounds. A record that reaches post-quantum shows that at least the commit quorum of distinct validators sealed the block post-quantum, in some round; it does not by itself prove that the block was decided. See the Errata entry of that date, which follows the AIP-22 erratum of the same day. Chain 2800 today, below AIP-22 stage 5, is not affected: a node imports a block only with the ECDSA commit quorum of a single round.

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

  • 2026-10-01, Abstract, Motivation, "The record" (the verdict post-quantum) and "The permanent record": the record counts Falcon-512 seals over M(B) = keccak256(RLP["AERE-PQ-COMMIT-1", chainId, number(B), hash(B)]), kept by the block's on-chain hash; neither the seal nor the key carries the round. In QBFT an honest validator can commit a block in one round while a different block is decided in a later round, and seals over M(B) made in different rounds cannot be told apart (AIP-22, Errata, 2026-10-01). Measured on 2026-10-01 in the reference client: seven valid Falcon-512 seals over M(p) from rounds 0 and 2 on a block p that no round decided (test class AereRoundFreeCertificateTest), and a quorum of one round assembled from the post-quantum seals of rounds 0 and 2 in the decision collector, which counts the same seals, under the adversary of AIP-22 who forges ECDSA (AereRoundFreeCommitTest, case RF2-Q1). For aere_getPqFinality itself this is derived from the code (the same seal store, kept by hash), not run against the method. Withdrawn as written, until the commit seal binds the round: (1) "the immediate post-quantum finality of a block has been true" (Abstract) and the reading of the record as the answer to "is this block final under post-quantum assumptions" (Motivation); (2) the verdict post-quantum as finality: the field and its values stay (clients read them) and mean that at least the commit quorum of distinct validators' seals over M(B) verify now, which is evidence of participation, not of the decision; (3) "The permanent record": the anchor certificate is the permanent record of the same participation, and the AIP-22 erratum says what it proves. Not affected: chain 2800 below AIP-22 stage 5, where a node imports a block only with the ECDSA commit quorum of one round, so the block of a record is final there against an adversary who cannot forge ECDSA; the record as evidence of which validators sealed the block; and the agreement of the two clients on the same record. The remedy is the one the AIP-22 erratum proposes: a commit seal that binds the round, with a quorum of one round; it is a coordinated fork and is not scheduled.

Post-Acceptance Outcome Record

Not accepted; nothing to record.

Copyright and related rights waived via CC0.