Skip to content

Latest commit

 

History

History
456 lines (303 loc) · 12.5 KB

File metadata and controls

456 lines (303 loc) · 12.5 KB

Miner Tutorial

Table of contents

1. Requirements

2. TL;DR

2.1. Clone the code and implement your model

  • Clone the Synth subnet repository.
  • Modify the implementation of this function to run your own model: simulations.py#L25
  • Use all parameters from the prompt except sigma, which you may ignore.

2.2. Check that your model generates a valid response

  • Run this command to test your model locally:
python synth/miner/run.py
  • If your format is correct, you’ll see the output:
$ CORRECT

2.3. Get a VM and open port 8091

  • Ensure port 8091 is open in your cloud provider's ingress rules.
  • Configure your VM's firewall to allow inbound traffic on this port.

2.4. Create or import a Bittensor wallet

  • Use btcli to:
    • Create or import a wallet.
    • Add funds.
    • Register your hotkey (this will purchase a UID).

2.5. Launch your miner with PM2

  • Create a new file called miner.local.config.js using the config from this link: miner.config.js#L1
  • Modify the wallet name and hotkey name as needed.
  • Start the miner with PM2:
pm2 start miner.local.config.js

2.6. Verify the port is open

2.7. Track your miner performance

2.8. Check your prediction validation

  • View validation status of your last submission:
https://api.synthdata.co/validation/miner?uid=<your UID>

2.9. More information

3. Getting started

3.1. Open ports

To ensure a miner can successfully connect to the network, the port 8091 MUST be open.

Back to top ^

3.1.1. Check open ports

Before the beginning, check what ports are open:

nmap localhost

which should output:

$ nmap localhost

Starting Nmap 7.80 ( https://nmap.org ) at 2025-07-15 12:43 CEST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000079s latency).
Not shown: 998 closed ports
PORT    STATE SERVICE
22/tcp  open  ssh
80/tcp  open  http
631/tcp open  ipp

Nmap done: 1 IP address (1 host up) scanned in 0.04 seconds

⚠️ NOTE: You can install nmap via sudo apt install nmap.

Back to top ^

3.1.2. Open using ufw

It is RECOMMENDED that ufw (Uncomplicated Firewall) is used to handle port connections.

ufw is a minimal front-end for managing iptables rules. It allows you to easily open ports with simple commands

First, enable ufw using:

sudo ufw enable

Next, allow incoming traffic on the correct port:

sudo ufw allow 8091

To ensure the port is accessible and the rule is active, execute:

sudo ufw status

which should output:

$ sudo ufw status

Status: active

To                         Action      From
--                         ------      ----
8091                       ALLOW       Anywhere
8091 (v6)                  ALLOW       Anywhere (v6)

Back to top ^

3.1.3. Test open port

Using nmap you can check if the port is open using:

nmap -p 8091 localhost

which should output:

$ nmap -p 8091 localhost

Starting Nmap 7.80 ( https://nmap.org ) at 2025-07-15 12:50 CEST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000073s latency).

PORT     STATE  SERVICE
8091/tcp open jamlink

Nmap done: 1 IP address (1 host up) scanned in 0.03 seconds

Back to top ^

3.2. Add ingress rules (optional)

If you have set up your miner on a remote server/VM using a cloud provider (GCP, AWS, Azure, e.t.c.), you will also need to add an ingress rule on port TCP/8091 to allow for incoming connections.

Please refer to your cloud provider's documentation on adding ingress rules to your server.

Back to top ^

3.3. Set up the miner

3.3.1. Install dependencies

Install rust:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Add the required apt repositories:

sudo add-apt-repository ppa:deadsnakes/ppa

⚠️ NOTE: The deadsnakes repository, while unofficial, it is hugely popular and used by many Python projects.

Install Python and Node/npm:

sudo apt update && \
  sudo apt install nodejs npm python3.11 python3.11-venv pkg-config

Install PM2 via npm:

sudo npm install pm2 -g

Back to top ^

3.3.2. Clone the repository

Clone the synth subnet repository:

git clone https://github.com/synthdataco/synth-subnet.git

Change directory to the project root

cd ./synth-subnet

Back to top ^

3.3.3. Set up & activate Python virtual environment

Install uv if you don't have it:

curl -LsSf https://astral.sh/uv/install.sh | sh
source $HOME/.local/bin/env

⚠️ NOTE: The second command puts uv on the PATH of the current shell; new shells pick it up automatically.

Create the virtual environment and install all locked dependencies:

uv sync

Activate and switch to the newly created Python virtual environment:

source .venv/bin/activate
export PYTHONPATH=.

⚠️ NOTE: This should activate the .venv environment, and you will see the command line prefixed with (.venv).

Back to top ^

3.4. Create a wallet

💡 TIP: For a more extensive list of the Bittensor CLI commands see here.

3.4.1. Create the cold/hot wallets

You will need to create the cold and hot wallets:

btcli wallet create \
  --wallet.name miner \
  --wallet.hotkey default

🚨 WARNING: You must ensure your wallets have enough TAO (0.25 should be enough) to be able to start mining. For testnet, check out the faucet on the Discord.

Back to top ^

3.4.2. Register the wallet

Next, register the wallets by acquiring a slot on the Bittensor subnet:

btcli subnet register \
  --wallet.name miner \
  --wallet.hotkey default \
  --netuid 50

if you want to try it on testnet first, run the following command:

btcli subnet register \
  --wallet.name miner \
  --wallet.hotkey default \
  --network test \
  --netuid 247

Back to top ^

3.4.3. Verify the wallet registration (optional)

You can verify the wallet registration by running:

btcli wallet overview \
  --wallet.name miner \
  --wallet.hotkey default

And, you can also check the network metagraph:

btcli subnet metagraph \
  --netuid 50

for testnet it's:

btcli subnet metagraph \
  --network test \
  --netuid 247

Back to top ^

3.5. Run the miner

3.5.1. Start the miner

Simply start PM2 with the miner config:

pm2 start miner.config.js

for testnet use:

pm2 start miner.test.config.js

Back to top ^

3.5.2. Check the miner is running (optional)

You can check if the miner is running by using:

pm2 list

Back to top ^

4. Protect your predictions

Your predictions are valuable. To stop unauthorized parties from querying your miner and copying your responses, make sure only legitimate validators can reach your miner port.

4.1. Restrict ingress to validator IPs

We RECOMMEND configuring your firewall with an allow-list for the ingress IPs on your miner port (8091).

Legitimate validators publish their IP on the Bittensor chain, and these IPs are visible on the metagraph:

https://taostats.io/subnets/50/metagraph?order=validator_trust%3Adesc

Your miner should only answer requests from a validator that:

  • Stakes at least 65000.
  • Publishes its IP on chain.
  • Holds the validator permit.

Maintaining this allow-list by hand is tedious, since validator IPs may change over time. We provide a chain-sync script that keeps your ufw allow-list in sync with the eligible validators on the metagraph automatically:

synth/miner/chain_sync.py

It admits only validators that hold the validator permit and stake at least --blacklist.validator_min_stake (default 65000), then adds/removes per-IP rules on each cycle. Use --dry-run to preview which IPs would be allowed without touching ufw:

python synth/miner/chain_sync.py --axon_port 8091 --dry-run

To run it for real (as root, so it can edit ufw):

python synth/miner/chain_sync.py --axon_port 8091

Back to top ^

4.2. Update and run the blacklist function

We ask all miners to run their miners with the blacklist function:

neurons/miner.py#L58 In particular, it includes a security fix that rejects unsigned requests:

if not synapse.dendrite.signature:
    bt.logging.warning(
        f"Blacklisting unsigned request claiming hotkey "
        f"{synapse.dendrite.hotkey}"
    )
    return True, "Missing signature"

The new blacklist function applies a minimum of 65000 stake by default. This is why you MUST update your blacklist function and restart all your miners.

Back to top ^

4.3. Blacklist parameters

  • --blacklist.validator_min_stake 65000 — gates requests by validator stake. The blacklist enforces a minimum of 65000, even if you configure a lower value. Back to top ^