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
83 changes: 49 additions & 34 deletions bittensor_cli/src/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,47 +626,62 @@ class WalletValidationTypes(Enum):
}


class RootSudoOnly(Enum):
FALSE = 0
TRUE = 1
COMPLICATED = 2


HYPERPARAMS = {
# btcli name: (subtensor method, root-only bool)
"rho": ("sudo_set_rho", False),
"kappa": ("sudo_set_kappa", False),
"immunity_period": ("sudo_set_immunity_period", False),
"min_allowed_weights": ("sudo_set_min_allowed_weights", False),
"max_weights_limit": ("sudo_set_max_weight_limit", False),
"tempo": ("sudo_set_tempo", True),
"min_difficulty": ("sudo_set_min_difficulty", True),
"max_difficulty": ("sudo_set_max_difficulty", False),
"weights_version": ("sudo_set_weights_version_key", False),
"weights_rate_limit": ("sudo_set_weights_set_rate_limit", True),
"adjustment_interval": ("sudo_set_adjustment_interval", True),
"activity_cutoff": ("sudo_set_activity_cutoff", False),
"target_regs_per_interval": ("sudo_set_target_registrations_per_interval", True),
"min_burn": ("sudo_set_min_burn", False),
"max_burn": ("sudo_set_max_burn", True),
"bonds_moving_avg": ("sudo_set_bonds_moving_average", False),
"max_regs_per_block": ("sudo_set_max_registrations_per_block", True),
"serving_rate_limit": ("sudo_set_serving_rate_limit", False),
"max_validators": ("sudo_set_max_allowed_validators", True),
"adjustment_alpha": ("sudo_set_adjustment_alpha", False),
"difficulty": ("sudo_set_difficulty", True),
# btcli name: (subtensor method, root-only enum)
"rho": ("sudo_set_rho", RootSudoOnly.FALSE),
"kappa": ("sudo_set_kappa", RootSudoOnly.FALSE),
"immunity_period": ("sudo_set_immunity_period", RootSudoOnly.FALSE),
"min_allowed_weights": ("sudo_set_min_allowed_weights", RootSudoOnly.FALSE),
"max_weights_limit": ("sudo_set_max_weight_limit", RootSudoOnly.FALSE),
"tempo": ("sudo_set_tempo", RootSudoOnly.TRUE),
"min_difficulty": ("sudo_set_min_difficulty", RootSudoOnly.TRUE),
"max_difficulty": ("sudo_set_max_difficulty", RootSudoOnly.FALSE),
"weights_version": ("sudo_set_weights_version_key", RootSudoOnly.FALSE),
"weights_rate_limit": ("sudo_set_weights_set_rate_limit", RootSudoOnly.TRUE),
"adjustment_interval": ("sudo_set_adjustment_interval", RootSudoOnly.TRUE),
"activity_cutoff": ("sudo_set_activity_cutoff", RootSudoOnly.FALSE),
"target_regs_per_interval": (
"sudo_set_target_registrations_per_interval",
RootSudoOnly.TRUE,
),
"min_burn": ("sudo_set_min_burn", RootSudoOnly.FALSE),
"max_burn": ("sudo_set_max_burn", RootSudoOnly.TRUE),
"bonds_moving_avg": ("sudo_set_bonds_moving_average", RootSudoOnly.FALSE),
"max_regs_per_block": ("sudo_set_max_registrations_per_block", RootSudoOnly.TRUE),
"serving_rate_limit": ("sudo_set_serving_rate_limit", RootSudoOnly.FALSE),
"max_validators": ("sudo_set_max_allowed_validators", RootSudoOnly.TRUE),
"adjustment_alpha": ("sudo_set_adjustment_alpha", RootSudoOnly.FALSE),
"difficulty": ("sudo_set_difficulty", RootSudoOnly.TRUE),
"commit_reveal_period": (
"sudo_set_commit_reveal_weights_interval",
False,
RootSudoOnly.FALSE,
),
"commit_reveal_weights_enabled": (
"sudo_set_commit_reveal_weights_enabled",
RootSudoOnly.FALSE,
),
"alpha_values": ("sudo_set_alpha_values", RootSudoOnly.FALSE),
"liquid_alpha_enabled": ("sudo_set_liquid_alpha_enabled", RootSudoOnly.FALSE),
"registration_allowed": (
"sudo_set_network_registration_allowed",
RootSudoOnly.TRUE,
),
"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),
"registration_allowed": ("sudo_set_network_registration_allowed", True),
"network_pow_registration_allowed": (
"sudo_set_network_pow_registration_allowed",
False,
RootSudoOnly.FALSE,
),
"yuma3_enabled": ("sudo_set_yuma3_enabled", False),
"alpha_sigmoid_steepness": ("sudo_set_alpha_sigmoid_steepness", True),
"user_liquidity_enabled": ("toggle_user_liquidity", True),
"bonds_reset_enabled": ("sudo_set_bonds_reset_enabled", False),
"transfers_enabled": ("sudo_set_toggle_transfer", False),
"min_allowed_uids": ("sudo_set_min_allowed_uids", True),
"yuma3_enabled": ("sudo_set_yuma3_enabled", RootSudoOnly.FALSE),
"alpha_sigmoid_steepness": ("sudo_set_alpha_sigmoid_steepness", RootSudoOnly.TRUE),
"user_liquidity_enabled": ("toggle_user_liquidity", RootSudoOnly.COMPLICATED),
"bonds_reset_enabled": ("sudo_set_bonds_reset_enabled", RootSudoOnly.FALSE),
"transfers_enabled": ("sudo_set_toggle_transfer", RootSudoOnly.FALSE),
"min_allowed_uids": ("sudo_set_min_allowed_uids", RootSudoOnly.TRUE),
}

HYPERPARAMS_MODULE = {
Expand Down
2 changes: 1 addition & 1 deletion bittensor_cli/src/bittensor/subtensor_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ async def get_total_stake_for_hotkey(

async def current_take(
self,
hotkey_ss58: int,
hotkey_ss58: str,
block_hash: Optional[str] = None,
reuse_block: bool = False,
) -> Optional[float]:
Expand Down
157 changes: 86 additions & 71 deletions bittensor_cli/src/commands/sudo.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import asyncio
import json
from typing import TYPE_CHECKING, Union, Optional
from typing import TYPE_CHECKING, Union, Optional, Type

from async_substrate_interface import AsyncExtrinsicReceipt
from bittensor_wallet import Wallet
Expand All @@ -12,6 +12,7 @@
from bittensor_cli.src import (
HYPERPARAMS,
HYPERPARAMS_MODULE,
RootSudoOnly,
DelegatesDetails,
COLOR_PALETTE,
)
Expand Down Expand Up @@ -83,7 +84,7 @@ def allowed_value(
return True, value


def string_to_bool(val) -> bool:
def string_to_bool(val) -> Union[bool, Type[ValueError]]:
try:
return {"true": True, "1": True, "0": False, "false": False}[val.lower()]
except KeyError:
Expand Down Expand Up @@ -158,7 +159,7 @@ def requires_bool(metadata, param_name, pallet: str = DEFAULT_PALLET) -> bool:
for call in pallet.calls:
if call.name == param_name:
if "netuid" not in [x.name for x in call.args]:
return False, None
return False
call_args = [arg for arg in call.args if arg.value["name"] != "netuid"]
if len(call_args) != 1:
return False
Expand Down Expand Up @@ -270,6 +271,7 @@ async def set_hyperparameter_extrinsic(
`False` if the extrinsic fails to enter the block within the timeout.
:param wait_for_finalization: If set, waits for the extrinsic to be finalized on the chain before returning `True`,
or returns `False` if the extrinsic fails to be finalized within the timeout.
:param prompt: If set to False, will not prompt the user.

:return: tuple including:
success: `True` if extrinsic was finalized or included in the block. If we did not wait for
Expand All @@ -295,7 +297,7 @@ async def set_hyperparameter_extrinsic(

arbitrary_extrinsic = False

extrinsic, sudo_ = HYPERPARAMS.get(parameter, ("", False))
extrinsic, sudo_ = HYPERPARAMS.get(parameter, ("", RootSudoOnly.FALSE))
call_params = {"netuid": netuid}
if not extrinsic:
arbitrary_extrinsic, call_params = search_metadata(
Expand All @@ -305,8 +307,8 @@ async def set_hyperparameter_extrinsic(
if not arbitrary_extrinsic:
err_msg = ":cross_mark: [red]Invalid hyperparameter specified.[/red]"
err_console.print(err_msg)
return False, err_msg
if sudo_ and prompt:
return False, err_msg, None
if sudo_ is RootSudoOnly.TRUE and prompt:
if not Confirm.ask(
"This hyperparam is only settable by root sudo users. If you are not, this will fail. Please confirm"
):
Expand All @@ -316,82 +318,93 @@ async def set_hyperparameter_extrinsic(
msg_value = value if not arbitrary_extrinsic else call_params
pallet = HYPERPARAMS_MODULE.get(parameter) or DEFAULT_PALLET

with console.status(
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",
):
if not arbitrary_extrinsic:
extrinsic_params = await substrate.get_metadata_call_function(
module_name=pallet, call_function_name=extrinsic
)

# 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 = [
pn_str
for param in extrinsic_params["fields"]
if "netuid" not in (pn_str := str(param["name"]))
]

if len(value) < len(non_netuid_fields):
err_msg = (
"Not enough values provided in the list for all parameters"
)
err_console.print(err_msg)
return False, err_msg, None
if not arbitrary_extrinsic:
extrinsic_params = await substrate.get_metadata_call_function(
module_name=pallet, call_function_name=extrinsic
)

call_params.update(
{name: val for name, val in zip(non_netuid_fields, value)}
)
# 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 = [
pn_str
for param in extrinsic_params["fields"]
if "netuid" not in (pn_str := str(param["name"]))
]

if len(value) < len(non_netuid_fields):
err_msg = "Not enough values provided in the list for all parameters"
err_console.print(err_msg)
return False, err_msg, None

call_params.update(
{name: val for name, val in zip(non_netuid_fields, value)}
)

else:
if requires_bool(
substrate.metadata, param_name=extrinsic, pallet=pallet
) and isinstance(value, str):
value = string_to_bool(value)
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(
call_module=pallet,
call_function=extrinsic,
call_params=call_params,
else:
if requires_bool(
substrate.metadata, param_name=extrinsic, pallet=pallet
) and isinstance(value, str):
value = string_to_bool(value)
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(
call_module=pallet,
call_function=extrinsic,
call_params=call_params,
)
if sudo_ is RootSudoOnly.TRUE:
call = await substrate.compose_call(
call_module="Sudo", call_function="sudo", call_params={"call": call_}
)
if sudo_:
elif sudo_ is RootSudoOnly.COMPLICATED:
if not prompt:
to_sudo_or_not_to_sudo = True # default to sudo true when no-prompt is set
else:
to_sudo_or_not_to_sudo = Confirm.ask(
f"This hyperparam can be executed as sudo or not. Do you want to execute as sudo [y] or not [n]?"
)
if to_sudo_or_not_to_sudo:
call = await substrate.compose_call(
call_module="Sudo", call_function="sudo", call_params={"call": call_}
call_module="Sudo",
call_function="sudo",
call_params={"call": call_},
)
else:
call = call_
else:
call = call_
with console.status(
f":satellite: Setting hyperparameter [{COLOR_PALETTE.G.SUBHEAD}]{parameter}[/{COLOR_PALETTE.G.SUBHEAD}]"
f" to [{COLOR_PALETTE.G.SUBHEAD}]{msg_value}[/{COLOR_PALETTE.G.SUBHEAD}]"
f" on subnet: [{COLOR_PALETTE.G.SUBHEAD}]{netuid}[/{COLOR_PALETTE.G.SUBHEAD}] ...",
spinner="earth",
):
success, err_msg, ext_receipt = await subtensor.sign_and_send_extrinsic(
call, wallet, wait_for_inclusion, wait_for_finalization
)
if not success:
err_console.print(f":cross_mark: [red]Failed[/red]: {err_msg}")
return False, err_msg, None
if not success:
err_console.print(f":cross_mark: [red]Failed[/red]: {err_msg}")
return False, err_msg, None
else:
ext_id = await ext_receipt.get_extrinsic_identifier()
await print_extrinsic_id(ext_receipt)
if arbitrary_extrinsic:
console.print(
f":white_heavy_check_mark: "
f"[dark_sea_green3]Hyperparameter {parameter} values changed to {call_params}[/dark_sea_green3]"
)
return True, "", ext_id
# Successful registration, final check for membership
else:
ext_id = await ext_receipt.get_extrinsic_identifier()
await print_extrinsic_id(ext_receipt)
if arbitrary_extrinsic:
console.print(
f":white_heavy_check_mark: "
f"[dark_sea_green3]Hyperparameter {parameter} values changed to {call_params}[/dark_sea_green3]"
)
return True, "", ext_id
# Successful registration, final check for membership
else:
console.print(
f":white_heavy_check_mark: "
f"[dark_sea_green3]Hyperparameter {parameter} changed to {value}[/dark_sea_green3]"
)
return True, "", ext_id
console.print(
f":white_heavy_check_mark: "
f"[dark_sea_green3]Hyperparameter {parameter} changed to {value}[/dark_sea_green3]"
)
return True, "", ext_id


async def _get_senate_members(
Expand Down Expand Up @@ -725,6 +738,8 @@ async def sudo_set_hyperparameter(
)
err_console.print(err_msg)
return False, err_msg, None
if json_output:
prompt = False
success, err_msg, ext_id = await set_hyperparameter_extrinsic(
subtensor, wallet, netuid, param_name, value, prompt=prompt
)
Expand Down
Loading