when ed25519breaks,keep your story.
Solana signs every transaction with ed25519. The day a cryptographically relevant quantum computer arrives, that assumption becomes a liability. qSAFE is a small Anchor program that binds a post-quantum ML-DSA-65 key to your wallet, so the messages you actually meant to authorize can be proven later by a signature scheme that does not fall to Shor.
what happens, step by step
The two columns track what lives off-chain (the user, the keys, the message) and what lives on-chain (the PDAs, their state, the events). A single anchored message takes nine moves.
no state yet
No identity, no session. The wallet exists; the post-quantum side does not.
four calls.
The SDK hides the chunked upload, the compute budget, and the event parsing. You write the four lines that matter; everything else is plumbing.
import { QsafeClient, generatePqKeypair, hashMessage, pqSign } from '@qsafe/sdk';
import { Connection, Keypair } from '@solana/web3.js';
const connection = new Connection(process.env.QSAFE_RPC!);
const wallet = Keypair.fromSecretKey(/* your secret key */);
const client = QsafeClient.forWallet(connection, wallet);
// 1. generate the post-quantum keypair offline
const pq = generatePqKeypair();
// 2. register the public key on-chain (chunked upload, sealed at the end)
await client.register(pq.publicKey);
// 3. sign any message with the pq secret key, off-chain
const message = Buffer.from('transfer 10 SOL to alice');
const sig = pqSign(hashMessage(message), pq.secretKey);
// 4. anchor the signature on-chain (chunked upload, then verify_session)
const result = await client.anchorMessage(message, sig);
console.log('verify tx:', result.anchorSignatures.at(-1));the surface, briefly.
PqIdentity
account[b"qsafe-identity", owner.pubkey]Session
account[b"qsafe-session", identity.pubkey, session_id]Full on-chain verification of an ML-DSA-65 signature does not fit inside Solana's SBF runtime today. The verifier overflows the per-frame stack limit, and size-optimizing the build pushes seal_identity past the 200K compute-unit meter. The default build therefore runs a deterministic attestation path and emits a SignatureAnchored event with verified=false. External verifiers can recompute the same commitment and run the real ML-DSA verify off-chain. Full on-chain verify is a tracked follow-up.