Bittensor Integration
How Thirty Spokes operates as a Bittensor subnet: what goes on chain, when, and what the chain's own parameters have to be for the mechanism to keep its promises.
Registered as Subnet 99. Thirty Spokes is registered on Bittensor mainnet as netuid 99. The v3 mechanism is being rehearsed end-to-end on testnet 526 — real chain, real wallet, real weights — before it opens on 99. The chain seam is the SDK (
bittensor10.x); the code defaults tofinneyand refuses nothing on mainnet that it would allow on testnet.
What the chain holds
| record | written by | slot |
|---|---|---|
the schedule root — schedule:v1:<sha256> |
the owner, once, before launch | the owner hotkey's commitment |
| a ready signal — the registration id and the manifest digest of the uploaded tree | each miner, once per hotkey, at the end of submit |
the miner hotkey's commitment |
| weights — the king's 0.85, the pensioners' shares, the burn | the validator, every window and every 180 blocks | set_weights under the owner hotkey |
A hotkey has exactly one commitment slot and set_commitment overwrites it. That is why the owner commits one root for the whole schedule rather than a hash per window (a per-window write would erase the previous one and leave nothing to check earlier windows against), and why a miner's ready signal is the shot: the slot survives forever and a hotkey that has committed is spent.
Registration and the one shot
A miner registers a fresh hotkey — ed25519, because the credential envelope is sealed to the hotkey's own public key and btcli's default sr25519 cannot open it — pays the network's registration burn, and gets one submission, ever. The upload prefix and the mailbox key are derived from four chain facts (netuid, uid, hotkey, registration block), so the owner cannot scope a credential to a prefix the miner would not compute, and an operator-supplied number cannot enter the derivation.
The queue and the immunity period
Challengers are judged in (commit block, hotkey) order, six per window, and commits beyond a depth of twelve are refused rather than queued. The cap is a drain time, not a headcount: the back of the queue is reached within two windows. Bittensor's immunity period protects a UID earning nothing for a fixed number of blocks and no longer, so the owner's chain-side obligation is one sentence — immunity_period must cover three windows (one to wait for the next window to open, two to drain) — and the validator reads the real value off the chain and refuses to start if the declared cadence does not fit it.
Weights
- The window must be longer than the chain's
weights_rate_limit, or a slate would be rejected and the previous one would silently keep paying. The validator checks this against the chain at launch. - The slate is re-submitted every 180 blocks even when unchanged, so a stable reign does not age out of Yuma's activity cutoff — measured on netuid 99, where
last_updatereached 2,234 blocks against a cutoff of 5,000 under the previous mechanism. - Shares are paid by hotkey, resolved to a UID against the live metagraph at write time and verified to still belong to that hotkey. UIDs are recycled; a remembered UID would pay a stranger.
- If the validator is down for a window, weights are left untouched: the king keeps earning, and the outage is the owner's documented liveness dependency rather than a penalty on the king.
The cadence, concretely
The validator is launched with a genesis block and a window length; window n opens at genesis + (n − 1) · window_blocks and its nonce is the beacon at that block. The testnet rehearsal runs 900-block windows × 3 against an immunity period of 5,000 and a rate limit of 100; a mainnet window is a day.
Mining on testnet
The same commands with --network test --netuid 526. Nothing about the mechanism changes; what changes is that the TAO is free and a mistake costs a testnet registration.