Lattice
OverviewPrimerLabReadiness checkDocs
§04 · primer

How Solana authorises transactions, and where post-quantum signatures hit limits

A walk through Solana's transaction format, signer verification, the Ed25519 precompile, PDAs and durable nonces, and the exact places where post-quantum key and signature sizes collide with them.

Intermediate 8 min read Reviewed

In short

  • A Solana transaction must fit in 1,232 bytes. Signatures are fixed 64-byte slots; account addresses are 32-byte Ed25519 public keys.
  • A single ML-DSA-44 signature (2,420 B) or public key (1,312 B) is larger than an entire transaction.
  • PDAs have no private key, so Shor cannot attack them directly, but the Ed25519 keys that control the owning program can be attacked.
  • As of this chapter's review, Solana authorises transactions with Ed25519 only. Any change to that is a protocol upgrade, not an app setting.
On this page
  1. Anatomy of a transaction
  2. The 1,232-byte budget
  3. Addresses are public keys
  4. The Ed25519 precompile
  5. PDAs: accounts with no private key
  6. Durable nonces and long-lived signatures
  7. Beyond user transactions
  8. Standards cited
  9. Not covered

Anatomy of a transaction

A Solana transaction has two parts: a list of signatures and a message. The message lists every account the transaction touches, a recent blockhash, and the instructions to run. Accounts that must sign are listed first, and the message header says how many there are.

Legacy transaction layout (simplified)
signatures        compact-u16 count, then 64 B per required signer
message
  header          3 B   (# required signatures, # read-only signed, # read-only unsigned)
  account keys    compact-u16 count, then 32 B per account
  recent blockhash 32 B
  instructions    compact-u16 count, then per instruction:
                    program id index (1 B), account indices, data bytes

When the runtime receives a transaction, it checks that signature i is a valid Ed25519 signature over the serialised message under account key i, for every required signer. Only if all of them verify do the instructions run. The first signature doubles as the transaction's identifier, which is why explorers show the base58 encoding of a 64-byte signature as the transaction ID. Version 0 transactions add address lookup tables, which let a transaction reference accounts by a 1-byte index into an on-chain table instead of by a full 32-byte key. Signers still have to appear in full.

The 1,232-byte budget

Solana caps a serialised transaction at the size of a single network packet. The limit of 1,232 bytes comes from the IPv6 minimum MTU of 1,280 bytes minus 40 bytes of IPv6 header and 8 bytes of UDP header. Everything — signatures, account keys, blockhash and instruction data — must fit inside it. A minimal SOL transfer looks like this:

Approximate size of a one-signer SOL transfer (legacy format)
ComponentBytes
Signature count + 1 Ed25519 signature65
Message header3
Account keys: payer, recipient, System Program (count + 3 × 32)97
Recent blockhash32
One transfer instruction (indices + 12 B data, with lengths)~18
Total~215
Exact sizes vary slightly with instruction encoding; the point is the order of magnitude.

Now swap in post-quantum numbers from chapter 02. An ML-DSA-44 signature is 2,420 bytes: on its own, about twice the entire packet. Its public key is 1,312 bytes, also larger than the packet. SLH-DSA has a 32-byte public key that would fit an address slot, but its smallest standard signature at the 128-bit level is 7,856 bytes. Even Falcon-512, the most compact of NIST's selected lattice signatures, needs 666 bytes for the signature plus 897 for the public key if the key has to travel with the transaction. You can see each scheme's fit against the budget on the dashboard spec sheet and in the Lab.

Signer footprint vs. the 1,232-byte packet
SchemeSignaturePublic keySig + keyFits?
Ed25519643296Yes, many times over
ML-DSA-442,4201,3123,732No (signature alone too big)
ML-DSA-653,3091,9525,261No
ML-DSA-874,6272,5927,219No
SLH-DSA-SHA2-128f17,0883217,120No

Addresses are public keys

On Solana, the address of a keypair account is its Ed25519 public key. That has two consequences for post-quantum migration. First, every funded keypair account already exposes the exact input Shor's algorithm needs; there is no hash that hides the key until first spend. Second, the 32-byte address slot cannot hold an ML-DSA public key. Any post-quantum account design must either store the public key somewhere else and use a 32-byte commitment (for example, a hash of the key) as the identifier, or make the public key travel with every transaction. Both are protocol-level design decisions.

The Ed25519 precompile

Programs sometimes need to verify a signature that is not a transaction signer: an oracle price update, an off-chain order, a permit. Solana provides a native Ed25519 signature-verification program for this. A transaction includes an instruction to it whose data carries the public key, signature and message; the runtime verifies them before execution, and the user's program inspects the instructions sysvar to confirm the verification instruction was present and covered the expected data. There is a similar native program for secp256k1 signature recovery.

These programs exist because doing elliptic-curve verification in program code would cost too much compute. There is no equivalent native program for ML-DSA or SLH-DSA today. Verifying one in a program would mean getting a 2-to-17 KB signature into the program (it cannot fit in one transaction's instruction data, so it would have to be uploaded to an account across several transactions) and then running the verification within the per-transaction compute budget. Both are possible in principle and expensive in practice.

PDAs: accounts with no private key

A Program Derived Address is computed by hashing a set of seeds, a bump byte and the owning program's ID with SHA-256, and choosing the bump so the result is not a valid point on the Ed25519 curve. No private key exists for it. The owning program "signs" for it with invoke_signed by presenting the seeds, and the runtime checks the derivation.

This is good news: Shor's algorithm has nothing to attack in a PDA itself, and SHA-256 is not meaningfully weakened by known quantum algorithms. But a PDA is only as safe as the program that controls it. Ask who can upgrade that program (its upgrade authority is normally an Ed25519 key or a multisig of them) and which Ed25519 keys the program's own logic treats as admins, owners or delegates. Vault balances held by PDAs are protected by those keys, not by the PDA.

Durable nonces and long-lived signatures

Normally a transaction expires when its recent blockhash ages out, roughly 150 slots after that blockhash was produced (on the order of a minute or two). Durable nonces remove that expiry: the transaction uses a value stored in a nonce account instead of a recent blockhash, and its first instruction advances the nonce, authorised by the nonce authority's signature. This enables offline signing, custody workflows and scheduled operations.

From a post-quantum perspective, durable nonces widen the window in which a signature matters. A pre-signed transaction can sit unused for months. The nonce authority is itself an Ed25519 key. Teams relying on durable nonces should inventory them, keep their lifetimes short, and treat nonce authorities as long-lived keys in the migration plan.

Beyond user transactions

Ed25519 is also used throughout the validator layer: validator identity keys, vote authorities, signed gossip messages and leader-signed block data. Migrating consensus is a separate and larger problem than migrating user accounts, owned by client teams and the SIMD (Solana Improvement Document) process. For app builders the relevant takeaway is that you cannot opt your app into post-quantum transaction signatures today. You can prepare the parts you own.

  • Find every 64-byte and 32-byte assumption in your serialisers, account layouts, fee estimators and size checks.
  • Inventory long-lived authorities: upgrade authorities, mint and freeze authorities, multisig members, nonce authorities, admin keys stored in program state.
  • Design account state to be agile: store authorities with a scheme tag or behind an indirection so a key type can change later.
  • Watch the protocol. Follow the SIMD repository and client release notes rather than social posts for what has actually been proposed, accepted or activated.

Standards cited

  • RFC 8032
    Edwards-Curve Digital Signature Algorithm (EdDSA)
    Ed25519 signatures used for Solana transaction authorisation.
  • FIPS 204
    Module-Lattice-Based Digital Signature Standard (ML-DSA)
    ML-DSA signature and public-key sizes used in the budget comparison.
  • FIPS 205
    Stateless Hash-Based Digital Signature Standard (SLH-DSA)
    SLH-DSA signature and public-key sizes used in the budget comparison.

Reviewed against the documents above.

What this chapter does not cover

  • Validator, gossip and consensus-layer migration in any depth.
  • Specific SIMD proposals, their status, or any rollout timeline.
  • Address lookup table mechanics beyond their effect on size.
  • Writing a production on-chain verifier for any post-quantum scheme.
  • Fees, compute-unit pricing or transaction-landing strategies.