Skip to content
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
17 changes: 11 additions & 6 deletions bittensor_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
WalletValidationTypes as WV,
Constants,
COLOR_PALETTE,
HYPERPARAMS,
)
from bittensor_cli.src.bittensor import utils
from bittensor_cli.src.bittensor.balances import Balance
Expand Down Expand Up @@ -3229,10 +3230,11 @@ def stake_remove(
ask_for=[WO.NAME, WO.PATH],
)
else:
if not hotkey_ss58_address and not wallet_hotkey:
if not hotkey_ss58_address and not wallet_hotkey:
hotkey_or_ss58 = Prompt.ask(
"Enter the [blue]hotkey[/blue] name or [blue]ss58 address[/blue] to unstake all from [dim](or enter 'all' to unstake from all hotkeys)[/dim]",
default=self.config.get("wallet_hotkey") or defaults.wallet.hotkey,
default=self.config.get("wallet_hotkey")
or defaults.wallet.hotkey,
)
else:
hotkey_or_ss58 = hotkey_ss58_address or wallet_hotkey
Expand Down Expand Up @@ -3983,7 +3985,7 @@ def sudo_set(
param_name: str = typer.Option(
"", "--param", "--parameter", help="The subnet hyperparameter to set"
),
param_value: str = typer.Option(
param_value: Optional[str] = typer.Option(
"", "--value", help="Value to set the hyperparameter to."
),
quiet: bool = Options.quiet,
Expand Down Expand Up @@ -4032,9 +4034,12 @@ def sudo_set(
param_value = f"{low_val},{high_val}"

if not param_value:
param_value = Prompt.ask(
f"Enter the new value for [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{param_name}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] in the VALUE column format"
)
if HYPERPARAMS.get(param_name):
param_value = Prompt.ask(
f"Enter the new value for [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{param_name}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] in the VALUE column format"
)
else:
param_value = None

wallet = self.wallet_ask(
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH]
Expand Down
2 changes: 1 addition & 1 deletion bittensor_cli/src/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@ class WalletValidationTypes(Enum):
"commit_reveal_weights_enabled": ("sudo_set_commit_reveal_weights_enabled", False),
"alpha_values": ("sudo_set_alpha_values", False),
"liquid_alpha_enabled": ("sudo_set_liquid_alpha_enabled", False),
"network_registration_allowed": ("sudo_set_network_registration_allowed", False),
"registration_allowed": ("sudo_set_network_registration_allowed", False),
"network_pow_registration_allowed": (
"sudo_set_network_pow_registration_allowed",
False,
Expand Down
8 changes: 2 additions & 6 deletions bittensor_cli/src/commands/stake/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,7 @@ async def safe_stake_extrinsic(
)
return
else:
err_out(
f"\n{failure_prelude} with error: {format_error_message(e)}"
)
err_out(f"\n{failure_prelude} with error: {format_error_message(e)}")
return
else:
await response.process_events()
Expand Down Expand Up @@ -180,9 +178,7 @@ async def stake_extrinsic(
extrinsic, wait_for_inclusion=True, wait_for_finalization=False
)
except SubstrateRequestException as e:
err_out(
f"\n{failure_prelude} with error: {format_error_message(e)}"
)
err_out(f"\n{failure_prelude} with error: {format_error_message(e)}")
return
else:
await response.process_events()
Expand Down
8 changes: 3 additions & 5 deletions bittensor_cli/src/commands/subnets/subnets.py
Original file line number Diff line number Diff line change
Expand Up @@ -889,8 +889,8 @@ async def show_root():
total_emission_per_block = 0
for netuid_ in range(len(all_subnets)):
subnet = all_subnets[netuid_]
emission_on_subnet = (
root_state.emission_history[netuid_][idx] / (subnet.tempo or 1)
emission_on_subnet = root_state.emission_history[netuid_][idx] / (
subnet.tempo or 1
)
total_emission_per_block += subnet.alpha_to_tao(
Balance.from_rao(emission_on_subnet)
Expand Down Expand Up @@ -2135,9 +2135,7 @@ async def get_identity(subtensor: "SubtensorInterface", netuid: int, title: str
title = "Subnet Identity"

if not await subtensor.subnet_exists(netuid):
print_error(
f"Subnet {netuid} does not exist."
)
print_error(f"Subnet {netuid} does not exist.")
raise typer.Exit()

with console.status(
Expand Down
163 changes: 126 additions & 37 deletions bittensor_cli/src/commands/sudo.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
normalize_hyperparameters,
unlock_key,
blocks_to_duration,
float_to_u64,
float_to_u16,
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -70,12 +72,76 @@ def allowed_value(
return True, value


def search_metadata(
param_name: str, value: Union[str, bool, float, list[float]], netuid: int, metadata
) -> tuple[bool, Optional[dict]]:
"""
Searches the substrate metadata AdminUtils pallet for a given parameter name. Crafts a response dict to be used
as call parameters for setting this hyperparameter.

Args:
param_name: the name of the hyperparameter
value: the value to set the hyperparameter
netuid: the specified netuid
metadata: the subtensor.substrate.metadata

Returns:
(success, dict of call params)

"""

def string_to_bool(val) -> bool:
try:
return {"true": True, "1": True, "0": False, "false": False}[val.lower()]
except KeyError:
return ValueError

def type_converter_with_retry(type_, val, arg_name):
try:
if val is None:
val = input(
f"Enter a value for field '{arg_name}' with type '{arg_type_output[type_]}': "
)
return arg_types[type_](val)
except ValueError:
return type_converter_with_retry(type_, None, arg_name)

arg_types = {"bool": string_to_bool, "u16": float_to_u16, "u64": float_to_u64}
arg_type_output = {"bool": "bool", "u16": "float", "u64": "float"}

call_crafter = {"netuid": netuid}

for pallet in metadata.pallets:
if pallet.name == "AdminUtils":
for call in pallet.calls:
if call.name == param_name:
if "netuid" not in [x.name for x in call.args]:
return False, None
call_args = [
arg for arg in call.args if arg.value["name"] != "netuid"
]
if len(call_args) == 1:
arg = call_args[0].value
call_crafter[arg["name"]] = type_converter_with_retry(
arg["typeName"], value, arg["name"]
)
else:
for arg_ in call_args:
arg = arg_.value
call_crafter[arg["name"]] = type_converter_with_retry(
arg["typeName"], None, arg["name"]
)
return True, call_crafter
else:
return False, None


async def set_hyperparameter_extrinsic(
subtensor: "SubtensorInterface",
wallet: "Wallet",
netuid: int,
parameter: str,
value: Union[str, bool, float, list[float]],
value: Optional[Union[str, bool, float, list[float]]],
wait_for_inclusion: bool = False,
wait_for_finalization: bool = True,
) -> bool:
Expand Down Expand Up @@ -110,44 +176,58 @@ async def set_hyperparameter_extrinsic(
if not unlock_key(wallet).success:
return False

arbitrary_extrinsic = False

extrinsic, sudo_ = HYPERPARAMS.get(parameter, ("", False))
if extrinsic is None:
err_console.print(":cross_mark: [red]Invalid hyperparameter specified.[/red]")
return False
if not extrinsic:
arbitrary_extrinsic, call_params = search_metadata(
parameter, value, netuid, subtensor.substrate.metadata
)
extrinsic = parameter
if not arbitrary_extrinsic:
err_console.print(
":cross_mark: [red]Invalid hyperparameter specified.[/red]"
)
return False

substrate = subtensor.substrate
msg_value = value if not arbitrary_extrinsic else call_params
with console.status(
f":satellite: Setting hyperparameter [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{parameter}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] to [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{value}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] on subnet: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{netuid}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] ...",
f":satellite: Setting hyperparameter [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{parameter}"
f"[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] to [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{msg_value}"
f"[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] on subnet: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]"
f"{netuid}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] ...",
spinner="earth",
):
substrate = subtensor.substrate
extrinsic_params = await substrate.get_metadata_call_function(
"AdminUtils", extrinsic
)
call_params: dict[str, Union[str, bool, float]] = {"netuid": netuid}

# if input value is a list, iterate through the list and assign values
if isinstance(value, list):
# Ensure that there are enough values for all non-netuid parameters
non_netuid_fields = [
param["name"]
for param in extrinsic_params["fields"]
if "netuid" not in param["name"]
]

if len(value) < len(non_netuid_fields):
raise ValueError(
"Not enough values provided in the list for all parameters"
)

call_params.update(
{str(name): val for name, val in zip(non_netuid_fields, value)}
if not arbitrary_extrinsic:
extrinsic_params = await substrate.get_metadata_call_function(
"AdminUtils", extrinsic
)
call_params = {"netuid": netuid}

# if input value is a list, iterate through the list and assign values
if isinstance(value, list):
# Ensure that there are enough values for all non-netuid parameters
non_netuid_fields = [
param["name"]
for param in extrinsic_params["fields"]
if "netuid" not in param["name"]
]

if len(value) < len(non_netuid_fields):
raise ValueError(
"Not enough values provided in the list for all parameters"
)

else:
value_argument = extrinsic_params["fields"][
len(extrinsic_params["fields"]) - 1
]
call_params[str(value_argument["name"])] = value
call_params.update(
{str(name): val for name, val in zip(non_netuid_fields, value)}
)

else:
value_argument = extrinsic_params["fields"][
len(extrinsic_params["fields"]) - 1
]
call_params[str(value_argument["name"])] = value

# create extrinsic call
call_ = await substrate.compose_call(
Expand All @@ -167,11 +247,16 @@ async def set_hyperparameter_extrinsic(
if not success:
err_console.print(f":cross_mark: [red]Failed[/red]: {err_msg}")
await asyncio.sleep(0.5)

elif arbitrary_extrinsic:
console.print(
f":white_heavy_check_mark: "
f"[dark_sea_green3]Hyperparameter {parameter} values changed to {call_params}[/dark_sea_green3]"
)
# Successful registration, final check for membership
else:
console.print(
f":white_heavy_check_mark: [dark_sea_green3]Hyperparameter {parameter} changed to {value}[/dark_sea_green3]"
f":white_heavy_check_mark: "
f"[dark_sea_green3]Hyperparameter {parameter} changed to {value}[/dark_sea_green3]"
)
return True

Expand Down Expand Up @@ -470,7 +555,7 @@ async def sudo_set_hyperparameter(
subtensor: "SubtensorInterface",
netuid: int,
param_name: str,
param_value: str,
param_value: Optional[str],
):
"""Set subnet hyperparameters."""

Expand All @@ -481,7 +566,12 @@ async def sudo_set_hyperparameter(
"commit_reveal_weights_enabled",
"liquid_alpha_enabled",
]:
normalized_value = param_value.lower() in ["true", "True", "1"]
normalized_value = param_value.lower() in ["true", "1"]
elif param_value in ("True", "False"):
normalized_value = {
"True": True,
"False": False,
}[param_value]
else:
normalized_value = param_value

Expand All @@ -492,7 +582,6 @@ async def sudo_set_hyperparameter(
f"Value is {normalized_value} but must be {value}"
)
return

success = await set_hyperparameter_extrinsic(
subtensor, wallet, netuid, param_name, value
)
Expand Down
Loading