Dated corrections (2026-10-27): formal-consensus/RULEAZA-TOT.md translated into English and dated (it stated, without a date, facts of the chain of August 2026); the models print the chain facts of their time with the date, or the facts of today (labels and printed strings only, the logic and the verdicts unchanged: 37 of 37 models pass); README: 37 models counted on 2026-10-27 and the reproduction pointer to aere-docs REPRODUCE.md section 3b

This commit is contained in:
Aere Network 2026-10-27 15:01:25 +02:00
parent 9b2a69ab6b
commit 6d24576357
8 changed files with 149 additions and 133 deletions

View File

@ -55,8 +55,8 @@ Two more limits, both of which cut against claims made in this repository:
## Layout ## Layout
- `formal-consensus/` Z3 / SMT models of consensus and contract safety properties (30 Python - `formal-consensus/` Z3 / SMT models of consensus and contract safety properties (37 Python
models plus a Quint spec `FalconQuorum.qnt`), driven by `run_consensus_verification.py`. These models, counted on 2026-10-27, plus a Quint spec `FalconQuorum.qnt`), driven by `run_consensus_verification.py`. These
cover QBFT safety and liveness, the money-contract invariants, and a PROPOSED hybrid cover QBFT safety and liveness, the money-contract invariants, and a PROPOSED hybrid
dual-quorum activation that is modelled research and is NOT running on chain 2800, and the dual-quorum activation that is modelled research and is NOT running on chain 2800, and the
invariants. `CONSENSUS-VERIFICATION-2026-07-12.md` documents the results. invariants. `CONSENSUS-VERIFICATION-2026-07-12.md` documents the results.
@ -84,8 +84,9 @@ python run_consensus_verification.py
``` ```
The STARK references are cross-checked against their ground-truth vectors; see each The STARK references are cross-checked against their ground-truth vectors; see each
`spec-*.md` and the `test_*.py` files. Full commands and expected outputs are in the `aere-docs` `spec-*.md` and the `test_*.py` files. Full commands and expected outputs, dated, are in the `aere-docs`
repository (`REPRODUCE.md`). repository (`REPRODUCE.md`; its section 3b gives the result of the command above as measured on 2026-10-27, and
the older runs it records use the paths of the development tree).
## What is deliberately not here ## What is deliberately not here

View File

@ -1,83 +1,85 @@
# RULEAZA-TOT: verificarea formala a consensului AERE, un capat la altul # RULEAZA-TOT: the formal verification of AERE consensus, end to end
Rularea completa a tot ce se poate verifica automat pe consensul AERE (QBFT / IBFT 2.0, *Translated into English and dated on 2026-10-27. Until that date this document was in Romanian and stated, without a date,
chain 2800), cu doua metode independente: facts that were true only of the chain of August 2026 (a set of nine validators, an anchor minimum of three); the
corrections are marked below, and the results it records keep the date they were measured on.*
- **SMT (z3)** parametric, in acest dosar (`formal-consensus/*_smt.py`): dovedeste fiecare A complete run of everything that can be checked automatically about AERE consensus (QBFT / IBFT 2.0, chain 2800), with two
proprietate aratand ca negatia ei e UNSAT, plus un control negativ care planteaza independent methods:
incalcarea si trebuie sa iasa SAT. Scaleaza la N=9 (flota reala).
- **TLA+ / TLC** exhaustiv, in `aerenew/formal-tla/`: verifica prin explorare de stari la
scara mica (N=4), unde combinatoria e suficienta.
Regula peste tot: **niciun model nu se raporteaza verde daca nu poate iesi ROSU.** Fiecare - **SMT (z3)**, parametric, in this directory (`formal-consensus/*_smt.py`): each property is proved by showing that its
proprietate are un control negativ rulat. negation is UNSAT, plus a negative control that plants the violation and must come back SAT. The models scale to N=9,
the validator set of 2026-08-24, when the table below was written; the set has had ten validators since 2026-09-11, and
the models state the N each one is run at.
- **TLA+ / TLC**, exhaustive, in `formal-tla/` of the development tree (not in this repository): it explores the state
space at a small scale (N=4), where the combinatorics is enough.
The rule everywhere: **no model is reported green unless it can come out RED.** Every property has a negative control
that is run.
--- ---
## 1. Suita SMT (z3) - o singura comanda ## 1. The SMT suite (z3): one command
``` ```
cd aerenew/publish-bundle/aere-research/formal-consensus cd formal-consensus
python run_consensus_verification.py python run_consensus_verification.py
``` ```
Ruleaza TOATE modelele `*_smt.py` din dosar (garda de completitudine refuza sa iasa verde It runs ALL the `*_smt.py` models in this directory (the completeness guard refuses a green result if a model that is
daca vreun model prezent nu e cablat). Tipareste PASS/FAIL per model, timpul fiecaruia, si present is not wired). It prints PASS / FAIL per model, the time of each, and the tally of verdict lines.
tally-ul de linii de verdict.
**Masurat 2026-10-07** (Windows, python 3.14.4 / z3 4.16.0; timpii variaza cu masina): **Measured 2026-10-07** (Windows, Python 3.14.4 / z3 4.16.0; the times vary with the machine):
``` ```
models run: 37 passed: 37 (16 consensus + 11 contract + 10 application) models run: 37 passed: 37 (16 consensus + 11 contract + 10 application)
verdict lines: 301 PROVED 159 CEX-FOUND 0 FAILED verdict lines: 301 PROVED 159 CEX-FOUND 0 FAILED
wall time: ~37s total (cel mai lent: qbft_safety_smt.py ~20s) wall time: ~37s total (slowest: qbft_safety_smt.py ~20s)
coverage: 37 of 37 *_smt.py files wired coverage: 37 of 37 *_smt.py files wired
RESULT: ALL MODELS PASS (proofs PROVED, negative controls fired) RESULT: ALL MODELS PASS (proofs PROVED, negative controls fired)
``` ```
Istoria cifrelor, datata: 2026-08-24, 35 de modele (14 consens), 282 PROVED / 149 CEX-FOUND, ~39 s; The history of the figures, dated: 2026-08-24, 35 models (14 consensus), 282 PROVED / 149 CEX-FOUND, ~39 s;
2026-09-02, + `pq_message_enforcement_smt.py` (36 of 36); 2026-10-07, + `anchor_rewrite_bound_roundfree_smt.py` 2026-09-02, + `pq_message_enforcement_smt.py` (36 of 36); 2026-10-07, + `anchor_rewrite_bound_roundfree_smt.py`
(37 of 37; 13 dovezi, 2 leme, 4 martori, 1 definitie, 8 controale negative; limita de rescriere 32 / 33 sub modelul (37 of 37; 13 proofs, 2 lemmas, 4 witnesses, 1 definition, 8 negative controls; the rewrite bound is 32 / 33 under the
fara runda, ca functie de K_eff si de cheile PQ tinute; vezi `research/rewrite-bound-round-free-seal-2026-10-07.md` round-free model, as a function of K_eff and of the post-quantum keys held; see
si `anchor_rewrite_bound_roundfree_smt.RESULT.txt`). `research/rewrite-bound-round-free-seal-2026-10-07.md` and `anchor_rewrite_bound_roundfree_smt.RESULT.txt`).
Cele 16 modele de consens (14 pe 24 august, + 1 pe 2 septembrie, + 1 pe 7 octombrie): The 16 consensus models (14 on 24 August, + 1 on 2 September, + 1 on 7 October):
| model | ce dovedeste | N | | model | what it proves | N |
|---|---|---| |---|---|---|
| `qbft_safety_smt.py` | agreement (quorum-intersection unbounded; one-round + cross-round locking) | 4,5,7,10,13,16 | | `qbft_safety_smt.py` | agreement (quorum intersection unbounded; one-round + cross-round locking) | 4,5,7,10,13,16 |
| `qbft_liveness_smt.py` | progres post-GST (f+1 runde ating un proposer onest) | 4,5,7 | | `qbft_liveness_smt.py` | progress after GST (f+1 rounds reach an honest proposer) | 4,5,7 |
| `qbft_locking_smt.py` | locking IBFT 2.0 pe rolurile motorului (view-change / round-change) | 4,5,7 | | `qbft_locking_smt.py` | IBFT 2.0 locking on the engine roles (view change / round change) | 4,5,7 |
| `qbft_prepare_counting_smt.py`, `qbft_digest_keyed_smt.py` | numararea voturilor (bug+fix 2026-07-14) | mic | | `qbft_prepare_counting_smt.py`, `qbft_digest_keyed_smt.py` | the counting of votes (bug and fix of 2026-07-14) | small |
| `falcon_blocking_smt.py`, `anchor_blocking_quorum_smt.py` | pragul de sigilii pe ancora (K=3 din 9) | 9 | | `falcon_blocking_smt.py`, `anchor_blocking_quorum_smt.py` | the anchor seal threshold of 2026-08-15 (K=3 of 9; the minimum is 7 of 10 since block 20,715,632) | 9 |
| `qbft_pqc_activation_smt.py` | tranzitia log-only -> blocant | - | | `qbft_pqc_activation_smt.py` | the log-only -> blocking transition | - |
| **`partition_safety_smt.py`** (NOU) | **partitii de retea: split-brain, starvatie, vindecare** | **9 param.** | | **`partition_safety_smt.py`** (new on 2026-08-24) | **network partitions: split brain, starvation, healing** | **9, parametric** |
| **`anchor_viewchange_smt.py`** (NOU) | **o schimbare de runda pe o ancora nu da doua certificate valide** | **9** | | **`anchor_viewchange_smt.py`** (new on 2026-08-24) | **a round change at an anchor does not give two valid certificates, in the model, under its finalized-block guard (the code has no such guard: note added 2026-10-01)** | **9** |
| `pqanchor_ceiling_monotonicity_smt.py` | plafonul de urgenta doar coboara K | - | | `pqanchor_ceiling_monotonicity_smt.py` | the emergency ceiling only lowers K | - |
| `registry_index_binding_smt.py`, `registry_rotation_coverage_smt.py` | registrul de chei pe inaltime | - | | `registry_index_binding_smt.py`, `registry_rotation_coverage_smt.py` | the key registry by height (the registries of 2026-08-15) | - |
| **`anchor_rewrite_bound_roundfree_smt.py`** (2026-10-07) | **limita de rescriere sub adversarul cu toate cheile clasice: 32 de blocuri (ancora + 31), 33 sub exceptia din erata AIP-22 (fratele nedecis, bunicul comun); marginita exact cand cheile PQ tinute j < K_eff (K_eff = 7 pe validator, 1 pe urmaritorul publicat cu plafon); 128 / 129 in fereastra datata cu interval 128; punctul de referinta fixeaza prefixul (lantul de hash-uri desfasurat 1280 de inaltimi); `--plant-bounds` = controlul controlului** | 10, orice K_eff >= 1 | | **`anchor_rewrite_bound_roundfree_smt.py`** (2026-10-07) | **the rewrite bound under the adversary holding every classical key: 32 blocks (the anchor + 31), 33 under the exception of the AIP-22 erratum (the undecided sibling, the common grandparent); bounded exactly when the post-quantum keys held j < K_eff (K_eff = 7 on a validator, 1 on the published follower with its ceiling); 128 / 129 in the dated window with interval 128; the reference point pins the prefix (the hash chain unrolled over 1280 heights); `--plant-bounds` is the control of the control** | 10, any K_eff >= 1 |
> Nota: cele trei modele de registru/plafon existau in dosar din 15-19 august dar NU erau > Note: the three registry / ceiling models were in the directory from 15 to 19 August but were NOT wired into the runner
> cablate in rulator (garda de completitudine il facea sa iasa cu cod 2). Cablate pe 24 august > (the completeness guard made it exit with code 2). They were wired on 24 August together with the two new models.
> impreuna cu cele doua modele noi.
--- ---
## 2. TLA+ / TLC exhaustiv - partitiile de retea (NOU, 24 august) ## 2. TLA+ / TLC, exhaustive: network partitions (new on 24 August)
Modelul `aerenew/formal-tla/QBFTPartition.tla` face partitia un DEFECT modelat explicit The model `formal-tla/QBFTPartition.tla` (development tree) makes the partition an explicitly modelled FAULT (a predicate
(un predicat pe livrarea mesajelor intre grupuri) si o verifica exhaustiv la N=4. Sase on the delivery of messages between groups) and checks it exhaustively at N=4. Six configurations, each with its positive
configuratii, fiecare cu perechea ei pozitiv/negativ. / negative pair.
### Rularea (WSL, mult mai rapid decat pe Windows) ### The run (much faster under Linux, or WSL on Windows, than natively on Windows)
Scrie un script, copiaza-l, ruleaza-l fara ghilimele inline (comenzile inline se mangleaza Write a script, copy it, run it without inline quotes. Every run uses `-deadlock`, because the protocol TERMINATES
prin wsl.exe). Toate rularile folosesc `-deadlock` fiindca protocolul se TERMINA in mod normal normally (everyone has decided) and termination is not a defect:
(toti au decis) si terminarea nu e un defect:
```bash ```bash
# copie dosarul in /root (rulare rapida, in afara /mnt) # copy the directory outside any mounted Windows drive (a faster run)
AERE_REPO=/calea/catre/clona/depozitului # radacina clonei tale; dosarul formal-tla/ sta direct sub ea AERE_REPO=/path/to/the/clone # the root of your clone; the formal-tla/ directory sits directly under it
mkdir -p /root/ftla mkdir -p /root/ftla
cp -f "$AERE_REPO"/formal-tla/*.tla /root/ftla/ cp -f "$AERE_REPO"/formal-tla/*.tla /root/ftla/
cp -f "$AERE_REPO"/formal-tla/*.cfg /root/ftla/ cp -f "$AERE_REPO"/formal-tla/*.cfg /root/ftla/
@ -89,62 +91,61 @@ for CFG in MCpart_safety MCpart_safety_witness MCpart_safety_negctrl \
done done
``` ```
Lanseaza din PowerShell: ### Results measured 2026-08-24 (WSL, OpenJDK 21, exhaustive, 0 states left in the queue)
`MSYS_NO_PATHCONV=1 wsl.exe -d Ubuntu-24.04 -- bash /mnt/c/.../script.sh`
### Rezultate masurate 2026-08-24 (WSL, OpenJDK 21, exhaustiv, 0 stari ramase in coada) | config | what it checks | expected | result | time |
| config | ce verifica | asteptat | rezultat | timp |
|---|---|---|---|---| |---|---|---|---|---|
| `MCpart_safety` | 3-1, quorum 3, heal: SAFETY se pastreaza | fara eroare | **No error** (1866 stari) | ~3s | | `MCpart_safety` | 3-1, quorum 3, heal: SAFETY holds | no error | **No error** (1866 states) | ~3s |
| `MCpart_safety_witness` | acelasi, invariant `NoCommit` | VIOLARE (commit e atins) | **NoCommit violated** -> `committed={a}` | ~2s | | `MCpart_safety_witness` | the same, invariant `NoCommit` | VIOLATION (a commit is reached) | **NoCommit violated** -> `committed={a}` | ~2s |
| `MCpart_safety_negctrl` | 2-2, quorum COBORAT la 2 | VIOLARE (fork) | **NoFork violated** -> `committed={a,b}` (v1->a, v3->b) | ~4s | | `MCpart_safety_negctrl` | 2-2, quorum LOWERED to 2 | VIOLATION (fork) | **NoFork violated** -> `committed={a,b}` (v1->a, v3->b) | ~4s |
| `MCpart_noprogress` | 2-2, quorum 3, FARA vindecare, invariant `NoCommit` | fara eroare | **No error** (81 stari; nimic nu se finalizeaza) | ~2s | | `MCpart_noprogress` | 2-2, quorum 3, NO healing, invariant `NoCommit` | no error | **No error** (81 states; nothing finalizes) | ~2s |
| `MCpart_liveness` | 2-2, quorum 3, vindecare, `EventualCommit` | fara eroare | **No error** (liveness revine dupa heal) | ~3s | | `MCpart_liveness` | 2-2, quorum 3, healing, `EventualCommit` | no error | **No error** (liveness returns after the heal) | ~3s |
| `MCpart_liveness_negctrl` | 2-2, quorum 3, FARA vindecare, `EventualCommit` | VIOLARE | **EventualCommit violated** (stuttering, `committed={}`) | ~2s | | `MCpart_liveness_negctrl` | 2-2, quorum 3, NO healing, `EventualCommit` | VIOLATION | **EventualCommit violated** (stuttering, `committed={}`) | ~2s |
Cele trei perechi acopera exact intrebarile cerute: The three pairs answer exactly the questions asked:
- **SAFETY se pastreaza in ambele parti**: `MCpart_safety` verde, si non-vacuu prin `witness` - **SAFETY holds on both sides**: `MCpart_safety` is green, and non-vacuous through `witness` (the majority side does
(partea majoritara chiar finalizeaza). Controlul negativ `safety_negctrl` arata ca ce finalize). The negative control `safety_negctrl` shows that what stops the fork is the ceil(2N/3) quorum: lowered to 2,
opreste fork-ul e quorum-ul ceil(2N/3): coborat la 2, cele doua parti finalizeaza `a` si `b`. the two sides finalize `a` and `b`.
- **LIVENESS se pierde in grupul fara quorum**: `MCpart_noprogress` (nimic nu se finalizeaza - **LIVENESS is lost in the group without a quorum**: `MCpart_noprogress` (nothing finalizes in an unhealed 2-2
intr-o partitie 2-2 nevindecata). partition).
- **LIVENESS revine la vindecare**: `MCpart_liveness` verde; controlul negativ - **LIVENESS returns on healing**: `MCpart_liveness` is green; the negative control `liveness_negctrl` shows that without
`liveness_negctrl` arata ca fara pasul de vindecare `EventualCommit` PICA (heal e cauza). the healing step `EventualCommit` FAILS (the heal is the cause).
--- ---
## 3. TLA+ / TLC - modelul QBFT complet (agreement + view-change + echivocatie) ## 3. TLA+ / TLC: the complete QBFT model (agreement + view change + equivocation)
`aerenew/formal-tla/QBFT.tla` cu `MCsafety.cfg` (N=4) / `MCsafety7.cfg` (N=7) si `formal-tla/QBFT.tla` (development tree) with `MCsafety.cfg` (N=4) / `MCsafety7.cfg` (N=7) and `MCliveness.cfg`.
`MCliveness.cfg`. **Masurat 2026-07-19 si 2026-08-24: aceste configuratii NU se termina** in **Measured 2026-07-19 and 2026-08-24: these configurations do NOT terminate** within the local budget (the state space is
bugetul local (spatiul de stari e de ordinul zecilor de milioane; `MCliveness` a generat in the tens of millions; `MCliveness` generated 543k distinct states in 197 s with 527k still queued). What is established
543k stari distincte in 197s cu 527k inca in coada). Ce e stabilit acolo e un martor there is a partial explicit-state witness (9.35 million states without a violation at N=4 round 0), NOT a complete
explicit-state partial (9,35 milioane de stari fara violare pe N=4 round-0), NU o verificare check (`TLC-RUN-REPORT.md`, development tree). The all-N core (quorum intersection, agreement under locking) is already
completa. Vezi `TLC-RUN-REPORT.md`. Miezul all-N (quorum-intersection, agreement sub locking) proved for ANY N by the SMT suite; TLA+ is the independent method, and its value for partitions is that
e deja dovedit pentru ORICE N de suita SMT; TLA+ e metoda independenta, iar valoarea lui la `QBFTPartition.tla` does TERMINATE exhaustively (single height), unlike the complete model.
partitii este ca `QBFTPartition.tla` chiar SE TERMINA exhaustiv (single-height), spre
deosebire de modelul complet.
--- ---
## 4. Cross-check optional: quint / Apalache ## 4. Optional cross-check: quint / Apalache
`FalconQuorum.qnt` e un cross-check secundar (vezi `CONSENSUS-VERIFICATION-2026-07-12.md` `FalconQuorum.qnt` is a secondary cross-check (see `CONSENSUS-VERIFICATION-2026-07-12.md` for the `quint run`
pentru comenzile `quint run`). commands).
--- ---
## Granita cinstita (se citeste, nu se sare) ## The honest boundary (read it, do not skip it)
- Model checking **nu e demonstratie completa.** SMT dovedeste combinatoria design-ului - Model checking **is not a complete proof.** SMT proves the combinatorics of the design (vote counting, quorum
(numararea voturilor, intersectia quorum-urilor, legarea certificatului), nu bytecode-ul intersection, the binding of the certificate), not the Besu / EVM bytecode. TLC checks exhaustively only the finite
Besu/EVM. TLC verifica exhaustiv doar configuratia finita enuntata (N=4 la partitii). configuration stated (N=4 for partitions).
- SMT parametric la N=9 dovedeste proprietatea pentru **acel** N; miezul aritmetic - Parametric SMT at N=9 proves the property for **that** N; the arithmetic core (quorum intersection, 2q > N) is
(quorum-intersection, 2q>N) e unbounded in N. unbounded in N.
- Consensul chain 2800 comita cu **ECDSA clasic** secp256k1; ancora PQ e ADITIVA. Nimic de - When these models were written (July to October 2026), chain 2800 committed its blocks with **classical** secp256k1
aici nu implica "consens post-cuantic". ECDSA seals and the post-quantum anchor was ADDITIVE; nothing here implies "post-quantum consensus". The chain of today
- Primitivele criptografice (injectivitatea keccak, soliditatea gateway-ului SP1, validarea is described in the aere-node SPEC.md. (Corrected 2026-10-27: this point was stated in the present tense.)
sigiliului Falcon) sunt tratate ca `[VERIFY]`, modelate, nu re-dovedite. - The cryptographic primitives (keccak injectivity, the soundness of the SP1 gateway, the validation of the Falcon seal)
- Ancora foloseste K=3 = **f+1**, NU un quorum. Unicitatea certificatului vine din legarea la are treated as `[VERIFY]`: modelled, not re-proved.
blocul finalizat (dovada `anchor_viewchange_smt.py`), nu din intersectia sigiliilor. - In the models of August 2026 the anchor used K=3 = **f+1**, NOT a quorum; since block 20,715,632 the minimum is 7 of
10 per scheme, as many as the QBFT quorum of the ten validators (corrected 2026-10-27: this point was stated in the
present tense). In the model, the uniqueness of the certificate comes from its binding to the finalized block, the
guard of `anchor_viewchange_smt.py`, not from an intersection of seals; the client code has no such guard (note added
2026-10-01 in the runner).

View File

@ -155,9 +155,12 @@ class Block:
falcon_ok = If(is_anchor(self.h), anykey >= self.K_eff(), BoolVal(True)) falcon_ok = If(is_anchor(self.h), anykey >= self.K_eff(), BoolVal(True))
return And(self.qbft >= QBFT_Q, falcon_ok) return And(self.qbft >= QBFT_Q, falcon_ok)
print("### AERE anchor BLOCKING-QUORUM SAFETY -- fork at 14,050,000, K=3, N=9, q=6\n") print("### AERE anchor THRESHOLD SAFETY on the chain of 2026-08-15 (K=3, N=9, q=6, registries R1 of 7 keys and R2 of 9)")
print("### modelled for anchor heights >= 14,050,000, called 'the fork' below. Corrected 2026-10-27: that height is the bound of")
print("### this model, not a blocking fork: the property armed there changed no enforcement (correction of 2026-08-19), and the K=3")
print("### step is from 13,034,000. Today: ten validators since 2026-09-11, minimum 7 per scheme since block 20,715,632.\n")
print(f" anchor grid: every {ANCHOR_INTERVAL} blocks from {ANCHOR_START}; " print(f" anchor grid: every {ANCHOR_INTERVAL} blocks from {ANCHOR_START}; "
f"fork {FORK_BLOCKING} is {'ON' if (FORK_BLOCKING-ANCHOR_START)%ANCHOR_INTERVAL==0 else 'OFF'} the grid " f"model bound {FORK_BLOCKING} is {'ON' if (FORK_BLOCKING-ANCHOR_START)%ANCHOR_INTERVAL==0 else 'OFF'} the grid "
f"((14050000-13014000)/32 = {(FORK_BLOCKING-ANCHOR_START)//ANCHOR_INTERVAL})\n") f"((14050000-13014000)/32 = {(FORK_BLOCKING-ANCHOR_START)//ANCHOR_INTERVAL})\n")
# ============================================================================= # =============================================================================
@ -165,14 +168,14 @@ print(f" anchor grid: every {ANCHOR_INTERVAL} blocks from {ANCHOR_START}; "
# ============================================================================= # =============================================================================
s = Solver() s = Solver()
s.add(Int('r') == (FORK_BLOCKING - ANCHOR_START) % ANCHOR_INTERVAL, Int('r') != 0) s.add(Int('r') == (FORK_BLOCKING - ANCHOR_START) % ANCHOR_INTERVAL, Int('r') != 0)
check("S0a CONFIG: the blocking-fork height 14,050,000 lies ON the anchor grid " check("S0a CONFIG: the model bound 14,050,000 lies ON the anchor grid "
"(it is itself an anchor height)", s) "(it is itself an anchor height)", s)
s = Solver() s = Solver()
h = Int('h') h = Int('h')
s.add(h >= FORK_BLOCKING, sched_K(h) != K_TARGET) s.add(h >= FORK_BLOCKING, sched_K(h) != K_TARGET)
check("S0b SCHEDULE (all h >= fork): the min-seals schedule pins K == 3 at every " check("S0b SCHEDULE (all h >= 14,050,000, schedule of 2026-08-15): the min-seals schedule pins K == 3 at every "
"blocking-era height (13034000:3 step is below the fork)", s) "modelled height (the 13034000:3 step is below the bound)", s)
s = Solver() s = Solver()
h = Int('h') h = Int('h')
@ -185,8 +188,8 @@ check("S0c REGISTRY PARTITION (all h): every height from 13,014,000 on is covere
s = Solver() s = Solver()
h = Int('h') h = Int('h')
s.add(h >= FORK_BLOCKING, Not(h >= REG2_START)) s.add(h >= FORK_BLOCKING, Not(h >= REG2_START))
check("S0d REGISTRY AT FORK (all h >= fork): the active registry in the blocking " check("S0d REGISTRY AT THE BOUND (all h >= 14,050,000): the active registry in the "
"era is the 9-key registry (fork 14,050,000 > rotation 13,600,000)", s) "modelled range is the 9-key registry (14,050,000 > rotation 13,600,000)", s)
# ============================================================================= # =============================================================================
# S1 -- THE INVARIANT (positive result). An anchor block at h >= fork, with the # S1 -- THE INVARIANT (positive result). An anchor block at h >= fork, with the
@ -198,7 +201,7 @@ s = Solver(); s.add(b.wf())
s.add(b.h >= FORK_BLOCKING, is_anchor(b.h), Not(b.ceil_set)) s.add(b.h >= FORK_BLOCKING, is_anchor(b.h), Not(b.ceil_set))
s.add(b.finalized()) s.add(b.finalized())
s.add(b.distinct_eligible_valid() <= 2) s.add(b.distinct_eligible_valid() <= 2)
check("S1 BLOCKING-QUORUM SAFETY: post-fork ANCHOR block finalized with <= 2 " check("S1 THRESHOLD SAFETY: post-fork ANCHOR block finalized with <= 2 "
"distinct valid eligible Falcon seals is IMPOSSIBLE (K=3 floor holds)", s) "distinct valid eligible Falcon seals is IMPOSSIBLE (K=3 floor holds)", s)
# same, with the ceiling engaged but at/above K: still no hole below 3 # same, with the ceiling engaged but at/above K: still no hole below 3
@ -338,21 +341,22 @@ s = Solver()
s.add(c >= 0, w == If(c <= 2, c, 2)) # planted cap 2 < K s.add(c >= 0, w == If(c <= 2, c, 2)) # planted cap 2 < K
s.add(c >= K_TARGET, w < K_TARGET) s.add(c >= K_TARGET, w < K_TARGET)
check("S7b NEG-CTRL: PLANT a cap of 2 < K -> a 3-seal certificate is written short " check("S7b NEG-CTRL: PLANT a cap of 2 < K -> a 3-seal certificate is written short "
"of the quorum (why maxSeals below the schedule K is refused at load)", s, "of K (why maxSeals below the schedule K is refused at load)", s,
expect_unsat=False, kind="NEG-CTRL") expect_unsat=False, kind="NEG-CTRL")
# ============================================================================= # =============================================================================
print("\n=== SUMMARY (anchor BLOCKING-QUORUM SAFETY) ===") print("\n=== SUMMARY (anchor THRESHOLD SAFETY, chain of 2026-08-15) ===")
allok = True allok = True
for name, tag, ok, kind in results: for name, tag, ok, kind in results:
print(f" {tag:9} [{kind}] {name}") print(f" {tag:9} [{kind}] {name}")
allok = allok and ok allok = allok and ok
print() print()
if allok: if allok:
print(" PROVED: with the blocking fork active (h >= 14,050,000) no anchor block") print(" PROVED: on the chain of 2026-08-15, at anchor heights >= 14,050,000 (the bound of this model; that")
print(" height changed no enforcement, correction of 2026-08-19) no anchor block")
print(" can be finalized with fewer than K=3 valid Falcon seals from DISTINCT") print(" can be finalized with fewer than K=3 valid Falcon seals from DISTINCT")
print(" signers of the registry active at that height (the 9-key registry, since") print(" signers of the registry active at that height (the 9-key registry, since")
print(" the fork lies above the 13,600,000 rotation), and non-anchor blocks") print(" the bound lies above the 13,600,000 rotation), and non-anchor blocks")
print(" require no seals at all (proved in both directions). The mandated") print(" require no seals at all (proved in both directions). The mandated")
print(" negative control FIRES: a planted rule permitting 2 seals finalizes an") print(" negative control FIRES: a planted rule permitting 2 seals finalizes an")
print(" anchor block with exactly 2 seals (SAT), so the K>=3 guard is load-") print(" anchor block with exactly 2 seals (SAT), so the K>=3 guard is load-")
@ -362,7 +366,8 @@ if allok:
print(" (and is the single designed path below 3); the maxSeals=5 write cap can") print(" (and is the single designed path below 3); the maxSeals=5 write cap can")
print(" never starve a certificate below K, and a planted cap of 2 does.") print(" never starve a certificate below K, and a planted cap of 2 does.")
print(" BOUNDARY: design combinatorics of the finalization predicate, not Besu") print(" BOUNDARY: design combinatorics of the finalization predicate, not Besu")
print(" bytecode, not the live chain; registries modelled as index sets.") print(" bytecode, not the live chain; registries modelled as index sets. Today the set has ten validators")
print(" (since 2026-09-11) and the minimum is 7 per scheme (since block 20,715,632): not modelled here.")
else: else:
print(" NOT fully established (see FAILED / unexpected result above).") print(" NOT fully established (see FAILED / unexpected result above).")
import sys import sys

View File

@ -411,7 +411,7 @@ if allok:
print(" blocks (N in {4,5,7}) -- and LIVE at the fault bound (N-f >= quorum, all") print(" blocks (N in {4,5,7}) -- and LIVE at the fault bound (N-f >= quorum, all")
print(" N). The N>=7 requirement is machine-checked: N=7 is the smallest set that") print(" N). The N>=7 requirement is machine-checked: N=7 is the smallest set that")
print(" is BOTH safe (f>=2) and live (N-2>=quorum) against 2 Falcon faults. It is") print(" is BOTH safe (f>=2) and live (N-2>=quorum) against 2 Falcon faults. It is")
print(" also the next BFT-optimal 3f+1 size, and unlike the current N=5 (zero") print(" also the next BFT-optimal 3f+1 size, and unlike N=5, the mainnet size when this model was written (2026-07-12; zero")
print(" single-fault margin) it leaves margin > 0 over quorum for a single fault. At") print(" single-fault margin) it leaves margin > 0 over quorum for a single fault. At")
print(" N in {4,5} two Falcon faults drop the correct set below quorum and the") print(" N in {4,5} two Falcon faults drop the correct set below quorum and the")
print(" post-fork chain STALLS (shown reachable). Negative controls FIRE: dropping") print(" post-fork chain STALLS (shown reachable). Negative controls FIRE: dropping")
@ -426,10 +426,13 @@ if allok:
print(" an empty eligible set (F5, with the fail-open trap firing as a control); and arms") print(" an empty eligible set (F5, with the fail-open trap firing as a control); and arms")
print(" at full margin under coverage k=N (FIX-ARM).") print(" at full margin under coverage k=N (FIX-ARM).")
print(" BOUNDARY: bounded per-N/per-k safety; unbounded liveness identity; DESIGN") print(" BOUNDARY: bounded per-N/per-k safety; unbounded liveness identity; DESIGN")
print(" combinatorics not Besu bytecode; the mainnet Falcon layer was log-only, not blocking,") print(" combinatorics not Besu bytecode; the mainnet per-block Falcon layer was log-only until block")
print(" until 2026-08-14 (blocking needs N>=7 + an ADDRESS-BOUND registry covering the set);") print(" 13,014,000 (2026-08-09), when the anchor rules were armed (blocking needs N>=7 + an ADDRESS-BOUND")
print(" since then a validator refuses an anchor block whose certificate holds fewer valid seals than") print(" registry covering the set): minimum 0 in the warm-up, then from block 13,034,000 a schedule step")
print(" the schedule requires (aere-node SPEC.md).") print(" to 3, held at an effective one by the emergency ceiling until 2026-08-14 (anchors of 2026-08-10 to")
print(" 2026-08-14 that carry fewer than three are named in the production client's two dated windows);")
print(" since 2026-08-14 a validator refuses an anchor block whose certificate holds fewer valid seals than")
print(" the schedule requires (aere-node SPEC.md; corrected 2026-10-27: this said log-only until 2026-08-14).")
else: else:
print(" NOT fully established (see FAILED / unexpected result above).") print(" NOT fully established (see FAILED / unexpected result above).")
import sys import sys

View File

@ -346,7 +346,7 @@ if allok:
print(" {7,9,11} under <= f equivocating faults of each kind (H1); a block missing EITHER") print(" {7,9,11} under <= f equivocating faults of each kind (H1); a block missing EITHER")
print(" quorum is REJECTED (H2a/H2b); and every hybrid-valid block is ECDSA-valid, so the") print(" quorum is REJECTED (H2a/H2b); and every hybrid-valid block is ECDSA-valid, so the")
print(" Falcon requirement can only SHRINK the committable set -> the hybrid chain is AT") print(" Falcon requirement can only SHRINK the committable set -> the hybrid chain is AT")
print(" LEAST AS SAFE as today's ECDSA-only chain, a Falcon bug can never make it worse") print(" LEAST AS SAFE as the ECDSA-only chain of 2026-07-18, when this model was written; a Falcon bug can never make it worse")
print(" (H3, the core migration guarantee). The cost is liveness: hybrid needs 2f+1") print(" (H3, the core migration guarantee). The cost is liveness: hybrid needs 2f+1")
print(" validators good in BOTH dimensions; at f+1 combined-bad it can stall where") print(" validators good in BOTH dimensions; at f+1 combined-bad it can stall where")
print(" ECDSA-only would not (H4). N=7 has ZERO two-fault margin; N=9/N=11 restore margin.") print(" ECDSA-only would not (H4). N=7 has ZERO two-fault margin; N=9/N=11 restore margin.")

View File

@ -16,7 +16,8 @@
# chain-stopping validity rule; min() makes that inexpressible by construction, # chain-stopping validity rule; min() makes that inexpressible by construction,
# and this file machine-checks it. # and this file machine-checks it.
# #
# Chain facts modelled as LAW (chain 2800, live values): # Chain facts modelled as LAW (chain 2800 as of 2026-08-15; corrected 2026-10-27: this line said 'live values'.
# Today the set has ten validators, since 2026-09-11, and the minimum is 7 per scheme since block 20,715,632):
# N = 9 validators, QBFT quorum = ceil(2N/3) = 6 # N = 9 validators, QBFT quorum = ceil(2N/3) = 6
# anchor heights: every 32 blocks from 13,014,000 # anchor heights: every 32 blocks from 13,014,000
# K schedule (height:K): 13,014,000 -> 0 ; 13,034,000 -> 3 # K schedule (height:K): 13,014,000 -> 0 ; 13,034,000 -> 3
@ -50,14 +51,14 @@ K_STEP_HEIGHT = 13_034_000 # schedule step: K goes 0 -> 3 here
K_WARMUP = 0 # schedule K on [13,014,000 .. 13,034,000) K_WARMUP = 0 # schedule K on [13,014,000 .. 13,034,000)
K_ARMED = 3 # schedule K from 13,034,000 on K_ARMED = 3 # schedule K from 13,034,000 on
MAX_SEALS = 5 # write cap aere.pq.anchor.maxSeals MAX_SEALS = 5 # write cap aere.pq.anchor.maxSeals
BLOCKING_FORK = 14_050_000 # no block finalizes without the Falcon quorum BLOCKING_FORK = 14_050_000 # the withdrawn 'blocking fork' height (2026-08-19: it changed no enforcement); the FORK-* checks model the retired rule from here
REG1_HEIGHT, REG1_KEYS = 13_014_000, 7 # registry window 1 REG1_HEIGHT, REG1_KEYS = 13_014_000, 7 # registry window 1
REG2_HEIGHT, REG2_KEYS = 13_600_000, 9 # registry window 2 (rotation) REG2_HEIGHT, REG2_KEYS = 13_600_000, 9 # registry window 2 (rotation)
N_VALIDATORS = 9 N_VALIDATORS = 9
QBFT_QUORUM = 6 # ceil(2*9/3) QBFT_QUORUM = 6 # ceil(2*9/3)
def k_schedule(h): def k_schedule(h):
"""Height-indexed schedule 13014000:0, 13034000:3 (the live orar).""" """Height-indexed schedule 13014000:0, 13034000:3 (the schedule of 2026-08-15; the published one has 14961456:6, 17102384:0, 17102416:6 and 20715632:7 too)."""
return If(h >= K_STEP_HEIGHT, K_ARMED, K_WARMUP) return If(h >= K_STEP_HEIGHT, K_ARMED, K_WARMUP)
def k_eff(h, ceil_set, ceiling): def k_eff(h, ceil_set, ceiling):
@ -97,7 +98,10 @@ def check(name, s, expect_unsat=True, kind="PROOF"):
return ok return ok
print("### AERE PQ anchor -- CEILING MONOTONICITY: minSealsCeiling can only LOWER K_eff,") print("### AERE PQ anchor -- CEILING MONOTONICITY: minSealsCeiling can only LOWER K_eff,")
print("### and K_eff <= maxSeals at every height (a conforming producer always suffices)\n") print("### and K_eff <= maxSeals at every height (a conforming producer always suffices)")
print("### Chain of 2026-08-15: N=9, K schedule 13014000:0, 13034000:3, registries of 7 then 9 keys. The FORK-* rows")
print("### model the per-block rule withdrawn on 2026-08-19 at 14,050,000, which changed no enforcement (dated")
print("### 2026-10-27; today: ten validators, minimum 7 per scheme since block 20,715,632).\n")
# ---- CONFIG sanity: the quorum arithmetic and the height lattice are coherent - # ---- CONFIG sanity: the quorum arithmetic and the height lattice are coherent -
s = Solver() s = Solver()
@ -115,7 +119,7 @@ check(f"CONFIG K-step height {K_STEP_HEIGHT:,} lands ON the 32-block anchor latt
s = Solver() s = Solver()
s.add(Int('ok') == (1 if (BLOCKING_FORK - ANCHOR_START) % ANCHOR_STEP == 0 else 0)) s.add(Int('ok') == (1 if (BLOCKING_FORK - ANCHOR_START) % ANCHOR_STEP == 0 else 0))
s.add(Int('ok') == 1) s.add(Int('ok') == 1)
check(f"CONFIG blocking fork {BLOCKING_FORK:,} lands ON the 32-block anchor lattice", s, check(f"CONFIG the withdrawn fork height {BLOCKING_FORK:,} lands ON the 32-block anchor lattice", s,
expect_unsat=False, kind="CONFIG") expect_unsat=False, kind="CONFIG")
# ============================================================================= # =============================================================================
@ -223,7 +227,7 @@ h, ceiling, ceil_set = Int('h'), Int('ceiling'), Bool('ceil_set')
s.add(is_anchor_height(h), h >= BLOCKING_FORK, ceiling >= 0) s.add(is_anchor_height(h), h >= BLOCKING_FORK, ceiling >= 0)
keff = k_eff(h, ceil_set, ceiling) keff = k_eff(h, ceil_set, ceiling)
s.add(Or(keff > MAX_SEALS, keff > reg_keys(h))) # negate: unsatisfiable threshold s.add(Or(keff > MAX_SEALS, keff > reg_keys(h))) # negate: unsatisfiable threshold
check(f"FORK-1 blocking era (h >= {BLOCKING_FORK:,}): NO ceiling makes the anchor " check(f"FORK-1 modelled range (h >= {BLOCKING_FORK:,}): NO ceiling makes the anchor "
"threshold unsatisfiable (K_eff <= maxSeals AND K_eff <= registry keys)", s) "threshold unsatisfiable (K_eff <= maxSeals AND K_eff <= registry keys)", s)
# ============================ NEGATIVE CONTROLS ============================== # ============================ NEGATIVE CONTROLS ==============================
@ -248,7 +252,7 @@ s = Solver()
h, ceiling = Int('h'), Int('ceiling') h, ceiling = Int('h'), Int('ceiling')
s.add(is_anchor_height(h), h >= BLOCKING_FORK, ceiling >= 0) s.add(is_anchor_height(h), h >= BLOCKING_FORK, ceiling >= 0)
s.add(k_eff_buggy_max(h, True, ceiling) > MAX_SEALS) s.add(k_eff_buggy_max(h, True, ceiling) > MAX_SEALS)
check(f"NEG-CTRL 2 PLANTED max() ceiling, blocking era: K_eff CAN exceed " check(f"NEG-CTRL 2 PLANTED max() ceiling, h >= {BLOCKING_FORK:,}: K_eff CAN exceed "
f"maxSeals={MAX_SEALS} (a settable value becomes a chain-stop switch)", s, f"maxSeals={MAX_SEALS} (a settable value becomes a chain-stop switch)", s,
expect_unsat=False, kind="NEG-CTRL") expect_unsat=False, kind="NEG-CTRL")
@ -292,11 +296,11 @@ if allok:
print(" threshold -- K_eff = min(K_schedule, ceiling), K_eff <= K_schedule for every") print(" threshold -- K_eff = min(K_schedule, ceiling), K_eff <= K_schedule for every")
print(" height and every ceiling (a raising case is UNSAT, i.e. inexpressible), a") print(" height and every ceiling (a raising case is UNSAT, i.e. inexpressible), a")
print(" ceiling at/above the schedule is a no-op, and K_eff <= maxSeals=5 and") print(" ceiling at/above the schedule is a no-op, and K_eff <= maxSeals=5 and")
print(" K_eff <= registry keys (7 then 9) at every height including the blocking era") print(" K_eff <= registry keys (7 then 9, the registries of 2026-08-15) at every height,")
print(" from 14,050,000 -- so a conforming producer (heard >= K_eff) always writes") print(" 14,050,000 and above included -- so a conforming producer (heard >= K_eff) always writes")
print(" min(heard, maxSeals) >= K_eff and the valve can never become a halt switch.") print(" min(heard, maxSeals) >= K_eff and the valve can never become a halt switch.")
print(" Negative controls FIRE: the planted max() variant raises K_eff (SAT), pushes") print(" Negative controls FIRE: the planted max() variant raises K_eff (SAT), pushes")
print(" it past the write cap in the blocking era (SAT, a chain-stop), a planted") print(" it past the write cap at h >= 14,050,000 (SAT, a chain-stop), a planted")
print(" under-cap without the loader guard yields only rejected certificates (SAT,") print(" under-cap without the loader guard yields only rejected certificates (SAT,")
print(" why AERE-PQC-ANCHOR-CONF-01 exists), and the valve itself is non-vacuous (SAT).") print(" why AERE-PQC-ANCHOR-CONF-01 exists), and the valve itself is non-vacuous (SAT).")
print(" BOUNDARY: design arithmetic of the threshold pipeline, not Besu bytecode;") print(" BOUNDARY: design arithmetic of the threshold pipeline, not Besu bytecode;")

View File

@ -66,7 +66,7 @@ ANCHOR_STEP = 32
K_STEP_HEIGHT = 13_034_000 # K schedule: 13014000:0, 13034000:3 K_STEP_HEIGHT = 13_034_000 # K schedule: 13014000:0, 13034000:3
K_MIN_SEALS = 3 K_MIN_SEALS = 3
MAX_SEALS = 5 # write cap MAX_SEALS = 5 # write cap
FORK_BLOCKING = 14_050_000 # no finality without the Falcon quorum from here FORK_BLOCKING = 14_050_000 # the withdrawn 'blocking fork' height (2026-08-19: it changed no enforcement), kept as a modelled bound
REG1_HEIGHT = 13_014_000 REG1_HEIGHT = 13_014_000
REG1_KEYS = 7 REG1_KEYS = 7
REG2_HEIGHT = 13_600_000 REG2_HEIGHT = 13_600_000
@ -123,7 +123,9 @@ def check(name, s, expect_unsat=True, kind="PROOF"):
return ok return ok
print("### AERE PQ anchor -- REGISTRY ROTATION COVERAGE" print("### AERE PQ anchor -- REGISTRY ROTATION COVERAGE"
" (R1@13,014,000 x7 keys, R2@13,600,000 x9 keys)\n") " (R1@13,014,000 x7 keys, R2@13,600,000 x9 keys: the registries of 2026-08-15)")
print("### (dated 2026-10-27: later epochs, ten keys from 2026-09-11 and post-quantum ids from block 20,836,228, are not")
print("### modelled here; 14,050,000 below is the withdrawn 'blocking fork' height, which changed no enforcement)\n")
# ============================================================================= # =============================================================================
# C1a NO GAP: every anchor height >= 13,014,000 has at least one registry # C1a NO GAP: every anchor height >= 13,014,000 has at least one registry
@ -178,7 +180,7 @@ check("boundary: K-step height 13,034,000 IS anchor-aligned "
s = Solver() s = Solver()
k, r = Int('k'), Int('r') k, r = Int('k'), Int('r')
s.add(FORK_BLOCKING == ANCHOR0 + ANCHOR_STEP * k + r, r >= 1, r <= 31) s.add(FORK_BLOCKING == ANCHOR0 + ANCHOR_STEP * k + r, r >= 1, r <= 31)
check("boundary: blocking fork 14,050,000 IS anchor-aligned " check("boundary: the withdrawn fork height 14,050,000 IS anchor-aligned "
"(remainder 1..31 is infeasible)", s) "(remainder 1..31 is infeasible)", s)
# ============================================================================= # =============================================================================
@ -223,7 +225,7 @@ h = Int('h')
add_anchor(s, h, 'k') add_anchor(s, h, 'k')
s.add(h >= FORK_BLOCKING) s.add(h >= FORK_BLOCKING)
s.add(Or(Not(active_r2(h)), active_r1(h))) # negate: not-R2 or still-R1 s.add(Or(Not(active_r2(h)), active_r1(h))) # negate: not-R2 or still-R1
check("blocking era: every anchor >= 14,050,000 is covered by the 9-key R2 " check("modelled range: every anchor >= 14,050,000 is covered by the 9-key R2 "
"and only by it", s) "and only by it", s)
# the active registry at any blocking-era anchor can supply the Falcon quorum # the active registry at any blocking-era anchor can supply the Falcon quorum
@ -232,8 +234,8 @@ h = Int('h')
add_anchor(s, h, 'k') add_anchor(s, h, 'k')
s.add(h >= FORK_BLOCKING) s.add(h >= FORK_BLOCKING)
s.add(reg_size(lookup(h)) < QBFT_QUORUM) # negate: registry too small s.add(reg_size(lookup(h)) < QBFT_QUORUM) # negate: registry too small
check("blocking era: active registry size (9) >= Falcon quorum (6) at every " check("modelled range: active registry size (9) >= Falcon quorum (6) at every "
"blocking-era anchor", s) "anchor >= 14,050,000", s)
# minSealsCeiling only LOWERS K; effective K never exceeds K=3, the write cap # minSealsCeiling only LOWERS K; effective K never exceeds K=3, the write cap
# maxSeals=5, or the size of the registry active at any covered anchor # maxSeals=5, or the size of the registry active at any covered anchor
@ -308,9 +310,9 @@ if allok:
print(" active-until-next semantics) covers every anchor height >= 13,014,000") print(" active-until-next semantics) covers every anchor height >= 13,014,000")
print(" with EXACTLY one registry, unbounded in height: no gap, no overlap.") print(" with EXACTLY one registry, unbounded in height: no gap, no overlap.")
print(" The rotation boundary 13,600,000 is not anchor-aligned and interval") print(" The rotation boundary 13,600,000 is not anchor-aligned and interval")
print(" coverage loses no anchor; the K-step and blocking-fork heights are") print(" coverage loses no anchor; the K-step height and the withdrawn fork height are")
print(" anchor-aligned. Anchor-keyed validation is replay-stable and rejects") print(" anchor-aligned. Anchor-keyed validation is replay-stable and rejects")
print(" R2-only keys on R1-era anchors; the blocking era >= 14,050,000 is") print(" R2-only keys on R1-era anchors; with the registries of 2026-08-15, every anchor >= 14,050,000 is")
print(" served entirely by the 9-key registry, which always covers the Falcon") print(" served entirely by the 9-key registry, which always covers the Falcon")
print(" quorum (6) and the effective K (<= 3 <= maxSeals 5). All four negative") print(" quorum (6) and the effective K (<= 3 <= maxSeals 5). All four negative")
print(" controls FIRE: a gapped schedule orphans an anchor, a forgotten") print(" controls FIRE: a gapped schedule orphans an anchor, a forgotten")

View File

@ -27,7 +27,7 @@ CONSENSUS_MODELS = [
("QBFT/IBFT 2.0 SAFETY (agreement)", "qbft_safety_smt.py"), ("QBFT/IBFT 2.0 SAFETY (agreement)", "qbft_safety_smt.py"),
("Falcon LOG-ONLY no-op", "falcon_logonly_noop_smt.py"), ("Falcon LOG-ONLY no-op", "falcon_logonly_noop_smt.py"),
("Falcon BLOCKING safety/liveness/N>=7", "falcon_blocking_smt.py"), ("Falcon BLOCKING safety/liveness/N>=7", "falcon_blocking_smt.py"),
("Anchor THRESHOLD safety (K=3 of 9 on anchor blocks since 2026-08-14, registry rotation)", "anchor_blocking_quorum_smt.py"), ("Anchor THRESHOLD safety (the chain of 2026-08-15: K=3 of 9 on anchor blocks, registry rotation; 7 of 10 since block 20,715,632)", "anchor_blocking_quorum_smt.py"),
("PQC ACTIVATION transition safety (log-only->blocking + contract-anchored registry)", "qbft_pqc_activation_smt.py"), ("PQC ACTIVATION transition safety (log-only->blocking + contract-anchored registry)", "qbft_pqc_activation_smt.py"),
("QBFT LIVENESS (partial synchrony)", "qbft_liveness_smt.py"), ("QBFT LIVENESS (partial synchrony)", "qbft_liveness_smt.py"),
("QBFT explicit-Prepare counting (2026-07-14 2nd-client bug+fix)", "qbft_prepare_counting_smt.py"), ("QBFT explicit-Prepare counting (2026-07-14 2nd-client bug+fix)", "qbft_prepare_counting_smt.py"),