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.
124 lines
7.6 KiB
Markdown
124 lines
7.6 KiB
Markdown
# Spec 3: Deterministic fault-injection harness + on-chain attested recovery
|
|
|
|
Built 2026-07-19. Purpose: turn "we ran some fault tests" into a reproducible adversarial evidence
|
|
suite that de-risks the biggest gated item (the post-quantum consensus flip) for zero capital.
|
|
Extends the existing measured fault-tolerance work into a repeatable chaos matrix plus an on-chain
|
|
recovery-attestation contract, honest about what runs locally vs what needs a live testnet.
|
|
|
|
**Scope boundary (held throughout):** this DE-RISKS the consensus flip. It does NOT activate
|
|
post-quantum consensus. That flip stays founder-gated and audit-gated.
|
|
|
|
---
|
|
|
|
## Part 1: `AereRecoveryRegistry.sol` (REAL, BUILT + TESTED)
|
|
|
|
- Contract: `aerenew/contracts/contracts/AereRecoveryRegistry.sol` (solc 0.8.23, repo style).
|
|
- Test: `aerenew/contracts/test/AereRecoveryRegistry.test.js`.
|
|
|
|
Records recovery events (validator-set drop below quorum -> halt -> subsequent resume), each
|
|
authenticated by a Falcon-512 signature verified on-chain by the LIVE precompile 0x0AE1.
|
|
- Fields per record: haltHeight, resumeHeight, faultKind (1=crash, 2=netsplit,
|
|
3=byzantine-proposer), attesting operator key (operatorId), Falcon signature over the record
|
|
hash, plus validator-set context (nValidators, quorum, aliveDuringFault) that encodes the
|
|
"drop below quorum."
|
|
- **Fail-closed:** invalid signature, stale nonce, inconsistent heights, or bad validator set
|
|
records nothing and advances no nonce; an empty/zero/short precompile return (pre-fork / stale
|
|
chain) is treated as INVALID. Reverts with `PQCVerificationFailed`.
|
|
- **Append-only:** records live in a push-only array; recordId is an immutable index; a strictly
|
|
increasing per-operator nonce is consumed each write (no replay). There is NO owner, admin, or
|
|
overwrite/delete function anywhere (structurally verified in the test's ABI scan).
|
|
- Wired to 0x0AE1 for production; Falcon-512 encoding matches the live precompile
|
|
(pk 897/header 0x09; envelope nonce(40) || esig(0x29..)), mirroring `AerePQCAttestation.sol`.
|
|
|
|
### REAL TEST RESULT: 10/10 PASSING
|
|
Command: `npx hardhat test test/AereRecoveryRegistry.test.js` from `aerenew/contracts`.
|
|
Compiled clean; all 10 tests green (~1s):
|
|
- registerOperator: accepts well-formed Falcon-512 key + sequential ids; rejects wrong length/header.
|
|
- valid attestation records: kill-2 (f=2 boundary) crash recovery stores every field; netsplit +
|
|
byzantine-proposer under one operator with nonce advancing.
|
|
- fail-closed: tampered signature rejected (nothing recorded); signature bound to different
|
|
heights/fault-kind rejected; empty precompile return treated invalid; unknown operator / invalid
|
|
fault kind / bad heights / bad validator set all revert.
|
|
- append-only: appends without rewriting an earlier record; replay of a consumed signature rejected;
|
|
ABI exposes no set/update/delete/overwrite/admin/owner function.
|
|
|
|
**[MEASURE] flag on Part 1:** the Hardhat EVM has no 0x0AE1, so the test installs the repo's
|
|
faithful `MockPQCPrecompile` (scheme 1) at 0x0AE1 via `hardhat_setCode` (same pattern the existing
|
|
`AerePQCAttestation.test.js` uses). The mock parses input at the LIVE precompile's spec offsets, so
|
|
a passing record proves the contract builds the 0x0AE1 input correctly. The real-precompile path
|
|
(that on-chain 0x0AE1 accepts a genuine Falcon-512 signature) is proven separately against live
|
|
mainnet 2800 via eth_call, not inside the unit test.
|
|
|
|
---
|
|
|
|
## Part 2: chaos-matrix runner (SCAFFOLD + CONFIG; multi-node runs [MEASURE])
|
|
|
|
Under `aerenew/chaos/`:
|
|
- `matrix.json` — single source of truth. N=7 (quorum 5, f=2) and N=9 (quorum 6, crash-tol 3)
|
|
fault matrix: C1 kill-1, C2 kill-2 (N=7 f=2 boundary), C3 kill-3 (N=7 sub-quorum halt / N=9
|
|
crash boundary), C4 kill-4 (N=9 sub-quorum halt), P1 network partition (minority halts), B1
|
|
byzantine-proposer. Documented tool = Pumba (toxiproxy / Chaos Mesh as alternatives), plus a
|
|
process-mode fallback that reuses the existing `audit-package-pq-consensus/harness/n7/` scripts.
|
|
- `run-chaos-matrix.sh` — reads the matrix, injects each fault, snapshots per-node heights across
|
|
the fault + recovery windows, decides halt/resume/fork, and (on a halt-then-recover) invokes the
|
|
attester. Has a hard guard that REFUSES to run on the live infra box.
|
|
- `lib/partition.sh` — network partition via pumba netem / iptables so the majority keeps quorum.
|
|
- `lib/attest-recovery.js` — ethers script that reads the record hash from the deployed registry,
|
|
signs it with the operator's offline Falcon-512 key, and submits `submitRecovery(...)`.
|
|
|
|
Validated locally: `matrix.json` parses (6 scenarios, N7/q5 + N9/q6); `bash -n` clean on both
|
|
shell scripts; `node --check` clean on the JS.
|
|
|
|
**[MEASURE] flag on Part 2:** the ACTUAL multi-node runs require a live isolated QBFT testnet on a
|
|
SCRATCH box, NEVER the infra box. The runner is inert without a net up (heights read 0). The
|
|
already-measured numbers are CITED from `matrix.json` `evidence`, not re-invented:
|
|
- Kill-2 soak (docs/FAULT-TOLERANCE-CHARACTERIZATION-2026-07-14.md): 100 adversarial cycles
|
|
(40 RT=4 mixed + 40 RT=1 mixed + 20 pure-Besu), **0 forks, 100/100 self-resync**, rare
|
|
temporary self-recovering f=2-boundary stall (3/40 RT=4, 1/40 RT=1, 0/20 Besu) that is inherent
|
|
QBFT-at-f=2 (FLP), not a client bug.
|
|
- Sub-quorum halt-and-recover and partition (spec 5.3/5.4): halts in place, no fork, resumes from
|
|
the exact halt height on restore, no re-genesis.
|
|
- Byzantine negatives (harness/n7/run-b-negatives.sh): 1-2 Falcon-faulty TOLERATED (<= f=2),
|
|
3 faulty (> f) HALT post-detection, restore RESUMES with no re-genesis.
|
|
|
|
---
|
|
|
|
## Part 3: watchtower design (DESIGN)
|
|
|
|
`aerenew/chaos/WATCHTOWER-DESIGN.md`. An independent off-chain observer holding a registered
|
|
Falcon-512 key that: (1) detects a halt by combining a progress stall with quorum loss and no
|
|
fork (so it does not false-positive on the rare temporary f=2-boundary stall), classifying the
|
|
fault kind; (2) waits for quorum restoration, doing nothing that could influence consensus; (3)
|
|
submits the signed recovery attestation to Part 1, verified fail-closed by 0x0AE1. Includes the
|
|
watchtower's own failure modes and the honest single-operator caveat.
|
|
|
|
Composition: Part 2 generates adversarial fault evidence reproducibly, Part 3 produces it live and
|
|
independently, Part 1 makes all of it un-doctorable and quantum-durable on chain. Together they
|
|
make the flip decision rest on honest, checkable evidence. The flip itself stays a founder + audit
|
|
decision; the suite does not pull the trigger.
|
|
|
|
---
|
|
|
|
## All [VERIFY] / [MEASURE] flags
|
|
|
|
- [MEASURE] Part 1: real-precompile 0x0AE1 acceptance of a genuine Falcon-512 sig is proven vs live
|
|
mainnet via eth_call, not in the Hardhat unit test (Hardhat has no 0x0AE1; mock installed there).
|
|
- [MEASURE] Part 2: multi-node chaos runs need a live isolated QBFT testnet on a scratch box; not
|
|
run here. Existing soak numbers cited, none invented.
|
|
- [VERIFY] Part 2/3: `lib/attest-recovery.js` needs the operator's offline Falcon-512 signer + key
|
|
(AERE_FALCON_SIGN / AERE_FALCON_KEY) and a chain where 0x0AE1 is live to complete the submit; on
|
|
a plain testnet without the precompile the on-chain verify fails closed (correct, safe).
|
|
- [MEASURE]/[VERIFY] Part 3: the live watchtower daemon and its detection-threshold tuning against
|
|
live inter-validator RTT are designed, not built; single-operator vantage is corroboration, not
|
|
independence, until third-party watchtowers run.
|
|
|
|
## Files
|
|
- aerenew/contracts/contracts/AereRecoveryRegistry.sol
|
|
- aerenew/contracts/test/AereRecoveryRegistry.test.js
|
|
- aerenew/chaos/matrix.json
|
|
- aerenew/chaos/run-chaos-matrix.sh
|
|
- aerenew/chaos/lib/partition.sh
|
|
- aerenew/chaos/lib/attest-recovery.js
|
|
- aerenew/chaos/WATCHTOWER-DESIGN.md
|
|
- aerenew/chaos/README.md
|