AIP-22: four dated notes (2026-11-01): two items withdrawn from the 2026-10-27 erratum, a commit's author in the form of rule 3, the field ecdsa required in fact; Errata entry

This commit is contained in:
Aere Network 2026-11-01 19:13:59 +02:00
parent 777bebf547
commit 9ed3c91f7d

View File

@ -29,6 +29,8 @@
> **Note added 2026-10-25.** Stage 4 is active on chain 2800 since block 24,300,000: from it every validator, on both clients, takes the author of a consensus message from its verified post-quantum seal, and the second client's proposal, prepare and round-change layers, named in the notes above as taking effect at stage 4, are in force. Rule 4 of section 4 (the provisional tail and its rollback) is not part of the stage-4 binaries on chain 2800: neither client implements it at this date, a block is final on import as before, and its post-quantum proof is the anchor that covers it; the bound of rule 1 holds because every anchor height must carry a valid certificate. Headers keep their ECDSA commit seals until stage 5. > **Note added 2026-10-25.** Stage 4 is active on chain 2800 since block 24,300,000: from it every validator, on both clients, takes the author of a consensus message from its verified post-quantum seal, and the second client's proposal, prepare and round-change layers, named in the notes above as taking effect at stage 4, are in force. Rule 4 of section 4 (the provisional tail and its rollback) is not part of the stage-4 binaries on chain 2800: neither client implements it at this date, a block is final on import as before, and its post-quantum proof is the anchor that covers it; the bound of rule 1 holds because every anchor height must carry a valid certificate. Headers keep their ECDSA commit seals until stage 5.
> **Note added 2026-11-01 (to the note of 2026-10-25 above).** For a commit, "takes the author of a consensus message from its verified post-quantum seal" holds in the form of rule 3 of section 4: the author of a commit is its index's `id` only when that `id` is the signer of its ECDSA commit seal, it is given before the post-quantum seal is verified, and the vote counts only if that seal verifies (the note of 2026-11-01 under the correction of 2026-10-26 to rule 2 says it once, with the code paths). The note above is kept as it was written.
> **Note added 2026-10-30.** Stage 5 is active on chain 2800 since block 25,080,000: from it every header, anchors included, is admitted only with an empty ECDSA committed-seals element and a valid Falcon-512 proposer seal in element 6 (section 5), so no header carries an ECDSA signature. Below it every header carried the ECDSA commit quorum, which both clients required on import exactly as upstream does: rule 2 of section 4 was not implemented separately. Since stage 4 a vote counts only with its author's verified post-quantum seal, and a commit still carries the validator's ECDSA commit seal as an additional check (the correction of 2026-10-25 under section 5), so the classical uses that remain are that commit seal, the ECDSA envelope that every consensus message still carries on the wire (no longer naming its author) and the RLPx transport between nodes; the ten validators are run by one operator, and no third party has audited the stages. A node that does not take part in consensus admits a header between anchors on the Falcon-512 seal of its proposer alone, so the post-quantum key of one validator can serve such a node a branch up to the block before the next anchor (below block 25,080,000 that took the ECDSA keys of a quorum), and the next anchor ends it for a node that requires the seals of a quorum in its certificate (the published follower, with its seal ceiling at 1, is not such a node: for it one leaked or misused post-quantum key of a validator makes the rewrite depth unbounded, section 6.4 of the aere-node SPEC). Where the notes above, Motivation item 1 and the "Today" of the per-height bullet in Security Considerations say that headers carry ECDSA commit seals, they describe chain 2800 below that block. Item (4) of the Abstract describes the design; on chain 2800 the ECDSA commit seal of a commit remains a validity criterion, as rule 3 of section 4 and the correction of 2026-10-25 under section 5 say. > **Note added 2026-10-30.** Stage 5 is active on chain 2800 since block 25,080,000: from it every header, anchors included, is admitted only with an empty ECDSA committed-seals element and a valid Falcon-512 proposer seal in element 6 (section 5), so no header carries an ECDSA signature. Below it every header carried the ECDSA commit quorum, which both clients required on import exactly as upstream does: rule 2 of section 4 was not implemented separately. Since stage 4 a vote counts only with its author's verified post-quantum seal, and a commit still carries the validator's ECDSA commit seal as an additional check (the correction of 2026-10-25 under section 5), so the classical uses that remain are that commit seal, the ECDSA envelope that every consensus message still carries on the wire (no longer naming its author) and the RLPx transport between nodes; the ten validators are run by one operator, and no third party has audited the stages. A node that does not take part in consensus admits a header between anchors on the Falcon-512 seal of its proposer alone, so the post-quantum key of one validator can serve such a node a branch up to the block before the next anchor (below block 25,080,000 that took the ECDSA keys of a quorum), and the next anchor ends it for a node that requires the seals of a quorum in its certificate (the published follower, with its seal ceiling at 1, is not such a node: for it one leaked or misused post-quantum key of a validator makes the rewrite depth unbounded, section 6.4 of the aere-node SPEC). Where the notes above, Motivation item 1 and the "Today" of the per-height bullet in Security Considerations say that headers carry ECDSA commit seals, they describe chain 2800 below that block. Item (4) of the Abstract describes the design; on chain 2800 the ECDSA commit seal of a commit remains a validity criterion, as rule 3 of section 4 and the correction of 2026-10-25 under section 5 say.
## Preamble ## Preamble
@ -158,6 +160,8 @@ A registry epoch is a JSON manifest with rows keyed `"0".."count-1"`, `formatVer
| `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 | | `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 | | `transport` | `{ secp256k1Address }`: the address of the node key the validator's client uses on RLPx | optional; see 3.4 |
**Note added 2026-11-01 (to the field `ecdsa` in the table above).** "Optional afterwards" describes the loader: after the switch epoch it accepts a row without the field. Both clients require it in fact, the row's own or inherited by `id`: for the node's own identity at every height (a validator whose row does not link its own key does not recognize itself in the set, and does not propose), for the author of a commit (rule 3 of section 4), and, in the Nethermind-derived client, to place a commit in the per-author bounds of its message stores. No row without it is admitted to the set. The table is kept as it was written.
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. 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. 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.
@ -194,6 +198,8 @@ From `H_fin` (a height at or above `H_id`), on every node that validates or read
**Correction added 2026-10-26 (to rule 2 above).** On chain 2800 since block 24,300,000 both clients still apply the upstream rule to every header below `H_hdr`: it must carry at least Q ECDSA committed seals of one round of the parent's set, and a header that does not is refused (the Besu-derived client through `PqHeaderSealRule`, which below `H_hdr` is the upstream `BftCommitSealsValidationRule`; the Nethermind-derived client in `QbftHeaderValidator`). This is the admission filter that the second sentence of rule 2 allows until section 5, and its failure is a refusal, so in effect it is still a validity criterion: the first sentence of rule 2 ("is no longer applied to headers at or above `H_fin`") does not describe the stage-4 binaries. Because rule 4 is not implemented either (note of 2026-10-25 at the top of this document), a header admitted on those seals is final on import, as before; its post-quantum proof is the anchor that covers it. What `H_fin` changed is rule 3: the author of every consensus message is taken only from its verified post-quantum seal, on both clients and all four message types. Rule 2 above is kept as it was written. **Correction added 2026-10-26 (to rule 2 above).** On chain 2800 since block 24,300,000 both clients still apply the upstream rule to every header below `H_hdr`: it must carry at least Q ECDSA committed seals of one round of the parent's set, and a header that does not is refused (the Besu-derived client through `PqHeaderSealRule`, which below `H_hdr` is the upstream `BftCommitSealsValidationRule`; the Nethermind-derived client in `QbftHeaderValidator`). This is the admission filter that the second sentence of rule 2 allows until section 5, and its failure is a refusal, so in effect it is still a validity criterion: the first sentence of rule 2 ("is no longer applied to headers at or above `H_fin`") does not describe the stage-4 binaries. Because rule 4 is not implemented either (note of 2026-10-25 at the top of this document), a header admitted on those seals is final on import, as before; its post-quantum proof is the anchor that covers it. What `H_fin` changed is rule 3: the author of every consensus message is taken only from its verified post-quantum seal, on both clients and all four message types. Rule 2 above is kept as it was written.
**Note added 2026-11-01 (to the correction above).** Its last sentence, that the author of every consensus message is taken only from its verified post-quantum seal on all four message types, holds for a commit only in the form of rule 3 of this section: a commit's author is its index's `id` only when that `id` is the signer of its ECDSA commit seal. The author is given, and the commit relayed, before the post-quantum seal is verified (the Besu-derived client in `AerePqFinality.authorFromSeal`, the Nethermind-derived client in `AerePqFinality.CommitAuthor`), and the vote counts only if that seal verifies and the commit seal recovers to the same `id` (rule 3, and the correction of 2026-10-25 to section 5). So for a commit "only" does not hold, neither for the author nor at counting: whoever holds only a validator's ECDSA key can have commits relayed in its name, and they do not count. The correction above is kept as it was written.
**Correction added 2026-11-01 (to rule 3 above).** Until 2026-10-31 12:27Z the second client on chain 2800 derived the author of a proposal at the height named in its payload and then routed and voted on the block by the block's own number, without requiring the two to be equal. For a payload height below `H_fin` that author is the ECDSA envelope signer, so on that path rule 3 did not hold in the second client. The primary client was not exposed: it drops a message by its payload height before relaying it and requires the block number to equal that height. A commit on a false block was not possible on either client, because prepares are counted by the payload height and carry post-quantum seals; the reachable effect was a lost or silenced vote of the second client's validator. Exploitation was not measured. Since 2026-10-31 12:27Z the second client running on chain 2800 refuses at decoding, before authorship and before relay, any proposal whose block number differs from its payload height, and the same for the prepared block of a round-change; it also bounds a round-change's target round to [1, 1000] and its prepared round to [0, target), as the primary client does. **Correction added 2026-11-01 (to rule 3 above).** Until 2026-10-31 12:27Z the second client on chain 2800 derived the author of a proposal at the height named in its payload and then routed and voted on the block by the block's own number, without requiring the two to be equal. For a payload height below `H_fin` that author is the ECDSA envelope signer, so on that path rule 3 did not hold in the second client. The primary client was not exposed: it drops a message by its payload height before relaying it and requires the block number to equal that height. A commit on a false block was not possible on either client, because prepares are counted by the payload height and carry post-quantum seals; the reachable effect was a lost or silenced vote of the second client's validator. Exploitation was not measured. Since 2026-10-31 12:27Z the second client running on chain 2800 refuses at decoding, before authorship and before relay, any proposal whose block number differs from its payload height, and the same for the prepared block of a round-change; it also bounds a round-change's target round to [1, 1000] and its prepared round to [0, target), as the primary client does.
### 5. ECDSA out of the header ### 5. ECDSA out of the header
@ -270,6 +276,8 @@ Every activation height here is a coordinated fork: the same binary and the same
- **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. - **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.
**Erratum added 2026-10-27.** Two parts of this sentence do not hold as written. (1) Neither client's consensus layer bounds the messages of one peer: what bounds them today is deduplication on bytes, the total event queue of the Besu-derived client (1,000), the future-message buffer (per author and in total), the frame size and the RLP limits, and none of these bounds the refused messages of one peer; whether the devp2p layer below bounds a peer's istanbul messages is not measured. (2) A refusal does not cost one verification: a proposal may nest up to 512 messages in each of its two justification lists and the Besu-derived client verifies all of them while decoding, so a forged proposal can cost about 1,025 Falcon-512 verifications; the Nethermind-derived client verifies a carrier twice (relay and handler); a forged commit costs ECDSA recovery only. The cost per message type on the validator machines is not measured. The sentence is kept as it was written. **Erratum added 2026-10-27.** Two parts of this sentence do not hold as written. (1) Neither client's consensus layer bounds the messages of one peer: what bounds them today is deduplication on bytes, the total event queue of the Besu-derived client (1,000), the future-message buffer (per author and in total), the frame size and the RLP limits, and none of these bounds the refused messages of one peer; whether the devp2p layer below bounds a peer's istanbul messages is not measured. (2) A refusal does not cost one verification: a proposal may nest up to 512 messages in each of its two justification lists and the Besu-derived client verifies all of them while decoding, so a forged proposal can cost about 1,025 Falcon-512 verifications; the Nethermind-derived client verifies a carrier twice (relay and handler); a forged commit costs ECDSA recovery only. The cost per message type on the validator machines is not measured. The sentence is kept as it was written.
**Note added 2026-11-01 (to the erratum above).** Two items of the list in (1) are withdrawn. Deduplication on bytes does not bound a peer: it stops an honest gossip loop from repeating a message, not a peer from sending new ones. The parenthesis "(per author and in total)" of the future-message buffer holds for the Nethermind-derived client only; the Besu-derived client's future-message buffer is upstream's, with a total only. Nothing else in the erratum changes, and the erratum is kept as it was written.
## Reference Implementation and On-Chain Deployment ## 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: 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:
@ -426,6 +434,8 @@ Two refinements to the text above, recorded rather than silently applied: the Me
- 2026-11-01, section 4, rule 3: on chain 2800 the rule did not hold on one path of the second client until 2026-10-31 12:27Z (a proposal's author taken at its payload height while the block was handled at its own number, with no check that they are equal); a dated correction under section 4 says what, why the primary client was not exposed, and what the second client refuses since then. - 2026-11-01, section 4, rule 3: on chain 2800 the rule did not hold on one path of the second client until 2026-10-31 12:27Z (a proposal's author taken at its payload height while the block was handled at its own number, with no check that they are equal); a dated correction under section 4 says what, why the primary client was not exposed, and what the second client refuses since then.
- 2026-11-01, the Security Considerations erratum of 2026-10-27, the note of 2026-10-25 at the top of this document, the correction of 2026-10-26 to rule 2 of section 4, and the field `ecdsa` of table 3.2: four dated notes. Two items of that erratum's list of what bounds a peer are withdrawn (deduplication on bytes, and the parenthesis on the future-message buffer, which holds for the Nethermind-derived client only); for a commit, the author is taken in the form of rule 3 of section 4, not only from the post-quantum seal; and the field `ecdsa`, optional in the loader after the switch epoch, is required in fact by both clients. Nothing else changes.
## Post-Acceptance Outcome Record ## Post-Acceptance Outcome Record
Not accepted; nothing to record. Not accepted; nothing to record.