Key setup and management
A validator is a handful of keypairs and on-chain authorities. Most of the damage operators suffer comes from one of two mistakes: a key that should be cold sits on the server, or a change takes effect later than the operator expected. This page covers both.
The keys at a glance
Section titled “The keys at a glance”| Key | What it controls | Where it lives |
|---|---|---|
| Identity (node key) | Signs blocks, shreds, gossip, and the QUIC connections that carry votes. By default it also receives your block-revenue commission. | Hot, on the validator. |
| Authorized voter | Signs your consensus votes. Under Alpenglow your BLS voting key is derived from it, so leaking one leaks the other. Defaults to the identity. | Hot, on the validator. |
| Vote account keypair | Nothing while the account exists. It makes the vote account’s address, and it’s the only way to recreate an account at that address if it’s ever closed. | Offline, not deleted. Your client needs only the vote account’s public key. |
| Withdraw authority | Everything that matters: commission, reward collectors, the identity bound to the vote account, the voter, the withdrawer itself, and withdrawals. | Cold: a hardware wallet or an air-gapped machine. Never on the validator. |
| Stake authorities (staker, withdrawer) for your own stake | Delegating and withdrawing your self-stake. | Cold. |
The reward collectors are addresses, not keys, but they’re worth knowing:
- Inflation-rewards collector: receives your share of staking rewards. Defaults to the vote account.
- Block-revenue collector: receives your share of block fees. Defaults to the identity account. Since the identity is a hot key, sweep that balance to cold storage regularly, or point the collector somewhere colder (
solana vote-update-commission-collector, signed by the withdrawer).
Generating the keys
Section titled “Generating the keys”# Hot keys: generate them on, or copy them to, the validator.solana-keygen new --outfile identity.json# Optional: a separate authorized voter. See "Separate voter key?" below.solana-keygen new --outfile authorized-voter.json
# Used once to create the vote account, then kept offline.solana-keygen new --outfile vote-account.json
# Cold: the withdraw authority should be a hardware wallet (for example# usb://ledger) or a key generated on an air-gapped machine. You only need its# public key on the machine that creates the vote account.solana-keygen pubkey usb://ledgerBack up every keypair before you fund anything. Losing the withdraw authority means losing control of the vote account. Losing the identity or the voter is recoverable, but it costs time (see How long changes take).
Creating the vote account (and its BLS key)
Section titled “Creating the vote account (and its BLS key)”Alpenglow only admits a vote account to consensus if it holds a BLS public key, has active stake, and keeps a balance above the admission minimum (rent-exempt plus the per-epoch validator admission ticket fee, SIMD-0357). An account without a BLS key gets no leader slots and casts no votes, whatever its stake.
How the BLS key gets there depends on whether the VoteInitV2 instruction (SIMD-0464) is active on your cluster:
- Once SIMD-0464 is active,
create-vote-accountderives the BLS key from the identity keypair and registers it in the same transaction, along with commission in basis points. - While it is not active,
create-vote-accountfalls back to the original instruction, which writes no BLS key. You have to add one in a second step. (On 2026-10-30 SIMD-0464 was not yet active on mainnet. Check withsolana feature status.)
# 1. Create the account. Set the commission explicitly: if you omit# --commission, the CLI defaults to 100%.solana create-vote-account vote-account.json identity.json <WITHDRAWER_PUBKEY> \ --commission 5
# 2. If the account has no BLS key yet, re-authorize the voter. The checked# variant derives the BLS key from the new voter keypair and attaches a# proof of possession. Re-authorizing the current voter (here the# identity) to itself is allowed and just adds the BLS key.solana vote-authorize-voter-checked <VOTE_ACCOUNT_PUBKEY> identity.json identity.json
# Check: the BLS key on the account must match the one your voter key derives.solana vote-account <VOTE_ACCOUNT_PUBKEY> | grep "BLS Public Key"solana-keygen bls_pubkey identity.json # `bls-pubkey` also works from v4.4The plain vote-authorize-voter command can’t register a BLS key. The CLI rejects it with “use vote-authorize-voter-checked instead”, because deriving the BLS key needs the new voter’s signature.
Pointing your client at the keys
Section titled “Pointing your client at the keys”Both clients need the identity keypair, the vote account’s public key (not its keypair), and the authorized voter keypair(s), if those differ from the identity.
Agave / Jito-Solana
agave-validator \ --identity /path/to/identity.json \ --vote-account <VOTE_ACCOUNT_PUBKEY> \ --authorized-voter /path/to/authorized-voter.json # repeatable; omit to vote with the identityIf you pass any --authorized-voter, Agave votes only with those keys and does not also try the identity. The vote account’s BLS key must derive from one of them. You can add voters at runtime with agave-validator authorized-voter add.
Firedancer ([paths] in the config file)
[paths] identity_key = "/path/to/identity.json" vote_account = "<VOTE_ACCOUNT_PUBKEY>" # a pubkey string is accepted authorized_voter_paths = [] # empty = vote with the identityFiredancer derives BLS keys from the identity and every authorized-voter path. If none of them matches the vote account’s BLS key for the epoch, it logs no identity or authorized voter keypair matches the BLS key of vote account …, unable to vote and casts no votes. firedancer add-authorized-voter and remove-all-authorized-voters change the set without a restart.
Separate voter key?
Section titled “Separate voter key?”How long changes take
Section titled “How long changes take”Most vote-account changes go through the epoch-stakes snapshot: it is taken at the start of epoch N+1, and it decides leaders, consensus membership and BLS keys for epoch N+2. Plan changes with that delay in mind.
| Change (made in epoch N) | Takes effect | Signed by |
|---|---|---|
New authorized voter / BLS key (vote-authorize-voter-checked) |
Epoch N+2 | Current voter or withdrawer, plus the new voter |
New identity on the vote account (vote-update-validator) |
Written immediately; leader slots and votes follow from epoch N+2 | Withdrawer + new identity |
Commission (vote-update-commission-bps) |
Applies to rewards for epoch N+2 | Withdrawer |
| Block-revenue collector | Epoch N+2 | Withdrawer |
| Inflation-rewards collector | The next reward payout (the next epoch boundary) | Withdrawer |
| Withdraw authority | Immediately | Withdrawer |
Only one voter change per target epoch is allowed, and the first one wins. A second attempt for the same epoch fails with TooSoonToReauthorize, even when the withdrawer signs it.
When a key leaks
Section titled “When a key leaks”The response depends on which key leaked. In every case, move fast at the start of an epoch: most fixes land two epochs later.
| Leaked key | What an attacker can do | What you do |
|---|---|---|
| Withdraw authority | Take the vote account: move the withdrawer to themselves (immediately), redirect collectors, raise commission, withdraw down to the protected minimum. | Race to move the withdrawer to a new cold key now. If you lose the race, the account is gone: stand up a new vote account and ask your delegators to re-delegate. |
| Identity that is also the voter | Run “your” validator: take over your gossip entry, produce blocks in your leader slots, cast your votes, sweep the identity account’s balance, and re-authorize the voter to a key they hold. | With the withdrawer: set a new identity (vote-update-validator), a new voter with BLS, and a block-revenue collector away from the identity, all early in epoch N. Sweep the identity account. Have a node with the new keys ready for N+2. Expect the attacker to keep leading and voting through the end of N+1. |
| Authorized voter only | Can’t vote as you (that needs the identity too), but can re-authorize the voter to a key they hold and stop you voting from N+2. | Re-authorize the voter with the withdrawer as early in the epoch as you can, and watch for repeat attempts. If you keep losing the race, move to a new vote account. |
| Identity only (separate voter) | Gossip takeover, block production in your slots, sweeping the identity account. | Set a new identity with the withdrawer (effective N+2), sweep the identity account, and move the block-revenue collector. |
A new vote account is a last resort. Delegators have to deactivate and re-delegate, which costs them at least an epoch of rewards and leaves your new account out of consensus until about N+3.
Checklist
Section titled “Checklist”- Withdraw authority on a hardware wallet or air-gapped machine, with a tested backup.
- Vote account keypair kept offline; the client configured with the vote account’s public key.
- Commission set explicitly at creation.
- Vote account shows a BLS public key, and it equals
solana-keygen bls_pubkey <voter keypair>. - The client loads a key that derives that BLS key (no key-mismatch warnings in the logs).
- Vote account balance comfortably above the admission minimum.
- Identity balance swept regularly, or the block-revenue collector pointed at a colder address.
- A written plan for each row of the leak table, including who holds the withdrawer and how fast they can sign.
Sources
- Agave CLI vote commands (cli/src/vote.rs @ v4.4.0)
- Agave vote program authorized-voter rules (programs/vote/src/vote_state/handler.rs @ v4.4.0)
- Agave vote account withdrawal and close rules (programs/vote/src/vote_state/mod.rs @ v4.4.0)
- Agave epoch-stakes admission filter (vote/src/vote_account.rs @ v4.4.0)
- Agave validator authorized-voter defaults (validator/src/commands/run/execute.rs @ v4.4.0)
- Agave votor BLS key matching (votor/src/voting_utils.rs @ v4.4.0)
- Firedancer [paths] key settings (default.toml @ v26.10.4)
- Firedancer BLS keys for identity plus authorized voters (fd_sign_tile.c @ v26.10.4)
- Firedancer votor BLS key check (fd_votor_tile.c @ v26.10.4)
- Agave solana-keygen bls_pubkey (keygen/src/keygen.rs @ v4.4.0)
- SIMD-0357 (validator admission ticket), SIMD-0387 (BLS keys in vote accounts), SIMD-0464 (VoteInitV2)
Content CC BY 4.0 · code snippets CC0 · site code MIT ·contribute· maintained by Vortex