aere-node/validator
2026-10-20 08:12:28 +03:00
..
AereCandidacy.java validator/: the operator kit for becoming a validator of chain 2800 (keys generated on the operator's machine, a public candidacy file with proof of possession and a signed clock report, the corrected runbook); run-node.sh, RUN-A-NODE.md and SPEC.md: the follower configuration described as it is (the attach, validatorCount, forkBlock and seal-cap properties it carries are inert on a follower) 2026-10-20 08:12:28 +03:00
kit-common.sh validator/: the operator kit for becoming a validator of chain 2800 (keys generated on the operator's machine, a public candidacy file with proof of possession and a signed clock report, the corrected runbook); run-node.sh, RUN-A-NODE.md and SPEC.md: the follower configuration described as it is (the attach, validatorCount, forkBlock and seal-cap properties it carries are inert on a follower) 2026-10-20 08:12:28 +03:00
README.md validator/: the operator kit for becoming a validator of chain 2800 (keys generated on the operator's machine, a public candidacy file with proof of possession and a signed clock report, the corrected runbook); run-node.sh, RUN-A-NODE.md and SPEC.md: the follower configuration described as it is (the attach, validatorCount, forkBlock and seal-cap properties it carries are inert on a follower) 2026-10-20 08:12:28 +03:00
validator-candidacy.sh validator/: the operator kit for becoming a validator of chain 2800 (keys generated on the operator's machine, a public candidacy file with proof of possession and a signed clock report, the corrected runbook); run-node.sh, RUN-A-NODE.md and SPEC.md: the follower configuration described as it is (the attach, validatorCount, forkBlock and seal-cap properties it carries are inert on a follower) 2026-10-20 08:12:28 +03:00
validator-keys.sh validator/: the operator kit for becoming a validator of chain 2800 (keys generated on the operator's machine, a public candidacy file with proof of possession and a signed clock report, the corrected runbook); run-node.sh, RUN-A-NODE.md and SPEC.md: the follower configuration described as it is (the attach, validatorCount, forkBlock and seal-cap properties it carries are inert on a follower) 2026-10-20 08:12:28 +03:00

Run an AERE node, operator runbook

This is the runbook for standing up an independent Hyperledger Besu node on the AERE Network, chain ID 2800, and applying to become one of the first non-Foundation validators.

Read it end to end before you start. It is written for someone who has run a node before and is comfortable with Docker and a Linux server.

Corrected 2026-10-20. Until this date this runbook said that a validator's post-quantum keys are "issued at admission", listed a property (aere.falcon.genesis) that no running validator carries, and did not name the SLH-DSA key at all. All three were wrong. Every key of a validator is generated by its operator, on the operator's own machine, with the tools in the validator/ directory of the aere-node repository; nothing private ever leaves that machine. Section 6 describes admission as it now works, step by step, and section 3b the clock requirement.


What AERE actually is today (read this first)

AERE runs Hyperledger Besu with QBFT consensus and sub-second blocks (0.62 s on average over the 100,000 blocks before 2026-10-15). Consensus is a permissioned proof-of-authority BFT set, not proof-of-work and not on-chain proof-of-stake.

  • The active validator set is 10 validators as read from the chain at 2026-09-29 07:55 UTC, all Foundation-operated; f = 3, quorum 7-of-10 (as read from the chain at 2026-09-29 07:55 UTC). Read the live set with qbft_getValidatorsByBlockNumber and believe the chain over this line.
  • QBFT tolerates f = floor((n - 1) / 3) faulty validators. At n = 10, f = 3: the network tolerates three simultaneous Byzantine faults (commit quorum 7 of 10). It is honest to say the set is small and single-operator today.
  • The public path is 10 to 21 validators. This program exists specifically to admit the first independent (non-Foundation) operators.
  • Admission is a governance vote of the existing validator set, not an automatic or permissionless process. There is no staking, no bond, and no slashing. A validator that misbehaves or goes down for a prolonged period is removed by the same governance vote that admitted it. Accountability is social and on-chain, not economic.

If you are looking for a stake-and-earn validator with slashing and unbonding, that is not how AERE works. Do not trust older pages that describe self-staking, slashing, unbonding periods, or APY tiers; they predate the current QBFT design.


What running this gives you

A full, syncing node on chain 2800, built from the same published patch series the validators run. A validator differs from a following node in four things, all of them yours to hold and none of them issued by anyone else:

  1. its node key (data/key), which is also its consensus key: the address voted into the set;
  2. a Falcon-512 key and an SLH-DSA-SHA2-128s key, generated on your machine (section 3);
  3. a row in a post-quantum registry epoch that carries those public keys, signed by them (section 6);
  4. the validator-only properties: the paths of the two key files and the heights from which the node emits post-quantum seals (section 7b).

So the sequence is:

  1. Stand up a following node with this runbook (or with run-node.sh in aere-node), and keep it healthy. The Foundation observes it from outside for fourteen days before a vote is proposed.
  2. Generate your keys and write your candidacy file on your own machine (sections 3 and 6).
  3. The Foundation verifies the candidacy independently and puts your row into a new registry epoch, which every node, yours included, loads before your admission.
  4. Your node restarts as a validator and connects to every validator; then the existing validators vote. After the vote your node proposes and seals blocks. No reinstall, no migration.

1. Prerequisites

Software

  • A Linux host (the live nodes run Docker on Linux).
  • Docker and the Docker Compose plugin, or a build from source (run-node.sh in aere-node needs git and a JDK 21). The key tools of section 3 need the same JDK 21 and a build from the published patch series, which ./run-node.sh --no-start produces.

Hardware

There is no published minimum-hardware spec sheet for AERE, so treat the following as guidance, not a documented requirement. The Foundation confirms final sizing on application.

  • The node is configured with a 4 GB JVM heap (-Xmx4g), matching the live validators. Give the host meaningful headroom above that. A reasonable starting point is 4 vCPU, 8 GB RAM, NVMe SSD, but confirm on application.
  • A CPU with SHA hardware instructions (x86 SHA-NI, or the ARMv8 SHA2 extension). A validator signs an SLH-DSA-SHA2-128s seal on the consensus thread at the parent of every anchor block; measured on chain 2800 that costs 0.3 to 0.7 s per signature with the JDK digest, which uses those instructions (AIP-22, table of constants). A slower signature delays the anchor round.
  • Local NVMe, not network-attached block storage. The node writes its post-quantum seal store on the consensus thread; on a network volume every such write adds milliseconds to each slot.
  • Storage uses Besu Bonsai format. At sub-second blocks the trie-log data grows faster than on a slow chain, so provision generous, growable NVMe disk and monitor free space over time. Block headers are most of what a node stores.

Network / firewall

  • 30303/tcp and 30303/udp: open to the internet. This is P2P. Peers must be able to reach you.
  • 8545 (JSON-RPC): keep private. The compose binds it to 127.0.0.1 on the host. Do not expose it to the public internet without an authenticating proxy in front.
  • 9545 (metrics): keep private, localhost only.

RPC policy for a validator. A validator's JSON-RPC stays on localhost, always: it serves the qbft_* methods, including qbft_proposeValidatorVote, and a public endpoint on a consensus node is a denial-of-service surface on the very node that has to answer within a slot. If you want to offer public reads, run a separate following node for them and keep the validator private.


2. Get the config bundle

Everything you need to start is in this directory (https://aere.network/validator/):

File What it is Source
docker-compose.yml The node service, real QBFT flags Published here
config.toml Same config for bare-metal / from-source runs Published here
genesis.json Chain 2800 genesis (no private keys) Published here
static-nodes.json Current peer / bootnode enode list Provided by the Foundation on application
Bootnode enode string For --bootnodes Provided by the Foundation on application
Canonical genesis hash To verify your genesis Provided by the Foundation on application

Download the published files into a working directory, for example /opt/aere:

mkdir -p /opt/aere && cd /opt/aere
curl -fSLO https://aere.network/validator/docker-compose.yml
curl -fSLO https://aere.network/validator/config.toml
curl -fSLO https://aere.network/validator/genesis.json

The post-quantum registry files (added 2026-09-12)

docker-compose.yml mounts two directories that the steps above did not create, and a node started without them cannot judge an anchor certificate at all. Fetch them:

mkdir -p /opt/aere/aere-pqc /opt/aere/pq && cd /opt/aere/aere-pqc
curl -fSLO https://aere.network/pq/manifests/manifest-13014000.json
curl -fSLO https://aere.network/pq/manifests/manifest-18082816.json
curl -fSLO https://aere.network/pq/manifests/registru-2800-v2-13600000.properties
cd /opt/aere/pq
curl -fSLO https://aere.network/pq/manifests/hibrid-10.properties

Check what you downloaded, because a 200 is not proof of a file. Until 2026-09-12 two of these paths were not published, and the site answered every one of them with HTTP 200 and the 51 KB HTML page of the web app. curl -fSLO succeeds on that: exit code 0, a file on disk, the wrong bytes. So look at the first character of each file, and refuse anything that starts with <:

for f in /opt/aere/aere-pqc/* /opt/aere/pq/*; do
  head -c 1 "$f" | grep -q '<' && echo "NOT A REGISTRY FILE: $f" || echo "ok: $f"
done

The same four files ship inside the aere-node package, with a SHA256SUMS beside them, if you prefer to take them from there and compare.

Added 2026-10-07: a fifth file, the stage-3 registry epoch. Since block 20,836,228 (AIP-22 stage 3, active on chain 2800 since 2026-09-30) the header carries post-quantum validator identities, and docker-compose.yml now passes aere.pq.identityBlock=20836228 with aere.pq.registryV3=/opt/aere-pqc/epoca-v3-2800-20836228.json. Until 2026-10-07 this file did not list that option at all: a validator started from it would have stopped at block 20,836,228. The epoch file is the one published as registry-v3-20836228.json; save it under the name the option expects:

cd /opt/aere/aere-pqc
curl -fSL -o epoca-v3-2800-20836228.json https://aere.network/pq/manifests/registry-v3-20836228.json
sha256sum epoca-v3-2800-20836228.json

Expected: 0212d8ff9e857f1c756b0004929e9ad4c7988341af4837d947e7b5263fb8c581 (194,122 bytes; measured on a running validator of the fleet and on the served file on 2026-10-07). The option aere.pq.registryV3.hashes pins the epoch's identity hash, so a node given the wrong file refuses to start rather than following the chain with a wrong registry; the first-character check above applies to this file too.

Every later epoch is added, never swapped. When an epoch that admits a new validator is announced, the index at https://aere.network/pq/manifests/index.json lists it (registry-v3-<height>.json, with its sha256 and registry hash), and every node appends the file to aere.pq.registryV3 and its <height>:<hash> pin to aere.pq.registryV3.hashes, keeping the earlier ones. The announcement gives the exact values and the height by which every node must carry them.

Verify the genesis

The genesis.json published here is the chain-2800 genesis. It contains no private keys. The comment fields inside alloc are human labels that Besu ignores, so they do not affect the genesis block hash.

After your node's first start, confirm your node computed the same genesis hash the Foundation gives you on application:

curl -s -X POST http://127.0.0.1:8545 \
  -H 'Content-Type: application/json' \
  --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x0",false],"id":1}' \
  | grep -o '"hash":"0x[0-9a-f]*"'

The value must equal the canonical chain-2800 genesis hash provided by the Foundation on application. If it does not match, stop and contact the Foundation; do not keep running against a divergent genesis.


3. Your keys: generated on your machine, never sent anywhere

A validator holds three private keys. You generate all three; the Foundation never sees, holds or issues any of them.

The node key, data/key (secp256k1). Besu creates it the first time the node starts. It is your node's P2P identity and your consensus key: the address derived from it is the one voted into the set, and Besu sends consensus messages only to peers whose node-key address is in the set. A validator whose node key is not its validator key receives no consensus message at all. So never start the node with a node key from another place than the data directory you register.

Create the data directory, then start the node once so Besu writes the key:

cd /opt/aere
mkdir -p data
docker compose up -d

Read your node's public info (enode and address) once it is up:

curl -s -X POST http://127.0.0.1:8545 \
  -H 'Content-Type: application/json' \
  --data '{"jsonrpc":"2.0","method":"net_enode","params":[],"id":1}'

The post-quantum keys (Falcon-512 and SLH-DSA-SHA2-128s). They are generated by PqRegistryV3Tool keygen, a tool inside your own build of the published patch series (patch 0008), through the kit in the aere-node repository:

git clone https://git.aere.network/aere-network/aere-node && cd aere-node
./run-node.sh --no-start            # builds the Aere fork from the published patches (JDK 21)
validator/validator-keys.sh --params admission-params.json --data-path <your node's data directory>

admission-params.json is a small public file the Foundation sends you (the chain id, the height and size of the registry epoch that will carry your row, and your row index). The script refuses unless the build comes from the bundle's patch series, writes the two key files owner-only (mode 600) into an owner-only directory (default ~/.aere-validator/keys, outside the repository on purpose), never overwrites an existing key, prints only public keys and your post-quantum id, and checks its own output for any private value before it ends.

Protect your keys

  • data/key and the two post-quantum key files are your validator identity. Back them up together, somewhere secret and offline. Anyone with them can sign as your validator; losing them means a new admission.

  • Never rm -rf data/. That destroys the node key and, if you were already a validator, forces re-admission. To wipe chain data while keeping the key:

    find /opt/aere/data -mindepth 1 ! -name key -exec rm -rf {} +
    

3b. The clock (added 2026-10-20)

Chain 2800 rejects a block header whose timestamp is more than one second ahead of the node's own clock (QBFT's TimestampBoundedByFutureParameter(1)), and at 0.6 s per block that rule bites at every head:

  • a node whose clock is behind rejects the head blocks it is sent and disconnects the peer with BREACH_OF_PROTOCOL, which reads like an attack and is a clock;
  • a validator whose clock is ahead proposes blocks the others reject, and loses its slot.

What to do: run NTP or chrony against good sources, and measure against the chain head, not against a flag: a host that reports NTPSynchronized=yes was measured one full second behind on 2026-09-12. The kit measures it for you, in the same terms the Foundation measures its own fleet (head timestamp minus local clock, at most 1 s behind and at most 2 s ahead):

validator/validator-candidacy.sh --clock-only --params admission-params.json --enode-host <your host>

On the day of the vote the Foundation asks for exactly this report, fresh (at most six hours old). It is signed by your node key and holds nothing private.


4. Add peers and finish syncing

Until you have the Foundation's peer list, the node has nothing to connect to. On application you receive:

  • a bootnode enode string, and
  • a static-nodes.json file (belt-and-braces; Besu reads it from inside the data directory).

Wire them in:

  1. Put static-nodes.json next to the compose file. It is bind-mounted to data/static-nodes.json by the compose (uncomment that volume line if you commented it out).

  2. Replace BOOTNODE_ENODE_PROVIDED_ON_APPLICATION in docker-compose.yml (or config.toml) with the real enode string.

  3. Restart:

    docker compose up -d
    

Watch it find peers and import blocks:

docker compose logs -f aere-node

The two traps that stop a fresh node cold

  • The 5-peer wait. Besu will not begin BFT block import until it has enough peers, and it defaults to needing 5. A small network never reaches 5 and the node waits forever, never importing block 1. The compose already sets --sync-min-peers=1 to fix this. Keep it.
  • Gas price. AERE nodes run --min-gas-price=0: the protocol's base-fee floor (from block 10,141,734) sets the price of a transaction, not the node. Do not set a nonzero min gas price of your own; you would drop normal AERE transactions. The compose already sets it to 0.

You do not need the public RPC fee-shim proxy. That proxy exists only for the public wallet-facing RPC endpoint; a syncing full node talks to the chain directly.


5. Confirm the node is healthy

# Current block height (should be climbing, then tracking the public head):
curl -s -X POST http://127.0.0.1:8545 -H 'Content-Type: application/json' \
  --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'

# Peer count (should be >= 1, ideally several):
curl -s -X POST http://127.0.0.1:8545 -H 'Content-Type: application/json' \
  --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":1}'

# The current QBFT validator set (you will NOT be in it yet):
curl -s -X POST http://127.0.0.1:8545 -H 'Content-Type: application/json' \
  --data '{"jsonrpc":"2.0","method":"qbft_getValidatorsByBlockNumber","params":["latest"],"id":1}'

Compare your height against the public head at https://aere.network/validators (the live validator-state dashboard). When your eth_blockNumber is tracking the public head and you have steady peers, your node is ready to apply.


6. Admission (the governance vote)

This is the honest part: admission is a decision of the existing validators, not a transaction you can send yourself. Here is the whole path, in order.

  1. Observation. Your following node runs for fourteen days while the Foundation measures it from outside (that it follows the head, with the same block hashes as the fleet). You tell the Foundation the read endpoint it may use for that.

  2. Admission parameters. The Foundation sends admission-params.json: chain id 2800, the height of the registry epoch that will carry your row, its size, and your row index. Public data.

  3. Your keys and your candidacy, on your machine. validator/validator-keys.sh (section 3), then:

    validator/validator-candidacy.sh --params admission-params.json --enode-host <your public P2P host or IP> \
      --data-path <your node's data directory>
    

    With your node running, the script checks that the node runs with exactly the key in your data directory (the enode it reports must match), measures your clock against the chain head (section 3b), writes your registry row with PqRegistryV3Tool row from your build (your post-quantum id, both public keys, a proof of possession by each, the link signed by your node key, and your node key's address as the transport address), signs the candidacy message with all three keys, verifies its own signatures, and checks that no private value appears in anything it wrote. Send the resulting aere-candidacy.json. It holds public data only.

  4. Independent verification. The Foundation verifies the candidacy with an implementation that shares no code with the client (every signature, the proofs of possession, that your id is derived from your Falcon key, that the enode's key is the row's address, that the date and the clock are fresh and in margin), and refuses it otherwise, with the reason.

  5. The new registry epoch. The existing validators re-sign their own rows for the new epoch (the same keys; a proof of possession is bound to the epoch's height and size), your row is added as the last one, and the epoch is checked by two independent loaders. The epoch is published at https://aere.network/pq/manifests/ in the same hour it takes effect, and every node, yours included, appends its file and pin (section 2).

  6. Your node becomes a validator. You restart it with the validator properties of section 7b and the new epoch, connected to every validator (with the peer list the Foundation gives you, as in section 4), and you send a fresh clock report (section 3b).

  7. The vote. A majority of the current validators propose your post-quantum id with qbft_proposeValidatorVote(<your id>, true). Since block 20,836,228 (AIP-22 stage 3) the set and the votes are on post-quantum ids, and a vote for an id that has no row in the registry in force is invalid: that is why the epoch comes first. The vote is proposed only after every check of the steps above passes, including that your node is connected to all validators.

  8. After the vote. Your already-running, already-synced node detects that it is now in the set and begins proposing and sealing blocks. The Foundation checks, from the chain and from its own nodes, that you propose in turn, that your post-quantum commit seal is heard and verified by every node, that your index appears in the anchor certificates, and that the chain's rhythm did not change.

The Foundation decides whether an admission grows the set or whether a Foundation validator steps out after you are in; for you the steps are the same.

Removal is the same mechanism in reverse: qbft_proposeValidatorVote(<id>, false) by a majority. This is how a misbehaving or long-offline validator is dropped. There is no slashing and no stake to lose; the consequence is removal from the set.

You can always read the live set yourself with qbft_getValidatorsByBlockNumber (see step 5), so admission and removal are publicly verifiable on-chain.

The candidacy file

aere-candidacy.json (format aere-validator-candidacy/1) carries: chainId, bindHeight, count, index, issued (UTC date), enode, address, id, row (the registry v3 row, AIP-22 section 3.2), rowHash, proof and clock. The two signed messages, so that anyone can verify a candidacy without our tools (integers big-endian, i32 two's complement, || concatenation):

candidacy = keccak256("AERE-CANDIDACY-1" || u64 chainId || u64 bindHeight || u32 count || u32 index
                      || u32 len(issued) || issued || id (20 bytes) || rowHash (32 bytes))
clock     = keccak256("AERE-CLOCK-1" || u64 chainId || u64 measuredAt || u64 headNumber || u32 samples
                      || i32 dMin || i32 dMax)

proof.secp256k1 (65 bytes, r || s || v) must recover to the row's ecdsa.addr, which must equal its transport address and the address of the enode's public key; proof.falcon-512 and proof.slh-dsa-sha2-128s must verify under the row's two keys; clock.secp256k1 must recover to the same address. dMin and dMax are the smallest and largest "head timestamp minus local clock" over the samples; the margin is dMax <= 1 and dMin >= -2.


7. How validators are paid

Rewards are transparent and on-chain. Measured 2026-10-15: the beneficiary of every block in a 40-block sample is the proposing validator's own identity address (ten addresses, none with code), and blocks carry almost no transactions. The split below is the design of the AereCoinbaseSplitterV2 contract (0x8C1A48eFA57b66fEE743A00E3899c29ad3Fd27b4); block fees do not pass through it today (its balance was 0 that day), so read it as a deployed mechanism, not a present-tense flow. It does a fixed basis-points split:

  • Burn: 3750 bps (37.5%) to the fee-burn vault.
  • Sink: 1500 bps (15.0%) routed through AereSink (the sAERE flywheel).
  • Rebate to the validator: the remainder, 47.5% at the defaults.

These are the current default splits. They are owner-adjustable within hard caps written into the contract (burn at most 5000 bps, sink at most 3000 bps), and any change to the sink destination is time-locked for 7 days. If the sink is unset, its share is added to the validator rebate instead. Everything is readable on-chain; nothing here is off-book.

There is no staking yield, because there is no staking. A delegation UI tied to the sAERE flywheel is on the roadmap but is not live today; do not assume any delegation mechanics until the Foundation announces them.


7b. If you are being admitted as a validator: the validator properties

Everything above gets you a following node, and that is the normal case until the vote. A validator passes, through BESU_OPTS, the whole line of docker-compose.yml (it is derived from a running validator of the fleet and carries the validators' own seal cap) plus the properties below. The Foundation confirms the exact values when your admission is scheduled.

property what it is
aere.falcon.key the path of YOUR Falcon-512 key file, written by validator-keys.sh
aere.pq.hybrid.key.slh-dsa-sha2-128s the path of YOUR SLH-DSA-SHA2-128s key file, written by validator-keys.sh
aere.pq.registryV3, aere.pq.registryV3.hashes every registry epoch and its pin, including the one that carries your row (section 2)
aere.pq.hybrid.attachBlock, aere.pq.proposalPq.attachBlock, aere.pq.preparePq.attachBlock, aere.pq.roundChangePq.attachBlock the heights from which the node EMITS post-quantum seals; already in docker-compose.yml

Two things a validator must NOT carry: aere.pq.anchor.minSealsCeiling (a node syncing from genesis with run-node.sh sets it to 1 to start inside the small genesis set; a validator starts into the full set and must judge anchors at the scheduled threshold), and a node key from anywhere else than its data directory (section 3). From block 20,836,228 the key a node signs with, and the index it signs under, are looked up in the registry epoch in force by the PUBLIC key, and the client refuses to start a validator registered in an epoch whose row does not match the key it holds (AERE-PQC-KEY-NEXT-02).

One path not yet measured, stated so you do not lose an evening to it. A node that synced as a follower and restarts as a validator passes the client's attach-height guard when it finds a recent Falcon-sealed header; otherwise it refuses to start with AERE-PQC-CFG-UNSAFE-05, and the recovery is aere.falcon.attachBlockAcknowledgePast=<attachBlock> for one restart. Both behaviours were measured on 2026-08-12 on the fleet of that time; for a node joining after block 20,836,228 they have not been measured yet (the Foundation measures them on its rehearsal network before the first admission). If you hit that refusal, send the log line; do not work around it alone: an attachment height that disagrees with the fleet is a liveness incident, not a local setting.

One more measured fact, because it decides how you schedule your upgrades. If your node is a validator and it is still on a build without a rule the fleet has armed, it does not fork and it does not accept anything wrong. But every time it is proposer at an anchor height, the upgraded majority rejects its block and the round is lost. Measured with two of seven nodes un-upgraded (2026-08): the chain head paused for about twenty seconds across a hundred blocks. Being behind costs the network rhythm, not safety.

7c. Post-quantum seals on consensus messages (live since September 2026)

Every 32nd block carries a post-quantum certificate under its hash. The blocks between anchors carry no Falcon seal of their own, and their validity at import rests on ECDSA, so the measured depth a fabricated segment could reach before an anchor stops it is 31 consecutive blocks.

Beyond the anchors, each of the four QBFT messages (proposal, prepare, commit, round-change) carries a Falcon-512 seal of its author, each under its own domain. On chain 2800 the nine Besu-derived validators refuse a message without a valid seal: COMMIT from block 17,250,000, PROPOSAL from 17,400,000, ROUND-CHANGE from 17,550,000 and PREPARE from 17,700,000. The tenth validator, which runs the second client, refuses a COMMIT without one from block 18,131,633 and applies the other three types from AIP-22 stage 4, whose height is not yet set. Each message has two switches, passed like the anchor properties:

property what it does
aere.pq.<message>Pq.attachBlock height from which this node emits a seal on that message
aere.pq.<message>Pq.forkBlock height from which this node refuses that message without a valid seal

where <message> is one of prepare, proposal, roundChange (commit uses aere.pq.commitPq.forkBlock).

Two things worth knowing, both measured:

  • Emission and enforcement are separate on purpose. The fleet emitted for a while before anything refused. If they were one switch, the first node to start emitting would also start refusing, and that is a flag day.
  • A mistyped value refuses to start, it does not quietly disarm. If you set one of these to something that is not a plain block height, the client stops with a configuration error: a node that boots disarmed because of a stray character looks exactly like a correctly configured one, right up to the day it matters.

What this asks of you as a validator: your post-quantum keys (Falcon-512, and SLH-DSA for the hybrid anchor certificate), generated by you on your machine and carried in the registry epoch that admits you, and the same emission and enforcement heights as the fleet, which the Foundation gives you. A validator whose seals are refused does not fork and does not accept anything wrong: it loses its turn as proposer, and the chain continues without it as long as a quorum of the others can seal.

What we do not claim. Per-block finality on chain 2800 still rests on classical ECDSA, so AERE is not a "fully post-quantum consensus" and we do not describe it as one. What you can verify yourself, without taking our word for it, is the anchor certificate at every 32nd block, with the public verifier.


8. Day-two operations

  • Updates: the live network runs a pinned build of the Aere fork of Besu, not stock upstream. Every new fleet build is published as a patch in aere-node before it is required, with the height from which it is needed; rebuild with ./run-node.sh --no-start --rebuild and restart before that height. Do not move to :latest on your own.
  • Restarts: tell the Foundation before a planned restart. A restarted validator starts with an empty post-quantum seal store, and two validator restarts within minutes of each other can stall an anchor round. A node restarting with its data/ intact keeps its identity and does not re-hit the 5-peer trap.
  • Emergencies: the emergency settings of the anchor rules are applied uniformly to every node, never to one; when the Foundation announces one, it applies to your node too, at the same time.
  • Backups: back up data/key and the two post-quantum key files. Those are the irreplaceable files.
  • Monitoring: scrape Prometheus metrics on 127.0.0.1:9545. Track block height versus the public head, peer count, disk free space (Bonsai growth) and the clock against the chain head (section 3b).
  • Disk: watch free space. At sub-second blocks storage grows steadily; plan for a growable NVMe volume.

Quick reference

Item Value
Network name AERE Network
Chain ID / network ID 2800
Consensus Hyperledger Besu, QBFT
Block time sub-second since block 2,137,652 (0.62 s average over the 100,000 blocks before 2026-10-15)
Gas price min-gas-price 0 on the node; the protocol base-fee floor sets the price
Storage format Bonsai
Client Aere fork of Besu, built from the public patch series of the aere-node bundle (0001 to 0010 as of 2026-10-14) on the named upstream commit. Stock upstream cannot follow chain 2800 past block 9,189,161. See RUN-A-NODE.md in aere-node.
Required JVM flags the full BESU_OPTS line in docker-compose.yml (base-fee floor, post-quantum anchor, registry epochs, post-quantum identities, post-quantum transactions); a node missing one stops at the first height that needs it
Validator keys node key data/key (also the consensus key), Falcon-512 and SLH-DSA-SHA2-128s; all generated by the operator (validator/validator-keys.sh in aere-node)
Candidacy validator/validator-candidacy.sh in aere-node: registry row, enode, proof of possession, signed clock report
Clock at most 1 s behind and 2 s ahead of the chain head, measured against the head
JVM heap -Xmx4g
P2P port 30303 tcp + udp (public)
RPC port 8545 (keep private; on a validator, localhost only)
Metrics port 9545 (keep private)
Active validators today 10 (Foundation), as read from the chain on 2026-10-15
Fault tolerance f = 3, quorum 7-of-10 (as read from the chain at 2026-09-29 07:55 UTC)
Public path 10 to 21
Staking / bond / slashing None
Admission Governance vote of existing validators, after the registry epoch that carries your row
Reward contract AereCoinbaseSplitterV2 0x8C1A48eFA57b66fEE743A00E3899c29ad3Fd27b4
Genesis hash Provided by the Foundation on application
Bootnode enode Provided by the Foundation on application
static-nodes.json Provided by the Foundation on application

Live consensus explainer: https://aere.network/consensus Live validator state: https://aere.network/validators