A Cortex validator downloads the sealed epoch bundle from the gateway, verifies it and submits the weights on Bittensor subnet 100. scripts/run-validator.sh does the setup. The master (gateway, Proof, challenge containers) runs only on the master operator's machine, and this script never starts it.
For the underlying CLI and the challenge profile served by the gateway, see the validator guide.
- Linux, Python 3.12 or 3.13, uv,
curland libsodium 1.0.18 or newer. - A clone of this repository.
- To submit weights only: a Bittensor wallet with a hotkey registered on netuid 100. Verifying needs no wallet.
sudo apt-get install libsodium23
uv sync --locked --extra chain-
Run one verification. It never submits and needs no wallet.
scripts/run-validator.sh --verify-only
-
To submit, set the wallet.
export WALLET_NAME=validator WALLET_HOTKEY=default -
Run for real. It verifies and submits every epoch.
scripts/run-validator.sh
Environment variables:
| Variable | Default | Meaning |
|---|---|---|
WALLET_NAME |
required to submit | Validator wallet name |
WALLET_HOTKEY |
required to submit | Registered validator hotkey |
GATEWAY |
https://chain.joinbase.ai |
Gateway URL |
NETUID |
100 |
Subnet |
NETWORK |
finney |
Bittensor network |
STATE_DB |
$HOME/.cortex/validator.sqlite3 |
Local state database |
WALLET_PATH |
$HOME/.bittensor/wallets |
Wallet directory |
VERSION_KEY |
read from the chain | Override the subnet weights_version |
Flags:
| Flag | Effect |
|---|---|
--verify-only |
Verify once, never submit |
--once |
Run one tick, then exit |
--dry-run |
Print the masked command without running it |
--help |
Show usage |
--verify-only runs one verification and exits without submitting. Use it first, to confirm your gateway, chain access and network work. --dry-run goes one step less: it prints the cortex validator command, with the wallet name and hotkey masked, and starts nothing.
Before starting, the script:
- fetches
GET $GATEWAY/v1/weights/latestand requires HTTP 200; - requires the answer to be JSON with the expected
netuid; - reads the subnet
weights_versionfrom the chain, unless you setVERSION_KEY.
Then cortex validator takes over. It fetches the challenge profile from the gateway, verifies the sealed bundle's hashes and Merkle root against it and the chain, and recomputes the weights from the leaves. It doesn't trust the display fields in the gateway answer. See the validator guide for the full rules.
- The script refuses
master,challenge-supervisorandvm-hostas arguments, and exits with code 2. - It also refuses to run if
CORTEX_MASTER=1,BASE_MASTER_SECRETS_HOST_DIRorBASE_CHALLENGE_SECRETS_HOST_DIRis set. Unset them first. - Keep wallet files private.
--dry-runmasks the wallet name and hotkey in its output. - Run
--verify-onlybefore the first real run.
Do I need to run challenge containers or Docker? No. Validators never run challenge containers or Proof evaluation, and they need no registry or challenge token.
Do I need a GPU or a KVM host? No. Those are for the master operator.
The script says the netuid doesn't match.
The gateway answered for a different subnet than NETUID. Check GATEWAY and NETUID.
It can't read weights_version.
Set VERSION_KEY yourself, or check that NETWORK is reachable.
Where does the challenge profile come from?
From the gateway at GET /v1/trust over HTTPS; no local files are needed.
Do I need a hotkey?
Only to submit weights. scripts/run-validator.sh --verify-only and the CLI --verify-only need no wallet; submitting needs WALLET_NAME/WALLET_HOTKEY (--wallet-name/--wallet-hotkey).
Does the validator CLI need anything else? The validator guide lists the current requirements for the underlying CLI, such as the consensus seed file.