Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release/2.2.4 #57

Merged
merged 9 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## 2.2.4 / 2024-05-20

## What's Changed
* fix subtensor scripts by @eclipsevortex in https://github.com/eclipsevortex/SubVortex/pull/56
* upgrade bittensor by @eclipsevortex in https://github.com/eclipsevortex/SubVortex/pull/58
* implement penalty factor by @eclipsevortex in https://github.com/eclipsevortex/SubVortex/pull/59


**Full Changelog**: https://github.com/eclipsevortex/SubVortex/compare/v2.2.3...v2.2.4

## 2.2.3 / 2024-05-06

## What's Changed
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.2.3
2.2.4
118 changes: 118 additions & 0 deletions docs/features/incentive_mechanism.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
SubVortex's incentive mechanism will score miners based on multiple criteria of their subtensor node:

- **Availability** - Subtensor nodes must be reliable to ensure good uptime.
- **Latency** - Subtensor nodes must be efficient to ensure good performance.
- **Reliability** and Stability - Subtensor nodes must be efficient to ensure good service quality.
- **Global distribution** - Subtensor nodes must be worldwide to ensure a good reach.

The final score used to set the weight is an average of all these scores and will replace 10% of the weight of the previous weights.

To better understand the following, you need to grasp a few concepts:

- A miner is flagged as suspicious if it appears in the suspicious UID file. A penalty factor between ]0,1[ may be provided to adjust the scores accordingly depending on the use cases.
- A miner is considered verified if both the miner and subtensor are operational and accessible.

<br />

# Availability

This reward incentivizes miners to maintain high levels of uptime and accessibility.

To assign a score for each miner, we will establish a connection with the subtensor and retrieve the current block. The score will be determined by the success of getting that block.

The score will be computed based on these rules:

- If the miner is not verified, the score will be 0.
- If there are more than one miner on the same IP, the score will be 0.
- Otherwise, the score will be 1.

<br />

# Latency

This reward incentivizes miners to low-latency services and minimizes response times.

To assign a score to each miner, we will establish a connection with the subtensor and retrieve the current block. The score will be determined by the time taken to process that request, using a normalized method as part of the reward system.

The validator can be in a different country than the miner, so we will incorporate a distance-based weighting factor into the scoring formula.

The score will be computed based on these rules:

- If the miner is not verified, the score will be 0.
- If there are more than one miner on the same IP, the score will be 0.
- Otherwise, the score will be computed based on the time taken to request directly the subtensor, adding a tolerance based on the distance between validator/miner and normalise it against other miners. So the best miner will receive 1 and the worst will receive 0.

<br />

# Reliability and Stability

This reward incentivizes miners to have high levels of reliability and minimize the occurrence and impact of failures.

To assign a score to each miner, we will establish a connection with the subtensor and retrieve the current block. The score will be determined by computing the ratio of successes/attempts, using a normalized method as part of the reward system.

The score will be computed based on these rules:

- Otherwise the score will be # of attempts / # of success normalised with wilson.

<br />

# Global Distribution

This reward incentivizes miners to effectively distribute subtensors across different geographical locations to optimize performance and reduce latency for a better subnet experience.

The score will be computed based on these rules:

- If the miner is not verified, the score will be 0.
- If there are more than one miner on the same IP, the score will be 0.
- Otherwise, the score will be 1 / # of miners in that location (your miner included)

<br />

# Final score

The final score is the score for the current challenge. It will be computed as the weighted average of the scores above.

The weight for each score will be as follows:

- Availability: Weight will be **3** if the miner's subtensor is synchronized, and **1** otherwise.
- Latency: Weight will be **1**.
- Reliability: Weight will be **1**.
- Distribution: Weight will be **1**.

So, the final formula will be calculated using the following expression

```
final score = (
(availability weight * availability score) +
(latency weight * latency score) +
(reliability weight * reliability score) +
(distribution weight * distribution score)
) / (
availability weight +
latency weight +
reliability weight +
distribution weight
)
```

The final score can be overrided with

- 0 if the miner is suspicious with no penalty factor provided
- penalty factor if the miner is suspicious with penalty factor provided (new final score = final score \* penalty factor)

<br />

# Average Moving Score

The average moving score represents the score for all previous challenges. It is calculated by applying a weighting factor (alpha) to the current average moving score and the new score.

So, the final formula will be calculated using the following expression

```
average moving score = 0.1 * score * 0.9 previous average moving score
```

The average moving score can be overrided with

- 0 if the miner is suspicious with no penalty factor provided
- penalty factor if the miner is suspicious with penalty factor provided (new average moving score = average moving score \* penalty factor)
32 changes: 23 additions & 9 deletions neurons/miner.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,13 @@ def config(cls):
def __init__(self):
self.config = Miner.config()
self.check_config(self.config)
bt.logging(config=self.config, logging_dir=self.config.miner.full_path)
bt.logging(
config=self.config,
logging_dir=self.config.miner.full_path,
debug=True,
)
bt.logging.set_trace(self.config.logging.trace)
bt.logging._stream_formatter.set_trace(self.config.logging.trace)
bt.logging.info(f"{self.config}")

# Show miner version
Expand Down Expand Up @@ -126,10 +132,12 @@ def __init__(self):

# The axon handles request processing, allowing validators to send this process requests.
self.axon = bt.axon(
wallet=self.wallet, config=self.config, external_ip=bt.net.get_external_ip()
wallet=self.wallet,
config=self.config,
external_ip=bt.utils.networking.get_external_ip(),
)
bt.logging.info(f"Axon {self.axon}")

# Attach determiners which functions are called when servicing a request.
bt.logging.info("Attaching forward functions to axon.")
self.axon.attach(
Expand All @@ -143,8 +151,9 @@ def __init__(self):
f"Serving axon {self.axon} on network: {self.subtensor.chain_endpoint} with netuid: {self.config.netuid}"
)
self.axon.serve(netuid=self.config.netuid, subtensor=self.subtensor)

# Check there is not another miner running on the machine
bt.logging.debug(f"Checking number of miners on same ip")
number_of_miners = len(
[axon for axon in self.metagraph.axons if self.axon.external_ip == axon.ip]
)
Expand Down Expand Up @@ -187,7 +196,7 @@ def _score(self, synapse: Score) -> Score:
bt.logging.success(f"[{validator_uid}] Score {synapse.score}")

synapse.version = THIS_VERSION

return synapse

def blacklist_score(self, synapse: Score) -> typing.Tuple[bool, str]:
Expand Down Expand Up @@ -262,10 +271,11 @@ def run_miner():
This function initializes and runs the neuron. It handles the main loop, state management, and interaction
with the Bittensor network.
"""

Miner().run_in_background_thread()

miner = None
try:
miner = Miner()
miner.run_in_background_thread()

while 1:
time.sleep(1)
except KeyboardInterrupt:
Expand All @@ -275,7 +285,11 @@ def run_miner():
bt.logging.error(traceback.format_exc())
bt.logging.error(f"Unhandled exception: {e}")
sys.exit(1)
finally:
if miner:
bt.logging.info("Stopping axon")
miner.axon.stop()


if __name__ == "__main__":
run_miner()
run_miner()
11 changes: 9 additions & 2 deletions neurons/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,14 @@ def __init__(self, config=None):
self.config = Validator.config()
self.config.merge(base_config)
self.check_config(self.config)
bt.logging(config=self.config, logging_dir=self.config.neuron.full_path)
bt.logging(
config=self.config,
logging_dir=self.config.neuron.full_path,
debug=True,
)
bt.logging.set_trace(self.config.logging.trace)
bt.logging._stream_formatter.set_trace(self.config.logging.trace)
bt.logging.info(f"{self.config}")

# Show miner version
bt.logging.debug(f"validator version {THIS_VERSION}")
Expand Down Expand Up @@ -204,7 +211,7 @@ async def run(self):
load_state(self)

# Monitor miners
self.monitor = Monitor()
self.monitor = Monitor(self.config.netuid)
self.monitor.start()

try:
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
bittensor==6.9.3
bittensor==6.12.1
torch==2.0.1
redis==5.0.1
aioredis==2.0.1
wandb==0.16.5
loguru==0.7.0
Loading