BlockTimer.java carried a Romanian one-liner explaining why the anchor
proposal-delay configuration is loaded at construction rather than lazily. The
explanation matters and is kept in full, in English: a lazily-loaded consensus
setting turned an unreadable file into 125 seconds of halted chain on 2026-09-03,
while every configuration gate stayed green because the files existed.
Production strings and comments are read by people who do not speak Romanian.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
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.
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.
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.
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.
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.
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.
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.
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.