Skip to main content

Quantum-safe by default

QoreChain treats post-quantum cryptography as a first-class signature scheme. An account registers an ML-DSA-87 (Dilithium-5, NIST FIPS 204) key on-chain, after which its transactions can carry a hybrid signature — the usual classical secp256k1 signature plus an ML-DSA-87 signature. The chain's ante handler verifies both, so a quantum-safe account stays fully compatible with classical verification while gaining protection against a future quantum adversary.

The SDK packages this into a tiny, idempotent surface so a dApp becomes quantum-safe by default: one call to be PQC-protected.

Check status​

isPqcRegistered / getPqcStatus read whether an address has a registered PQC key via the qor_getPQCKeyStatus JSON-RPC method. They accept either a QorClient or the composed client from createClient:

import { createClient, isPqcRegistered, getPqcStatus } from "@qorechain/sdk";

const client = createClient({ network: "mainnet", endpoints: { /* … */ } });

const safe = await isPqcRegistered(client, "qor1…");
const status = await getPqcStatus(client, "qor1…");
// status: { registered: boolean; algorithmId?: number; pubkey?: string | Uint8Array }

The same status is also readable on the EVM side via the pqcKeyStatus(address) returns (bool registered, uint8 algorithmId, bytes pubkey) precompile at 0x0000000000000000000000000000000000000A02 (exposed as pqcKeyStatus in @qorechain/evm). The helpers above prefer the JSON-RPC method, which needs no viem peer.

Register in one call​

ensurePqcRegistered makes an account quantum-safe. It is idempotent: pass a status source and it skips the registration when the key is already registered, so it is safe to call on every app start.

import { generatePqcKeypair, ensurePqcRegistered } from "@qorechain/sdk";

const tx = await client.connectTx(signer);
const pqcKeypair = generatePqcKeypair(); // or derive deterministically from the wallet

const res = await ensurePqcRegistered(tx, {
pqcKeypair,
statusSource: client, // makes the call idempotent (skips if already registered)
});
// res: { alreadyRegistered: boolean; txHash?: string }

Under the hood it builds and broadcasts MsgRegisterPQCKey with the signer's Dilithium public key (from pqcKeypair) plus, optionally, the account's ECDSA public key.

Sign hybrid​

migrateToHybrid ensures registration and hands back a hybrid send path with the keypair pre-bound to the existing buildHybridTx / signAndBroadcastHybrid builders:

import { migrateToHybrid } from "@qorechain/sdk";

const hybrid = await migrateToHybrid(tx, { pqcKeypair, statusSource: client });

await hybrid.signAndBroadcastHybrid({
registry,
signer, // classical secp256k1 direct signer
messages,
fee,
chainId,
accountNumber,
sequence,
transport, // a connected broadcast transport (e.g. StargateClient)
});

Rotate a key​

If you need to rotate the PQC key (algorithm upgrade or a compromised key), use migratePqcKey, which broadcasts MsgMigratePQCKey proving ownership of both the old and the new key:

import { migratePqcKey } from "@qorechain/sdk";

await migratePqcKey(tx, {
oldPublicKey,
newPublicKey,
oldSignature, // by the old key
newSignature, // by the new key
});

In the UI​

The @qorechain/react kit surfaces all of this in React: the usePqcStatus hook and the <QuantumSafeBadge/> component show a Quantum-safe indicator whenever the connected account has a registered PQC key.