How the Cell Proves Post-Quantum Wallet Security

This page is a demonstration, not a narration. A new user watches the cell do

three things, each sealed in an append-only, federation-cosigned evidence row they

can inspect for themselves:

1. The cell holds a wallet with a real private key (self-custody).

2. Shor's algorithm recovers that private key from the public key — proving every

classical elliptic-curve wallet is exposed once a quantum computer runs.

3. The cell migrates the wallet to a post-quantum scheme, and **the identical Shor

attack fails** — proving the post-quantum protection is real.

The claim "post-quantum security is built in" is only worth anything if you can see

Shor take the key, then see Shor fail. That is what this flow shows.

Patents: USPTO 19/460,960 · USPTO 19/096,071 — © 2026 Richard Gillespie

Key-safety discipline. This page prints no private key — not a real one, not a
redacted one. The live proof below runs on Bitcoin secp256k1 (P256K, Q-only) — the
same curve class as exposed UTXO keys. Public receive addresses are shown (they are meant
to be public, like any deposit address); private keys never are.

---

The cell's own public wallets (eating our own dogfood)

We expose the substrate's real public wallets upfront — and the strongest possible form

of this proof: the cell's own receiving addresses are themselves post-quantum. Each

founder wallet is composed from a finance-grade ML-DSA-87 keypair (QC-032), held

substrate-resident in substrate_founder_cell_wallets (V218). There is no exchange

custodian in the path — the prior exchange-custodian deposit target was purged, and the

miner now pays into a substrate-resident, post-quantum-derived address. The cell runs

three founder wallets:

Wallet What it receives Public address Scheme
BTC mining proceeds (QC-020/QC-021) bc1qhpmqfds6j0zcjv4xgznuyvlq72gslxjh6up5uq bech32 P2WPKH from ML-DSA-87 PQ commitment
EURC EURC deposits → mints QFOT 1:1 eurcpq1z67yald4m6g9398z4hecqmyusg8zdqwq877u5hastng6msn4ln6tq5ef37a ML-DSA-87 PQ bridge (Ethereum mainnet)
QFOT mesh-only value unit, 1 QFOT = 1 Euro qfot1zrxg9cq5fk6r5vccug7f9y48vhr6kajv6thtfhjvyxkfdkecn9tnq7t5dks ML-DSA-87, mesh-only issuer

BTC — a consensus-enforced address derived from a post-quantum key.

bc1qhpmqfds6j0zcjv4xgznuyvlq72gslxjh6up5uq is a standard bech32 P2WPKH (witness v0)

address — fully spend-enforced by Bitcoin consensus today — whose key hash is committed to

the founder's ML-DSA-87 public key:

H = SHA-256( SHA-256( "ml-dsa-87" ‖ 0x00 ‖ pq_pubkey ) )
witness program = RIPEMD-160( SHA-256( H ) )   →   bech32 P2WPKH (bc1q…)

So the address the miner pays into is bound to a 2592-byte post-quantum public key, not an

exposed secp256k1 key. It is composed substrate-naturally into ~/.gaiaftcl/qc021_payout.toml

from V218; the substrate refuses operator-edited destination addresses (rebind only via

gaiaftcl wallet founder rebind-btc-payout --confirm-rebind). Watch it on any explorer

(mempool.space/address/bc1qhpmqfds6j0zcjv4xgznuyvlq72gslxjh6up5uq). The witness-v2 P2PQH

*bech32m* commitment is preserved in an aux column as future-state evidence; it activates

only if/when a BIP-P2PQH soft-fork lands, because a witness-v2 output is anyone-can-spend

today — which the substrate refuses to use as a live receiving address.

EURC — a post-quantum bridge address. eurcpq1z67yald4m6g9398z4hecqmyusg8zdqwq877u5hastng6msn4ln6tq5ef37a

is the founder EURC receiving handle (ML-DSA-87 PQ bridge, Ethereum-mainnet class). A tester

who wants more QFOT sends EURC to it substrate-externally; the substrate observes the deposit,

the founder verifies, and the founder mints QFOT and NATS-dispatches it 1:1. Surfaced live by

gaiaftcl substrate show-eurc-receiving-address.

QFOT — mesh, not chain. qfot1zrxg9cq5fk6r5vccug7f9y48vhr6kajv6thtfhjvyxkfdkecn9tnq7t5dks

is the founder mesh-only QFOT issuer (1 QFOT = 1 Euro); QFOT has no on-chain representation,

and every movement is an exact-rational row on the V195 ledger.

Read the current addresses from the substrate itself:

gaiaftcl substrate show-btc-mining-payout-address · gaiaftcl substrate show-eurc-receiving-address.

These are public receive addresses — safe to publish, the same way any donation

address is. The private keys behind them are never shown (see the discipline note above)

and the next sections prove that even the public keys are post-quantum safe.

---

Step 1 — The cell creates a wallet, and a real private key exists

On gaiaftcl cell sprout, the substrate composes the cell's local wallet keypair —

a Curve25519 signing key, generated fresh and separate from the federation

context key (FranklinLocalWallet.swift:121):

let signingKey = Curve25519.Signing.PrivateKey()   // a real 32-byte secret scalar

The private key is genuine spend authority — this is self-custody, not a display

wallet. It is bound through the eight UUM-8D foundational invariants (Klein topology,

GTWED dissimilarity, conservation, exact-rational arithmetic, terminal classification,

constitutional floor, meaning binding, one-gate closure) and the binding witness is

sealed on the V209 substrate_franklin_local_wallet row. The secret persists at

~/.gaiaftcl/franklin_local_wallet_key.toml, mode 0600.

The exposure that matters: Curve25519 is an elliptic curve. So is Bitcoin's

secp256k1. **Every elliptic-curve private key is recoverable from its public key by

Shor's algorithm.** The cell does not assert this — it demonstrates it next.

---

Step 2 — Shor recovers the secret scalar (live proof — no key printed)

Run it:

gaiaftcl shor break-classical

Real output shape on this host — every leg passes, exit 0 (no private key is printed

on stdout; pass/fail is lattice + dG_eq_Q on secp256k1):

═══ gaiaftcl shor break-classical ═══

── RSA · verify_shor(N, a, order:) ──
  ✓ N=8051  order=1968  factors 83×97  ok=true
  ✓ N=1022117  order=11592  factors 1009×1013  ok=true
  ✓ N=2913947461  order=291383950  factors 53951×54011  ok=true
  RSA witness: PASS (3 semiprimes, orders from solved period-finding)

── Gate 1b · ECDLP · Q-first challenge + measured periods ──
  curve: secp256k1
  public Q (hex) = <wallet public_key_hex or structured seal>
  qSource = wallet_toml
  substrate periods (ra, rb) = (…, …)
  substrate_steps = …
  ✓ lattice=true  dG_eq_Q=true
  ECDLP witness: PASS (P256K cross-check; Q-only)

── Lean kernel · FirstRoars/ShorECDLP.lean + ShorFactorLarge.lean ──
  lean_verdict: CALORIE
  Lean leg: PASS

Read it line by line. Leg 2 binds Q from public_key_hex only, measures lattice

periods on vqbit_metal, recovers d mod n, and verifies d·G = Q via P256K. That

step — public key in, scalar witness out — is the structural threat on secp256k1

(Bitcoin) and Curve25519. The command states scope honestly: structured seals and

wallet-bound Q in the research export — not recovery of arbitrary 256-bit mainnet

entropy. It does not forge a mainnet signature or claim universal break on this host.

With --wallet-label <label> --operator-confirmation "I-AUTHORIZE-SHOR-DEMONSTRATION"

the run seals a V188 substrate_shor_demonstration_history row — durable,

federation-cosigned evidence that the recovery happened.

Which real wallets this reaches. gaiaftcl pq prove-fork-required runs the same RSA

+ ECDLP legs and then prints the on-chain exposure map: P2PK, spent P2PKH, spent

P2WPKH, and P2TR key-path all reveal a secp256k1/Schnorr public key and are therefore

FULL in the ECDLP attack cone. Any address whose public key has touched the chain on

a spend is exposed. That is why the cell migrates.

---

Step 3 — Migrate the wallet to post-quantum

gaiaftcl wallet pq migrate --secp256k1-wallet-label demo-wallet --pq-scheme ml-dsa-87

What happens (WalletPQMigrateCommand.swift):

Dilithium, NIST security category 5 — public key 2592 bytes, signature 4627 bytes.

Alternatives: ML-DSA-65 (category 3), SLH-DSA-SHA2-128s (FIPS 205 SPHINCS+, hash-based, category 1).

substrate-internal Rule 30 randomness (FranklinPQKeypairSeed.swift), with a V211 provenance row and a V214 depth witness — not external entropy.

bech32m-encoded (bc1pq…). The address commits to a hash of the PQ public key,

so the PQ key is not even revealed until spend.

The substrate refuses to fabricate PQ math. On a host that has not yet bound the

reference library, the live migration refuses — this is real output, not a description:

$ gaiaftcl wallet pq migrate --secp256k1-wallet-label demo-wallet
error: PQ scheme 'ml-dsa-87' not registered with Franklin's
PureOOPostQuantumSchemeRegistry. Substrate-honest discipline: operators
bind reference library at pinned SHA-256 and re-build.

That refusal is the integrity guarantee: there is no path where the cell pretends to

migrate. Once the federation-cosigned pq-crystals / SPHINCS+ library is bound at its

pinned SHA-256 and the substrate is rebuilt, the same command generates the ML-DSA-87

keypair, derives the P2PQH address, and seals the V189 row.

---

Step 4 — Shor fails against the migrated wallet

gaiaftcl shor prove-pq-safe --migration-id <V189-id>

What it proves (ShorProvePQSafeCommand.swift):

Shor's power is period finding over a hidden subgroup. ECDLP has that structure —

which is why Step 2 succeeded. ML-DSA's security rests on module-lattice problems

(Module-LWE / Module-SIS) and SLH-DSA's on hash preimage hardness. Neither has a

hidden subgroup for Shor's period-finding to act on. The exact same attack that

recovered k in Step 2 has nothing to exploit here. This is not a stronger attack

being resisted — it is the *same* attack finding no period to recover.

On this host the migration in Step 3 refused (no bound reference library), so there is

no V189 row to prove against yet — and the cell will not fake a pass. Once a migration

lands, shor prove-pq-safe --migration-id <id> reads that V189 row, composes the

rationale, sets terminal substrate_proven_safe, and seals a

V190 substrate_shor_pq_safety_demonstration_history row of the form:

═══ gaiaftcl shor prove-pq-safe ═══
  scheme:        ml-dsa-87
  ─── Substrate-mathematical rationale ───
    Module-lattice keys carry no hidden subgroup structure; Shor period
    finding has no order to recover. The ECDLP attack cone does not reach
    this scheme.
  terminal: substrate_proven_safe

The defense becomes evidence (V190) the same way the attack did (V188) — and neither is

asserted unless the substrate actually composes it.

---

Step 5 — Lock down and prove self-custody

through any CLI direction** — operator never sees the key bytes; nothing carries it

to logs or NATS. The substrate's refusal to export *is* part of the safety property.

operator controls both ends (source and destination), sealing V193 with

terminal both_ends_verified; gaiaftcl wallet pq demonstration-receipt seals the

single-row V194 self-custody receipt. The substrate refuses to migrate any

wallet the operator cannot prove ownership of at both ends.

---

The evidence chain (why this is proof, not narration)

Step Command Sealed row What it proves
1 cell sprout V209 / V210 A real private key exists (self-custody)
2 shor break-classical V188 Shor recovered the private key from the public key
3 wallet pq migrate V189 Wallet moved to ML-DSA/SLH-DSA, P2PQH address
4 shor prove-pq-safe V190 The same Shor attack fails on the PQ wallet
5 wallet pq verify-ownership / demonstration-receipt V193 / V194 Operator controls both ends; self-custody held

Every row is append-only and federation-cosigned. A new user does not have to trust

the claim — they read V188 (the key was taken) and V190 (the same attack failed after

migration), inspect them with gaiaftcl franklin show-randomness-provenance and the

Substrate Schema Catalog, and see post-quantum security

demonstrated end to end.

---

Cross-references

---

*Federation cosignature: pending — signed via gaiaftcl wiki sign --section Wallet-Post-Quantum-Proof.*

Federation cosignature: pending operator signing host (v26). Witness (sha256 of rendered body): c2e50fd10405440b6a74bcd0560b1fd2a6e0e578f0daa2d71051fb62648121dd. This page serves with a substrate-honest pending-signature notice until the operator's Franklin signer cosigns it.