aere-docs/AERE-FAULT-INJECTION-HARNESS.md
Aere Network e4cead319d Initial public release
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.
2026-07-20 01:01:36 +03:00

7.6 KiB

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