diff --git a/README.md b/README.md index a0cc4d7..b93ca46 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ - # Bittensor Subnet Template This repository provides a minimal template for setting up a simple Bittensor subnet with a miner and a validator. The miner and validator communicate using a custom protocol defined in `protocol.py`. This template serves as a starting point for developers interested in building on the Bittensor network. @@ -57,13 +56,15 @@ Before you begin, ensure you have the following installed: ## Setup Instructions -### 1. Clone the Repository +### 1. Fork and clone the Repository + +Fork the [subnet template](https://github.com/opentensor/subnet-template) repository to create a copy of the repository under your GitHub account. -Clone this repository to your local machine: +Next, clone this repository to your local machine and change directory ask shown: ```bash -git clone https://github.com/yourusername/bittensor_subnet.git -cd bittensor_subnet +git clone https://github.com/YOUR_USERNAME/subnet_template.git +cd subnet_template ``` ### 2. Install Dependencies @@ -111,61 +112,57 @@ Register both the miner and validator on the Bittensor network. - **Register the Miner**: ```bash - btcli s register --wallet.name mywallet --wallet.hotkey miner_hotkey --subtensor.network finney + btcli s register --wallet.name mywallet --wallet.hotkey miner_hotkey --subtensor.network NETWORK ``` - **Register the Validator**: ```bash - btcli s register --wallet.name mywallet --wallet.hotkey validator_hotkey --subtensor.network finney + btcli s register --wallet.name mywallet --wallet.hotkey validator_hotkey --subtensor.network NETWORK ``` -> **Note**: Replace `finney` with the name of the network you are connecting to if different. +> **Note**: Replace `NETWORK` with the name of the network you are connecting to if different. --- ## Running the Miner and Validator -### Running the Miner +### Start the miner process -In one terminal window, navigate to the project directory and run: +To start the miner, run the following Python script in the `subnet-template` directory: -```bash -python miner.py --wallet.name mywallet --wallet.hotkey miner_hotkey --subtensor.network finney --axon.port 8901 +```sh +python miner.py --wallet.name WALLET_NAME --wallet.hotkey HOTKEY --netuid NETUID --axon.port 8901 --subtensor.network NETWORK ``` -**Arguments**: +The script launches an Axon server on port `8901`, which the miner uses to receive incoming requests from validators. -- `--wallet.name`: The name of the wallet. -- `--wallet.hotkey`: The hotkey name for the miner. -- `--subtensor.network`: The Bittensor network to connect to. +### Start the validator process -### Running the Validator +To start the validator process, run the following Python script in the `subnet-template` directory: -In another terminal window, navigate to the project directory and run: - -```bash -python validator.py --wallet.name mywallet --wallet.hotkey validator_hotkey --subtensor.network finney +```sh +python validator.py --wallet.name WALLET_NAME --wallet.hotkey HOTKEY --netuid NETUID --subtensor.network NETWORK ``` +This script begins the process of sending inputs to the miners and setting weights based on miner responses. + **Arguments**: - `--wallet.name`: The name of the wallet. - `--wallet.hotkey`: The hotkey name for the validator. +- `--netuid`: The uid of the subnet in the network. - `--subtensor.network`: The Bittensor network to connect to. --- ## Monitoring and Logging -Both the miner and validator will output logs to the console and save logs to files in the following directory structure: +Use the `--logging.info` flag to print miner and validator log messages directly to the console. This helps you monitor activity in real time. For example +```sh +python validator.py --wallet.name WALLET_NAME --wallet.hotkey HOTKEY --netuid NETUID --subtensor.network NETWORK --logging.info ``` -~/.bittensor/wallets///netuid// -``` - -- **Miner Logs**: Located in the `miner` directory. -- **Validator Logs**: Located in the `validator` directory. You can monitor these logs to observe the interactions and performance metrics. @@ -203,7 +200,7 @@ else: ### Changing Network Parameters -You can adjust network parameters like `netuid`, timeouts, and other settings via command-line arguments or by modifying the code. +You can adjust network parameters like `netuid`, timeouts, and other settings via command-line arguments or by modifying the code in the `miner.py` and `validator.py`. --- diff --git a/validator.py b/validator.py index ef3bb36..ca5d4b0 100644 --- a/validator.py +++ b/validator.py @@ -14,12 +14,12 @@ def __init__(self): self.setup_logging() self.setup_bittensor_objects() self.my_uid = self.metagraph.hotkeys.index(self.wallet.hotkey.ss58_address) - self.scores = [1.0] * len(self.metagraph.S) + self.scores = [0] * len(self.metagraph.S) self.last_update = self.subtensor.blocks_since_last_update( self.config.netuid, self.my_uid ) self.tempo = self.subtensor.tempo(self.config.netuid) - self.moving_avg_scores = [1.0] * len(self.metagraph.S) + self.moving_avg_scores = [0] * len(self.metagraph.S) self.alpha = 0.1 def get_config(self): @@ -99,8 +99,9 @@ def setup_bittensor_objects(self): # Set up initial scoring weights for validation. bt.logging.info("Building validation weights.") - self.scores = [1.0] * len(self.metagraph.S) - bt.logging.info(f"Weights: {self.scores}") + self.scores = [0] * len(self.metagraph.S) + weights_with_uids = [(int(self.metagraph.uids[i]), score) for i, score in enumerate(self.scores)] + bt.logging.info(f"Weights (uid, weight): {weights_with_uids}") def run(self): # The Main Validation Loop. @@ -116,38 +117,65 @@ def run(self): axons=self.metagraph.axons, synapse=synapse, timeout=12 ) bt.logging.info(f"sending input {synapse.dummy_input}") - if responses: - responses = [ - response.dummy_output - for response in responses - if response is not None - ] - - # Log the results. - bt.logging.info(f"Received dummy responses: {responses}") - - # Adjust the length of moving_avg_scores to match the number of responses - if len(self.moving_avg_scores) < len(responses): - self.moving_avg_scores.extend( - [1] * (len(responses) - len(self.moving_avg_scores)) - ) - - # Adjust the scores based on responses from miners and update moving average. - for i, resp_i in enumerate(responses): - current_score = 1 if resp_i == synapse.dummy_input * 2 else 0 - self.moving_avg_scores[i] = ( - 1 - self.alpha - ) * self.moving_avg_scores[i] + self.alpha * current_score - - bt.logging.info(f"Moving Average Scores: {self.moving_avg_scores}") + + # Log the results with UIDs showing input and output + responses_with_uids = [] + for i, response in enumerate(responses): + uid = int(self.metagraph.uids[i]) + if response is not None and response.dummy_output is not None: + responses_with_uids.append({ + 'uid': uid, + 'input': response.dummy_input, + 'output': response.dummy_output + }) + else: + responses_with_uids.append({ + 'uid': uid, + 'input': synapse.dummy_input, + 'output': None + }) + bt.logging.info(f"Received responses: {responses_with_uids}") + + # Filter successful responses for logging with UIDs + successful_responses_with_uids = [] + for i, response in enumerate(responses): + if response is not None: + successful_responses_with_uids.append((int(self.metagraph.uids[i]), response.dummy_output)) + bt.logging.info(f"Successful responses (uid, response): {successful_responses_with_uids}") + + # Score all miners based on their responses + for i, response in enumerate(responses): + if response is not None: + # Miner responded - score based on correctness + current_score = 1 if response.dummy_output == synapse.dummy_input * 2 else 0 + self.moving_avg_scores[i] = ( + (1 - self.alpha) * self.moving_avg_scores[i] + + self.alpha * current_score + ) + else: + # Miner didn't respond - set score to 0 + self.moving_avg_scores[i] = ( + (1 - self.alpha) * self.moving_avg_scores[i] + + self.alpha * 0 + ) + + # Create list of (uid, score) tuples + scores_with_uids = [(int(self.metagraph.uids[i]), score) for i, score in enumerate(self.moving_avg_scores)] + bt.logging.info(f"Moving Average Scores (uid, score): {scores_with_uids}") self.last_update = self.subtensor.blocks_since_last_update( self.config.netuid, self.my_uid ) # set weights once every tempo total = sum(self.moving_avg_scores) - weights = [score / total for score in self.moving_avg_scores] - bt.logging.info(f"[blue]Setting weights: {weights}[/blue]") + if total > 0: + weights = [score / total for score in self.moving_avg_scores] + else: + # If no miners responded, set zero weights + weights = [0.0] * len(self.moving_avg_scores) + # Create list of (uid, weight) tuples + weights_with_uids = [(int(self.metagraph.uids[i]), weight) for i, weight in enumerate(weights)] + bt.logging.info(f"[blue]Setting weights (uid, weight): {weights_with_uids}[/blue]") # Update the incentive mechanism on the Bittensor blockchain. self.subtensor.set_weights( netuid=self.config.netuid,