Bittensor · Multisig Guide
ledgers · multisig · proxies

Bittensor Key Security

Securing a wallet: Ledgers, multisig, proxies

How a hardware wallet, a multisig, and a value-blind proxy combine to let you operate on Bittensor day-to-day without exposing the key that holds your TAO & alpha — and where the sharp edges still are. Written with subnet owners in mind, but it applies to validators and anyone looking to secure a high-value wallet.

TL;DR

1. Why a frequently-used coldkey needs this

Operating on Bittensor is a hands-on job, and the exact calls depend on your role. A subnet owner tunes hyperparameters, sets subnet identity, activates emission (start_call), and manages subnet admin. A validator sets weights, manages stake, runs child keys, and claims rewards. Either way you're routinely signing transactions — a hot workload, frequent, sometimes automated, often from a machine that touches the network. (One person may wear both hats: an owner whose hotkey also validates does both sets of calls — but they're distinct roles, not the same job.)

The problem is that the same coldkey you sign with also owns potentially large staked TAO & alpha. If your day-to-day signing key is your treasury key, then every routine transaction is an opportunity for a phishing site, a malicious frontend, or a compromised machine to walk away with everything.

The whole point of the patterns below is to split "does the work" from "controls the money" — so the key you use constantly can't touch the funds, and the key that controls the funds is used almost never. This holds for subnet owners, validators, and anyone securing a high-value wallet.

2. The two building blocks

The Ledger (hardware wallet)

A Ledger keeps your private key inside a certified secure element — a dedicated chip isolated from the host computer. Keys are generated on-device and never leave it; transactions are signed inside the chip and only the signature comes out. A PIN protects the device, and an optional passphrase can create a hidden wallet.

Its strength is key isolation: even a fully compromised computer can't extract the key. Its historical weakness on Bittensor was blind signing — a Ledger's ability to decode Bittensor's custom Substrate extrinsics on its own screen is limited, so you could end up approving a transaction you couldn't fully read. The wallet software you sign through matters enormously here (see below).

Product note — the Taostats wallet decodes your extrinsic

The Taostats wallet supports Ledger and shows you the fully decoded extrinsic — the exact call, pallet, and parameters — before you sign. That closes most of the blind-signing gap: instead of approving an opaque blob, you can read that you're calling, say, add_proxy(NonFungible) and not add_proxy(Any), or that a transfer is going where you intended. It's the single easiest way to de-risk the signing step, and it's why "blind signing" is much less of a concern in practice than the raw hardware limitation suggests.

Caveat worth keeping honest: the wallet decoding the call in its UI is what protects you here. A dedicated air-gapped signer (§6) additionally verifies on a device the host can't influence — a stronger guarantee for the highest-value keys, but overkill for most.

The NonFungible proxy

Substrate's proxy system lets one account (the delegator) authorize another account (the proxy) to submit a restricted set of calls on its behalf. The restriction is enforced by the chain runtime itself, not by convention.

Bittensor ships a custom proxy type called NonFungible, whose enum comment in the runtime source reads, verbatim: // Nothing involving moving TAO. It's the proxy designed for exactly this: do your operational work, touch nothing fungible.

Every call the proxy submits is checked by the runtime against the NonFungible allow-list before it executes. This is the gate — enforced on-chain, so a compromised proxy key hits the same wall you do:

NonFungible PROXY submits a call │ ▼ ┌──────────────────────────┐ │ RUNTIME FILTER GATE │ ← checked on-chain, every call │ is this call on the │ │ NonFungible allow-list? │ └──────────────────────────┘ │ ┌────┴─────────────────────────────┐ ▼ ▼ ✅ ALLOWED — executes ❌ REJECTED — never runs set_weights · hyperparams transfer · add_stake start_call · identity remove_stake · swap_coldkey set_children · claim_root swap_hotkey · move_stake
What NonFungible CAN do

Everything you need to operate, across both roles. Owner calls:

hyperparameters (tempo, difficulty, immunity, alpha…) start_call (activate emission) set_subnet_identity

Validator calls:

set_weights commit / reveal weights register / burned_register set_children / set_childkey_take claim_root

What NonFungible CANNOT do

Anything that moves value or seizes the account:

Balances::transfer_* add_stake / remove_stake unstake_all move_stake / swap_stake transfer_stake swap_hotkey swap_coldkey

This is the key distinction from the more common NonTransfer proxy, which — on Bittensor — does allow remove_stake and unstake_all. NonTransfer is not safe for protecting your stake; NonFungible is the correct choice.

3. The architecture

OWNER COLDKEY ── on a Ledger, kept cold │ holds all TAO · can move value · signs RARELY │ (only for transfers, adding/removing proxies, ownership changes) │ │ delegates a ▼ NonFungible PROXY ── your operational key └─ does the daily work — owner and/or validator: hyperparams · start_call · identity · set_weights · child keys but is physically blocked from: transfers · staking · unstaking · key swaps

You register the proxy once (an add_proxy call signed by the owner Ledger), then hand the day-to-day workload to the proxy key. The owner Ledger goes back in the drawer and only comes out for the rare, high-stakes operations.

4. Security pros and cons

Pros

BenefitWhy it matters
Value is unreachable from the operational key Even if the operational proxy key is fully compromised — malware, phishing, leaked seed — the attacker cannot transfer, stake, or unstake a single TAO or alpha. The runtime rejects those calls from a NonFungible proxy. This is enforced on-chain, not by trust.
The treasury key barely gets used The owner Ledger signs only a handful of times a year. Minimal exposure, minimal blind-sign events on the key that actually holds the funds.
Blast radius is contained A proxy compromise is survivable and recoverable — you revoke the proxy from the (safe) owner key and add a new one. No funds moved in the meantime.
Hardware key isolation The Ledger's secure element means even a compromised computer can't extract the owner key. Combined with the proxy split, the valuable key is both cold and hardware-isolated.
Automatable ops without treasury risk Because the proxy can't move value, you can even run it as a warmer/automated key for high-frequency weight-setting without putting your stake at risk.

Cons and sharp edges

RiskDetail
Emissions can still be siphoned NonFungible allows set_children and set_childkey_take. A compromised proxy can redirect your future emission stream to a child key it controls. It can't touch the principal, but it can steal the yield. If that matters, grant narrower proxies instead of one broad NonFungible and leave child-key calls out.
Operational sabotage without theft A compromised proxy can wreck things without moving any TAO or alpha — hostile hyperparameters (owner) or bad weights (validator). Value-safe is not operation-safe. Monitor the proxy's activity.
Ledger blind-signing A Ledger's own screen can't fully decode every Bittensor extrinsic. This is largely mitigated by signing through the Taostats wallet, which shows you the decoded call before you approve — so you're reading what you sign, not trusting a blob. The residual risk is only if you sign through software that doesn't decode the call; then you're back to trusting whatever built the transaction.
The add_proxy setup call is the one that matters most The one transaction that defines the entire security boundary is the add_proxy call. Sign it through the Taostats wallet and confirm it reads add_proxy(NonFungible) — not Any or NonTransfer — before you approve. A wrong proxy type here silently defeats the whole design, so this is the call to read carefully.
Single point of failure on the owner key One Ledger + one seed backup controls everything. Lose the seed, or have it compromised, and it's over. This is the single biggest weakness of the pattern — and it's exactly what a multisig owner (§5) fixes.
Proxy nesting NonFungible can call add_proxy, so a compromised proxy could add its own sub-proxies. Inner calls are re-filtered against the original rights, so it still can't move value — but confirm this behavior on the live runtime before depending on it.

5. Multisig: fixing the single-point-of-failure

The one real weakness of the pattern so far is that the owner key — even cold on a Ledger — is a single key. One lost seed, one compromised device, and the subnet is gone. A multisig owner removes that single point of failure entirely.

A Substrate multisig is a deterministic account derived from a set of signers plus a threshold (e.g. 3 signers, 2 required). No single signer can act alone — a transaction only executes once the threshold of signers approve it. Make each signer its own Ledger, held by a different person or stored in a different place, and you get real redundancy: you can lose up to (signers − threshold) devices and still control the subnet, and no single compromised device or rogue co-owner can do anything.

Here's how a single transaction moves through a 2-of-3 — nothing touches the chain until the threshold is met:

2-of-3 MULTISIG (Signers A · B · C — each its own Ledger) Someone proposes a call (e.g. transfer, or add_proxy) │ ▼ Signer A approves ──▶ pending: 1/2 ── not enough, nothing executes │ ▼ Signer B approves ──▶ pending: 2/2 ── THRESHOLD MET │ ▼ ✅ TRANSACTION EXECUTES ON-CHAIN Signer C ── never needed. Can be offline, lost, or held in reserve. (this is your redundancy — one key can vanish, funds still move)
See it on-chain — four real worked examples

Want to watch this flow happen for real? Four real Bittensor multisig lifecycles, pulled from Finney with live links to every extrinsic on Taostats — a 3-of-3 and a 2-of-2 that executed, one that reached threshold but whose inner call failed, and one that was cancelled before completing. It's the same NewMultisig → approve → execute trail above, traced step by step on the actual chain.

Choosing a threshold — the two numbers that trade off

A multisig is written M-of-N: N total signers, M required to approve. Those two numbers set two opposing budgets, and you can't max both:

Raising M buys attack-resistance but spends redundancy; lowering M does the reverse. N is your total budget to split between them. Here's what common thresholds actually mean in practice:

Threshold Keys needed to steal Keys you can lose & still transact Lose 1 key Lose 2 keys
2-of-3 2 1 ✓ still fine (2 left = threshold) ✗ locked out — only 1 left, can't reach 2
2-of-4 2 2 ✓ fine ✓ fine — 2 left = threshold
3-of-4 3 1 ✓ fine — 3 left = threshold ✗ locked out — only 2 left, can't reach 3
3-of-5 3 2 ✓ fine ✓ fine — 3 left = threshold
The lockout trap — losing keys is as fatal as losing all of them

If you drop below the threshold, the funds are frozen forever. There is no recovery, no support line, no reset — the same on-chain rule that stops an attacker with too few keys stops you. In a 2-of-3, losing 2 keys means the 1 remaining key is useless: your TAO & alpha are permanently locked. Read the table above as "how much loss can I absorb before I'm locked out," not just "how hard am I to attack."

Recovery play — a compromised key doesn't mean lost funds

Loss and compromise are different problems with different outcomes. If one signer's wallet is compromised (but you still hold threshold with the honest keys), you're not stuck: the surviving uncompromised signers can authorize a swap_coldkey to a brand-new multisig — built from one fresh replacement wallet plus the existing uncompromised keys — cutting the bad key out entirely. As long as the honest signers still meet the threshold (e.g. 2 good keys left in a 2-of-3, or 3 in a 3-of-5), you rotate to a clean owner account before the attacker can reach the threshold themselves. This is a decisive edge over a single-key owner, where one compromise is unrecoverable — and it's a strong argument for a threshold with spare honest keys (2-of-4, 3-of-5) so a single compromise still leaves you enough to execute the swap.

Single Ledger ownerMultisig owner (e.g. 2-of-3 Ledgers)
One device stolen → funds gone? Needs PIN too, but then yes No — below threshold, useless alone
Lost seed / dead device → subnet lost? Yes — total loss No — survives losing up to (n − threshold)
Rogue / compromised co-owner acts alone? N/A (one person) No — needs threshold to collude
Operational friction Low — one device High — every op needs M people to coordinate & approve
Blind-signing One person signs blind Worse — every signer blind-signs the same call

Multisig buys redundancy and insider-resistance, but it's operationally heavy — you don't want to convene three people for every routine transaction. Which is exactly why you combine it with the proxy.

The best-of-both setup: multisig owner + NonFungible proxy

A multisig account is just an ordinary AccountId, so it can be the delegator in add_proxy exactly like any other account. That unlocks the strongest practical structure for a serious subnet:

OWNER COLDKEY = 2-of-3 MULTISIG (each signer its own Ledger) │ holds all TAO · can move value · survives a lost/dead key │ convenes RARELY — only for transfers, proxy changes, ownership │ │ delegates a ▼ NonFungible PROXY = single operational key (one Ledger, or a warm key) └─ runs the subnet daily — no 3-way coordination needed and physically cannot move a single TAO or alpha even if fully compromised
Sharp edge

The add_proxy that wires this up is executed by the multisig — so each signer approves the one call that defines the whole security boundary. Sign it through the Taostats wallet so every signer can read the decoded call and confirm it grants NonFungible (not Any or NonTransfer) before approving. Get this wrong and the entire structure is hollow.

6. What about Polkadot Vault?

For the highest-value keys there's an even stronger option: Polkadot Vault — an old phone, wiped and permanently air-gapped, that signs via QR codes and displays the full decoded extrinsic on a device the host computer can't touch. The Taostats wallet already shows you the decoded call (above); Vault adds the extra guarantee that the decoding and signing happen on hardware fully isolated from a potentially-compromised machine.

Practical note

For most users, Vault is too onerous: you need a dedicated wiped phone, you manage chain metadata by hand, and every signature is a QR-scanning dance. It's the right call for a very high-value wallet run by someone security-obsessed, but it's not where most operators should start. A Ledger for the owner key — signed through the Taostats wallet so you can read every extrinsic — plus a NonFungible proxy is the pragmatic default. Vault is the upgrade path if your threat model demands it.

7. Bottom line

The NonFungible-proxy + Ledger pattern is the right default for anyone operating a high-value key on Bittensor — subnet owner or validator. It cleanly separates the constantly-used operational key (which can't touch your money) from the rarely-used treasury key (which stays cold on hardware). The runtime enforces the value boundary — this is real, on-chain protection, not a promise.

If the wallet holds serious value, upgrade the owner key from a single Ledger to a multisig of Ledgers, and keep the NonFungible proxy for daily ops. That combination — multisig owner + value-blind proxy — is the strongest practical setup: no single device or person can move funds, the structure survives a lost key, and the day-to-day work still runs from one key that can't be drained.

Just go in clear-eyed about the two things it does not protect: emissions (child-key redirection) and subnet operation itself (sabotage). Neither is fund theft, but both are real. And when you set it up, sign the add_proxy call through the Taostats wallet and read the decoded extrinsic — that one call defines everything, and the wallet lets you confirm it's exactly what you intended.

Provenance: Proxy type behavior verified against the Bittensor runtime source (RaoFoundation/subtensor, main): common/src/proxy.rs (ProxyType enum) and runtime/src/proxy_filters/ (per-type allow-lists + regression tests). Note that main can run ahead of the deployed runtime; confirm the live filter set via the get_proxy_filters runtime API before configuring on-chain.