Commit Graph

43 Commits

Author SHA1 Message Date
Aere Network
8d3ae8a83d 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 2026-09-02 16:08:24 +03:00
Aere Network
2f6950e44e Add SECURITY.md and AUDITS.md
Both are prerequisites for any external review programme, and one of them was already
promised by our live security.txt to a file that did not exist.

SECURITY.md states the scope, the response times we hold ourselves to, and three things
we would rather a reviewer heard from us than discovered: there has been no third-party
audit, every validator is operated by the Foundation, and the post-quantum guarantee is
at anchor heights rather than on every block.

AUDITS.md opens by saying we have had no third-party audit, and keeps that first line
until it stops being true.
2026-09-01 11:58:34 +03:00
Aere Network
2b73bcb961 Prove that consensus safety does not depend on the transport
The network layer authenticates peers by their secp256k1 node key, and consensus
messages are routed by the address derived from it. An adversary who recovers a
validator's ECDSA key therefore gets everything the transport can give: it completes
the handshake as that validator and signs syntactically perfect messages that recover
to its address. This test models exactly that adversary - full ECDSA compromise, no
Falcon key - and requires all four hot-path messages to be refused while the
post-quantum enforcement is armed, with a harvested seal replayed across message
kinds, blocks, heights, rounds, chains, and from another validator entirely.

The honest form of the claim: the transport is not post-quantum, and breaking it
does not buy a break of safety. It says nothing about liveness.
2026-09-01 01:52:18 +03:00
Aere Network
2ac6ecc316 Prove scheme agility of the proposal and round-change enforcements
One shared harness for both surfaces (the twin-class lesson applied in advance):
a seal made with SLH-DSA passes through the same untouched consensus code, and a
Falcon seal against an SLH-DSA registry is refused on both surfaces. The Falcon
nail sits only in the production wiring, for all three message enforcements.
2026-09-01 00:28:13 +03:00
Aere Network
473832438c Consolidate twin test classes: one copy of each proof
Twelve test classes existed twice, under a neutral name and under an internal
inventory name, ~4,600 duplicated lines. Two copies of the same proof diverge
silently: one receives a repair and the other does not - which is exactly what
happened once, and what the cache-hygiene test below documents. The neutral
names survive; per pair the test counts are identical, and the only code
difference (a warm-up window constant) exercises the same path and the same
assertion. The cache-hygiene reproduction now runs the surviving class's
lifecycle, unchanged in what it asserts.
2026-09-01 00:13:42 +03:00
Aere Network
7242a2c388 The round-change now carries an optional post-quantum seal, disarmed by default
The last hot-path QBFT message under the same pattern as prepare and proposal:
its own domain AERE-PQ-ROUNDCHANGE-1 over (chainId, height, targetRound, prepared
metadata - so a bare 'move on' seal cannot be replayed as 'move on and re-propose
THIS block'), a separate emission gate (aere.pq.roundChangePq.attachBlock), a
separate enforcement height (aere.pq.roundChangePq.forkBlock) self-wired into the
payload validator so it also judges round-changes inside proposal justifications,
and byte-for-byte upstream encoding when no seal is present. The seal is signed
once and the same object goes on the wire; Falcon signatures are randomised, so
a re-signing would put a different message on the wire than the one handled
locally.
2026-09-01 00:03:54 +03:00
Aere Network
a9af2de488 The wire copy of a sealed proposal now carries the seal, proven on a test network
The first witness run caught a real gap: the proposal was signed twice - once for the
local copy, once for the wire - and only the local copy carried the proposer's Falcon
seal. Locally sealed, unsealed on the wire: with enforcement armed, the fleet stopped at
the enforcement height even though every node was emitting. Falcon signatures are
randomised, so the fix is structural rather than cosmetic: the proposal is built once,
seal included, and the transmitter sends that same object - two signings would produce
two valid and different proposals from the same proposer.

A new plumbing test refuses the defect's return: it fails if the transmitter's wire path
ever builds its own payload again. On the test network after the fix: emission covered
seven of seven proposers, each sealing exactly its first proposal past the gate; with
enforcement armed and emission on, the chain crossed the enforcement height with zero
refusals; with emission off it stopped exactly one block short of the height, every
refusal logged; and one unarmed node could not keep the chain alive.

Still armed nowhere: the properties are unset, and unset means never.
2026-08-31 15:36:42 +03:00
Aere Network
3afe906fb2 The proposal now carries an optional post-quantum seal, disarmed by default
The remaining hot-path gap, stated precisely because the imprecise version oversells: with
PREPARE enforcement armed, an ECDSA-breaking adversary cannot finalize anything, since
"prepared" needs a full quorum of PREPAREs. What forged proposals could still do is OPEN
rounds and waste them. With proposal enforcement armed, a proposal without a valid Falcon
seal from its own proposer does not open a round.

Same pattern as the PREPARE layer, deliberately: an optional fifth payload element that
leaves the unsealed encoding byte-identical to upstream; a third, separate emission gate;
enforcement self-wired in the payload validator so no refactor can drop it silently; its
own domain over (chainId, height, round, digest), tested in both directions so an honest
offer seal cannot be replayed as a vote nor a vote seal as an offer.

Nothing is armed anywhere: the properties are unset, and unset means never. The armed-
layers table in the README says so, and says what stays classical: the ROUND-CHANGE
message itself and node-level devp2p authentication.

1,042 tests, 0 failures, counted from the XML. The enforcement's negative control ran at
5 of 5: four planted defects each turned the suite red, the untouched source stayed green.
2026-08-30 13:38:33 +03:00
Aere Network
4ef6565275 Apply the isolation guard one twin had and the other lacked
D140FleetRestartArmingTest did not clear the aere.pq.* properties and the per-JVM anchor
config cache in setUp, while its twin PqFleetRestartArmingTest has done so since 20 August
2026. Without it the class is green on its own and red inside the full suite, on identical
sources, because a neighbouring class leaves an armed anchor config cached.

That is the concrete cost of keeping two copies of a test: a repair lands in one and not
the other, and nothing fails to say so.

1,012 tests, 0 failures.
2026-08-29 18:50:10 +03:00
Aere Network
a7b24b8f30 Bring the published anchor overlay level with the tree we run, and say which layers are armed
The first publication of this directory, on 11 August 2026, was staged by hand and was
never refreshed. Measured on 29 August: of the 78 files published here, only 14 were still
identical to the tree we run, 63 had changed, and 50 files had never been published at all.
Nobody was hiding anything; there was simply no tool that could redo the selection, so
nobody redid it. There is one now, and it derives this directory from the authoritative
overlay rather than from anyone's memory.

Two things in here contradicted themselves, and both are fixed rather than trimmed.

The README withdrew, in one section, a claim that the source next to it still made: that
from block 14,050,000 a per-block 2f+1 Falcon quorum was required for a block to finalize.
The rule that property arms is retired at the anchor block, so it was inert on arrival.
Three places in the code said otherwise and now carry the correction with its date. The
old text is kept, not deleted: the rule is real code and can be armed on a chain that never
reached an anchor block. What was missing was that on chain 2800 it does not apply.

The terminology section said the certificate is signed by f+1 validators and "not by a
quorum", and invited the reader to count. Since 14,961,456 the enforced minimum is six of
nine, which is a quorum, and the paragraph had not been revised. It now says so, with the
date it changed, and adds the two things that make the claim defensible: the word applies
only at anchor heights, and the higher threshold costs liveness margin.

New in this directory: the post-quantum seal on PREPARE, the hybrid Falcon + SLH-DSA scheme
layer, and the test suites for both. Neither is armed on any network, and the README now
carries a table saying which layers are armed on chain 2800 and which are only present.
They are disarmed by absence rather than by a flag: the properties that arm them are unset,
and unset means never.

Not published, and it is the same three files every time: the negative-control harnesses.
They plant a defect on purpose to prove a guard can fail, which makes them a recipe for
disabling a guard rather than a description of one. What they prove is stated in the README.

Per-file SHA-256 in MANIFEST-sha256.txt. 1,012 tests, 0 failures, counted from the XML.
2026-08-29 18:39:31 +03:00
Aere Network
249da4ff7c Terminology: the anchor certificate is a quorum since 14,961,456, and this document said both
Line 23 stated the enforced minimum is six of nine, a full 2f+1 quorum. Line 192 stated
the certificate is signed by f+1 validators, not by a quorum, and that we do not call it
one - inviting the reader to count. The terminology paragraph was written when the
threshold was three, where it was true, and was not revised when the threshold was raised
on 21 August 2026. A document that asks to be counted and does not survive the count loses
more than the paragraph.

Corrected without deleting the distinction, and with the two things that were missing and
without which the claim is not defensible: the word quorum applies only at anchor heights,
about every 32nd block, and the blocks between them carry no Falcon seals at all; and the
higher threshold costs liveness margin, since at six of nine three late validators stall an
anchor block where three of nine tolerated six.

Not pushed. Publishing is the founder's decision.
2026-08-29 18:18:15 +03:00
Aere Network
39d3275e17 Bootnode 1 (37.27.216.110) now serves snap/1 (SnapServer on Bonsai flat db): SNAP clients skip historic body replay; run-node.sh stays FULL on purpose. Measured vs not-measured stated. 2026-08-28 02:31:48 +03:00
Aere Network
e5da289a8e Citations ledger: the floor-lapse source now resolves in the published aere-client2 repository; entry pruned 2026-08-28 00:52:42 +03:00
Aere Network
34bb4ccb20 Citations ledger refreshed: every unresolvable cited path declared, stale entries pruned (generated by legaturi-repara) 2026-08-28 00:46:14 +03:00
Aere Network
c6d36f54b5 LICENSING: record the 27 upstream-copyright files under anchor/ with the Apache-2.0 section 4(b) modification notice, measured from headers 2026-08-28 00:35:12 +03:00
Aere Network
a134a899ac Honesty: drop the uncited 'audited' adjective from Bouncy Castle references; state the citable facts instead (not FIPS-validated, no published third-party audit known) 2026-08-28 00:28:29 +03:00
Aere Network
184ec23cd4 Publish the two bootnodes; run-node.sh works with zero arguments now
Founder approved publishing the network entry points. Both are public read hosts
outside the validator set, so their downtime cannot cost consensus, and their
addresses were already public through the services they serve. One runs Besu and
one runs Nethermind, so a new node's first two peers are two independent
implementations. run-node.sh uses both by default; --bootnode still overrides.
The mail path stays as fallback for the day both are down.

This closes the last gap between "one command plus an email" and one command.
2026-08-25 01:11:25 +03:00
Aere Network
44dbc1bc06 Point 47: the unified protocol specification, SPEC.md
One document from which a third party can implement a client that follows chain
2800 without reading our code: chain parameters, QBFT with the full extraData
layout and what the block hash does and does not cover, the post-quantum anchor
rules with exact pre-images and the follower configuration, precompile formats
with the message in the middle and variable signature lengths, fee rules with
their historical windows, sync requirements including the genesis-set ceiling,
and the formal models with their honest boundaries.

Every normative statement carries a file citation, a [MEASURED <date>] marker
with the command, or [NOT MEASURED]. Section 8 documents twelve dated
divergences a syncing client will meet on the real chain (the 2138451 transition
value that must not be corrected, the base-fee lapse window, the anchor disarmed
window, the threshold window, the retired falcon.forkBlock rule), because a spec
that hides history cannot sync anyone. Section 9 lists ten things this spec
cannot state from published sources, by name, rather than papering over them.
2026-08-25 00:57:53 +03:00
Aere Network
edfc637ebd Point 29: one command to run a node, proven from a fresh clone
run-node.sh folds the four manual steps (apply patches, build the fork, load the
registries, set BESU_OPTS) into a single deterministic, idempotent command. It
verifies the genesis sha256 and every registry against SHA256SUMS and refuses on
mismatch; applies patches 0001,0003,0004,0005 on a pristine upstream checkout
(0002 testnet excluded) with a reverse-apply idempotence check; builds with
installDist; starts a follower with the correct BESU_OPTS. It holds no key.

The registries a from-genesis follower needs were missing from this package, only
the code that reads them was here, so nobody outside could cross block 13,014,000.
Added them as public data (Falcon public keys, validator addresses, possession
proofs; no private material), byte-identical across three independent validators,
with SHA256SUMS and a provenance README. Secret gate passes.

Proven from a fresh git clone in WSL, as a stranger: built (BUILD SUCCESSFUL),
idempotent on re-run, started, loaded all three registries with verified
possession proofs, block-0 hash equals the network genesis, and synced from block
0 with zero anchor rejections and zero stateroot mismatches.

A real finding this test surfaced, fixed and documented: a from-genesis node
starts into the genesis validator set N=3, where the published seal schedule
(K=3 at 13,034,000, K=6 at 14,961,456) is unreachable, so PqAnchorThresholdGuard
refuses to start. The fix baked in is the guard's own documented remedy,
minSealsCeiling=1, which relaxes only the seal-count floor (a proposer-liveness
property) without weakening the PQ binding: every anchor still needs a valid
registry-verified Falcon seal. A validator does not set this.

Honest limit: crossing 13,014,000 was not reached in-session because the two
public bootnodes serve historical block bodies at only ~7 blk/s sustained (ETA
~19 days), and syncing bodies from validators would breach the read-only fleet
rule. The crossing rests on these registries being byte-identical to those in the
Aug 15 import proof that reached the live tip.
2026-08-24 20:48:51 +03:00
Aere Network
9109adce96 Anchor threshold raised to a full 2f+1 quorum: since block 14,961,456 (August 21, 2026) an anchor block does not finalize without at least six of nine valid Falcon-512 validator seals; measured on-chain before this text changed 2026-08-22 12:49:41 +03:00
Aere Network
05192bcf9c README: nine validators (seven until 2026-08-09); consensus is classical ECDSA on every block with a post-quantum checkpoint every 32 blocks (>=3 of 9 seals since 2026-08-14); live height dated 2026-08-19 15:50:43 +03:00
Aere Network
ac7c0adaa5 Precision fix 2026-08-19: the three-seal anchor minimum has been enforced since 2026-08-14 (the schedule step is at block 13,034,000 but an emergency ceiling held the effective minimum to one until then); anchors universal since block 13,889,296 2026-08-19 15:46:53 +03:00
Aere Network
b7669355eb Correction 2026-08-19: the per-block Falcon quorum armed at 14,050,000 is retired in the shipped code; what is enforced is the anchor certificate (>=3 of 9 seals every 32nd block). Patches 0003/0004/0005 regenerated with Apache 4(b) notices and upstream headers visible; 0004 message now states the floor fork is active since 10,141,734 2026-08-19 14:14:57 +03:00
Aere Network
d0cb9ca298 RUN-A-NODE: the import proof is no longer owed, it is measured: from block 0 to 14,088,211 and following the tip, 2026-08-16 2026-08-19 12:07:40 +03:00
Aere Network
94438cd8f1 A package-built node has now imported chain 2800 from block 0 to the live tip, with zero anchor rejections
Reaching the tip needed two historical facts encoded, and the second one was
not in the original hypothesis.

First, the disarmed window: 36 anchor heights (13,267,824 to 13,268,944) whose
blocks carry an attached certificate but no digest, and whose signer indices are
not strictly increasing, produced while anchoring was disarmed fleet-wide to
unblock the chain after an incident. Encoded as a named list of historical
windows with fixed bounds in code, after the precedent of the base-fee lapse
windows: inside, the header is accepted as written; outside, nothing changes.

Second, the recovery, found by measuring rather than guessing. After the
emergency re-arm the fleet ran for a stretch with a lowered seal threshold, so
proposers legitimately wrote shorter certificates. Its extent was measured by
reading 25,252 anchor heights one at a time, with NO binary search, because the
property is not monotone: only about 15 percent of heights are affected and the
largest gap between two affected heights is 44, so a binary search would have
returned an answer that looks exactly like a good one. Result: 13,268,976 to
13,890,544, thresholds measured at 1 or 2, never 0.

The second window relaxes the seal COUNT only. Digest binding and index
ordering stay enforced and every seal is still verified. Widening the disarmed
window to cover both would have been easier and would have thrown away
certificate binding on 19,425 anchor heights, which is the one property the
anchor exists for.

Negative control in four directions, because an exception can fail both ways:
the window predicate forced always-false turns 10 tests red; forced always-true
turns 39 red, of which 22 are pre-existing strictness tests, making the
exception swallowing the chain visible; the historical threshold emptied turns 7
red; pinned at 1 turns 8 red. Restored: 641 tests, 0 failures, counted from XML.

Patch verified on a pristine upstream checkout, alone and in series, and the
resulting tree compiles.
2026-08-16 02:00:01 +03:00
Aere Network
d96ae52430 The 13,267,729 boundary explained: a historical window where anchoring was deliberately disarmed fleet-wide
Measured on the live chain by reading vanityData block by block: the last
anchor carrying a digest before the window is 13,267,792; heights 13,267,824
through 13,268,944 (37 anchor heights) carry the ordinary client string instead
of a digest; the digest resumes at 13,268,976. All 37 still carry an attached
seal certificate (2,620 to 3,282 byte headers), which is direct on-chain proof
that seal attachment and digest anchoring are two independent switches and were
in different states here.

What happened: several validators restarted inside a short window and were all
left holding no heard seals at the same time, while the next height was an
anchor height with a seal threshold, so no node could propose. Unblocking meant
disarming the anchor fleet-wide, which restarted block production immediately.
Blocks produced while disarmed also carry signer indices that are not strictly
increasing, because canonical ordering is applied on the anchoring path.

Why it matters to anyone running a node: those 37 heights are real, immutable
chain history. A node syncing from genesis meets them and correctly refuses
them if it carries a single anchoring configuration; nodes that were already
running do not stumble because the blocks are already in their database and are
not revalidated. So the package needs the historical disarmed windows, named
with exact bounds, in which the anchoring rules accept the header as given,
exactly like the base-fee lapse windows the second client already carries. The
fix is in progress; until it is proven by import past the window, this section
states the limit rather than hiding it.
2026-08-16 00:14:32 +03:00
Aere Network
67e3c26e1c Patch 0003 regenerated with the schedule-boundary fix: a package-built node now crosses the first real anchor
The published patch carried a one-block boundary defect: the seal rule asks the
index-to-address map at the parent height (H-1) while the registry schedule
binds inclusively from H, so at the very first anchor the schedule was empty and
the lookup fell back to a head map that is empty on a node synced from genesis.
A valid certificate was rejected. Fixed in both lookup paths: when the schedule
has an entry at exactly blockNumber+1, answer from that entry's verified bound
registry. The boundary stays exactly one block.

Proven by import, not by assertion: the package-built node was stuck at
13,013,999 with 6,646 rejections; with the fix it crossed 13,014,000 in 42
seconds and imported 253,729 further blocks through the anchor era with zero
rejections. Tests: new PqParentHeightAlignmentTest 3/3, consensus:common 391/0,
consensus:qbft 217/0. Negative control measured: disarm the condition and the
measuring test goes red; restore it and it is green.

Patch verified to apply cleanly on a pristine upstream checkout, alone and in
series with 0001/0004/0005; file list is the previous 75 plus the new test, and
every untouched section is byte-identical to the old patch. The anchor/ source
copy in this package was brought to the same state so the two cannot diverge.

Honest limit, recorded in IMPORT-PROOF-STARE: further along, at 13,267,729, the
node stops again for a DIFFERENT reason. Blocks in a band there carry an
attached certificate whose vanityData is the ordinary client string rather than
the digest, at heights a single static interval treats as anchor heights. The
best-supported reading is that the fleet ran a different anchoring configuration
in that window (these values are not consensus-bound), so the package needs a
HISTORICAL anchoring schedule, not one value. Stated rather than implied.
2026-08-16 00:03:20 +03:00
Aere Network
85747e23af Import-proof honesty pass: production validates since Aug 9 (not 'two months'), internal image tag and finding IDs removed, registry provenance stated plainly 2026-08-15 23:28:26 +03:00
Aere Network
8fb08eeee7 Import-proof state: the public patch 0003 binds the registry differently than the seal rule reads it (D-150 class)
A from-genesis sync of the patches-only build reached the first real anchor
(13,014,000, certificate index 0) and was rejected there: PqAnchorSealsRule
says index 0 is unbound, though the registry the node itself bound contains
key 0 and production validates the same block. Two paths over one registry
that disagree. Fix (align the index->address mapping in 0003 with production
source) needs a dedicated binary session with a negative control. Written
honestly; RUN-A-NODE already flags the build as a follower until a full
import proof. Trying the proof for real found the missing link in one evening.
2026-08-15 22:05:28 +03:00
Aere Network
600a716070 Patch 0005: the import proof was attempted, and it found what no green test had
A from-genesis sync of a patches-only build stopped at block 9,189,161, the
futureEipsTime activation, with a stateroot mismatch. Two causes, one patch:
upstream bases futureEips on the unreleased amsterdam definition while chain
2800 isolates it on Osaka, and the fleet activates EIP-2935 history storage in
the same fork, one system state write per block that a build without this
patch never performs. With 0005 applied the same node, same data directory,
crossed the activation and keeps importing. The fleet's optional Block-STM
wiring is deliberately omitted and the omission is stated in the patch header.
2026-08-15 16:07:02 +03:00
Aere Network
54f6ffed05 RUN-A-NODE: the build recipe is measured again, with all three patches
Pristine d2032017, plain git apply of 0001+0003+0004, installDist exit 0 on
JDK 21, besu/v26.8-develop-d203201. Stated next to what it does not prove:
the import proof against the live chain is still owed.
2026-08-15 13:30:15 +03:00
Aere Network
35911fb5c7 The three patches apply again with plain git apply, proven on a pristine checkout
The licence-note edits had normalized whitespace inside hunks, so the recipe
this repository tells its reader to run failed at step one with 'patch does
not apply'; only --ignore-whitespace passed, and the README nowhere says to
use it. Each patch was re-applied to pristine d2032017 with whitespace
tolerance, then regenerated from the resulting tree with its prose header
kept, and the full sequence 0001, 0003, 0004 was applied with PLAIN git
apply on a fresh pristine checkout before this commit was made.
2026-08-15 13:26:35 +03:00
Aere Network
2f1858d10e gitattributes: genesis, patches and vectors are byte streams, never line-ending converted
A Windows checkout was silently rewriting genesis.json to CRLF, so the
working-copy hash stopped matching the published and fleet hash, and the
package gate went red on a file whose bytes in git were correct. bd4f8b4
fixed this once by re-adding the file; this pins the rule so no checkout
can undo it again.
2026-08-15 13:21:42 +03:00
Aere Network
4fa48bb41c RUN-A-NODE: the genesis fingerprint in the table is the published file's real one
The table carried the hash of an earlier derived export; the published file
has been the fleet's byte-for-byte genesis since the registry-binding commit.
The line-ending caveat is written next to it because that is exactly how the
wrong hash survives review on a Windows checkout.
2026-08-15 13:20:31 +03:00
Aere Network
a70d06fef6 Reunite the two lines of this repository: the runnable package joins the anchor
The published line delivered the anchor (source and patch 0003) but had lost
the chain configuration: no genesis, no run recipe. The unpublished local line
had genesis.json, RUN-A-NODE.md and the measured claims, but predated the
anchor. This commit carries the package files onto the anchor line:

- genesis.json restored, byte for byte as the running nodes hold it
- RUN-A-NODE.md restored; the basefee-floor patch returns as 0004; the anchor
  section states plainly that a build without patch 0003 has not been shown to
  import headers past block 13,014,000, and that an import proof for a
  patches-only build is the next thing this repository owes its reader
- bootnodes are deliberately NOT published: today's entry points are consensus
  or origin hosts, and this project does not print its machines' addresses; a
  dedicated bootnode host is the planned replacement, an enode is available by
  mail until then
2026-08-15 13:18:55 +03:00
Liviu
3f62a21a70 Place this anchor correctly among the defences that already exist
We went and read the field instead of asserting into it, and two things in the
README were saying more than the literature supports.

The attack has a name we were not using. It is posterior corruption, also called
the founders' attack, long-range attack, history revision or costless simulation.
Tas, Tse, Gai, Kannan, Maddah-Ali and Yu (arXiv 2207.08392) survey the four known
mitigations: social consensus, key-evolving signatures, verifiable delay
functions, and timestamping onto a proof-of-work chain.

That paper proves an impossibility, and the previous wording here would have read
as if we had stepped around it. We had not, because it says something narrower
than it first appears: slashable safety, which is safety plus the ability to
punish the attacker, needs an external trusted source. Plain safety against
posterior corruption does not, and key-evolving signatures are shown to give it
under an honest majority. This anchor does not claim slashable safety and the
README now says so.

What it does claim is now stated where it is actually strong. Key-evolving
signatures rest on an old key being gone once deleted. A quantum adversary does
not need it to have been kept: QBFT headers carry addresses, but every seal is an
ECDSA signature from which the public key is recoverable, and from that the
private one. Deleting the key buys nothing when the chain reconstructs it. The
certificate under the block hash still has to be forged, and that needs a secret
no amount of computation derives from the chain.

So this is the post-quantum analogue of what key-evolving signatures give
classically, in the setting where their central assumption is void. Narrower than
checkpointing, and borrowing nothing from another chain. Both true at once.

Sources opened and checked, not recalled: arXiv 2207.08392, eprint 2019/1440,
arXiv 2208.05408.
2026-08-12 12:18:58 +03:00
Liviu
067a57eb87 Say exactly what Winkle supports and what is ours
We cite Azouvi, Danezis and Nikolaenko's "Winkle" for the threat this anchor
addresses. Today we opened the paper instead of repeating the citation, and two
things need saying, because a reader who opens it will notice both.

Winkle does not mention quantum adversaries anywhere. It treats old validator
keys becoming compromised, by any means. The quantum framing is ours.

And Winkle's defence is not this one. It adds a secondary layer of client-based
validation in which clients sign a hash of the previously sequenced block. The
same authors' later work, Pikachu, checkpoints into Bitcoin instead. Both are
established answers to this threat, and a reader weighing our design deserves to
be pointed at them rather than left to find them.

So the README now says it plainly: the threat has peer-reviewed grounding, the
defence in this repository is ours, and the honest difference from checkpointing
is that checkpointing borrows security from another chain while this borrows
nothing.

Citations verified at source, not from memory: eprint.iacr.org/2019/1440, AFT
2020 pp. 189-201; arXiv 2208.05408, 2022.
2026-08-12 11:14:43 +03:00
Liviu
820ae134f7 Carry the Apache 4(b) and 4(d) notices the anchor was missing
Caught by our own licence gate the minute the anchor went up, which is the only
reason this is a same-day correction rather than something a reader finds first.

Two separate requirements, both real:

- section 4(b): the twenty upstream files this overlay modifies must carry a
  prominent notice that we changed them. They did not. They do now, placed after
  the upstream copyright header rather than over it, because 4(c) requires that
  header to survive untouched. It does: eighteen still read "Copyright ConsenSys
  AG.", two "Copyright contributors to Besu."

- section 4(d): NOTICE must carry the attribution notices of the work this
  derives from. It named Hyperledger Besu only, while the files themselves carry
  three distinct notices. All three are now reproduced. Naming one of three was a
  smaller truth than the files tell.

The patch is regenerated from the corrected files and re-verified end to end, not
assumed: git apply --check and git apply both 0 on a pristine d2032017 checkout,
the resulting tree byte-identical to anchor/ (75 files compared, 0 differences),
and 605 tests with 0 failures across consensus:common and consensus:qbft.
2026-08-12 02:28:48 +03:00
Liviu
50290b47c8 Deliver the anchor as a patch as well as files
This repository argues, in its own README, that a patch against a named upstream
commit is the honest way to publish a contribution to a million-line project: the
diff is the contribution, the reader fetches the rest from upstream, and a patch
fails loudly when upstream moves while a whole file overwrites in silence.

The anchor was published as whole files only, which contradicted that argument.
It is now both: patches/0003 to apply, anchor/ to read.

Verified on a pristine d2032017 checkout rather than assumed:
- git apply --check and git apply both returned 0
- the resulting tree is byte-identical to anchor/: 75 files compared, 0 differences
- :consensus:common:test and :consensus:qbft:test returned 605 tests, 0 failures,
  the same count class by class as the same tree built from the files

The README also said "no build file changes are required" in a place that now
reads as if it covered all three patches. It covered the first two. Patch 0003
changes one build file by one line, and that line is named.
2026-08-12 02:08:38 +03:00
Liviu
56a02656aa Add the post-quantum certificate anchor for QBFT
This is the code that puts a post-quantum validator certificate under the block
hash. It is the thing this project exists to do, and it is published so that the
claim can be checked rather than believed.

What it is. In QBFT the block hash is computed over a re-encoding of the decoded
extraData with the seals removed, so anything the decoder does not know about is
dropped before hashing. Appending a certificate as a new element gives you a
certificate that is stored, gossiped, and entirely absent from the hash. The
design that works instead puts a 32-byte digest of the certificate into
vanityData, which is already under keccak. anchor/README.md sets out the four
designs that died before this one and why.

Scope, stated in the README and repeated here because it matters: consensus on
chain 2800 is classical secp256k1 ECDSA. This binds a post-quantum certificate to
the block hash. It does not make consensus post-quantum and is never described as
such.

What is here: the anchor, the validation rules, the wiring, and the tests,
including the negative controls. Applied to upstream d2032017bb, the pinned base
named in anchor/BASE.txt. One build file changes, by one line, and the README says
which and why. No cryptography is implemented here; Falcon verification calls
Bouncy Castle.

What is not here: no keys, no fleet configuration, and nothing about what is armed
on any running network.

Measured before publishing, on upstream d2032017bb with this overlay applied:
consensus:common and consensus:qbft, 605 tests, 0 failures, identical to the same
tree before this work, class by class.

Three things were found while preparing it, and all three are fixed here:
- the code spoke Romanian in 134 comment lines and 43 strings, 37 of them on
  production paths, which is to say in the messages a node prints when it refuses
  to start. An auditor given the code to check the guards could not read the
  guards.
- ten test classes carried internal issue numbers in their names. They now say
  what they test.
- the suite was green partly by ordering luck. One class cleared its system
  properties but not the configuration PqAnchorProducer remembers, so it left the
  anchor armed for whichever class ran next. Renaming the classes changed the
  order and four tests began failing on a guard that was firing correctly. Fixed
  where it leaks, with the negative control measured: remove the line and the
  pair goes red, restore it and it goes green.
2026-08-12 01:43:58 +03:00
Liviu
e8deaa60b6 Licence hygiene, authoritative patches, and one spelling of the brand
- Apache 2.0 section 4(b): the patches modify files that are the work of
  Hyperledger Besu and now say so, with the notice inside the modified files,
  which is what the licence asks for and what applying the patch produces.
- patches/ and precompiles/ now carry the staged versions rather than an older
  export. The two had drifted in both directions; the only thing the published
  copy had that the staged one lacked was the word "audited" in front of Bouncy
  Castle, which we cannot evidence and which the staged version had dropped.
- the brand was spelled two ways in the same repository, 62 times one way and 23
  the other. It is Aere Network; AERE is the ticker. The 96 AERE_* code
  identifiers are untouched.
2026-08-11 23:47:17 +03:00
Liviu
6efc348f83 Replace the MIT LICENSE file with Apache 2.0, and add NOTICE
Every source file in this repository carries SPDX-License-Identifier: Apache-2.0,
and the README has always said Apache 2.0. The LICENSE file said MIT. It was the
only thing in the repository that disagreed, and it was wrong.

This code derives from Hyperledger Besu, which is Apache 2.0. Several files sit in
Besu's own packages because that is where the client loads them from. Publishing
that under MIT was not a choice we were free to make, and it is not one we made
knowingly.

The LICENSE file now contains the Apache 2.0 text as published by the Apache
Software Foundation, byte for byte (sha256 cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30).
NOTICE records the derivation from Besu.

Nothing about the terms these files were offered under has changed: the file
headers governed before this commit and govern after it. The correction is
recorded in the README rather than made silently, because a licence is the one
thing in a repository a reader should not have to verify.
2026-08-11 23:35:21 +03:00
Aere Network
48416dfe73 Initial public release
Aere Network public source. Everything here can be checked against the live
chain (chain id 2800, https://rpc.aere.network).

Scope note, stated up front rather than buried: consensus on chain 2800 is
classical secp256k1 ECDSA QBFT. The post-quantum work in this repository is at
the signature, precompile, account and transport layers. Nothing here makes the
consensus post-quantum, and no document in it should be read as claiming so.
2026-07-20 10:25:45 +03:00