aere-node/anchor
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
..
app/src Carry the Apache 4(b) and 4(d) notices the anchor was missing 2026-08-12 02:28:48 +03:00
config/src/main/java/org/hyperledger/besu/config Carry the Apache 4(b) and 4(d) notices the anchor was missing 2026-08-12 02:28:48 +03:00
consensus Carry the Apache 4(b) and 4(d) notices the anchor was missing 2026-08-12 02:28:48 +03:00
ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync Carry the Apache 4(b) and 4(d) notices the anchor was missing 2026-08-12 02:28:48 +03:00
BASE.txt Add the post-quantum certificate anchor for QBFT 2026-08-12 01:43:58 +03:00
README.md Say exactly what Winkle supports and what is ours 2026-08-12 11:14:43 +03:00

Post-quantum certificate anchor for QBFT

This is the code that puts a post-quantum validator certificate under the block hash in Hyperledger Besu's QBFT consensus, as an overlay on a named upstream commit.

It is published so that the claim can be checked rather than believed. Everything below that is not demonstrable from these files is marked as not demonstrable from these files.


Scope boundary, stated first and not in a footnote

Consensus on Aere Network chain 2800 is classical secp256k1 ECDSA QBFT. Block proposal, validator identity and the QBFT vote messages are all classical elliptic-curve cryptography. A cryptographically relevant quantum computer would break them exactly as it would break any other ECDSA chain.

What this code adds is narrower and is the whole point: the block hash commits to a Falcon certificate signed by the validators. That is a binding, not a replacement. It does not make consensus post-quantum and is never described as such.

The threat it addresses is not "harvest now, decrypt later". A signature is public; there is nothing to harvest. The threat is retroactive rewriting: validator keys recovered later can be used to re-sign old blocks, and a chain whose history is authenticated only by ECDSA cannot distinguish the rewrite from the original. Binding a post-quantum certificate into the hash of every anchored header means a rewrite must also forge the post-quantum signatures.

The threat is not ours to claim. It is the long-range attack, and the peer-reviewed treatment is Azouvi, Danezis and Nikolaenko, "Winkle: Foiling Long-Range Attacks in Proof-of-Stake Systems" (IACR 2019/1440; AFT 2020, pp. 189-201). Two things should be said plainly about that citation, because we checked it rather than repeated it. Winkle does not mention quantum adversaries at all: it treats old validator keys becoming compromised, by any means. The quantum framing is ours. And Winkle's own defence is not ours: it adds a secondary layer of client-based validation, where clients sign a hash of the previously sequenced block. A second published defence for the same threat, Azouvi and Vukolic, "Pikachu: Securing PoS Blockchains from Long-Range Attacks by Checkpointing into Bitcoin PoW using Taproot" (arXiv 2208.05408, 2022), checkpoints into Bitcoin's proof of work.

So: the threat has peer-reviewed grounding, and the defence in this repository is ours. Anyone weighing it should weigh it against checkpointing, which is the established answer. The honest difference is that checkpointing borrows security from somewhere else, and this borrows nothing: the guarantee is carried inside the header, by the validators who signed it.


The problem this solves, which is not obvious

In QBFT, extraData is an RLP list. The block hash is not computed over the stored bytes. It is computed over a re-encoding of the decoded list, with the seal fields removed, so that every node agrees on a hash before the seals exist.

That has a consequence that is easy to miss: anything the decoder does not know about is dropped before hashing. Append a certificate as a new element and it survives in storage, travels between nodes, and is entirely absent from the hash. Two nodes can hold different certificates for the same block and both consider it valid. The certificate would be decoration.

Four obvious designs were tried and all four died on that:

Attempt Why it died
new RLP element after the seals dropped by the re-encode, never reaches keccak
extend the seal list changes the seal encoding, so every existing node rejects the header
a second extraData-like field not in the header schema; a header with it is not a header
commit in the state root the state root is computed before the certificate exists

The design that works uses a field that is already under keccak: vanityData, element 0 of the list, 32 bytes, historically arbitrary. At an anchor height it carries the digest of the certificate instead of the usual vanity string. The certificate itself still rides outside the hash, but it is now pinned: change one byte of it and the digest no longer matches, and the header is rejected.

PqAnchor.java and PqAnchorDigestRule.java are where that lives. Read those two first.


What is in here

  • consensus/common/.../bft/ — the anchor itself: configuration, the digest, the seal cache and store, the producer that attaches seals, the Falcon registry that maps a validator to a key.
  • consensus/qbft/.../headervalidationrules/ — the validation rules: the digest must match, the seals must verify, and the rules must actually be wired into the validator chain.
  • app/.../controller/ — where the rules are built and where the node refuses to start on a configuration that would produce headers its own fleet rejects.
  • tests — including the negative controls. A test that cannot fail is not a test, and several of these exist specifically to prove the guards can fail.

BASE.txt names the upstream commit. Applying these files to any other tree overwrites whatever upstream added since, silently. That is stated there in more detail because it is a real hazard.

One build file changes, and it is one line. consensus/common/build.gradle gains implementation 'org.bouncycastle:bcprov-jdk18on'. Falcon verification happens inside the consensus module, so the module needs the library on its own compile path. No version is stated, because upstream pins it: platform/build.gradle declares bcprov-jdk18on:1.83, and four upstream modules already take the dependency in exactly this versionless form. So the line adds a compile-path entry and no new artifact, and it does not move any version. That is the entire build change, and it is called out here rather than left to be found in the diff.

No cryptography is implemented in this overlay. Falcon signature verification calls Bouncy Castle's implementation; what is ours is the framing, the registry that maps a validator to a key, the digest, and the validation rules.


What is proven, and by what

  • The certificate is byte-identical across nodes. Measured on a test network, six nodes.
  • A stripped certificate is rejected. 12 attempts, 12 rejections.
  • The guards compile and pass together, and the negative control was run: with the guards removed the proofs go red. A guard that has never failed cannot be trusted, so each was made to fail on purpose.
  • Arming does not halt the chain across a validator-set change. On a test network of ten processes, 1,110 blocks were produced across the arming height while four validator-set votes were driven through it, and the block rate did not change. The negative control for that run was separate and blunt: three nodes restarted without their Falcon key produced zero blocks in ninety seconds while every node was alive; with the keys restored, eighty-nine.
  • The wiring is tested. An earlier version of this code registered a rule that could not be seen from outside, because Besu's BlockHeaderValidator.Builder wraps detached rules in a lambda. The rule was present and untested for that reason alone. QbftAnchorRuleWiringTest exists because of that, and its negative control is measured: comment out the registration line and it goes red.

What is not proven here

  • This overlay has not been audited by a third party. No external security review of this code exists. If you are reading it as an auditor, you are the first.
  • A rehearsal with a deliberately un-upgraded node has not been run. Every rehearsal so far upgraded every node.
  • Nothing here demonstrates what is configured on any live network. These files show what the code does when armed. They are not evidence about any running fleet, and should not be read as any.

One claim we retracted, on purpose

An earlier version of our public material said that no public chain has a block hash covering a post-quantum validator certificate. That does not survive a hostile reading. Cellframe's ESBoCS signs blocks with keys that resolve to Dilithium, Falcon or SPHINCS+, and hashes the block with the signatures attached. The capability exists in their code today.

The defensible statement is narrower: no public chain has a post-quantum validator certificate under the block hash that is proven and independently verifiable. This repository is our half of that sentence. Someone else has to do the verifying, which is why it is here.


Terminology, used precisely

A certificate here is signed by f+1 validators, not by a quorum. With f Byzantine faults tolerated, f+1 signatures guarantee that at least one honest validator signed. That is a real property and it is not the same as a quorum, and we do not call it one. Anyone counting will notice, and they should.

The seal threshold is a floor, not a cap: nodes attach as many verified seals as arrive in time, which is at least the threshold and often more. A separate cap bounds how many are written, because each seal costs bytes in every header forever.


Licence

Apache 2.0, matching upstream Hyperledger Besu. See ../LICENSE and ../NOTICE. Files that modify upstream carry the change notice required by section 4(b); files that are new are ours.