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

Sudo Commands #8

Merged
merged 4 commits into from
Aug 14, 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
163 changes: 159 additions & 4 deletions cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import asyncio
import os.path
import re
from typing import Optional, Coroutine, Collection
from typing import Optional, Coroutine

from bittensor_wallet import Wallet
from git import Repo
Expand All @@ -14,8 +14,8 @@
from websockets import ConnectionClosed
from yaml import safe_load, safe_dump

from src import defaults, utils
from src.commands import wallets, root, stake
from src import defaults, utils, HYPERPARAMS
from src.commands import wallets, root, stake, sudo
from src.subtensor_interface import SubtensorInterface
from src.bittensor.async_substrate_interface import SubstrateRequestException
from src.utils import console, err_console
Expand Down Expand Up @@ -162,6 +162,7 @@ class CLIManager:
:var wallet_app: the Typer app as it relates to wallet commands
:var root_app: the Typer app as it relates to root commands
:var stake_app: the Typer app as it relates to stake commands
:var sudo_app: the Typer app as it relates to sudo commands
:var not_subtensor: the `SubtensorInterface` object passed to the various commands that require it
"""

Expand All @@ -186,6 +187,7 @@ def __init__(self):
self.wallet_app = typer.Typer()
self.root_app = typer.Typer()
self.stake_app = typer.Typer()
self.sudo_app = typer.Typer()

# config alias
self.app.add_typer(
Expand Down Expand Up @@ -221,6 +223,14 @@ def __init__(self):
)
self.app.add_typer(self.stake_app, name="st", hidden=True)

# sudo aliases
self.app.add_typer(
self.sudo_app,
name="sudo",
short_help="Sudo commands, alias: `su`",
)
self.app.add_typer(self.sudo_app, name="su", hidden=True)

# config commands
self.config_app.command("set")(self.set_config)
self.config_app.command("get")(self.get_config)
Expand Down Expand Up @@ -267,6 +277,13 @@ def __init__(self):
self.stake_app.command("set-children")(self.stake_set_children)
self.stake_app.command("revoke-children")(self.stake_revoke_children)

# sudo commands
self.sudo_app.command("set")(self.sudo_set)
self.sudo_app.command("get")(self.sudo_get)

# subnets commands
# self.subnets_app.command("hyperparameters")(self.sudo_get)

def initialize_chain(
self,
network: Optional[str] = typer.Option("default_network", help="Network name"),
Expand Down Expand Up @@ -297,8 +314,16 @@ def _run_command(self, cmd: Coroutine) -> None:
"""
Runs the supplied coroutine with asyncio.run
"""

async def _run():
if self.not_subtensor:
async with self.not_subtensor:
await cmd
else:
await cmd

try:
return asyncio.run(cmd)
return asyncio.run(_run())
except ConnectionRefusedError:
err_console.print(
f"Connection refused when connecting to chain: {self.not_subtensor}"
Expand Down Expand Up @@ -2600,6 +2625,136 @@ def stake_revoke_children(
)
)

def sudo_set(
self,
network: Optional[str] = Options.network,
chain: Optional[str] = Options.chain,
wallet_name: str = Options.wallet_name,
wallet_path: str = Options.wallet_path,
wallet_hotkey: str = Options.wallet_hotkey,
netuid: int = Options.netuid,
param_name: str = typer.Option(
"", "--param", "--parameter", help="The subnet hyperparameter to set"
),
param_value: str = typer.Option(
"", "--value", help="The subnet hyperparameter value to set."
),
):
"""
# sudo set
Executes the `set` command to set hyperparameters for a specific subnet on the Bittensor network.

This command allows subnet owners to modify various hyperparameters of theirs subnet, such as its tempo,
emission rates, and other network-specific settings.

## Usage:
The command first prompts the user to enter the hyperparameter they wish to change and its new value.
It then uses the user's wallet and configuration settings to authenticate and send the hyperparameter update
to the specified subnet.

### Example usage:

```
btcli sudo set --netuid 1 --param 'tempo' --value '0.5'
```

#### Note:
This command requires the user to specify the subnet identifier (``netuid``) and both the hyperparameter
and its new value. It is intended for advanced users who are familiar with the network's functioning
and the impact of changing these parameters.
"""
if not param_name:
param_name = Prompt.ask(
"Enter hyperparameter", choices=list(HYPERPARAMS.keys())
)
if not param_value:
param_value = Prompt.ask(f"Enter new value for {param_name}")
wallet = self.wallet_ask(wallet_name, wallet_path, wallet_hotkey)
return self._run_command(
sudo.sudo_set_hyperparameter(
wallet,
self.initialize_chain(network, chain),
netuid,
param_name,
param_value,
)
)

def sudo_get(
self,
network: str = Options.network,
chain: str = Options.chain,
netuid: int = Options.netuid,
):
"""
# sudo get
Executes the `get` command to retrieve the hyperparameters of a specific subnet on the Bittensor network.

This command is used for both `sudo get` and `subnets hyperparameters`.

## Usage:
The command connects to the Bittensor network, queries the specified subnet, and returns a detailed list
of all its hyperparameters. This includes crucial operational parameters that determine the subnet's
performance and interaction within the network.

### Example usage:

```

$ btcli sudo get --netuid 1



Subnet Hyperparameters - NETUID: 1 - finney

HYPERPARAMETER VALUE

rho 10

kappa 32767

immunity_period 7200

min_allowed_weights 8

max_weight_limit 455

tempo 99

min_difficulty 1000000000000000000

max_difficulty 1000000000000000000

weights_version 2013

weights_rate_limit 100

adjustment_interval 112

activity_cutoff 5000

registration_allowed True

target_regs_per_interval 2

min_burn 1000000000

max_burn 100000000000

bonds_moving_avg 900000

max_regs_per_block 1

```

#### Note:
Users need to provide the `netuid` of the subnet whose hyperparameters they wish to view. This command is
designed for informational purposes and does not alter any network settings or configurations.
"""
return self._run_command(
sudo.get_hyperparameters(self.initialize_chain(network, chain), netuid)
)

def run(self):
self.app()

Expand Down
26 changes: 26 additions & 0 deletions src/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,29 @@ class logging:
"finney": "https://x.taostats.io",
},
}


HYPERPARAMS = {
"serving_rate_limit": "sudo_set_serving_rate_limit",
"min_difficulty": "sudo_set_min_difficulty",
"max_difficulty": "sudo_set_max_difficulty",
"weights_version": "sudo_set_weights_version_key",
"weights_rate_limit": "sudo_set_weights_set_rate_limit",
"max_weight_limit": "sudo_set_max_weight_limit",
"immunity_period": "sudo_set_immunity_period",
"min_allowed_weights": "sudo_set_min_allowed_weights",
"activity_cutoff": "sudo_set_activity_cutoff",
"network_registration_allowed": "sudo_set_network_registration_allowed",
"network_pow_registration_allowed": "sudo_set_network_pow_registration_allowed",
"min_burn": "sudo_set_min_burn",
"max_burn": "sudo_set_max_burn",
"adjustment_alpha": "sudo_set_adjustment_alpha",
"rho": "sudo_set_rho",
"kappa": "sudo_set_kappa",
"difficulty": "sudo_set_difficulty",
"bonds_moving_avg": "sudo_set_bonds_moving_average",
"commit_reveal_weights_interval": "sudo_set_commit_reveal_weights_interval",
"commit_reveal_weights_enabled": "sudo_set_commit_reveal_weights_enabled",
"alpha_values": "sudo_set_alpha_values",
"liquid_alpha_enabled": "sudo_set_liquid_alpha_enabled",
}
89 changes: 89 additions & 0 deletions src/bittensor/chain_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,95 @@ def from_neuron_info(cls, neuron_info: dict) -> "AxonInfo":
)


@dataclass
class SubnetHyperparameters:
"""Dataclass for subnet hyperparameters."""

rho: int
kappa: int
immunity_period: int
min_allowed_weights: int
max_weight_limit: float
tempo: int
min_difficulty: int
max_difficulty: int
weights_version: int
weights_rate_limit: int
adjustment_interval: int
activity_cutoff: int
registration_allowed: bool
target_regs_per_interval: int
min_burn: int
max_burn: int
bonds_moving_avg: int
max_regs_per_block: int
serving_rate_limit: int
max_validators: int
adjustment_alpha: int
difficulty: int
commit_reveal_weights_interval: int
commit_reveal_weights_enabled: bool
alpha_high: int
alpha_low: int
liquid_alpha_enabled: bool

@classmethod
def from_vec_u8(cls, vec_u8: list[int]) -> Optional["SubnetHyperparameters"]:
"""Returns a SubnetHyperparameters object from a ``vec_u8``."""
if len(vec_u8) == 0:
return None

decoded = from_scale_encoding(vec_u8, ChainDataType.SubnetHyperparameters)
if decoded is None:
return None

return SubnetHyperparameters.fix_decoded_values(decoded)

@classmethod
def list_from_vec_u8(cls, vec_u8: list[int]) -> list["SubnetHyperparameters"]:
"""Returns a list of SubnetHyperparameters objects from a ``vec_u8``."""
decoded = from_scale_encoding(
vec_u8, ChainDataType.SubnetHyperparameters, is_vec=True, is_option=True
)
if decoded is None:
return []

return [SubnetHyperparameters.fix_decoded_values(d) for d in decoded]

@classmethod
def fix_decoded_values(cls, decoded: dict) -> "SubnetHyperparameters":
"""Returns a SubnetInfo object from a decoded SubnetInfo dictionary."""
return SubnetHyperparameters(
rho=decoded["rho"],
kappa=decoded["kappa"],
immunity_period=decoded["immunity_period"],
min_allowed_weights=decoded["min_allowed_weights"],
max_weight_limit=decoded["max_weights_limit"],
tempo=decoded["tempo"],
min_difficulty=decoded["min_difficulty"],
max_difficulty=decoded["max_difficulty"],
weights_version=decoded["weights_version"],
weights_rate_limit=decoded["weights_rate_limit"],
adjustment_interval=decoded["adjustment_interval"],
activity_cutoff=decoded["activity_cutoff"],
registration_allowed=decoded["registration_allowed"],
target_regs_per_interval=decoded["target_regs_per_interval"],
min_burn=decoded["min_burn"],
max_burn=decoded["max_burn"],
max_regs_per_block=decoded["max_regs_per_block"],
max_validators=decoded["max_validators"],
serving_rate_limit=decoded["serving_rate_limit"],
bonds_moving_avg=decoded["bonds_moving_avg"],
adjustment_alpha=decoded["adjustment_alpha"],
difficulty=decoded["difficulty"],
commit_reveal_weights_interval=decoded["commit_reveal_weights_interval"],
commit_reveal_weights_enabled=decoded["commit_reveal_weights_enabled"],
alpha_high=decoded["alpha_high"],
alpha_low=decoded["alpha_low"],
liquid_alpha_enabled=decoded["liquid_alpha_enabled"],
)


@dataclass
class StakeInfo:
"""Dataclass for stake info."""
Expand Down
Loading