TL;DR — Post-quantum spending is live on TensorCash from block zero:
- A new address type,
tc1z…(Witness v2). Consensus disables Taproot key-path spending; the standard wallet template commits to a single ML-DSA leaf (FIPS 204, via liboqs), so a wallet-generatedtc1zspend is post-quantum. - Holds native coin and issued assets — already on mainnet (block 20,246 shows a COMPUTE option held in a v2 output; an ML-DSA spend out of one is still to come).
- Free to receive; ~10× a standard spend to spend from — the multi-kilobyte lattice signature only appears at spend time.
- Before you use it: sign on hardware you control (liboqs isn’t meant for production with sensitive data) and back up each key (no seed-phrase derivation yet).
Most chains treat post-quantum safety as a someday problem — a contentious migration to run once a quantum computer gets close. TensorCash is a genesis fork with no legacy UTXOs to rescue, so we didn’t wait: a post-quantum spending rail has been live since block zero, alongside the familiar ECDSA/Schnorr one. You opt in by funding the right kind of address. This is the plain-words tour — what it is, how it spends, what it holds, and what to know before you use it.
A new address type: tc1z…
TensorCash runs two spending rails, and you choose per address:
- Witness v0/v1 — ECDSA/Schnorr, the mature Bitcoin-derived stack
(
tc1q…/tc1p…). - Witness v2 — the script-path-only Taproot stack the standard post-quantum
template uses. Addresses are
tc1z…(tct1z…testnet,tcrt1z…regtest).
A tc1z is an ordinary 32-byte Taproot output in bech32m — the same length and
shape as a v1 address, just with the version character p→z (and its checksum).
Receiving to it is unremarkable; what changes is how it spends.
Script-path only: the key path is switched off
A Taproot output can be spent by a single key-path signature or by a leaf script. On Witness v2 the key path is disabled by consensus — a v2 output spends only through its script path.
Why it matters: a key-path spend authorises with a Schnorr signature over
secp256k1, the exact curve a quantum computer would break. Disabling it means
there’s no key-path signature to attack on any tc1z output. What the leaf then
requires is up to the script — and TensorCash’s standard generatemldsaaddress
template makes it a single ML-DSA leaf, so spending authority rests on ML-DSA
plus the Taproot hash commitment, with no secp256k1 path at all. A custom v2 script
could use a different or mixed leaf, so the tc1z prefix proves the key path is
off, not that the policy is ML-DSA-only. The rest of this post describes that
standard template.
Why secp256k1 falls but a lattice doesn’t
secp256k1 rests on a discrete-log problem — your public key is a point k·G, and
safety depends on nobody recovering the secret k. That problem has a hidden
periodic structure, and Shor’s algorithm is built precisely to find it: a big
enough quantum computer recovers k outright. ML-DSA instead rests on structured
module-lattice problems with no known Shor-like polynomial-time attack. Quantum
algorithms can still chip at some attack costs, so ML-DSA’s parameter sets were
sized to meet NIST’s security-strength categories under classical and quantum
estimates — evidence-based confidence, not a proof that nothing better will be
found.
The signature: ML-DSA (FIPS 204), via liboqs
The leaf verifies an ML-DSA signature — the Module-Lattice DSA that NIST standardised in August 2024 as FIPS 204 — using the implementation in liboqs (the Open Quantum Safe project). Three parameter sets; you pick one at address creation:
| Parameter set | NIST level | Signature size | Roughly |
|---|---|---|---|
| ML-DSA-44 | Level 2 | ~2.4 KB | AES-128-class |
| ML-DSA-65 (TensorCash default) | Level 3 | ~3.3 KB | AES-192-class |
| ML-DSA-87 | Level 5 | ~4.6 KB | AES-256-class |
TensorCash defaults to ML-DSA-65 as a size/security compromise (FIPS 204
standardises all three; it doesn’t prescribe one). The signature is a witness stack
element the new OP_CHECKMLSIGVERIFY opcode checks against the public key, over a
domain-separated TapSighash/ML-DSA — so it never bloats the output you receive
to, only the input you spend. Hold that thought for the fee story below.

In the wallet it’s a two-field choice — address type Bech32m (Post-Quantum), security level ML-DSA-65 — and the app flags the same two caveats this post does: the key isn’t HD-derived (back it up), and spends cost more. (Name and figures are placeholders.)
What a tc1z address can hold
Native TSC: always — a v2 output holds coin like any other.
Assets: yes, and not in theory. TensorCash assets are first-class UTXOs, and one
can sit on a v2 output like any other. It’s already on mainnet: at block 20,246 a
transaction moved two units of COMPUTE.V26P100K (a COMPUTE
Index option) into a wallet-created tc1z… output (tx). Its
inputs were ordinary Witness-v1 spends, so the precise claim is: an issued asset can
be held in a v2 output — not yet an ML-DSA-authenticated spend out of one (the
public key and leaf stay hidden until that output is spent). Whether an asset may use
the PQ rail is up to its issuer’s policy, but the capability is real and live today.

The same event, wallet-side — a COMPUTE option arriving into a Witness-v2 output, tagged ml-dsa. (Wallet name, balances and other amounts/addresses are placeholders; the COMPUTE receipt is the real block-20,246 transaction.)
On explorer.tensorcash.org, a v2 output shows on its transaction page
(/tx/…) — with the multi-kilobyte ML-DSA witness visible once it’s spent — and
assets have their own /asset/… pages.
Fees: you pay to spend, not to receive
Fees are charged by weight, and an ML-DSA signature is 2.4–4.6 KB against a Schnorr ~64 bytes — but that weight only shows up when you spend a standard ML-DSA v2 output.
Receiving costs nothing extra: the output is the same 32-byte program. The block-20,246 transaction paid into a v2 output for 363 sats at 342 vB — no ML-DSA premium; its size is just ordinary inputs, outputs and asset metadata. The lattice signature appears only on the later spend.
Spending cost is set mostly by the fixed signature, revealed public-key script and control block. Segwit’s 4× witness discount softens it, but at the same ~1.06 sat/vB the block paid, a simple 1-in/2-out spend runs:
| Spend type | tx size | fee | vs. standard |
|---|---|---|---|
| Standard Taproot (Schnorr) | ~155 vB | ~165 sats | 1.0× |
| ML-DSA-44 | ~1,084 vB | ~1,151 sats | 7.0× |
| ML-DSA-65 (default) | ~1,466 vB | ~1,556 sats | 9.5× |
| ML-DSA-87 | ~1,956 vB | ~2,076 sats | 12.6× |
So a default PQ spend is on the order of ~10× a standard one (the spending input alone goes ~58 → ~1,370 vB). The wallet’s own “~70×” warning measures something else — the raw signature blow-up (~3.3 KB vs ~64 bytes); the witness discount and fixed overhead bring the whole-transaction premium down to the ~10× in the table. In absolute terms ~1,556 sats is 0.0000156 TSC at that rate. It’s a real premium, paid each time you spend a PQ output and only by you — budget for it like a large multisig spend.
Signing: use hardware you control
One honest caveat: the ML-DSA code is liboqs, and the liboqs project warns against relying on the library in production for sensitive data. It carries no-secret-branching claims and some side-channel checks, but not coverage of every timing or physical channel — and hardware-wallet support is limited-to-none today. So sign ML-DSA v2 transactions on hardware you own and trust, ideally offline for cold storage, not a shared or hosted signer that could observe timing or power.
Two operational facts:
- No seed-phrase derivation (yet) — a wallet limitation, not the algorithm’s
(FIPS 204 keys regenerate from a 32-byte seed). Each key must be backed up
separately;
generatemldsaaddressreturns the secret key at creation so you can. Lose the wallet file and you lose the key. - Encrypted-wallet ML-DSA signing is still being finished; use the direct RPC flow with supplied key material for now.
Address hygiene: the ML-DSA key stays hidden until spending
Use a fresh address per receive — good practice anywhere, and free. A nice property here: in the standard template the ML-DSA public key lives inside the Taproot leaf and is revealed only when the output is spent, so an unspent one exposes no post-quantum key at all. To be clear on scope: amounts, asset metadata and the transaction graph stay public as on any Bitcoin-style chain; only the key material is hidden. So a funded, never-spent PQ address gives an attacker no ML-DSA key to grind against.
Post-quantum from block zero
The upshot: TensorCash offers a post-quantum spending option from genesis — no
migration, no activation window, and (being a genesis fork) no exposed legacy
balance to rush somewhere safe. Whether a coin sits on the rail is your choice of
address, and it’s already in use: block 20,246 shows COMPUTE.V26P100K held in a v2
output.
Operators may still keep hot, short-lived balances on v0/v1 — mature tooling and hardware, and cryptanalysis isn’t overnight. Long-tenor custody carries a different exposure — the store-now, forge-later risk to authorisation — and may justify the standard ML-DSA v2 template despite its larger witnesses and younger signing stack.
The full construction — encodings, consensus rules, sighash, threat model — is in
the Post-Quantum Spending whitepaper. To try it,
generate a tc1z address with generatemldsaaddress in the
desktop wallet, fund it, and watch it on the
explorer. The post-quantum rail isn’t a roadmap item — it’s block zero.
Authored pseudonymously by Imosuke Takakuni.