Staking Setup — Identity, Vote Account, and Delegation¶
Docs-site note (2026-07-11): Part of the Vexor documentation site (Anza-style). This page documents how Vexor is wired to its on-chain identity and how stake reaches it, and how that maps onto the standard Solana stake/delegation model. Vexor is testnet-only, version 0.9.x pre-production — nothing on this page implies mainnet readiness. No private key material appears anywhere in this doc, and none ever should.
A Solana validator participates in consensus through two on-chain identities — a validator identity (the keypair it signs votes and gossip with) and a vote account (the on-chain account that accumulates credits and to which stake is delegated). This page covers how Vexor is pointed at those, the safety rules around the keys, the coordinated-restart gate, and how stake delegation works at a high level.
The keys and their roles¶
A Vexor deploy needs a small set of keypair files on disk. The files and their roles (described generically — the file contents are secret and are never printed, and the paths below are examples, not a real operator's layout):
| File | Role | Notes |
|---|---|---|
validator-keypair.json |
Validator identity | The hot signing key; passed to --identity. Signs every vote transaction and gossip message. |
vote-account-keypair.json |
Vote account | The on-chain vote account address; passed to --vote-account. Accumulates vote credits; stake is delegated to this account. |
authorized-withdrawer-keypair.json |
Withdraw authority | Controls commission changes and withdrawing rewards from the vote account. Used out-of-band (e.g. for vote-update-commission), not passed to the running validator. |
stake-keypair.json |
Stake account | A stake account that can delegate to the vote account. Managed with the solana CLI, off the validator's launch path. |
The validator's launch path uses only the identity and the vote-account keypairs. The withdraw authority and the stake account are management keys used out-of-band; they are never handed to the running process.
Never print, copy, commit, or transmit private keys
The *-keypair.json files contain raw private key bytes. Never cat them into a log, a chat, a commit, a
memory note, or a hand-off doc. This documentation refers to them only by file name and role, with
placeholder paths. Treat the withdraw-authority key as the most sensitive of all — it controls the vote
account's funds and commission.
Wiring the validator: --identity and --vote-account¶
The deploy script always launches the validator with its own staked keys — live votes are required for accurate
health signals and forensics, so there is no --no-voting mode and no throwaway key on a live node:
… run --testnet --bootstrap \
--identity /path/to/validator-keypair.json \
--vote-account /path/to/vote-account-keypair.json \
…
--identityselects the keypair the validator signs with.--vote-accountselects the on-chain vote account it votes into.
That's the whole binding. Everything else about staking happens on-chain, via stake accounts that delegate to the vote account.
Key isolation between separate validators
If a host runs more than one validator (for example, a reference/comparison node alongside Vexor), keep their keys and configuration strictly separate:
- Never put another validator's identity or vote-account pubkey into Vexor's
--identity,--vote-account,--known-validator, deploy scripts, or source. - Never point any Vexor flag at another validator's endpoints or RPC port.
- For cluster-authoritative facts (stake, credits, delinquency), query the public testnet RPC
(
https://api.testnet.solana.com) — never a co-located node's RPC, and never Vexor's own RPC for cluster-wide state (see the caveat in Checking stake and vote health below).
The coordinated-restart gate¶
Two launch flags exist for coordinated cluster restarts (when the cluster agrees to resume from a specific slot and bank hash). They are inert in normal operation and arm only when set.
Unverified against the docs fact sheet: these two flags/envs and the specifics below are not itemized in the current fact sheet's operator-facing, baked, vestigial, or experimental env lists. Confirm exact default and arming behavior against
VEXOR-CANONICAL-FLAGS.md/ the code before relying on them operationally.
| Flag / env | Purpose |
|---|---|
--expected-bank-hash (VEX_EXPECTED_BANK_HASH) |
Halt the boot if the bank at the restart slot does not match the agreed hash. (Default value and exact arming condition unverified here — see caveat above.) |
--wait-for-supermajority <slot> (VEX_WAIT_FOR_SUPERMAJORITY) |
Halt voting/production until a supermajority of the boot-epoch activated stake appears in gossip. (Threshold value and exact arming condition unverified here — see caveat above.) |
To perform a future coordinated restart, set both explicitly:
VEX_EXPECTED_BANK_HASH=<agreed-restart-bank-hash> \
VEX_WAIT_FOR_SUPERMAJORITY=<restart-slot> \
bash deploy.sh dev
A note on the two-phase / ephemeral-identity pattern¶
A common Agave operational technique is to boot with an ephemeral (unstaked) identity key, let the node catch up to the cluster tip and clear the supermajority / expected-bank-hash gate, and only then hot-swap to the staked identity — so the staked key never signs while the node is behind and at risk of voting a wrong fork.
Vexor's --wait-for-supermajority / --expected-bank-hash flags implement the gate side of that pattern. The
live Vexor deploy, however, does not use the ephemeral-key swap: it votes with the staked identity directly from
boot (operator directive — real votes are required for forensics, and the restart gate plus the offline-replay
parity gate provide the safety). Whether Vexor currently exposes a working admin set-identity hot-swap command is
unverified against the docs fact sheet, so the ephemeral→staked flow described here is documented as standard
background, not as Vexor's current practice.
How staking and delegation work (high level)¶
Stake is what gives a validator weight in consensus. The chain works through these layers:
- Stake accounts delegate to a vote account. A token holder creates a stake account and delegates it to a
validator's vote account (Vexor's
vote-account-keypair.jsonaddress). One vote account can receive delegations from many stake accounts. - Delegated stake becomes the validator's weight. The total active stake delegated to the vote account is the validator's stake weight for the epoch.
- Stake weight drives selection. Stake weight determines the validator's share of the leader schedule (how many slots it is assigned to produce blocks in) and its weight in Turbine (the shred-propagation tree) and in fork choice / voting.
- Voting earns credits; credits earn rewards. Each correct vote the validator lands accrues vote credits on the vote account, executed by Vexor's own vote-program implementation. On the live testnet node this currently lands ~98.7% of the theoretical maximum vote credits (measured against the 16-credits/slot ceiling). At epoch boundaries, inflation rewards are distributed in proportion to credits and stake, minus the validator's commission. The withdraw authority can change commission and withdraw the vote account's accumulated rewards.
- Warmup / cooldown. Newly delegated stake warms up over epochs before it is fully active, and deactivated stake cools down before it can be withdrawn — so stake changes affect the schedule gradually, not instantly.
Stake/delegation operations themselves (create stake account, delegate, deactivate, withdraw, change commission) are
performed with the standard solana CLI using the appropriate authority keys — they are on-chain transactions, not
validator launch flags.
Checking stake and vote health¶
Checking stake and vote health
For cluster-authoritative facts — your vote account's active stake, credits, commission, and whether you are delinquent — query the public testnet RPC. Don't rely on a validator's own RPC for facts about the wider cluster: a minimal or partially-implemented RPC surface (which is what Vexor currently ships) can return stale or naive answers for cluster-wide state:
curl -s https://api.testnet.solana.com -X POST -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"getVoteAccounts",
"params":[{"votePubkey":"<YOUR_VOTE_PUBKEY>"}]}' \
| jq '.result.current[] // .result.delinquent[]'
Green looks like: the account appears under current, not delinquent, and lastVote advances on each poll.
See also¶
- Network Setup — AF_XDP ingest, ports, and the core-pinning model.
- Deploy — the full deploy command, the STOP → BUILD → DEPLOY cadence, and verifying a deploy is green.
- Hardware — the reference box the validator runs on.