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.
481 lines
27 KiB
Markdown
481 lines
27 KiB
Markdown
# Aere Network Cross-Client Determinism
|
|
|
|
Technical specification. Chain 2800 (Aere Network mainnet).
|
|
|
|
Grounding and consistency: this document is the reproducible proof behind Aere's
|
|
client-diversity claim. It is consistent by construction with section 5.5 of
|
|
`aerenew/docs/AERE-ENGINEERING-SECURITY-SPEC.md` (the two clients disagree on state)
|
|
and the consensus row of `aerenew/docs/AERE-ARCHITECTURE-MAP.md`. Where those documents
|
|
and this one describe the same status, they say the same thing. If they ever diverge,
|
|
the engineering spec 5.5 is authoritative and this document is wrong.
|
|
|
|
Evidence cited here lives in `aerenew/nethermind-pqc/` (the second-client work and its
|
|
proof logs), `aerenew/conformance/` (the executable conformance vector suite),
|
|
`aerenew/docs/NETHERMIND-2ND-CLIENT-LIVE-2026-07-17.md`,
|
|
`aerenew/docs/DECENTRALIZATION-2ND-CLIENT-RUNBOOK.md`, and
|
|
`aerenew/docs/AERE-ENGINEERING-SECURITY-SPEC.md`.
|
|
|
|
---
|
|
|
|
## 1. Why cross-client determinism matters, and the honest scope
|
|
|
|
### 1.1 A single producing client is a systemic risk
|
|
|
|
A blockchain is a deterministic state machine: for one ordered sequence of inputs (the
|
|
blocks) there is exactly one correct output (the state). A network that runs a single
|
|
client implementation has no independent check on whether that implementation computes
|
|
the one correct output. If the sole client has a consensus-relevant bug, the whole
|
|
network inherits it, and there is nothing to compare against that would reveal the error
|
|
before it is finalized.
|
|
|
|
The reference case is the September 2025 Reth halt. A chain whose block production
|
|
depended on one implementation stopped when that implementation hit a bug. The failure
|
|
was not in the protocol; it was in the monoculture. This is the exact risk Aere's
|
|
second-client program exists to retire, and it is the reason `AERE-ENGINEERING-SECURITY-SPEC.md`
|
|
section 4.2 records "a single producing client is a demonstrated systemic risk" as the
|
|
design driver.
|
|
|
|
Aere's live mainnet today runs one production client: a fork of Hyperledger Besu v26.4.0
|
|
(base commit d2032017, JDK 21), the sole producer for all seven QBFT validators. A second,
|
|
independent implementation that computes the same state from the same inputs turns "trust
|
|
the one client" into "two independent implementations agree", which is a materially
|
|
different and stronger assurance.
|
|
|
|
### 1.2 What this proves, and what it does not
|
|
|
|
The second client is a patched Nethermind 1.39.0 (.NET), chosen for implementation
|
|
diversity: a different codebase in a different language, so a consensus-relevant bug in
|
|
one is unlikely to exist in the other. A second Besu instance would not be client
|
|
diversity, because it would share every Besu bug.
|
|
|
|
This document proves one specific property:
|
|
|
|
> **State-computation determinism across two independent implementations.** For the same
|
|
> chain-2800 inputs, the patched Besu producer and the patched Nethermind client compute
|
|
> byte-identical block hashes and byte-identical state roots, and agree on seal validity
|
|
> and post-quantum precompile outputs.
|
|
|
|
This document does **not** claim any of the following, and the reader should not infer them:
|
|
|
|
- It does **not** claim Nethermind is a live producing validator on mainnet. It is not.
|
|
Nethermind runs as a non-validating follower and as a cross-check; it takes zero part in
|
|
live consensus. Besu remains the sole live producer.
|
|
- It does **not** claim client-diverse consensus or a "two-client mainnet". Making
|
|
Nethermind a live sealer is a separate, founder-gated, high-risk change documented in
|
|
`DECENTRALIZATION-2ND-CLIENT-RUNBOOK.md` Phase B, not started and not authorized here.
|
|
- It does **not** claim post-quantum consensus. Consensus is classical secp256k1 ECDSA
|
|
QBFT. The post-quantum surface is signatures, accounts, and applications only. This scope
|
|
boundary holds throughout every section below.
|
|
|
|
The value delivered is real and bounded: two independent implementations demonstrably
|
|
compute the same state, so a consensus-relevant divergence between them is detectable
|
|
rather than silent. The gap between that assurance and a fully automated live fail-safe
|
|
gate is stated plainly in section 4.
|
|
|
|
---
|
|
|
|
## 2. The determinism protocol
|
|
|
|
This is the method a third party uses to verify cross-client determinism directly. It has
|
|
five parts, each an independent check on the same underlying property. Each part states
|
|
what is asserted and what evidence supports it. Reproduction commands are in section 5.
|
|
|
|
### 2.a Full re-validation to genesis (zero invalid seals)
|
|
|
|
**Assertion.** The patched Nethermind re-validates chain-2800 blocks from genesis forward
|
|
through its own header-import and seal-validation code path, accepting every genuine header
|
|
and asserting zero invalid seals, and rejecting any tampered header.
|
|
|
|
**Method.** Nethermind reproduces the genesis exactly
|
|
(`0xd86d57a899cbfa580669f0e1c7cd4ae5f525247c3c823f8f75df176a0c5d7f1a`), then for each block
|
|
recomputes the QBFT canonical block hash (extraData re-encoded seal-stripped, round kept),
|
|
recovers each 65-byte committed seal to a distinct in-set validator address, and requires
|
|
the recovered-signer count to meet the QBFT quorum `ceil(2N/3)` (N=7, quorum 5). This runs
|
|
inside Nethermind's production `HeaderValidator` / `ISealValidator` seam, subclassed as
|
|
`AereQbftHeaderValidator` and `AereQbftSealValidator`, so it is the client's own validation
|
|
logic, not a bespoke script.
|
|
|
|
**Evidence.**
|
|
- `aerenew/nethermind-pqc/QBFT-VALIDATION-2026-07-12.md` and
|
|
`aerenew/nethermind-pqc/QBFT-FOLLOWER-2026-07-12.md`: real chain-2800 headers driven
|
|
through Nethermind's own `HeaderValidator.Validate()`; genuine headers accepted, four
|
|
tamper modes rejected. Vectors in `aerenew/nethermind-pqc/test/AerePqc.Tests/qbft-vectors.json`
|
|
(16 real chain-2800 headers).
|
|
- Live follower re-validation from genesis forward with zero invalid-seal rejects over the
|
|
synced range (section 2.c).
|
|
|
|
**Honest boundary.** Header and seal re-validation is proven over sampled real headers and
|
|
over the contiguous ranges the follower has synced from genesis. A single unbroken
|
|
re-validation across the entire history to current head, asserting zero invalid seals over
|
|
all of it, completes when the permanent follower finishes its sync to head.
|
|
[VERIFY: at-head, full-history re-validation with a zero-invalid-seal count over the complete
|
|
0..head range is pending the permanent follower reaching head; per
|
|
`NETHERMIND-2ND-CLIENT-LIVE-2026-07-17.md` section 6 this is an explicit open TODO.]
|
|
|
|
### 2.b Byte-identical re-execution (block hash AND state root at each height)
|
|
|
|
**Assertion.** Replaying real chain-2800 blocks through both clients yields an identical
|
|
block hash **and** an identical state root at each height. State-root identity is the strong
|
|
check: it means both implementations executed every transaction, applied every reward and
|
|
fee rule, and arrived at the same world state, not merely copied a header.
|
|
|
|
**Method.** Full-sync mode (`FastSync/SnapSync/FastBlocks = false`) so every block is
|
|
executed and its post-state root is recomputed by the node, then compared against the
|
|
reference client's state root at the same height.
|
|
|
|
**Evidence.**
|
|
- `aerenew/nethermind-pqc/QBFT-GENESIS-SYNC-FIX-2026-07-13.md`: a real Nethermind node
|
|
full-syncs from genesis, re-executes all transactions, and every node-computed state root
|
|
matches the real chain exactly. Genesis stateRoot
|
|
`0x2d2255d41483c22e8a2d51ca18249157e25a47f949e8a6c54552d0f790b7b127`. Spot-checked
|
|
read-only against the live chain:
|
|
|
|
| height | node-computed stateRoot | live chain-2800 stateRoot | match |
|
|
|---|---|---|---|
|
|
| 458 | `0xc314d2c3…` | `0xc314d2c3…` | yes |
|
|
| 694 | `0xf0a4309e…` | `0xf0a4309e…` | yes |
|
|
| 872 | `0xcda2107d…` | `0xcda2107d…` | yes |
|
|
| 1661 | `0x44baac17…` | `0x44baac17…` | yes |
|
|
| 3000 | `0x44baac178e561fe2…243e8575` | `0x44baac178e561fe2…243e8575` | yes |
|
|
|
|
This run is bounded to the first 3000 blocks (22 transactions re-executed), genuine
|
|
full-state re-derivation over that range, not a header copy.
|
|
- `aerenew/docs/NETHERMIND-2ND-CLIENT-LIVE-2026-07-17.md` section 4: the live permanent
|
|
follower matches `rpc.aere.network` on block hash AND state root at heights 1, 100, 1,000,
|
|
10,000, 11,133, and 11,136 (head at check time).
|
|
|
|
**Honest boundary.** Byte-identical re-execution is proven over the ranges executed to date
|
|
(offline genesis..3000, and the live follower's synced heights). The cross-boundary check at
|
|
the AerePQC precompile fork (block 9,189,161) and at current head completes when the
|
|
permanent follower crosses that height.
|
|
[MEASURE: state-root identity at the fork boundary 9,189,160 and 9,189,161 and at current
|
|
head, per `DECENTRALIZATION-2ND-CLIENT-RUNBOOK.md` A.6, is verified once the follower is at
|
|
head. A mismatch at or across the boundary would indicate a wrong precompile gate.]
|
|
|
|
### 2.c Live follower cross-check
|
|
|
|
**Assertion.** A listen-only Nethermind following the live chain over devp2p matches the
|
|
live RPC's block hash and state root at each checked height, with zero invalid-seal rejects.
|
|
|
|
**Method.** The follower is hardened to be non-validating: no validator key, no `AERE_*`
|
|
environment, `eth/68`-only on the wire (the `istanbul/100` QBFT capability is stripped), so
|
|
the engine, producer, and importer paths are inert. It peers to nodes under Foundation
|
|
control (rpc2 primary, infra secondary), full-syncs from genesis, and its per-height
|
|
hash and state root are compared to `rpc.aere.network`.
|
|
|
|
**Evidence.**
|
|
- `aerenew/docs/NETHERMIND-2ND-CLIENT-LIVE-2026-07-17.md`: the permanent second client
|
|
`aere-client2` (a dedicated second-client host, Helsinki, dedicated firewall,
|
|
JSON-RPC bound to `127.0.0.1` only, durable `systemd` service). Parity table of hash and
|
|
state root MATCH at 1 / 100 / 1,000 / 10,000 / 11,133 / 11,136; zero invalid-seal rejects
|
|
in range.
|
|
- The first live-devp2p run (recorded in the memory note `client_diversity_2026-07-13` and
|
|
the live doc) full-executed genesis to block 182,777 and matched hash and state root at
|
|
1 / 100 / 1,000 / 10,000 / 100,000 / 111,130 / 182,777, with zero divergence in range.
|
|
|
|
**Honest boundary.** The follower is a listen-only cross-check, not a validator. As of the
|
|
recorded state it is syncing toward head (honest ETA roughly 18 hours from the recorded
|
|
start; DB projected near 48 GB at head).
|
|
[VERIFY: "at head, tracking within a few blocks of `rpc.aere.network`, zero divergence over a
|
|
sustained soak" per runbook A.6/A.7 is the completion criterion and is pending the follower
|
|
reaching and holding head.]
|
|
|
|
### 2.d Generated edge-case corpus
|
|
|
|
**Assertion.** Adversarial and edge-case inputs, run through both clients, widen coverage
|
|
beyond organic blocks. Organic chain-2800 blocks are near-empty, so replaying only real
|
|
blocks under-exercises the state-transition surface. A generated corpus of adversarial
|
|
transactions and malformed inputs closes that gap.
|
|
|
|
**Status, split by layer:**
|
|
|
|
- **Precompile edge-case corpus: EXISTS.** `aerenew/conformance/conformance-vectors.json`
|
|
carries the adversarial precompile surface directly: valid, wrong-key, tampered-signature,
|
|
tampered-nonce or message, wrong-header-byte, wrong-length, empty, too-short,
|
|
below-minimum, and at-minimum-all-zero cases for each verifier, plus the full vendored NIST
|
|
ACVP negative test groups (ML-DSA-sigVer-FIPS204 tg8: 15 records, 3 pass / 12 fail;
|
|
SLH-DSA-sigVer-FIPS205 tg31: 14 records, 2 pass / 12 fail) and the SHAKE256 output-length
|
|
domain including the over-cap truncation edge. These are the "trap for a second client"
|
|
cases and they are pinned as vectors (`aerenew/conformance/README.md`).
|
|
|
|
- **Block-level and transaction-level adversarial corpus: [MEASURE], to build.** A dedicated
|
|
corpus of adversarial or edge-case transactions (deep call stacks, storage-collision
|
|
patterns, gas-edge and revert-edge transactions, EIP-2935 lookback boundary calls, base-fee
|
|
floor boundary blocks) executed through both clients with state-root diff at each step does
|
|
not yet exist as a committed artifact. It is the corpus to build to widen coverage beyond
|
|
organic blocks. [MEASURE: generate an adversarial block/transaction corpus, replay through
|
|
both clients, assert identical state root per step; store under `aerenew/conformance/` next
|
|
to the precompile vectors.]
|
|
|
|
### 2.e PQC precompile parity
|
|
|
|
**Assertion.** Both clients produce identical outputs for the same NIST vectors through the
|
|
0x0AE1..0x0AE5 precompiles (Falcon-512, Falcon-1024, ML-DSA-44, SLH-DSA-SHA2-128s, SHAKE256).
|
|
|
|
**Method.** The five Aere post-quantum precompiles are compiled into a real Nethermind
|
|
1.39.0 process via its own `IPrecompileProvider` extension seam (the same interface Optimism
|
|
and Taiko use), gated to activate at the fork boundary. NIST KAT and conformance vectors are
|
|
driven through the running Nethermind JSON-RPC by `eth_call` and compared byte-for-byte
|
|
against the Besu fork's output for the same input.
|
|
|
|
**Evidence.**
|
|
- `aerenew/nethermind-pqc/REAL-NETHERMIND-PQC-2026-07-12.md`: 27 of 27 NIST-KAT and
|
|
conformance vectors pass byte-for-byte via `eth_call` inside a genuine running Nethermind
|
|
1.39.0 (commit `14aca2c5`), matching the Besu 26.4.0 fork. Includes the tampered-signature
|
|
negative for each of Falcon-512, Falcon-1024, ML-DSA-44, and SLH-DSA-128s (each returns the
|
|
32-byte zero word, not-verified).
|
|
- `aerenew/conformance/`: the executable conformance suite has since grown to 83 precompile
|
|
vectors (Falcon-512 x12, Falcon-1024 x12, ML-DSA-44 x22, SLH-DSA-SHA2-128s x21, SHAKE256
|
|
x16), 112 vectors total including QBFT, EIP-2935, and extraData. Last live run: 112/112
|
|
passed against the chain-2800 Besu reference (`aerenew/conformance/README.md`). Note the
|
|
distinction: the 27/27 figure is the set re-run byte-for-byte inside the actual Nethermind
|
|
process; the 112/112 figure is the full suite confirmed against the live Besu reference by
|
|
`runner.mjs`.
|
|
|
|
**Precompile fail-closed semantics (both clients must match).** On malformed input the
|
|
signature precompiles (0x0AE1..0x0AE4) return a 32-byte zero word (not-verified) and never
|
|
revert; SHAKE256 (0x0AE5) returns empty when input is under 32 bytes or `outLen` is zero, and
|
|
truncates an over-cap `outLen` to 65536 rather than reverting. A second client that reverts,
|
|
or returns empty where the reference returns a zero word, diverges. These semantics are
|
|
observed-live, not assumed, and are pinned as vectors.
|
|
|
|
**Gate parity (a real divergence trap).** The precompiles must activate at exactly the Aere
|
|
fork boundary, block 9,189,161 (the first block with timestamp >= 1783820272), gated by
|
|
`chainId == 2800`. An ungated build (active from block 0) would diverge state if any pre-fork
|
|
block ever called an `0x0AE*` address as an ordinary account. The permanent follower gates on
|
|
the futureEips timestamp in `ReleaseSpec.cs` (`IsAerePqcEnabled`) and
|
|
`ChainSpecBasedSpecProvider.CreateReleaseSpec`, verified inactive pre-fork by an `eth_call`
|
|
to `0x0AE5` returning `0x` on the pre-fork head versus the SHAKE output on the post-fork head
|
|
(`NETHERMIND-2ND-CLIENT-LIVE-2026-07-17.md` section 3).
|
|
|
|
---
|
|
|
|
## 3. Existing evidence (byte-identical production and import)
|
|
|
|
Beyond the follower and precompile parity above, the second client has been shown to produce
|
|
QBFT blocks that the reference client accepts byte-for-byte, and to have that acceptance be
|
|
non-vacuous (a tampered seal is rejected). This is the production-encoding half of client
|
|
diversity. All of it is on an isolated test network; the live chain, the live validators, and
|
|
the infra box were never touched.
|
|
|
|
### 3.1 Byte-for-byte block production, then Besu import
|
|
|
|
`aerenew/nethermind-pqc/QBFT-PRODUCER-2ND-CLIENT-2026-07-13.md` (with proof log
|
|
`proofs/qbft-producer-besu-import-proof-2026-07-13.txt` and
|
|
`proofs/qbft-producer-manifest-2026-07-13.json`):
|
|
|
|
- **Byte-exact calibration.** Given the same key, genesis, and timestamp, the Nethermind-side
|
|
producer's full block RLP is byte-for-byte identical to Besu's `debug_getRawBlock(1)`: 1286
|
|
hex characters equal, including the ECDSA committed seal and the block hash
|
|
`0xa34f5e43…f6c616`.
|
|
- **Production interop.** The producer sealed 8 empty QBFT blocks; a fresh stock Besu 24.12.2
|
|
node imported all 8 through its real BFT block-validation path (offline `blocks import`,
|
|
which runs the same `BftCommitSealsValidationRule` and `MainnetBlockValidator` as live
|
|
import). Every imported block hash equals the producer's manifest; miner is the Nethermind
|
|
validator address.
|
|
|
|
### 3.2 Non-vacuity: a one-byte-tampered seal is rejected
|
|
|
|
Same proof, control C: one byte of block 1's committed seal was flipped
|
|
(`0x8d -> 0x72`), leaving the block hash unchanged so the check isolates the seal. Genuine
|
|
block imported; tampered block rejected by Besu's own rule
|
|
(`BftCommitSealsValidationRule | Invalid block header: Not all committers are in the locally
|
|
maintained validator list`, `tampered exit: 1`). The 8-block acceptance is therefore genuine
|
|
cryptographic agreement, not a rubber stamp.
|
|
|
|
### 3.3 Cross-client hash agreement across proposers
|
|
|
|
`aerenew/nethermind-pqc/proofs/mixed-client/proposer/01-onchain-alternation-hashmatch.txt`: on
|
|
a mixed set, proposers strictly alternate Besu and Nethermind, and the on-chain block hash
|
|
computed by the Nethermind node equals the Besu node's hash at every one of 20 consecutive
|
|
blocks (NM_hash == Besu_hash, YES, blocks 1..20). At N=4 (2 Besu + 2 Nethermind), all four
|
|
nodes agree on the head hash (`proofs/mixed-client/follower-sync/REGRESSION-n4.txt`, 4-way head
|
|
hash agreement at block `0x2d`).
|
|
|
|
### 3.4 PQC precompile parity inside a real Nethermind
|
|
|
|
Section 2.e: 27/27 NIST KAT and conformance vectors byte-for-byte via `eth_call` inside a
|
|
running Nethermind, matching the Besu fork
|
|
(`aerenew/nethermind-pqc/REAL-NETHERMIND-PQC-2026-07-12.md`); the broader 112/112 conformance
|
|
suite against the live Besu reference (`aerenew/conformance/`).
|
|
|
|
---
|
|
|
|
## 4. Honest status
|
|
|
|
This is the load-bearing honesty section. It states, without rounding up, exactly what is
|
|
proven and what is remaining operational work. It matches section 5.5 of
|
|
`AERE-ENGINEERING-SECURITY-SPEC.md`; the two must stay consistent.
|
|
|
|
**PROVEN, as a validation cross-check.** The second client demonstrably re-derives state
|
|
independently and would detect a state divergence. Concretely, it re-validates chain-2800
|
|
headers and seals through its own validation code (accept genuine, reject tampered);
|
|
re-executes real blocks to byte-for-byte identical block hashes and state roots (offline over
|
|
genesis..3000, and as a live listen-only follower matching the live RPC's hash and state root
|
|
at every checked height in range); and produces identical outputs for the five PQC precompiles
|
|
on the same NIST vectors. Because there is exactly one definition of correct state and two
|
|
independent implementations computing it, a consensus-relevant divergence (a differing state
|
|
root, a differing block hash, a differing seal decision) between Besu and Nethermind is
|
|
detectable by comparing the two. It does not silently pass. This is real client-diversity
|
|
assurance.
|
|
|
|
**NOT yet a live automated divergence gate.** The cross-check is not yet wired into production
|
|
monitoring as an automated, alerting fail-safe that watches Besu and Nethermind continuously
|
|
and raises an alarm on the first byte of divergence. Today the comparison is run and
|
|
spot-checked; it is not a continuously-armed live gate.
|
|
|
|
**NOT yet a live producing validator.** Nethermind is a non-validating follower and a
|
|
cross-check. It takes zero part in live consensus. Besu is the sole live producer on chain
|
|
2800. A Nethermind disagreement flags a discrepancy against the producer; it does not arbitrate
|
|
consensus, because Nethermind casts no vote and seals no block on mainnet.
|
|
|
|
**Behavior on a detected divergence.** This is a fail-safe, not an automatic consensus action.
|
|
A detected divergence is a signal to halt and investigate before the divergent block is
|
|
trusted, not something that itself forks or halts the live chain. In all adversarial fault
|
|
testing to date, zero forks were observed; the chain's failure posture is to halt and later
|
|
recover, not to fork.
|
|
|
|
**The remaining operational work** is turning the proven cross-check into an automated live
|
|
fail-safe gate: a supervised process that continuously reads both clients at head, diffs block
|
|
hash and state root per block, and alerts (and gates trust) on the first divergence, with the
|
|
permanent follower held at head under a sustained soak. Separately and further out, making
|
|
Nethermind a live sealing validator is the founder-gated, high-risk Phase B in
|
|
`DECENTRALIZATION-2ND-CLIENT-RUNBOOK.md` (extended mixed-client soak at production shape,
|
|
independent audit of the Nethermind QBFT engine, a rehearsed one-block rollback vote, and
|
|
fault tolerance preserved by construction), not started and not authorized by this document.
|
|
|
|
Public-copy rule that travels with this status: a second independent client follows and
|
|
validates live chain 2800 as a non-validating full node. Do not write "client-diverse
|
|
consensus", "two-client mainnet", or anything implying the second client seals live blocks.
|
|
The Nakamoto coefficient by operator is still about 1; a follower does not change it. Never
|
|
claim mainnet consensus is post-quantum; it is classical secp256k1 ECDSA.
|
|
|
|
---
|
|
|
|
## 5. Reproduction
|
|
|
|
A third party reproduces the differential by building both clients, replaying blocks, and
|
|
diffing state roots. Steps that need the fork host or a heavy full-history build are marked
|
|
[MEASURE] with the command rather than an asserted fresh number, because the numbers above
|
|
were measured on Foundation infrastructure and the point of reproduction is that an independent
|
|
party gets the same bytes, not that they trust ours.
|
|
|
|
### 5.1 Precompile parity and conformance suite (light, no chain build)
|
|
|
|
The executable spec runs read-only against the live reference and needs only `ethers` v6:
|
|
|
|
```bash
|
|
cd aerenew/conformance
|
|
node runner.mjs # validates every vector against the live Besu reference (read-only)
|
|
node build-vectors.mjs # regenerates vectors from NIST KATs + real chain-2800 headers
|
|
```
|
|
|
|
Expected: all vectors pass; `runner.mjs` re-confirms the live N=7 validator set and the
|
|
`validator_set_root` before asserting the QBFT vectors. This reproduces the precompile-output
|
|
half of determinism (section 2.e) against the reference without building a client.
|
|
|
|
To reproduce the same 27/27 inside a second client rather than against the reference, build
|
|
the patched Nethermind (5.2) and drive the vectors through its `eth_call`, per
|
|
`aerenew/nethermind-pqc/REAL-NETHERMIND-PQC-2026-07-12.md`.
|
|
|
|
### 5.2 Build the two clients
|
|
|
|
- **Reference (Besu fork).** Hyperledger Besu v26.4.0, base commit d2032017, JDK 21, plus the
|
|
Aere PQC precompile and EIP-2935 fork rules. [MEASURE: build on a scratch box, not infra;
|
|
Aere's live producer is not rebuilt for this. See `ops_no_heavy_compute_on_infra`.]
|
|
- **Second client (patched Nethermind).** Nethermind 1.39.0 commit `14aca2c5`, .NET SDK
|
|
10.0.30x, with the in-tree `Nethermind.AerePqc` project applied:
|
|
|
|
```bash
|
|
cd aerenew/nethermind-pqc/nethermind-intree
|
|
./apply.sh && ./apply2.sh && ./apply3.sh # precompiles + release-spec gate
|
|
# for the header/seal follower add through apply9.sh; for the producer path add apply5.sh
|
|
dotnet build src/Nethermind/Nethermind.Runner -c Release
|
|
```
|
|
|
|
For the non-validating follower build, exclude the istanbul-dependent QBFT engine and the
|
|
producer so the binary is `eth/68`-only, and leave `AERE_PRODUCER_KEY` and `AERE_QBFT_KEY`
|
|
unset (this is the invariant that keeps it non-validating). Gate the precompiles on the
|
|
futureEips timestamp so they activate at block 9,189,161, not block 0.
|
|
|
|
### 5.3 Full re-validation to genesis (2.a)
|
|
|
|
Start the follower in full-sync from genesis against a node under your control and confirm
|
|
zero invalid-seal rejects in the logs:
|
|
|
|
```bash
|
|
# config: chainspec with the reproduced genesis 0xd86d57a8…0c5d7f1a,
|
|
# --Sync FullSync (FastSync/SnapSync/FastBlocks = false), static peer to a Besu node,
|
|
# discovery off, RPC bound to 127.0.0.1
|
|
dotnet Nethermind.Runner.dll --config aere-live-config.json
|
|
```
|
|
|
|
[MEASURE: full-history re-validation to head with a zero-invalid-seal count over 0..head
|
|
requires the multi-hour full-history sync on the fork host; assert the count once the follower
|
|
is at head.]
|
|
|
|
### 5.4 Byte-identical re-execution, diff the state roots (2.b)
|
|
|
|
For each checked height, pull the state root from both clients and diff. Read-only, via each
|
|
client's own RPC (the follower on `127.0.0.1:8545`, the reference on its node RPC):
|
|
|
|
```bash
|
|
for h in 1 100 1000 10000 3000; do
|
|
a=$(cast rpc eth_getBlockByNumber $(printf '0x%x' $h) false --rpc-url http://127.0.0.1:8545 | jq -r .stateRoot)
|
|
b=$(cast rpc eth_getBlockByNumber $(printf '0x%x' $h) false --rpc-url <reference-node-rpc> | jq -r .stateRoot)
|
|
[ "$a" = "$b" ] && echo "$h stateRoot MATCH" || echo "$h stateRoot DIVERGE a=$a b=$b"
|
|
done
|
|
```
|
|
|
|
Do the same for `.hash` (block hash) at each height. Expected: MATCH at every height, per the
|
|
tables in section 2.b.
|
|
|
|
[MEASURE: extend the height list across the fork boundary (9,189,160 and 9,189,161) and to
|
|
current head once the follower has executed past 9,189,161. A mismatch at or across the
|
|
boundary indicates a wrong precompile gate; stop and fix.]
|
|
|
|
**baseFee reproduction trap.** Compare state roots and block hashes against a raw Besu node,
|
|
not the public `rpc.aere.network`. The public RPC is behind a proxy that overwrites
|
|
`baseFeePerGas` with a constant 1 Gwei for display; that shimmed value does not reproduce the
|
|
real block hash for blocks whose true base fee differs. A client reading directly from a Besu
|
|
node gets the true consensus value and needs no override (`aerenew/conformance/README.md`,
|
|
baseFee shim caveat).
|
|
|
|
### 5.5 Production interop and tamper control (3.1, 3.2)
|
|
|
|
On an isolated testnet, have the Nethermind-side producer seal a short chain and import it with
|
|
a stock Besu, then repeat with one seal byte flipped:
|
|
|
|
```bash
|
|
# produce N blocks -> nm-blocks.rlp (isolated chainId, single validator), then:
|
|
besu --data-path <fresh> blocks import --from nm-blocks.rlp # expect exit 0, all hashes match the manifest
|
|
# flip one byte of a committed seal, re-import -> expect BftCommitSealsValidationRule rejection, exit 1
|
|
```
|
|
|
|
Expected: genuine chain imports with byte-identical hashes; the tampered chain is rejected by
|
|
Besu's own BFT rule. This is the non-vacuity control, reproduced from
|
|
`aerenew/nethermind-pqc/QBFT-PRODUCER-2ND-CLIENT-2026-07-13.md`.
|
|
|
|
### 5.6 Live follower cross-check (2.c)
|
|
|
|
Run the non-validating follower against the live chain and diff hash and state root against a
|
|
raw live node at a spread of heights:
|
|
|
|
[MEASURE: the live follower cross-check at head requires the follower to be fully synced (honest
|
|
ETA roughly 18 hours) and peered to a live node; assert per-height hash and state-root MATCH and
|
|
zero divergence over a sustained soak per `DECENTRALIZATION-2ND-CLIENT-RUNBOOK.md` A.6 and A.7.]
|
|
|
|
---
|
|
|
|
## 6. Summary
|
|
|
|
Two independent implementations, in different languages, compute the same chain-2800 state:
|
|
identical block hashes, identical state roots, matching seal decisions, and byte-for-byte
|
|
identical post-quantum precompile outputs, with a tampered seal provably rejected. That is
|
|
proven as a validation cross-check. It is not yet a continuously-armed automated live
|
|
divergence gate, and Nethermind is not yet a live producing validator; those are the remaining
|
|
operational and founder-gated steps. The claim this document supports is precise and defensible:
|
|
Aere's client-diversity assurance is a demonstrated, reproducible cross-check on state
|
|
computation, not a marketing line, and its boundaries are stated in the same words as the
|
|
engineering spec it is consistent with.
|