# 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.60 s on average over the 100,000 blocks to 2026-11-03). 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`: ```bash 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: ```bash 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 `<`: ```bash 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: ```bash 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-.json`, with its sha256 and registry hash), and every node appends the file to `aere.pq.registryV3` and its `:` 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: ```bash 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: ```bash cd /opt/aere mkdir -p data docker compose up -d ``` Read your node's public info (enode and address) once it is up: ```bash 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: ```bash 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 ``` `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: ```bash 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 about 0.60 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): ```bash validator/validator-candidacy.sh --clock-only --params admission-params.json --enode-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: ```bash docker compose up -d ``` Watch it find peers and import blocks: ```bash 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 ```bash # 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: ```bash validator/validator-candidacy.sh --params admission-params.json --enode-host \ --data-path ``` 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(, 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(, 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=` 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 certificate of their own; below block 25,080,000 their validity at import rested on the ECDSA commit quorum, and from it (AIP-22 stage 5) on the Falcon-512 seal of their proposer, so a fabricated segment stops at the next anchor: the depth measured below block 25,080,000 with classical keys was **31 consecutive blocks**, and the bound derived from the anchor rule, for a node that requires a quorum of seals in the certificate, was 33 blocks below block 24,148,752 (32 plus the sealed-sibling exception) and is 32 from it, where that quorum must be of one round: the latest anchor and the 31 after it (SPEC.md 3.1; from block 25,080,000 such a segment takes the post-quantum key of one validator, not measured); for the published follower, with its ceiling at 1, the bound stays 33 against an adversary without a post-quantum key, and one leaked or misused post-quantum key of a validator makes the depth unbounded (SPEC.md 6.4). 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 since block 24,300,000 (AIP-22 stage 4, 2026-10-25). Each message has two switches, passed like the anchor properties: | property | what it does | |---|---| | `aere.pq.Pq.attachBlock` | height from which **this node emits** a seal on that message | | `aere.pq.Pq.forkBlock` | height from which **this node refuses** that message without a valid seal | where `` 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 claim, and what we do not.** Since block 25,080,000 (AIP-22 stage 5) headers no longer carry ECDSA commit seals and, since block 24,300,000 (AIP-22 stage 4), every vote counts only with the verified post-quantum seal of its author (corrected 2026-11-04: from block 24,300,000 until 2026-10-31 12:27Z one path of the second client took the author of a proposal that named a height below 24,300,000 from its ECDSA envelope, as the correction of 2026-11-01 to rule 3 of AIP-22 says), and a commit still carries the ECDSA commit seal of its validator as an additional check, which we call post-quantum consensus. We do not claim a post-quantum transport (the peer-to-peer transport is still authenticated by secp256k1), the ten validators are run by one operator, and no third party has audited it yet. 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. As of 2026-10-28, the published patch series (0001 to 0010) does not yet include the decision journal that the Foundation's validators run together with the decided-head rule. - **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.60 s average over the 100,000 blocks to 2026-11-03) | | 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`