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.
116 lines
7.9 KiB
Markdown
116 lines
7.9 KiB
Markdown
# Formal-verification broadening: new contract SMT models + canonical runner consolidation
|
|
|
|
Date: 2026-07-19. Tooling: Python 3.14.4, z3 4.16.0 (real z3 verdicts, no fabricated greens).
|
|
All verdicts below were produced by actually running the scripts.
|
|
|
|
## Part 1: four new z3 SMT models (all PROVED, negative controls fired)
|
|
|
|
Each model proves its safety property by asserting NOT-property under the real Solidity
|
|
guards (z3 returns UNSAT) and pairs every proof with a firing negative control that removes
|
|
one guard and returns SAT (non-vacuity). DESIGN-level caveats and [VERIFY]/[MEASURE] items
|
|
are stated in each model's SUMMARY block exactly as the money-contract models do.
|
|
|
|
### a. pqfinality_smt.py -> PROVED (10 PROVED, 3 CEX-FOUND, 0 FAILED, rc=0)
|
|
Contracts: contracts/contracts/pqfinality/AereFinalityCertificateVerifier.sol +
|
|
AerePQAttestationKeyRegistry.sol
|
|
Proved: quorum threshold is exactly ceil(2N/3) = (2N+2)/3 (Q0 for all N>=1; Q0b anchors
|
|
N in {4,5,7,9} -> {3,4,5,6}); an accepted certificate meets that quorum (P1; P1b a 4-of-7
|
|
cert is rejected); it is bound to the live registry validatorSetRoot (P2) and size (P2b); it
|
|
is bound to the chainId+registry attestation domain so a cross-chain/registry certificate is
|
|
rejected (P3 via injective domain hash; P3b direct); a key rotation that changes the root
|
|
makes an old-root certificate unaccept-able (P4 via injective root hash); an empty validator
|
|
set is rejected (P5).
|
|
Negative controls (all fired SAT): drop quorum -> sub-quorum accepted; drop root binding ->
|
|
stale/forged root accepted; drop domain binding -> cross-chain replay accepted.
|
|
Caveats stated: SP1 gateway soundness (verifyProof reverts on invalid proof) is a trusted
|
|
primitive [VERIFY]; the off-chain zkVM aggregation circuit is [MEASURE], NOT implemented
|
|
(contract tests use a MOCK gateway); keccak256 injectivity (root/domain) is [VERIFY];
|
|
additive PQ finality, consensus stays classical ECDSA QBFT; DESIGN math not EVM bytecode.
|
|
|
|
### b. pqaggregate_smt.py -> PROVED (7 PROVED, 2 CEX-FOUND, 0 FAILED, rc=0)
|
|
Contract: contracts/contracts/mpc/AerePQAggregateVerifier.sol
|
|
Proved: a registered committee is well-formed (R0: root!=0, 1<=t<=n, scheme!=0); an accepted
|
|
authorization is EXACTLY the registered committee's key set (P1; P1b via committee-root
|
|
injectivity, so a foreign key set is rejected); it is bound to the caller's message digest
|
|
(P2); it proves at least threshold t distinct signatures (P3); it binds size and scheme as
|
|
defense in depth (P4); and the on-chain accept reads only O(1) committee/public fields (keys
|
|
not stored), so verification cost is independent of n (P5).
|
|
Negative controls (all fired SAT): drop root binding -> a different committee's key set
|
|
authorizes; drop digest binding -> a proof for message A authorizes message B.
|
|
Caveats stated: SP1 gateway soundness [VERIFY]; off-chain zkVM aggregation circuit [MEASURE],
|
|
not implemented (MOCK gateway); keccak256 injectivity [VERIFY]; account/authorization
|
|
aggregation not consensus, no funds, no admin; DESIGN math not EVM bytecode.
|
|
|
|
### c. credential_registry_smt.py -> PROVED (7 PROVED, 3 CEX-FOUND, 0 FAILED, rc=0)
|
|
Contracts: contracts/contracts/compliance/AereTrustRegistry.sol + AereVerifiableCredential.sol
|
|
Proved: issuance requires accreditation (A: anchor success => Active AND in-scope; A2: a
|
|
None/Suspended/Revoked or out-of-scope issuer cannot anchor) and a valid Falcon-512 issuer
|
|
signature (A3); the status history is append-only so a committed record cannot be rewritten
|
|
(B, via the standard append relation); revocation is terminal (C: from Revoked no transition
|
|
returns to Active); and both the anchored (isValid, D) and presented (verifyPresented, D2)
|
|
verification paths are fail-closed on expired / not-yet-valid / revoked / un-accredited.
|
|
Negative controls (all fired SAT): drop the accreditation check -> a revoked issuer issues;
|
|
allow a status overwrite -> a committed record is silently rewritten; drop the validity
|
|
window -> an expired credential is accepted.
|
|
Caveats stated: Falcon-512 precompile 0x0AE1 soundness modelled as the sigValid predicate
|
|
[VERIFY]; the Bitstring Status List and live issuer status are trusted external oracles;
|
|
application-layer, no funds, consensus stays classical ECDSA QBFT; legal weight of any
|
|
accreditation is external; DESIGN logic not EVM bytecode.
|
|
|
|
### d. recovery_registry_smt.py -> PROVED (5 PROVED, 2 CEX-FOUND, 0 FAILED, rc=0)
|
|
Contract: contracts/contracts/AereRecoveryRegistry.sol
|
|
Proved: a record is written only if the Falcon-512 signature verifies (FC, fail-closed) and
|
|
is well-formed (FC2: fault kind / heights / validator set); the per-operator nonce strictly
|
|
increases on every write (NO); a nonce-k signature cannot be replayed once the nonce advances
|
|
because the record hash binds the nonce (RP, via injective nonce hash + EUF-CMA verify
|
|
predicate); and the records array is append-only so a committed record is never rewritten (AP).
|
|
Negative controls (all fired SAT): drop the nonce binding -> one signature replays to rewrite
|
|
history; drop append-only -> a committed record is silently overwritten.
|
|
Caveats stated: Falcon-512 precompile 0x0AE1 soundness (EUF-CMA, input parsing,
|
|
empty-return-is-invalid) modelled as the verify predicate [VERIFY]; keccak256 injectivity of
|
|
the nonce-bound record hash [VERIFY]; records attestations only, does not observe consensus or
|
|
activate PQ consensus (still classical ECDSA QBFT); uint64 nonce cannot realistically
|
|
overflow; DESIGN logic not EVM bytecode.
|
|
|
|
## Part 2: canonical runner consolidation
|
|
|
|
File changed: aerenew/formal-consensus/run_consensus_verification.py (had a hardcoded MODELS
|
|
list of 8 consensus models). Added a CONTRACT_MODELS section wiring in all 7 new contract SMT
|
|
scripts written in this loop, keeping the 8 consensus models intact:
|
|
computemarket_smt, destinationsettler_smt, migrator_smt (the 3 money models) +
|
|
pqfinality_smt, pqaggregate_smt, credential_registry_smt, recovery_registry_smt (the 4 new).
|
|
The runner now also captures each child's output and tallies the per-check verdict lines.
|
|
|
|
### Canonical runner fresh totals (real run, exit 0)
|
|
models run: 15 passed: 15 (8 consensus + 7 contract)
|
|
verdict lines: 128 PROVED 79 CEX-FOUND 0 FAILED
|
|
RESULT: ALL MODELS PASS (proofs PROVED, negative controls fired)
|
|
|
|
Breakdown of the 128/79 (per-check verdict lines, i.e. distinct property checks):
|
|
- 4 new models: 29 PROVED / 10 CEX-FOUND (pqfinality 10/3, pqaggregate 7/2,
|
|
credential_registry 7/3, recovery_registry 5/2)
|
|
- 3 fund-flow models: 26 PROVED / 11 CEX-FOUND (computemarket 16/3, destinationsettler 5/4,
|
|
migrator 5/4)
|
|
- 8 consensus models: 73 PROVED / 58 CEX-FOUND (remainder)
|
|
|
|
Note on scope: the 7 wired-in contract models live in aerenew/formal-consensus/ (the same
|
|
directory as the canonical runner). The research-stage staging copy
|
|
(aerenew/research-stage/formal-consensus/) is a separate curated publish target with its own
|
|
committed expected-output.log and was left unchanged.
|
|
|
|
### REPRODUCE.md update
|
|
Updated aerenew/REPRODUCE.md section 3b: the "canonical in-tree" subsection previously cited
|
|
"8 models" / "8 of 8 models PASS". It now reads "15 models: 8 consensus + 7 contract", "15 of
|
|
15 models PASS", with the real fresh runner tally of 128 PROVED / 79 CEX-FOUND / 0 FAILED, the
|
|
per-group breakdown above, the names of the 7 newly-added contract models, and a restatement
|
|
of the NOT-property-UNSAT + firing-negative-control discipline and the per-model DESIGN /
|
|
[VERIFY] / [MEASURE] boundaries. No fabricated numbers: every figure is from the actual run.
|
|
The staging "(10 models)" section and the older bash-loop "(9 models)" contract section were
|
|
left as-is (correct and separate).
|
|
|
|
## Honesty posture
|
|
- All verdicts are real z3 output; no green was fabricated.
|
|
- Every model has at least one firing negative control (SAT under a removed guard).
|
|
- No contract was modified. Only SMT scripts were added, the runner was extended, and
|
|
REPRODUCE.md was updated with real fresh numbers.
|