aere-research/formal-consensus/threshold_account_smt.py
Aere Network 6cb0140fae Republished from a clean root: the compiled artifact is gone from history, and the local line of work joins the sanitized public line
The public history carried kat/__pycache__/mlkem768_reference.cpython-314.pyc,
a compiled Python artifact embedding the operator's absolute local path. Text
secret scanners do not read compiled binaries, which is exactly how it slipped
through, and removing it from the tip would have left it reachable through the
old root commits. So this repository is republished from a single clean root.

This root also carries, from the previously unpublished line of work:
- corrected LICENSE year, LICENSING.md, VERIFY-POLICY.md, and
  CITATIONS-UNRESOLVED.md remeasured 2026-08-11 (101 paths, README aligned)
- O-018: run_consensus_verification.py ran 19 of 29 models and reported PASS;
  it now runs all 29, and computemarket_smt.py gains resolveByTimeout /
  reclaimUnsettled cases plus a negative control
- O-006: the word 'audited' removed from next to Bouncy Castle, twice, after a
  concurrent edit resurrected it
- O-014: prior art named and dated - Algorand's native falcon_verify shipped
  about ten months before AERE's precompiles; the primacy claim is withdrawn
  where it was implied
- bench/ scripts parametrized so they actually run for an outsider (the
  earlier textual sanitization left $STAGING unexpanded inside Python strings)
- AIP-2/AIP-3 errata with measured figures, spec remeasurements at 2026-08-01,
  and the spec-zk-stack retractions (owner is an operational key, not the
  Foundation; 'maximally sound' withdrawn; aggregator V1 deprecated)
The redacted bench-host environment files from the sanitized line are kept
exactly as published; the unredacted local variants are not carried.
2026-08-15 13:52:14 +03:00

107 lines
5.1 KiB
Python

#!/usr/bin/env python3
# SMT proof (z3) of the DISTINCT-KEY THRESHOLD property for AereThresholdAccount +
# AereThresholdPQCRegistry, formalising the duplicate-key finding fixed 2026-07-15.
#
# THE BUG: authorization counts distinct signers by member INDEX (the `seen` bitmask
# in _countMem / the strict DuplicateMember check). Member indices are 0..n-1, so they
# are ALWAYS distinct -- the index dedup can never fail on a real committee. Distinctness
# of the actual signing KEYS was never checked at committee registration, so the same
# public key could occupy two indices and one keyholder could fill multiple "distinct
# member" slots and reach the threshold t alone, collapsing the t-of-n guarantee.
#
# THE FIX: reject duplicate committee keys at the one place a committee is set
# (initialize / registerCommittee). Modelled here as Distinct(key).
#
# MODEL: key[i] = the id of the KEYHOLDER controlling slot i. A single keyholder h
# occupies slot i iff key[i] == h; the number of slots it can validly sign for is
# count(i: key[i] == h). "One keyholder reaches threshold" := exists h with count >= t.
#
# METHOD: assert the property's NEGATION; UNSAT => the property holds.
from z3 import Int, Solver, Sum, If, Distinct, sat, unsat
results = []
def check(name, s, expect_unsat=True, kind="PROOF"):
r = s.check()
ok = (r == unsat) if expect_unsat else (r == sat)
tag = "PROVED" if (ok and expect_unsat) else ("CEX-FOUND" if (ok and not expect_unsat) else "FAILED")
results.append((name, tag, ok, kind))
print(f"[{tag}] ({kind}) {name}: z3={r}")
if r == sat and not expect_unsat:
m = s.model()
print(f" witness: {m}")
return ok
def keys(N):
return [Int(f"key_{i}") for i in range(N)]
def count_for(key, h):
return Sum([If(key[i] == h, 1, 0) for i in range(len(key))])
print("### AereThresholdAccount / PQC registry -- DISTINCT-KEY THRESHOLD (dup-key finding 2026-07-15)\n")
print(" Distinct signers are counted by member INDEX (0..n-1, always distinct), so the")
print(" index dedup never fires on a real committee. The guarantee that matters is that")
print(" the KEYS are distinct. Proved below; the pre-fix (no key-distinctness) is CEX'd.\n")
print("=" * 74)
print("P1 distinct committee keys => every keyholder fills at most 1 slot, so reaching")
print(" threshold t>=2 requires >= t DISTINCT keyholders (the t-of-n guarantee holds)")
print("=" * 74)
for (N, T) in [(5, 2), (5, 3), (9, 5), (7, 4), (21, 11)]:
s = Solver()
key = keys(N)
h = Int("h")
s.add(Distinct(key)) # THE FIX: committee keys are pairwise distinct
s.add(count_for(key, h) >= T) # NEGATION: some single keyholder h fills >= t slots
check(f"N={N} t={T}: distinct keys AND one keyholder fills >= t is impossible", s, expect_unsat=True)
print("\n" + "=" * 74)
print("P2 NEG-CONTROL: WITHOUT the distinct-key check, one keyholder CAN reach the")
print(" threshold alone (the exact pre-fix bug: a committee like [A,A,A,B,C], t=3)")
print("=" * 74)
for (N, T) in [(5, 3), (9, 5)]:
s = Solver()
key = keys(N)
h = Int("h")
# No Distinct(key): a keyholder may occupy multiple indices (duplicate keys allowed).
s.add(count_for(key, h) >= T)
check(f"N={N} t={T}: no key-distinctness => one keyholder filling >= t is POSSIBLE",
s, expect_unsat=False, kind="NEG-CONTROL")
print("\n" + "=" * 74)
print("P3 index-distinctness ALONE does not imply key-distinctness (why the seen-bitmask")
print(" dedup was insufficient): indices are trivially distinct, keys can still repeat")
print("=" * 74)
for (N, T) in [(5, 3)]:
s = Solver()
key = keys(N)
h = Int("h")
idx = [Int(f"idx_{i}") for i in range(N)]
s.add(Distinct(idx)) # the index dedup the contract DOES have
s.add([idx[i] == i for i in range(N)]) # indices are 0..n-1 (always satisfiable)
s.add(count_for(key, h) >= T) # yet one keyholder still fills >= t slots
check(f"N={N} t={T}: indices distinct yet one keyholder fills >= t (key dedup needed)",
s, expect_unsat=False, kind="NEG-CONTROL")
print("\n=== SUMMARY (distinct-key threshold, AereThresholdAccount / PQC registry) ===")
allok = True
for name, tag, ok, kind in results:
print(f" {tag:9} [{kind}] {name}")
allok = allok and ok
print()
if allok:
print(" ESTABLISHED: the 2026-07-15 fix (reject duplicate committee keys at registration)")
print(" is exactly what makes t-of-n sound. P1 PROVES that with distinct keys no single")
print(" keyholder can reach threshold t>=2, so t signatures require t distinct parties.")
print(" P2/P3 are load-bearing neg-controls: without key-distinctness (index dedup alone),")
print(" one keyholder reaches the threshold alone -- the collapsed-guarantee bug that was")
print(" found by manual review and fixed + redeployed (factory V2, PQC registry V2).")
print(" BOUNDARY: a combinatorial model of the counting logic, not the Solidity bytecode;")
print(" complements the on-chain proof that the live V2 reverts DuplicatePubKey.")
else:
print(" NOT fully established (see FAILED above).")
import sys
sys.exit(0 if allok else 1)