Every Quantum Chain transaction carries a post-quantum signature that authorizes the spend. Block validators verify the signature against the sender’s registered public key on every block at or after quantumVerificationBlock.
The signing primitive is different from Ethereum’s ECDSA, but the transaction envelope is unchanged: legacy, EIP-1559, and EIP-2930 transactions are all supported.
Three signing models
| Model | Where the key lives | Best for |
|---|
| Local keystore | geth process memory | Development, single-user nodes |
| External signer (Clef) | A separate process you control | Hot wallets with policy enforcement |
| Custody platform (Qustody) | A signing service behind a network boundary | Institutional, multi-user, audited |
Local keystore signing
This is the path used by --unlock and personal_sendTransaction. geth reads the encrypted key from the keystore, decrypts it in memory using the unlock passphrase, and signs each transaction internally.
// Geth IPC console
personal.unlockAccount("0xfF81...", "strong-pass", 60)
eth.sendTransaction({
from: "0xfF81...",
to: "0x1865...",
value: web3.toWei(1, "ether")
})
Local keystore signing exposes your key inside the geth process. Anyone with read access to the host or to the RPC interface can drain the wallet. Use this only for development.
External signing with Clef
Clef is a separate process that owns the keystore. geth talks to clef over an IPC socket and never touches private keys.
Start clef:
./build/bin/clef \
--keystore ~/.quantum-chain/keystore \
--chainid 20803 \
--ipcpath /tmp/clef.ipc
Connect geth:
geth ... --signer /tmp/clef.ipc --nousb
Each signing request appears in clef’s terminal for approval, or you can write a JavaScript rule file (clef --rules rules.js) that auto-approves matching requests.
External signing via Qustody
For multi-user, policy-driven, auditable signing, use the Qustody platform.
The flow:
- Your application calls Qustody’s
POST /v1/transactions with {wallet_id, to, value}.
- Qustody runs its policy engine and AML screening, then enters
PENDING_SIGNATURE.
- Your post-quantum signing service fetches the signing payload via
GET /v1/transactions/{id}/signing-payload.
- The signing service produces a post-quantum signature using the wallet’s private key.
- The service POSTs the signature to
POST /v1/transactions/{id}/signature.
- Qustody verifies the signature, broadcasts via JSON-RPC, and emits webhooks for each subsequent state.
See External signing for the full payload schemas.
Building a transaction by hand
The signing payload is the Keccak-256 hash of the RLP-encoded transaction without signature fields. The signature is a post-quantum signature over that 32-byte digest. Reassemble the signed transaction by appending the signature in the transaction’s signature fields and broadcasting via eth_sendRawTransaction.
For library users, ethers.js v6, web3.py, and viem support custom signers — plug in a signer that produces post-quantum signatures and the rest of the transaction-building stack works unchanged.
Verifying a signature
Use the standard JSON-RPC:
curl -s -X POST $RPC \
-H 'Content-Type: application/json' \
--data '{
"jsonrpc":"2.0",
"method":"eth_getTransactionByHash",
"params":["0x..."],
"id":1
}'
The response includes the post-quantum public key and signature fields. A node will reject any block containing a transaction whose signature does not verify against the sender’s public key.
Where to go next