6.4 Local Deployment Guide
Run a fully isolated C-SWON subnet on your local machine using Docker. No testnet TAO. No external APIs.
Prerequisites
| Requirement | Version | Check |
|---|---|---|
| Python | 3.10–3.12 | python3 --version |
| Docker | recent | docker --version |
| bittensor | 10.x | python -c "import bittensor; print(bittensor.__version__)" |
Step 1 — Install C-SWON
git clone https://github.com/adysingh5711/C-SWON.git
cd C-SWON
python3.12 -m venv .venv && source .venv/bin/activate
pip install bittensor && pip install -e .
Step 2 — Create .env
python -c "
import secrets
lines = [
'CSWON_MOCK_EXEC=true',
'CSWON_SYNTHETIC_SALT=' + secrets.token_hex(32),
]
open('.env', 'w').write('\n'.join(lines) + '\n')
print(open('.env').read())
"
set -a && source .env && set +a
Step 3 — Start Local Chain
docker pull ghcr.io/opentensor/subtensor-localnet:devnet-ready
docker run -d --name local_chain -p 9944:9944 -p 9945:9945 \
ghcr.io/opentensor/subtensor-localnet:devnet-ready
# Wait for blocks
docker logs -f local_chain # Ctrl-C once blocks appear
| Port | Use |
|---|---|
ws://127.0.0.1:9944 | Metagraph, neuron traffic |
ws://127.0.0.1:9945 | Wallet ops (transfer, stake, register) |
docker restartresets all chain state — redo Steps 4–8.
Step 4 — Create Wallets
btcli wallet new_coldkey --wallet.name owner
btcli wallet new_hotkey --wallet.name owner --wallet.hotkey default
btcli wallet new_coldkey --wallet.name vali
btcli wallet new_hotkey --wallet.name vali --wallet.hotkey default
btcli wallet new_coldkey --wallet.name miner
btcli wallet new_hotkey --wallet.name miner --wallet.hotkey default
Import Alice (dev faucet, 1M TAO):
btcli wallet regen_coldkey --wallet.name alice --uri //Alice --network ws://127.0.0.1:9945
Step 5 — Fund Wallets
# Transfer 100k TAO from Alice to each wallet
for wallet_addr in <owner-coldkey> <vali-coldkey> <miner-coldkey>; do
btcli wallet transfer \
--wallet.name alice \
--destination $wallet_addr \
--network ws://127.0.0.1:9945
# Enter amount: 100000
done
Step 6 — Create and Start Subnet
btcli subnet create \
--network ws://127.0.0.1:9945 \
--wallet-name owner \
--hotkey default \
--no-mev-protection
# Note the netuid (usually 2)
export NETUID=2
# Start emissions (required before staking)
btcli subnet start \
--network ws://127.0.0.1:9945 \
--wallet-name owner \
--netuid "$NETUID"
Step 7 — Configure Hyperparameters
The devnet defaults break local testing. Fix using Alice's sudo key:
import asyncio
from bittensor_wallet import Wallet
from async_substrate_interface import AsyncSubstrateInterface
async def configure():
alice = Wallet(name='alice', path='~/.bittensor/wallets')
owner = Wallet(name='owner', path='~/.bittensor/wallets')
owner_kp = owner.get_coldkey(password='<your-password>')
sub = AsyncSubstrateInterface(url='ws://127.0.0.1:9945')
await sub.initialize()
# Disable commit-reveal (causes bad-signature on devnet)
for attempt in range(5):
call = await sub.compose_call(
call_module='AdminUtils',
call_function='sudo_set_commit_reveal_weights_enabled',
call_params={'netuid': 2, 'enabled': False},
)
ext = await sub.create_signed_extrinsic(call=call, keypair=owner_kp)
receipt = await sub.submit_extrinsic(ext, wait_for_inclusion=True)
if await receipt.is_success:
print('commit_reveal disabled')
break
err = await receipt.error_message
if 'WeightsWindow' in str(err):
await asyncio.sleep(12)
else:
print(f'Failed: {err}'); break
# Set weights_rate_limit = tempo (needs Alice sudo)
inner = await sub.compose_call(
call_module='AdminUtils',
call_function='sudo_set_weights_set_rate_limit',
call_params={'netuid': 2, 'weights_set_rate_limit': 10},
)
sudo = await sub.compose_call(call_module='Sudo', call_function='sudo', call_params={'call': inner})
ext = await sub.create_signed_extrinsic(call=sudo, keypair=alice.coldkey)
receipt = await sub.submit_extrinsic(ext, wait_for_inclusion=True)
print(f'weights_rate_limit: {await receipt.is_success}')
await sub.close()
asyncio.run(configure())
Verify:
python -c "
import bittensor as bt
hp = bt.Subtensor(network='ws://127.0.0.1:9944').get_subnet_hyperparameters(netuid=2)
print(f'commit_reveal={hp.commit_reveal_weights_enabled}')
print(f'weights_rate_limit={hp.weights_rate_limit}')
print(f'tempo={hp.tempo}')
"
Expected: commit_reveal=False, weights_rate_limit=10, tempo=10.
Step 8 — Register and Stake
# Register validator
btcli subnets register --network ws://127.0.0.1:9945 --netuid "$NETUID" \
--wallet-name vali --hotkey default --no-prompt
# Register miner
btcli subnets register --network ws://127.0.0.1:9945 --netuid "$NETUID" \
--wallet-name miner --hotkey default --no-prompt
# Stake validator (small amount — AMM pool is thin)
btcli stake add --network ws://127.0.0.1:9945 --wallet-name vali --hotkey default \
--amount 100 --no-mev-protection --tolerance 1.0
# When prompted for netuid, enter your NETUID (e.g. 2)
Verify:
btcli subnet metagraph --netuid "$NETUID" --network ws://127.0.0.1:9944
Step 9 — Resolve Axon IP
export LOCAL_AXON_IP="$(python -c "
from cswon.utils.hotkey_extrinsics import get_preferred_local_axon_ip
ip = get_preferred_local_axon_ip()
print(ip or '127.0.0.1')
")"
echo "$LOCAL_AXON_IP"
Step 10 — Start Miner (first)
python neurons/miner.py \
--netuid "$NETUID" \
--subtensor.network local \
--subtensor.chain_endpoint ws://127.0.0.1:9944 \
--wallet.name miner --wallet.hotkey default \
--axon.port 8091 --axon.external_port 8091 --axon.external_ip "$LOCAL_AXON_IP" \
--logging.debug
Step 11 — Start Validator (separate terminal)
set -a && source .env && set +a
python neurons/validator.py \
--netuid "$NETUID" \
--subtensor.network local \
--subtensor.chain_endpoint ws://127.0.0.1:9944 \
--wallet.name vali --wallet.hotkey default \
--axon.port 8092 --axon.external_port 8092 --axon.external_ip "$LOCAL_AXON_IP" \
--logging.debug
Step 12 — Verify Operation
Expected validator log:
Selected task: data_001 type=data_transform synthetic=False at block 1234
Received 1 responses from 1 miners
Validated 1 responses
Scored 1 miners: mean=0.9500
Check emissions:
import bittensor as bt
s = bt.Subtensor(network='ws://127.0.0.1:9944')
mg = s.metagraph(netuid=2)
for i in range(int(mg.n)):
print(f'UID {i}: stake={mg.S[i]:.2f} incentive={mg.I[i]:.4f} dividend={mg.D[i]:.4f}')
Troubleshooting
| Symptom | Fix |
|---|---|
bad signature on set_weights | Disable commit-reveal (Step 7) |
SubtokenDisabled on staking | Run btcli subnet start first (Step 6) |
SlippageTooHigh on staking | Use --tolerance 1.0 or smaller amount |
No serving miners found | Start miner first, wait 10s |
docker restart lost state | Redo Steps 4–8 |
AdminActionProhibitedDuringWeightsWindow | Retry after 12 seconds |
Navigation
| ← Previous | 6.3 Running Locally (Staging) |
| → Next | 6.5 Testnet Deploy Guide |
| Index | Documentation Index |