A Bittensor subnet where validators continuously generate novel ARC‑AGI‑2 problems and score miners based on quality and latency
- Validators
- Discover registered miners from chain, generate synthetic ARC‑AGI‑2 tasks, dispatch queries, score responses, and push on‑chain weights by performance.
- Persists results + metrics to Postgres for analytics and stability.
- Miners
- Expose a minimal HTTP API (FastAPI) that receives ARC tasks and returns predicted grids.
- You can plug your own solver (LLM, search, program synthesis, classical vision, HRMs, etc).
hone/
├── common/ # shared utilities
│ ├── chain.py # Bittensor chain interface
│ ├── constants.py
│ ├── epistula.py # message signing/verification
│ ├── mock_chain.py # mock chain for local tests
│ └── utils.py
├── validator/
│ ├── Dockerfile
│ ├── config.py
│ ├── cycle.py # main validation loop
│ ├── db.py # asyncpg DB client + queries
│ ├── discovery.py # miner discovery from chain
│ ├── main.py # entrypoint
│ ├── query.py # miner query client
│ ├── scoring.py # scoring & weight calc
│ ├── requirements.txt
│ ├── docker-compose.yml # production (real chain)
│ ├── docker-compose.test.yml # local test (mock chain + 3 miners)
│ └── sql/
│ └── init.sql # DB schema (Postgres)
└── miner/
├── Dockerfile
├── __init__.py
├── config.py
├── handlers.py # request handlers
├── main.py # FastAPI app
└── arc/
└── models.py # request/response schemas
└── solver.py # plug your solver here
├── task_queue.py # async job mgmt
├── keypair.py # signing if needed
├── health.py # liveness/readiness
├── query.py # (client helpers, if used)
├── check_task.py # background check helpers
└── requirements.txt
- Python 3.10+
- Docker & Docker Compose
- Bittensor installed (
btcliavailable) - A wallet with some TAO (Finney testnet or mainnet)
# Coldkey
btcli wallet new_coldkey --wallet.name default
# Hotkeys
btcli wallet new_hotkey --wallet.name default --wallet.hotkey validator
btcli wallet new_hotkey --wallet.name default --wallet.hotkey miner[!NOTE] Wallet files location Store wallet files on the host under
~/.bittensor/wallets.
The validator and miner containers mount this directory read‑only.
Minimum:
- 4 CPU
- 4gb RAM
- 10gb disk
Create validator/.env (or use your CI secrets).
Defaults shown match validator/docker-compose.yml:
# ---- Chain ----
CHAIN_ENDPOINT=wss://entrypoint-finney.opentensor.ai:443
NETUID=5
# ---- Wallets ----
WALLET_NAME=default
WALLET_HOTKEY=validator
WALLET_PATH= # optional custom path
# ---- DB ----
DB_URL=postgresql://postgres:postgres@db:5432/hone
# ---- Cycle config ----
CYCLE_DURATION=30 # blocks (≈ 6 min on Finney)
# ---- Logging ----
LOG_LEVEL=INFONote
The compose file will also pass DB_URL explicitly.
If you keep both, environment usually wins over .env.
# Register validator
btcli subnet register --netuid 5 --wallet.name default --wallet.hotkey validator
# Stake TAO
btcli stake add --wallet.name default --wallet.hotkey validator --amount 100From validator/:
# Bring up Postgres + Adminer + Validator
docker-compose up -d
# Follow logs
docker-compose logs -f validatorThis will:
- Start Postgres 15 with schema applied from
sql/init.sql - Expose Adminer on
${ADMINER_PORT:-8080}(optional UI) - Start the validator on
${VALIDATOR_PORT:-8092}
Schema: (from sql/init.sql)
miners(uid, hotkey, ip, port, stake, last_update_block, ...)query_results(...)with exact_match, partial_correctness, grid_similarity, efficiency_score, response_time, problem_idscores(...)with aggregate metrics
Create miner/.env:
# ---- Wallet ----
WALLET_NAME=default
WALLET_HOTKEY=miner
# ---- Server ----
HOST=0.0.0.0
MINER_PORT=8091
LOG_LEVEL=INFO
# ---- Testing toggles ----
SKIP_EPISTULA_VERIFY=false # true for local dev onlyIf using LLMs, set your model/provider secrets as needed (OPENAI_API_KEY & OPENAI_MODEL).
# Register the miner identity on the subnet
btcli subnet register --netuid 5 --wallet.name default --wallet.hotkey miner
# Set public IP + port on‑chain so the validator can discover you
python tools/post_ip_chain.py \
--wallet-name default \
--hotkey miner \
--ip YOUR_PUBLIC_IP \
--port 8091 # or any other port you're using[!TIP] Ensure ports are open Ensure your firewall allows inbound traffic to the miner port.
From the repo root (or miner/):
docker build -t hone-miner miner/
docker run -d --name miner \
-p 8091:8091 \
-v ~/.bittensor/wallets:/root/.bittensor/wallets:ro \
--env-file miner/.env \
hone-miner
docker logs -f minerTip
The miner serves FastAPI endpoints and should respond healthily at /health.
- Discovery (
discovery.py): Pull registered miners from chain (common/chain.py), ingest IP/port + stake. - Cycle Loop (
cycle.py):- For
CYCLE_DURATIONblocks:- Generate ARC‑AGI‑2 problem (
validator/synthetics/arc_agi2_generator.py). - Query all miners concurrently (
query.py, Epistula‑signed requests). - Score responses (
scoring.py) using:- Exact match (≈40% weight)
- Partial correctness (≈30%)
- Grid/pixel similarity (≈20%)
- Efficiency / latency (≈10%)
- Persist results to Postgres (
db.py).
- Generate ARC‑AGI‑2 problem (
- Aggregate last N cycles into a score per miner.
- For
- Weight Setting: Push updated weights on‑chain (via chain interface).
Tip
Exact weights and confi constants can be tuned in scoring.py.
Responses are polled (for now 50 attempts, 10s intervals between them).
GET /health→ basic liveness/readiness (fromhealth.py)POST /query→ solve an ARC task and return predicted grid- Typical request contains problem definition & input grid(s)
- Response returns an output grid
- The solver entrypoint is in
solver.py. Replace baseline logic with your own approach (LLM, search, programs, HRMs, etc ). - Request handlers live in
handlers.py. Background checks / queueing intask_queue.pyand helpers incheck_task.py.
Warning
Validator <-> miner messages are signed/verified using Epistula (common/epistula.py).
In production, do not set SKIP_EPISTULA_VERIFY=true.
chmod +x test_local.sh
./test_local.shThis will:
- Start Postgres
- Launch 3 mock miners (on different ports)
- Run validator with mock chain (
USE_MOCK_CHAIN=true) - Stream scoring, queries, and weight updates in real time
From validator/:
docker-compose -f docker-compose.test.yml up
# validator on 8092, miners on 8091/8093/8094, Adminer on 8081
# Tail logs
docker logs validator-validator-1
docker logs validator-miner1-1
# Teardown
docker-compose -f docker-compose.test.yml down -vNote
The test compose sets USE_MOCK_CHAIN=true, SKIP_EPISTULA_VERIFY=true, and points DB_URL to the test DB (hone_test).
# Chain (testnet / mainnet)
CHAIN_ENDPOINT=wss://test.finney.opentensor.ai:443
NETUID=5
# Wallets
WALLET_NAME=default
WALLET_HOTKEY=validator
WALLET_PATH=
# DB
DB_URL=postgresql://postgres:postgres@db:5432/hone
# Cycles
CYCLE_DURATION=30
# Testing flags (for local only)
USE_MOCK_CHAIN=false
SKIP_EPISTULA_VERIFY=false
# Logging
LOG_LEVEL=INFOWALLET_NAME=default
WALLET_HOTKEY=miner
HOST=0.0.0.0
MINER_PORT=8091
LOG_LEVEL=INFO
# Testing only
SKIP_EPISTULA_VERIFY=falseTip
If you use LLMs (e.g., OpenAI), include the relevant keys (e.g., OPENAI_API_KEY) and model names in your environment. miner/requirements.txt includes openai for a reference baseline.
Applied from validator/sql/init.sql at container start:
- miners: on‑chain view of registered miners + metadata
- query_results: per‑task metrics and raw response JSON
- scores: aggregated performance features for weight setting
Indexes are created for block, uid, and timestamp fields for efficient querying.
- Validator cannot connect to DB
- Check
DB_URLand thatdbservice is healthy:docker ps,docker logs validator-db-1
- Check
- Miner not discovered
- Ensure you registered miner hotkey on correct
NETUID. - Post correct public IP/port on‑chain and open firewall/NAT for the port.
- Ensure you registered miner hotkey on correct
- Signature/verification failures
- Set
SKIP_EPISTULA_VERIFY=falsein production on both sides. - Verify the miner and validator use the intended wallets.
- Set
- No scores updating
- Check
CYCLE_DURATIONand validator logs. Ensure miners respond within the timeout (~30s).
- Check
- Wallets are mounted read‑only from host:
~/.bittensor/wallets:/root/.bittensor/wallets:ro - Keep
SKIP_EPISTULA_VERIFY=falsein production. - Never expose Adminer to the public internet without access control.