SPEC 1.1.0: section 2.6 consensus messages under post-quantum seal (wire format, domains, commit form under armed anchor = D8, emission gates, enforcement rules, activation order), G11, registry-binding domains; amended 2026-09-02

This commit is contained in:
Aere Network 2026-09-02 16:08:24 +03:00
parent 2f6950e44e
commit 8d3ae8a83d

133
SPEC.md
View File

@ -1,6 +1,6 @@
# Aere Network chain 2800: full protocol specification
Version: 1.0.0, written 2026-08-25. Scope: everything a third party needs to implement a client
Version: 1.1.0, written 2026-08-25, amended 2026-09-02 (section 2.6, D8, G11). Scope: everything a third party needs to implement a client
that follows chain 2800 from block 0 to the live head and validates what the network validates,
without reading Aere source code. It specifies the follower (validation) protocol completely; it
describes seal production only where a follower must understand it to validate.
@ -264,6 +264,100 @@ factory and grepping `consensus/`; recorded in `RUN-A-NODE.md`, "Which Besu", an
over the block hash, which commits to it. Section 5 states what this means for a client that DOES
validate base fees.
### 2.6 Consensus messages under post-quantum seal (emission live since 2026-09-02; enforcement not yet armed)
Since 28-31 August 2026 every one of the four QBFT message types (PROPOSAL, PREPARE, COMMIT,
ROUND-CHANGE) can carry a Falcon-512 seal of its author, and since 2 September 2026 all nine
validators of chain 2800 EMIT such seals on every message they send (source:
`PqAnchor.java`, the four `*_DOMAIN` constants and `*Message` builders; the four payload classes
`ProposalPayload.java`, `PreparePayload.java`, `CommitPayload.java`, `RoundChangePayload.java`;
fleet configuration measured 2026-09-02). This section specifies the wire format, the signed
pre-images, the emission gates and the enforcement rules exactly as the shipped client implements
them. **Enforcement is a per-node height switch and is NOT active on chain 2800 at publication:**
a message without a seal, or with an invalid seal, still counts as a vote everywhere on 2800. On
the public testnet 28001 all four enforcements are active (source: `testnet-public/CITESTE-MA.md`).
**Wire format.** Each payload keeps its upstream RLP list and appends, as its LAST element, an
optional two-element list `[validatorIndex, signature]` (`validatorIndex` an integer index into the
active Falcon registry, `signature` the Falcon-512 signature bytes). The element is OMITTED when
there is no seal; an explicit empty list is non-canonical. `writeTo` DEFINES the canonical encoding
and `readFrom` refuses any encoding that does not reproduce the received bytes, so a message with
a seal and the same message without one never share a hash (source: `PreparePayload.writeTo`,
comment "This method DEFINES the canonical encoding"). A COMMIT may additionally carry a list of
non-Falcon "extra" seals for the hybrid certificate (`[schemeWireId, index, signature]`), REQUIRED
to be accompanied by a Falcon seal; no extra seals exist on the fleet today (source:
`CommitPayload.java`, constructor javadoc "empty for every commit on the fleet today").
**Signed pre-images: one domain per message type.** Every seal signs
`keccak256(RLP[DOMAIN, chainId, height, ...])` with an ASCII domain string that names the message
type, so a seal given honestly for one message type cannot be pasted onto another (source:
`PqAnchor.java`):
| message | domain | pre-image fields after the domain |
|---|---|---|
| PROPOSAL | `AERE-PQ-PROPOSAL-1` | chainId, height, round, proposed block digest |
| PREPARE | `AERE-PQ-PREPARE-1` | chainId, height, round, digest |
| ROUND-CHANGE | `AERE-PQ-ROUNDCHANGE-1` | chainId, height, target round, hasPrepared, prepared round, prepared digest |
| COMMIT | `AERE-PQ-COMMIT-1` or the committed-seal hash | see below |
The COMMIT seal is special, and the rule was corrected on 2026-09-02 (D8 in section 8): the
message a commit seal signs is decided in ONE place, `PqAnchorProducer.commitSealMessage`, and is
**the anchor form** `keccak256(RLP["AERE-PQ-COMMIT-1", chainId, height, round-independent block
hash])` whenever the anchor is armed at that height (`height + 1 >= aere.pq.anchorBlock`, which on
2800 is every height since 13,013,999), and the ECDSA committed-seal hash otherwise (source:
`PqAnchorProducer.commitSealMessage`, `QbftRound.pqSealMessageFor`,
`MessageValidator.SubsequentMessageValidator`). The anchor form is what lets the same seals be
carried into the next anchor header's certificate (section 3.3); the round-independent hash is the
on-chain hash with the round forced to 0 in the committed-seal encoding.
**Emission gates (producer side, per node).** `aere.falcon.attachBlock` arms Falcon seals on
COMMIT messages (on 2800: 13,889,296); `aere.pq.proposalPq.attachBlock`,
`aere.pq.roundChangePq.attachBlock` and `aere.pq.preparePq.attachBlock` arm the other three (on
2800: 16,620,000, 16,660,000, 16,690,000, measured 9 of 9 emitting). Absence of a property means
never. A node without a Falcon key emits nothing and is byte-for-byte upstream on the wire
(source: `FalconSealSupport.java`, `*_ATTACH_PROPERTY`; fleet options measured 2026-09-02).
**Enforcement (validator side, per node): `aere.pq.commitPq.forkBlock`,
`aere.pq.proposalPq.forkBlock`, `aere.pq.roundChangePq.forkBlock`, `aere.pq.preparePq.forkBlock`.**
From the configured height a message of that type COUNTS as a vote only if all of the following
hold; otherwise the message is logged and ignored ("the vote does not count"), it is not a
consensus fault of the sender and it does not disconnect the peer (source: `PqCommitEnforcement`,
`PqPrepareEnforcement`, `PqProposalEnforcement`, `PqRoundChangeEnforcement`, the `refusal`
methods and their message strings):
1. the message carries a seal;
2. the registry active at that height binds the seal's index to exactly the message's ECDSA
author (recovered from the upstream signature): the seal is bound to the author, so a seal
from validator A cannot be attached to validator B's message;
3. the registry accepts the index (it refuses indices outside the active set);
4. the signature verifies, with the Falcon-512 public key of that index, over the pre-image of
the table above (for COMMIT, over the message `commitSealMessage` names at that height);
5. for a COMMIT that carries extra seals, every scheme the hybrid schedule requires at that
height is present, of the same index, and verifies over the SAME message.
Below the configured height nothing changes: the upstream ECDSA rules alone decide. There is no
consensus binding on these heights (the same caveat as section 3.2): two validators armed at
different heights disagree about which votes count, and the published activation procedure arms
all nine at the same four heights, one node at a time, with the chain measured to advance between
restarts (source: `ARMAREA-IMPUNERII-MESAJELOR-2026-09-02.md`,
`armeaza-impunerea-pe-flota.sh`).
**Order of activation, and why.** The published package arms COMMIT first (a commit that does not
count only delays finality within the round; the liveness margin is measured), then PROPOSAL,
then ROUND-CHANGE (whose enforcement touches only the failure path: the happy path never emits a
round change), and PREPARE last (the strictest: without a quorum of sealed PREPAREs a round
cannot reach "prepared"). Rehearsed end to end on the seven-node kit (F95: the four heights in
one restart, a coordinated postponement, each height crossed, a muted node, a sub-quorum stop and
its healing) and, since 2026-09-02, WITH the anchor armed as on 2800 (source:
`consensus-pqc/fullpq-activare-2026-08-28/`, `F-lib.sh`, `dovezi/`). The machine-checked model of
these rules is `formal-consensus/pq_message_enforcement_smt.py` (section 7).
**What this section does not claim.** Node-to-node authentication (RLPx) is ECDSA. The hybrid
(Falcon + SLH-DSA) certificate is implemented and tested but no hybrid keys exist on 2800. None of
this is audited by a third party. Until the four `forkBlock` heights are set on the fleet, chain
2800's consensus is post-quantum in EMISSION only, and the defensible sentence remains the one in
section 3.1.
---
## 3. The post-quantum certificate anchor
@ -505,6 +599,25 @@ contract at `0x5214F0e53899Dad805ef3AdF0624F5e49d2a5EB5` from block 13,889,290 (
`RUN-A-NODE.md`, follower configuration; the contract's own interface is not specified in this
bundle, see section 9, G6).
**Domain tags of the registry binding and of node-local persistence (named here so that a
third-party client sees every `AERE-PQ-*` tag the shipped client uses).** A registry row binds a
Falcon key to a validator address with two signatures over two distinct pre-images (source:
`PqRegistryBinding.java`, class javadoc "The canonical pre-image"):
- the **possession proof** is a Falcon-512 signature over
`"AERE-PQ-POP-1" || uint8(formatVersion) || uint64be(chainId) || uint64be(bindHeight) ||
uint32be(count) || uint32be(index) || address(20) || uint32be(len(publicKey)) || publicKey`.
The tag sits at offset 0 INSIDE the hashed pre-image, so a possession proof can never be
replayed as a seal (the seal pre-images are `AERE-PQ-COMMIT-1` and the section 2.6 domains);
the public key is inside the signed message because Falcon does not have exclusive ownership;
- the **claim** is an ECDSA signature by the validator's consensus key, in an EIP-191 context
that mixes the tag `AERE-PQ-CLAIM-1`, so a key cannot be moved under another validator's
address, indices cannot be swapped, and a key cannot appear under an address whose owner did
not ask for it.
- `AERE-PQ-SEALSTORE-1` is the label of the node-local file in which a node persists the seals it
has heard for its chain head across restarts (`aere-pq-seals.rlp`); it is not consensus data and
a client is free to implement it differently or not at all (source: `PqSealStore.java`).
### 3.6 The canonical registry hash
(source: `anchor/consensus/common/.../PqRegistryHash.java`; exact and normative)
@ -905,6 +1018,18 @@ are the authoritative in-protocol trace of the expansion (source: `registries/RE
---
**D8. The COMMIT seal message under an armed anchor (found 2026-09-02, D-311).** A verifier of the
COMMIT enforcement that checks the seal over the ECDSA committed-seal hash refuses EVERY commit as
soon as the anchor is armed, because the emitter signs the anchor form (section 2.6). The shipped
client before 2026-09-02 had exactly this divergence between its emitter and its verifier; it was
found on the public testnet 28001 at the first enforcement height (the chain stopped at block
999), fixed by deriving both sides from one function, proven with unit and plumbing tests, a
rehearsal with the anchor armed, and the testnet itself, and the fleet was moved to the fixed
build on 2026-09-02 (image `d311-20260902`, version `26.4.0-aere.1-d203201-wt95fac2d7`). A
third-party client implementing COMMIT enforcement MUST verify over the anchor form whenever
`height + 1 >= aere.pq.anchorBlock` (source: `testnet-public/D-311-DOVADA-2026-09-02.md`,
`deploy/validators/d311-2026-09-02/SURSA.md`).
## 9. What this specification cannot state from the published sources
Honest list, for completion in a later revision. An implementer hitting one of these should treat
@ -941,7 +1066,11 @@ the gap as real rather than assume.
- **G9. Whether a certificate reused by an adversary for its one permitted fork block passes
eligibility in every corner case** was argued from code and never executed as a run (source:
`CE-DEVINE-INVALID-LA-ANCORA-2026-08-07.md`, NEMASURAT item 8).
- **G10. Anything about the chain after 2026-08-25.** Every measured statement carries its date;
- **G11. When, and whether, the four message-layer enforcements of section 2.6 are armed on
2800.** At publication they are not; the heights are a founder decision. A reader must measure
the fleet's `aere.pq.*Pq.forkBlock` properties (or observe refusals in node logs) rather than
assume either state.
- **G10. Anything about the chain after 2026-09-02.** Every measured statement carries its date;
the live schedule, set size, and head move. The registries directory and the follower
configuration are the values current at publication.