Concepts
Wallets and keys
Coldkeys, hotkeys, key material and backups, security tiers, key rotation, and how address arguments resolve.
A Bittensor wallet is a pair of keys stored on disk (default
~/.bittensor/wallets/<wallet-name>/):
- The coldkey holds funds and signs financial operations: transfers, staking, registration, subnet ownership. It is encrypted at rest with a password. Keep it offline where possible — proxies exist precisely so day-to-day operations don't need it.
- The hotkey is your operational identity on subnets: it gets the UID when you register, signs weights and axon serving, and is safe to keep on a running machine. One wallet can hold many hotkeys.
Key material
Coldkeys and hotkeys are sr25519 keypairs, addressed with SS58 network prefix 42. Each key is generated from a mnemonic (12 words by default), and that mnemonic is the only recovery path: the wallet password merely decrypts the keyfile on one machine — it cannot regenerate a lost key, and no password is needed to regenerate the key from the mnemonic. Whoever holds the mnemonic owns the funds.
On disk, each wallet directory contains:
coldkey— the coldkey secret, password-encrypted (NaCl);coldkeypub.txt— the coldkey's public key and ss58 address, unencrypted (no secret material);hotkeys/<hotkey-name>— one file per hotkey, unencrypted: the SDK's create and regen helpers always write hotkeys in plaintext, private key and mnemonic included. Treat every hotkey file as readable by anything that can read the disk.
Create, import, inspect
btcli wallet create -w my_coldkey # new coldkey + hotkey (prints mnemonics once — save them)
btcli wallet new-hotkey -w my_coldkey -H my_hotkey
btcli wallet regen-coldkey -w my_coldkey # recover from mnemonic (prompted securely)
btcli wallet regen-hotkey -w my_coldkey
btcli wallet regen-coldkeypub -w watch_only --ss58 5F... --public-key 0x... # watch-only, no secrets
btcli wallet list # wallets on disk, multisigs, address book
btcli wallet show # public keys + crypto schemes
btcli wallet balance my_coldkey # free TAO + stake marked to TAOThe same flows exist in Python under sub.wallets (create, regen_coldkey,
regen_hotkey, list_wallets, sign_message, verify_message, ...). Key
material is handled by the SDK's native wallet module (bittensor.wallet,
backed by the in-repo py-sp-core extension); this package adds thin
conveniences.
from bittensor.wallet import Wallet
wallet = Wallet(name="my_coldkey", hotkey="my_hotkey")Back up the seed phrase
A seed phrase fails in two ways: loss (the funds are gone permanently — nobody, including the Opentensor Foundation, can recover them) and leak (anyone who saw it can drain the wallet — respond by rotating keys, see below). Backups defend against loss; handling discipline defends against leak.
- Never type a seed phrase into messaging apps, email, cloud documents, or any networked application. Assume keyloggers, screen capture, and cameras exist when generating or restoring keys.
- The "hex-encoded seed" or "private key hex" is the seed phrase in another encoding — anyone asking for it is asking for the seed phrase. Nobody legitimate asks for either. "Fix your RPC settings" DMs are phishing, and unsolicited DMs offering support are scams; keep help requests in public channels.
- Keep redundant physical backups in separate locations so one fire, flood, or theft cannot destroy every copy: paper in a tamper-evident envelope inside a safe or deposit box; a stamped metal plate survives what paper doesn't.
- A digital backup should live on an encrypted offline drive (GPG or VeraCrypt, strong unique passphrase) that is only ever connected to a trusted, offline machine.
- A hardware wallet is a signing device, not a backup: it will not export the seed phrase, and too many wrong PINs factory-reset it. Use it in addition to seed-phrase backups, never instead of them.
Security model
Match each key to the least-trusted machine that needs it:
- Public keys only — balances and state are readable without any secret:
import just the address with
btcli wallet regen-coldkeypuband use any query from an everyday machine. - Hotkey machines — mining and validation servers run subnet code and ML dependencies, which is untrusted code sitting next to your hotkey. Create hotkeys on a trusted workstation and provision them to servers through a secrets manager (Vault, AWS/GCP secret stores) or ephemeral CI injection; never commit key files to a repository. A leaked hotkey can't move TAO, but it can submit garbage weights and burn the reputation of its UID.
- Coldkey workstation — a dedicated, clean machine for coldkey-signed operations, ideally holding only a scoped proxy key rather than the real coldkey.
- Primary coldkey in a hardware wallet — Ledger works through Talisman, Nova Wallet, or SubWallet; Polkadot Vault turns a permanently offline phone into an air-gapped signer that can sign any extrinsic via QR codes (Ledger apps cover a narrower operation set).
This CLI and SDK cannot sign with hardware wallets. That is what the proxy
pattern is for: the hardware-held primary coldkey creates a single delayed
NonTransfer proxy, and that proxy creates and
revokes narrower scoped proxies (Staking, Registration, ...) for daily
work. Only two operations ever strictly require the primary coldkey: the first
add-proxy, and coldkey rotation.
Supply-chain risk
Pin exact package versions in anything unattended, and upgrade only to
releases announced on official channels. This is not hypothetical: in July
2024 a compromised PyPI release of the legacy bittensor package (6.12.2)
exfiltrated coldkey material from machines that installed it, and the chain
ran in safe mode from July 2 to July 12, 2024 while the damage was contained.
For high-value machines, installing from the source repository at a signed
tag (git tag -v) beats trusting a package index.
Signing and verification
btcli wallet sign --message "hello" -w my_coldkey # coldkey signature
btcli wallet sign --message "hello" --use-hotkey -w my_coldkey
btcli wallet verify --message "hello" --signature 0x... --ss58 5F...Every transaction declares which key signs it — the signer column on each
transaction page. Staking and transfers are coldkey-signed; weights
and serving are hotkey-signed.
How address arguments resolve
Any address option in the CLI (--dest, --hotkey, --coldkey, ...) accepts
three forms:
- a raw ss58 address;
- a local name — hotkey options take
HOTKEYorWALLET/HOTKEY, coldkey options take a wallet name (its coldkey is used), and address-book or proxy-book names resolve too; - omitted —
--hotkey/--coldkeyfall back to the configured wallet's own keys. Destination-style options never default.
btcli query hotkey-owner --hotkey my_coldkey/my_hotkey
btcli wallet balance my_coldkeyAddress hygiene
Transfers are irreversible, and address poisoning exploits that: attackers grind vanity addresses matching the first and last characters of addresses you transact with, then send you a dust transfer so the lookalike appears in your history — waiting for you to copy the wrong entry. Defenses:
- read the whole address, not just both ends;
- know the shape: every Bittensor ss58 address starts with "5" (SS58 prefix 42) — anything else isn't a Bittensor address;
- pay from a saved address book (
btcli wallet listshows yours), never from transaction history; - treat unexpected dust transfers as hostile;
- send a small test transaction before any large transfer.
Always send TAO to a coldkey address. Transferring to a hotkey address is technically possible but can strand the funds. And there is no undo anywhere in this system: no one — the Opentensor Foundation included — can reverse a theft or recover lost keys.
Key rotation and recovery
Hotkey swap. swap-hotkey replaces a hotkey with
a new one, moving its registrations and delegated stake. Swapping across all
subnets recycles 0.1 TAO from the coldkey; swapping on a single subnet
recycles 0.001 TAO and is limited to once per subnet per 7,200 blocks
(~1 day).
Coldkey swap is the response to a leaked coldkey — but only worth it if the coldkey has registrations or owns a subnet. A plain holder or staker should simply transfer their TAO and stake to a fresh coldkey instead. The swap is a two-step, delayed process:
announce-coldkey-swapdeclares the destination and starts a 36,000-block (~5-day) waiting period. The first announcement costs 0.1 TAO, which must be in the coldkey at announcement time (reannouncing later is free). During the window the wallet is locked — no transfers or staking; the coldkey can only execute or dispute.swap-coldkey-announcedexecutes after the delay, moving everything — balance, stake, hotkeys, registrations, subnet ownership — to the destination, which must be an unused coldkey with no existing stake, registrations, or child hotkeys.
Check a pending announcement with the
coldkey-swap-announcement read. An
announcement can be reannounced (overwriting it and restarting the clock) or
cleared only after a further 7,200 blocks (~1 day). The delay exists so the
real owner can catch a thief's announcement:
dispute-coldkey-swap freezes the key until
the dispute is manually resolved.
Non-interactive unlock
For automation, the coldkey password resolves in this order (first match
wins): an explicit password= argument in Python; the BT_WALLET_PASSWORD
environment variable; the per-wallet variable named after the keyfile path
(BT_PW__..., from the SDK); a password file via
--wallet-password-file or BT_WALLET_PASSWORD_FILE; the macOS Keychain
(btcli wallet keychain); then an interactive prompt. A browser-extension
signer is also available so the coldkey never touches the machine running the
CLI — see --signer extension.