diff --git a/Makefile b/Makefile
index f36e0e3..802eb95 100644
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@ ifeq ($(NETWORK),localnet)
else ifeq ($(NETWORK),testnet)
netuid = 256
else ifeq ($(NETWORK),finney)
- #netuid = 64
+ netuid = 55
$(error Finney network not supported yet)
endif
diff --git a/README.md b/README.md
index f379af8..c2c384c 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,15 @@
# **CoinMetrics Precog Subnet**
+
+
+| **Testnet UID:** 256
**Mainnet UID:** 55 |
+| - |
+
+
+
+
+
| | |
| :-: | :-: |
| **Status** |
|
@@ -35,6 +44,29 @@ The incentive mechanism was specifically designed to reward precise statements o
| 2 vCPUs | 2 vCPUs |
---
+
+## Prerequisites
+
+Before beginning, ensure you have:
+
+1. **Python Installation**
+ - Python version 3.9, 3.10, or 3.11 installed
+ - We recommend using `pyenv` for Python version management
+
+2. **Bittensor Knowledge**
+ - Understanding of the Bittensor ecosystem and wallet management
+ - Familiarity with creating and managing Bittensor wallets
+ - Review the [Bittensor Wallet Documentation](https://docs.bittensor.com/getting-started/wallets)
+ - For general understanding, see the [Bittensor Documentation](https://docs.bittensor.com/)
+
+3. **Poetry**
+ - Basic understanding of Poetry for dependency management
+ - See the [Poetry Documentation](https://python-poetry.org/docs/) for installation and usage
+
+4. **System Requirements**
+ - NodeJS and NPM (for PM2 installation)
+ - Basic understanding of command-line interfaces
+
## Installation
First, install PM2:
@@ -70,10 +102,8 @@ poetry install
---
## Configuration
-### Makefile
-
### .env Files
-Copy the example `.env` files and edit all desired values:
+Copy the example `.env` files and edit all desired values. If you are running a validator, you will only need to copy the .env.validator file. If you are running a miner, you will only need to copy the .env.miner file:
#### .env.validator
```
@@ -81,18 +111,61 @@ cp .env.validator.example .env.validator
```
Edit `.env.validator` with your desired values.
+```
+# Network Configuration
+# Options: localnet, testnet, finney
+NETWORK=testnet
+
+# Wallet Configuration
+COLDKEY=your_validator_coldkey
+VALIDATOR_HOTKEY=your_validator_hotkey
+
+# Node Configuration
+VALIDATOR_NAME=validator
+VALIDATOR_PORT=8091
+
+# Logging
+# Options: info, debug, trace
+LOGGING_LEVEL=debug
+```
+
#### .env.miner
```
cp .env.miner.example .env.miner
```
Edit `.env.miner` with your desired values.
-### Wandb
-Wandb integration is planned for mainnet launch and does not currently work.
+```# Network Configuration
+# Options: localnet, testnet, finney
+NETWORK=testnet
+
+# Wallet Configuration
+COLDKEY=your_miner_coldkey
+MINER_HOTKEY=your_miner_hotkey
+
+# Node Configuration
+MINER_NAME=miner
+# This port must be open to accept incoming TCP connections.
+MINER_PORT=8092
+
+# Miner Settings
+TIMEOUT=16
+VPERMIT_TAO_LIMIT=2
+
+#Adjust this function if you would like to specify a custom forward function
+FORWARD_FUNCTION=base_miner
+
+# Logging
+# Options: info, debug, trace
+LOGGING_LEVEL=debug
+```
---
## Deployment
+### Registering a Hotkey
+Once you have configured your .env files as per the instructions above, you can register a miner with `make register ENV_FILE=.env.miner` or register a validator with `make register ENV_FILE=.env.validator`.
+
### Running a Miner
Base miner:
1. Run the command:
diff --git a/docs/Release Notes.md b/docs/Release Notes.md
index ee8f021..43408dd 100644
--- a/docs/Release Notes.md
+++ b/docs/Release Notes.md
@@ -1,6 +1,11 @@
Release Notes
=============
+1.0.0
+-----
+Released on January 14th 2025
+- Release to mainnet
+
0.3.0
-----
Released on January 7th 2025
diff --git a/precog/utils/bittensor.py b/precog/utils/bittensor.py
index ce48803..b283c0f 100644
--- a/precog/utils/bittensor.py
+++ b/precog/utils/bittensor.py
@@ -31,32 +31,8 @@ def setup_bittensor_objects(self):
self.metagraph = self.subtensor.metagraph(self.config.netuid)
self.wallet = bt.wallet(config=self.config)
self.dendrite = bt.dendrite(wallet=self.wallet)
+ self.axon = bt.axon(wallet=self.wallet, config=self.config, port=self.config.axon.port)
- # Initialize axon config
- axon_config = bt.axon.config()
- axon_config.max_workers = self.config.axon.max_workers
- axon_config.port = self.config.axon.port
- axon_config.ip = self.config.axon.ip
- axon_config.external_ip = self.config.axon.external_ip
- axon_config.external_port = self.config.axon.external_port
- self.config.axon = axon_config
-
- # Debug prints
- bt.logging.debug(f"Axon config - port: {self.config.axon.port}")
- bt.logging.debug(f"Axon config - ip: {self.config.axon.ip}")
- bt.logging.debug(f"Axon config - external_ip: {self.config.axon.external_ip}")
- bt.logging.debug(f"Axon config - external_port: {self.config.axon.external_port}")
- bt.logging.debug(f"Axon config - max_workers: {self.config.axon.max_workers}")
-
- self.axon = bt.axon(
- wallet=self.wallet,
- config=self.config,
- port=self.config.axon.port,
- ip=self.config.axon.ip,
- external_ip=self.config.axon.external_ip,
- external_port=self.config.axon.external_port,
- max_workers=self.config.axon.max_workers,
- )
# Connect the validator to the network.
if self.wallet.hotkey.ss58_address not in self.metagraph.hotkeys:
bt.logging.error(
diff --git a/precog/validators/weight_setter.py b/precog/validators/weight_setter.py
index 8780f04..c8cc71c 100755
--- a/precog/validators/weight_setter.py
+++ b/precog/validators/weight_setter.py
@@ -89,26 +89,61 @@ async def get_available_uids(self):
return miner_uids
async def resync_metagraph(self):
- """Resyncs the metagraph and updates the hotkeys and moving averages based on the new metagraph."""
+ """Resyncs the metagraph and updates the hotkeys, available UIDs, and MinerHistory.
+ Ensures all data structures remain in sync."""
+ # Resync subtensor and metagraph
self.subtensor = bt.subtensor(config=self.config, network=self.config.subtensor.chain_endpoint)
bt.logging.info("Syncing Metagraph...")
self.metagraph.sync(subtensor=self.subtensor)
bt.logging.info("Metagraph updated, re-syncing hotkeys, dendrite pool and moving averages")
- # Zero out all hotkeys that have been replaced.
+
+ # Get current state for logging
+ old_uids = set(self.available_uids)
+ old_history = set(self.MinerHistory.keys())
+ bt.logging.debug(f"Before sync - Available UIDs: {old_uids}")
+ bt.logging.debug(f"Before sync - MinerHistory keys: {old_history}")
+
+ # Update available UIDs
self.available_uids = asyncio.run(self.get_available_uids())
+ new_uids = set(self.available_uids)
+
+ # Process hotkey changes
for uid, hotkey in enumerate(self.metagraph.hotkeys):
- new_miner = uid not in self.hotkeys
- # replaced_miner will throw a key error if the uid is not in the hotkeys dict
+ new_miner = uid in new_uids and uid not in old_uids
if not new_miner:
replaced_miner = self.hotkeys[uid] != hotkey
else:
replaced_miner = False
+
if new_miner or replaced_miner:
bt.logging.info(f"Replacing hotkey on {uid} with {self.metagraph.hotkeys[uid]}")
- self.hotkeys = {uid: value for uid, value in enumerate(self.metagraph.hotkeys)}
+ self.moving_average_scores[uid] = 0
+ if uid in new_uids: # Only create history for available UIDs
+ self.MinerHistory[uid] = MinerHistory(uid, timezone=self.timezone)
+
+ # Update hotkeys dictionary
+ self.hotkeys = {uid: value for uid, value in enumerate(self.metagraph.hotkeys)}
+
+ # Ensure all available UIDs have MinerHistory entries
+ for uid in self.available_uids:
+ if uid not in self.MinerHistory:
+ bt.logging.info(f"Creating new MinerHistory for available UID {uid}")
self.MinerHistory[uid] = MinerHistory(uid, timezone=self.timezone)
self.moving_average_scores[uid] = 0
- self.scores = list(self.moving_average_scores.values())
+
+ # Clean up old MinerHistory entries
+ for uid in list(self.MinerHistory.keys()):
+ if uid not in new_uids:
+ bt.logging.info(f"Removing MinerHistory for inactive UID {uid}")
+ del self.MinerHistory[uid]
+
+ # Update scores list
+ self.scores = list(self.moving_average_scores.values())
+
+ bt.logging.debug(f"After sync - Available UIDs: {new_uids}")
+ bt.logging.debug(f"After sync - MinerHistory keys: {set(self.MinerHistory.keys())}")
+
+ # Save updated state
self.save_state()
def query_miners(self):
@@ -182,7 +217,13 @@ async def scheduled_prediction_request(self):
if is_query_time(self.prediction_interval, self.timestamp) or query_lag >= 60 * self.prediction_interval:
responses, self.timestamp = self.query_miners()
try:
+ bt.logging.debug(f"Processing responses for UIDs: {self.available_uids}")
+ bt.logging.debug(f"Number of responses: {len(responses)}")
+ for uid, response in zip(self.available_uids, responses):
+ bt.logging.debug(f"Response from UID {uid}: {response}")
+
rewards = calc_rewards(self, responses=responses)
+
# Adjust the scores based on responses from miners and update moving average.
for i, value in zip(self.available_uids, rewards):
self.moving_average_scores[i] = (
@@ -192,7 +233,19 @@ async def scheduled_prediction_request(self):
if not self.config.wandb.off:
log_wandb(responses, rewards, self.available_uids)
except Exception as e:
- bt.logging.error(f"Failed to calculate rewards with error: {e}")
+ import traceback
+
+ bt.logging.error(f"Failed to calculate rewards with error: {str(e)}")
+ bt.logging.error(f"Error type: {type(e)}")
+ bt.logging.error("Full traceback:")
+ bt.logging.error(traceback.format_exc())
+ bt.logging.error(f"Available UIDs: {self.available_uids}")
+ bt.logging.error(f"Response count: {len(responses)}")
+ bt.logging.error(f"MinerHistory keys: {list(self.MinerHistory.keys())}")
+ bt.logging.error(f"Full MinerHistory: {self.MinerHistory}")
+ for uid, response in zip(self.available_uids, responses):
+ bt.logging.error(f"UID {uid} response status: {getattr(response, 'status_code', 'unknown')}")
+ bt.logging.error(f"UID {uid} response type: {type(response)}")
else:
print_info(self)
diff --git a/pyproject.toml b/pyproject.toml
index 4d70659..79819cd 100755
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "precog"
-version = "0.3.0"
+version = "1.0.0"
description = "Bitcoin Price Prediction Subnet"
authors = ["Coin Metrics", "Yuma Group"]
readme = "README.md"
diff --git a/tests/test_package.py b/tests/test_package.py
index d94327e..89b0eb0 100644
--- a/tests/test_package.py
+++ b/tests/test_package.py
@@ -16,4 +16,4 @@ def setUp(self):
def test_package_version(self):
# Check that version is as expected
# Must update to increment package version successfully
- self.assertEqual(__version__, "0.3.0")
+ self.assertEqual(__version__, "1.0.0")