# Proof of Quantum Solvency

**Specification, version 1.0**
**Status:** Published for public comment. Stable: an implementation that conforms today will conform to any 1.x revision.
**Date:** 22 September 2026
**Maintainer:** LatticeScan (LSCC LLC), hello@latticescan.com
**Licence:** This specification is released under CC BY 4.0. Anyone may implement it, extend it, or assess against it, with attribution.

---

## 0. Why this document exists

Proof of Reserves shows that the coins exist. It does not show whether the coins will still be their owner's once a cryptographically relevant quantum computer can recover a private key from a public one. On a blockchain there is no key rotation and no revocation, so a public key that has been revealed is a permanent target and cannot be un-revealed.

Several parties now assert facts about this risk: exchanges say their reserves are safe, custodians say client holdings are hash-protected, ETF prospectuses say the risk depends on the custodian's key practices. None of those assertions can be checked by the party making them, because a holder cannot credibly attest to itself, and no attestation criteria exist for an auditor to apply.

This specification defines, in terms precise enough for an independent party to compute and a third party to reproduce from public data:

1. what it means for a balance to be **quantum-exposed** (Section 3);
2. how to measure the **quantum solvency** of a set of addresses (Section 4);
3. how to rank exposure by **practical risk** (Section 5);
4. how to check a holder's **published key policy** (Section 6);
5. how a result is **signed, anchored, and verified** so that nobody has to trust the assessor or the holder (Sections 7 to 9);
6. what an assessor must **disclose** about coverage, sources and limitations (Section 10).

The normative words MUST, MUST NOT, SHOULD and MAY are used as in RFC 2119.

## 1. Scope

This version covers Bitcoin (mainnet, native units of BTC) and Ethereum (mainnet, native units of ETH, externally-owned and contract accounts). Tokens, Layer 2 networks, other chains and extended public keys (xpub, zpub) are out of scope for 1.0 and reserved for later versions. Nothing in this specification requires access to a holder's systems, keys or private records; every input is public chain data plus the holder's own published address set and policy.

## 2. Definitions

- **Holder.** The party whose balances are measured: an exchange, custodian, fund, treasury, protocol or sovereign.
- **Address set.** The list of addresses being measured. For a Proof of Quantum Solvency it MUST come from the holder's own publication (a proof-of-reserves file, a published catalogue, a signed statement), never from third-party wallet labels or clustering heuristics.
- **Assessor.** The independent party that computes and signs the result. An assessor MUST NOT hold custody of, or a financial interest in, the balances it measures.
- **Snapshot.** One measurement of an address set at one point in time, read from public chain data.
- **Cryptographically relevant quantum computer (CRQC).** A quantum computer able to recover a secp256k1 private key from its public key. None exists at the date of this version; see Section 10.

## 3. Exposure

A balance is **exposed** when the public key that controls it is already recoverable from public chain data. Exposure is a property of the key, not a prediction about hardware.

### 3.1 Bitcoin

Classify each address by its output type, then apply the rule:

| Output type | Address form | Exposure rule |
|---|---|---|
| Pay-to-public-key (P2PK), bare multisig | No standard address; legacy base58 form for known cases | **Exposed.** The public key is in the output. |
| Pay-to-taproot (P2TR) | `bc1p…` | **Exposed.** The x-only public key is placed directly in the output (BIP-341), whether or not the output has been spent. |
| Pay-to-public-key-hash (P2PKH) | `1…` | **Exposed if the address has ever been spent from** (the key is published in the spending input). Otherwise **hash-protected**. |
| Pay-to-witness-public-key-hash (P2WPKH) | `bc1q…`, 42 characters | Same rule as P2PKH. |
| Pay-to-script-hash (P2SH) | `3…` | **Exposed if the address has ever been spent from.** Exposure of an unspent P2SH depends on the redeem script; an assessor MUST treat a spent P2SH as exposed and MUST disclose that redeem-script contents were not evaluated. |
| Pay-to-witness-script-hash (P2WSH) | `bc1q…`, 62 characters | Same rule as P2SH. |

"Spent from" means at least one transaction input references an output paid to the address. An address with any spent output is exposed for all of its balance, including outputs funded after the spend, because the key is the same.

**Hash-protected** means only a hash of the key is on-chain and the address has never been spent from. It is not exposed at rest. It becomes exposed at its first spend, and during the interval between broadcast and confirmation the key is visible in the mempool; an assessor SHOULD state this "on-spend" window.

### 3.2 Ethereum

| Account type | Detection | Exposure rule |
|---|---|---|
| Externally-owned account (EOA) | `eth_getCode` returns `0x` | **Exposed if the account has sent at least one transaction** (`eth_getTransactionCount` > 0): the public key is recoverable from any ECDSA signature. Otherwise **not exposed**. |
| Delegated EOA (EIP-7702) | Code begins `0xef0100` | Treated as an EOA. |
| Contract account | Any other code | **Not classified.** Exposure depends on the signer(s) that control the contract, which are outside the account. An assessor MUST report contract balances separately and MUST NOT count them as protected. |

### 3.3 Balances

Balance is the confirmed on-chain balance at the snapshot, in native units, excluding unconfirmed transactions. Bitcoin balances MUST be computed in satoshis and Ethereum balances in wei before conversion, so that comparisons (Section 6) are exact.

## 4. Quantum solvency

For an address set S on one chain, at one snapshot:

- **Total** = sum of balances of all readable addresses in S.
- **Exposed balance** = sum of balances of exposed addresses in S.
- **Exposed share** = Exposed balance ÷ Total, as a percentage.
- **Quantum solvency** = 100% − Exposed share.

Quantum solvency is the share of the holder's on-chain value that is not behind a revealed key. It is balance-weighted: one large exposed key matters more than many dust addresses. Chains MUST NOT be summed with each other; report each unit separately.

Unreadable addresses (Section 10.2) MUST be excluded from Total and reported by count. They MUST NOT be assumed safe.

## 5. Practical risk

Exposure is binary, but an attacker must recover each key separately and the cost scales per key. A total spread across many small keys is a weaker target than the same total behind one key. An assessor MUST therefore report, in addition to the exposed share:

**5.1 Tiers.** Each exposed address is assigned a tier by the balance behind it:

| Tier | Bitcoin | Ethereum |
|---|---|---|
| High concentration | ≥ 100 BTC | ≥ 1,000 ETH |
| Material | ≥ 10 BTC | ≥ 100 ETH |
| Moderate | ≥ 1 BTC | ≥ 10 ETH |
| Low | below 1 BTC | below 10 ETH |

**5.2 Concentration.** The number of exposed keys at or above the Material floor, the balance they hold in total, and the balance of the single largest exposed key.

The tiers are a ranking, not an estimate of when any key could be broken. They exist so that the result answers the question critics of headline exposure figures rightly ask: what would actually be worth attacking, and what should be moved first.

## 6. Policy attestation

A holder MAY publish a key policy. An assessor MAY check it against the snapshot and report whether it holds. Version 1.0 defines two policy rules:

**6.1 Maximum per address.** No single address holds more than N units. Compared in smallest units (satoshis, wei). A **dust tolerance** of 0.001 units is applied above the cap, so that a change output of a few hundred satoshis does not register as a breach. The tolerance MUST be stated in the attestation.

**6.2 Hash-protected only.** Every address holding funds at rest is hash-protected under Section 3. An address holding less than the dust tolerance is treated as emptied: it is reported as informational, not as a breach, since the policy concerns where funds are held.

An attestation MUST list every address checked, the finding per rule, and a single overall verdict: the policy **holds** at this snapshot, or the number of findings against it. It MUST NOT omit failing addresses.

## 7. The signed result

Every result an assessor publishes MUST be a single JSON document carrying a `signature` member of this form:

```
"signature": {
  "algorithm":        "ML-DSA-65",
  "keyId":            "<hex identifier of the assessor's public key>",
  "publicKey":        "<URL where the public key is published, PEM>",
  "canonicalization": "<the exact rule used to serialize the signed bytes>",
  "signedAt":         "<ISO 8601 UTC>",
  "value":            "<base64 signature>"
}
```

**7.1 Algorithm.** ML-DSA-65 as specified in NIST FIPS 204. The point of a post-quantum signature is that the proof of the measurement is itself not breakable by the machine the measurement warns about. An assessor MAY additionally sign with a classical algorithm; it MUST NOT sign only with one.

**7.2 Canonicalization.** The signed bytes are the UTF-8 encoding of the document with its `signature` member removed, serialized as canonical JSON: object keys sorted lexicographically, array order preserved, members whose value is undefined omitted, no insignificant whitespace. The exact rule MUST be stated in the `canonicalization` field so a verifier needs nothing outside the document.

**7.3 Key publication.** The assessor's public key MUST be published at a stable HTTPS URL on the assessor's own domain, and the `keyId` MUST identify it uniquely. The private key MUST exist only in the assessor's signing environment; it MUST NOT be distributed in any client-side or downloadable software.

**7.4 Document types.** This version defines five document types, identified by the `type` member:

| `type` | Contents |
|---|---|
| `latticescan.exposure` | One measurement of an ad-hoc address set (Sections 3 to 5) with a migration plan and method statement. |
| `latticescan.attestation` | A policy attestation (Section 6) over a named holder's published address set, carrying the underlying exposure measurement unsigned inside it; the attestation is signed as a whole. |
| `latticescan.index-snapshot` | One holder's entry in an index: totals, exposure by class, tiers, concentration, the largest exposed keys, coverage (Section 10.1), and an anchor (Section 8). |
| `latticescan.quantum-solvency-index` | The ranked set of snapshots served together, signed as one document. |
| `latticescan.evidence` | Transport and on-chain findings mapped to named regulatory clauses. |

Implementers other than LatticeScan SHOULD use their own reverse-domain prefix for `type` and keep the field structure.

## 8. Anchoring

A snapshot that will be relied on later (an index entry, an attestation, a published letter) SHOULD be **anchored**: its SHA-256, computed over the canonical bytes of the document with any `anchor` member removed, is committed to the Bitcoin blockchain via OpenTimestamps. The document then carries:

```
"anchor": {
  "method":          "opentimestamps",
  "sha256":          "<hex>",
  "proof":           "<base64 .ots proof>",
  "stampedAt":       "<ISO 8601 UTC>",
  "bitcoinAttested": true | false,
  "upgradedAt":      "<ISO 8601 UTC, once Bitcoin-attested>"
}
```

Anchoring proves the document existed at a point in time, on the chain it measures, with no party to trust. A proof is first a calendar promise (`bitcoinAttested: false`) and upgrades within hours to a Bitcoin block attestation; a verifier MAY accept a calendar promise as provisional and MUST report which state it verified.

**8.1 What the anchor covers.** The hash is computed over the document as it was committed, with the `anchor` member removed. Members a server adds when serving (`signature`, `servedAt`, `quantumSolvencyPct`) are not part of the anchored document and MUST be removed before hashing. A verifier MUST hash the document after one JSON round trip, so that numbers are in their shortest round-trip form (RFC 8785 §3.2.2.3).

**8.2 Exact balances.** Because a sum of floating-point values can differ in its last digit between serializers, every balance in an anchored document MUST be rounded to the smallest unit of its chain (satoshi for BTC, micro-ether for ETH) before the document is committed and anchored. This guarantees the anchored bytes survive any conforming transport.

## 9. Verification

A conforming verifier, given a document and the assessor's public key, MUST:

1. Confirm the `signature.algorithm` is ML-DSA-65 and the `keyId` matches the supplied key.
2. Remove the `signature` member, serialize per the stated canonicalization, and verify the signature over those bytes. Any change of one byte MUST fail.
3. If an `anchor` is present, remove it, recompute the SHA-256 of the canonical bytes, and confirm it equals `anchor.sha256`. It SHOULD verify the OpenTimestamps proof against Bitcoin and report whether it is block-attested.
4. For an index snapshot or attestation, recompute Total, Exposed balance, Exposed share and Quantum solvency (Section 4) and the tier totals (Section 5) from the per-address items in the document, and confirm they equal the stated values within rounding.

A verifier that can reach a public explorer MAY additionally re-read a sample of addresses and confirm the exposure classification (Section 3); balances will drift with time and MUST NOT be expected to match exactly.

The reference verifier published with this specification (`verify-pqs.mjs`) performs steps 1 to 4 with no dependencies beyond Node.js 24.

## 10. Disclosure

Every published result MUST state:

**10.1 Coverage.** How many addresses the holder published, how many were targeted, how many were read, and, where the holder declared per-address balances, the share of the declared balance the read set covers. An assessor MAY read the largest declared holdings first and stop at a coverage target of no less than 99.5% of declared balance; if it does, the target and the achieved coverage MUST be shown.

**10.2 Unreadable addresses.** The count of addresses the public data source could not return at snapshot time. These are excluded from every total and MUST NOT be presumed safe.

**10.3 Sources.** The explorer or node used for each chain, and the holder's publication (URL, date, and block height if declared) from which the address set was taken.

**10.4 Limitations.** At minimum: that P2SH and P2WSH exposure depends on the redeem script; that bare P2PK is recognised only for known addresses; that contract accounts are not classified; that extended public keys are unsupported; that balances exclude unconfirmed transactions; and that exposure is not a prediction. No CRQC exists at the date of this version; NIST IR 8547 (Initial Public Draft) sets classical elliptic-curve signatures to be deprecated after 2030 and disallowed after 2035, and no production post-quantum signature scheme exists yet for the balances measured.

**10.5 Independence.** That the assessor holds none of the balances measured and has no financial relationship with the holder beyond any disclosed assessment fee.

## 11. Conformance

An implementation conforms to this specification if it: classifies exposure exactly per Section 3; computes quantum solvency per Section 4 and tiers per Section 5; where it attests a policy, does so per Section 6; signs per Section 7 and, for relied-on documents, anchors per Section 8; produces documents a Section 9 verifier accepts; and discloses everything in Section 10.

An **assessor** conforms if, in addition, it satisfies the independence requirement in Section 2 and Section 10.5.

## 12. Change control

Revisions within 1.x add fields, chains, policy rules or document types; they never change the meaning of a field already defined. A 2.0 will be issued for any breaking change, with at least ninety days' notice. Proposed changes are accepted at hello@latticescan.com and considered in public.

## 13. References

- NIST FIPS 204, Module-Lattice-Based Digital Signature Standard (ML-DSA), August 2024.
- NIST IR 8547 (Initial Public Draft), Transition to Post-Quantum Cryptography Standards, November 2024.
- BIP-341, Taproot: SegWit version 1 spending rules.
- BIP-360, Pay-to-Merkle-Root (Draft).
- EIP-7702, Set EOA account code.
- OpenTimestamps, opentimestamps.org.
- RFC 2119, Key words for use in RFCs to indicate requirement levels.
- RFC 8785, JSON Canonicalization Scheme (the canonicalization in Section 7.2 is a strict subset).

---

*Reference implementation: latticescan.com. Live index: latticescan.com/quantum-solvency. Verifier: latticescan.com/spec/verify-pqs.mjs.*

## Appendix A. Ownership commitments (informative in 1.0, normative from 1.1)

A **commitment** is a holder's dated, signed declaration of which post-quantum public key belongs to an existing classical address. It exists so that, once the classical key can be recovered by an adversary, the earliest verified commitment identifies the rightful owner. It moves nothing on-chain.

### A.1 Statement

The signed text is exactly, with `
` line breaks and no trailing newline:

```
LatticeScan Proof of Quantum Solvency registry (pqs-registry-v1)
I control the <chain> address <address>.
My post-quantum public key (ML-DSA-65) has key id <keyId>.
Signed by the key that controls the address above.
```

`<chain>` is `bitcoin` or `ethereum`; `<address>` is the address as the holder wrote it (Ethereum addresses are compared case-insensitively); `<keyId>` is the first 16 hex characters of the SHA-256 of the DER-encoded SubjectPublicKeyInfo of the ML-DSA-65 public key (FIPS 204).

### A.2 Proof of control

- Bitcoin: the legacy signed-message scheme (double-SHA-256 of the length-prefixed magic `Bitcoin Signed Message:
` and the statement; 65-byte compact recoverable signature, base64). The verifier recovers the public key and derives P2PKH, P2WPKH and P2SH-P2WPKH addresses from it; the commitment is valid if one equals `<address>`. Taproot (BIP-322) is reserved for a later revision.
- Ethereum: EIP-191 `personal_sign` over the statement; the recovered key's keccak-256 address must equal `<address>`.

### A.3 Record and anchor

The canonical record is the JSON object with keys sorted: `address, address_type, chain, classical_signature, committed_at, pq_algorithm, pq_key_id, pq_public_key, signature_scheme, statement`. Its SHA-256 is anchored per Section 8. A record whose signature fails A.2, whose statement differs from A.1, or whose hash differs from its anchor is invalid and MUST be reported as such, never silently dropped.

### A.4 Precedence

Between competing claims for one address, the valid commitment with the earliest Bitcoin-attested anchor takes precedence. A holder may supersede their own commitment by publishing a later one; the earlier one remains on record.
