> ## Documentation Index
> Fetch the complete documentation index at: https://cosmos-docs-security-release.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrate a validator to ML-DSA

> Move a validator's consensus key to the post-quantum ml_dsa_65 algorithm through an ordinary key rotation.

Migrating a validator to post-quantum signing is an ordinary key rotation with an ML-DSA target key. This guide adds the ML-DSA-specific steps around the standard procedure in [Rotate a consensus key, Staking](/sdk/next/keys/rotate-validator-key). For more information on ML-DSA, see [Post-quantum keys](/sdk/next/keys/post-quantum-keys).

## Prerequisites

* The chain lists `ml_dsa_65` in its consensus params. Check with the commands in [Enable ML-DSA keys](/sdk/next/keys/enable-ml-dsa-keys). If the type is missing, follow the guide to add it.
* All prerequisites of the rotation procedure, including [jq](https://jqlang.org/) and [curl](https://curl.se/): no rotation in the current unbonding period, and fee funds on the operator account. See [Rotate a consensus key, Staking](/sdk/next/keys/rotate-validator-key).

## 1. Generate an ML-DSA consensus key

Generate a fresh ML-DSA keypair for the new node.

<Danger>The new key must be freshly generated. Reusing existing key material on two nodes is a double sign, which tombstones the validator.</Danger>

## 2. Rotate to the new key

The procedure is the standard rotation for your chain type. The only change is that the new node runs the ML-DSA key from step 1 instead of a key the rotation guide generates.

### On a staking chain

Follow [Rotate a consensus key, Staking](/sdk/next/keys/rotate-validator-key) with one change: Step 1 of that guide creates the second node with `simd init`, which generates an ed25519 key. Before starting that node, replace its `priv_validator_key.json` with the ML-DSA key file from step 1.

Everything else runs as written. The guide's rotation command derives the public key with `simd comet show-validator` on the second node's home, which now prints the ML-DSA key, so the rotation message carries it automatically.

### On a PoA chain

Follow [Rotate a consensus key, PoA](/sdk/next/keys/rotate-validator-key-poa) with two changes:

1. Step 1 of that guide generates the new key with `simd init`. Before submitting, replace `~/.poa-newkey/config/priv_validator_key.json` with the ML-DSA key file from step 1 of this guide.
2. The submit command passes the key type as an argument. Pass `ml_dsa_65` instead of `ed25519`:

```shell theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
simd tx poa rotate-cons-pub-key "$(simd comet show-validator --home ~/.poa-newkey | jq -r .key)" ml_dsa_65 --operator-address "$(simd keys show val -a)" --from val
```

The cutover timing is unchanged: keep the node on the old key until the validator set switches, then swap the key file in place, exactly as the guide's steps 3 and 4 describe.

### On a remote signer

If the validator's consensus key lives in Cosmos-KMS rather than a local file, the shadow node gets its own signer and the public key derivation differs. See [Rotate a consensus key held in Cosmos-KMS](/sdk/next/kms/rotate-key-remote-signer).

## 3. Verify

Check the key type in the validator set:

```shell theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
curl -s localhost:26657/validators | jq -r '.result.validators[].pub_key.type'
```

A migrated validator reports `cometbft/PubKeyMlDsa65` instead of `tendermint/PubKeyEd25519`. The chain's consensus is post-quantum secure once validators holding at least two thirds of voting power report a post-quantum type. For more information, see [Post-quantum keys](/sdk/next/keys/post-quantum-keys).

## What can go wrong

* The rotation is rejected for an unsupported key type: the chain does not list `ml_dsa_65` yet. See [Enable ML-DSA keys](/sdk/next/keys/enable-ml-dsa-keys).
* The rotation is rejected with a rotation limit error: a rotation already happened this unbonding period. Wait out the window.
* Anything else follows the standard rotation failure modes. See [Rotate a consensus key, Staking](/sdk/next/keys/rotate-validator-key).

## Next steps

* Track migration progress across the validator set with the allowed-vs-in-use commands. See [Enable ML-DSA keys](/sdk/next/keys/enable-ml-dsa-keys).
* Understand the storage and bandwidth costs the chain takes on as the set migrates. See [Post-quantum keys](/sdk/next/keys/post-quantum-keys).
