diff --git a/bittensor_cli/cli.py b/bittensor_cli/cli.py index 8372b5517..c26defd6d 100755 --- a/bittensor_cli/cli.py +++ b/bittensor_cli/cli.py @@ -4816,7 +4816,7 @@ def sudo_set( wallet = self.wallet_ask( wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH] ) - result = self._run_command( + result, err_msg = self._run_command( sudo.sudo_set_hyperparameter( wallet, self.initialize_chain(network), @@ -4828,7 +4828,7 @@ def sudo_set( ) ) if json_output: - json_console.print(json.dumps({"success": result})) + json_console.print(json.dumps({"success": result, "err_msg": err_msg})) return result def sudo_get( diff --git a/bittensor_cli/src/__init__.py b/bittensor_cli/src/__init__.py index ebb01b433..7cd09ab84 100644 --- a/bittensor_cli/src/__init__.py +++ b/bittensor_cli/src/__init__.py @@ -631,10 +631,10 @@ class WalletValidationTypes(Enum): "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", False), + "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", 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), @@ -645,7 +645,7 @@ class WalletValidationTypes(Enum): "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", False), + "difficulty": ("sudo_set_difficulty", True), "commit_reveal_period": ( "sudo_set_commit_reveal_weights_interval", False, @@ -653,7 +653,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), - "registration_allowed": ("sudo_set_network_registration_allowed", False), + "registration_allowed": ("sudo_set_network_registration_allowed", True), "network_pow_registration_allowed": ( "sudo_set_network_pow_registration_allowed", False, diff --git a/bittensor_cli/src/commands/sudo.py b/bittensor_cli/src/commands/sudo.py index 1046c28cf..6d4ae13e8 100644 --- a/bittensor_cli/src/commands/sudo.py +++ b/bittensor_cli/src/commands/sudo.py @@ -177,7 +177,7 @@ async def set_hyperparameter_extrinsic( wait_for_inclusion: bool = False, wait_for_finalization: bool = True, prompt: bool = True, -) -> bool: +) -> tuple[bool, str]: """Sets a hyperparameter for a specific subnetwork. :param subtensor: initialized SubtensorInterface object @@ -200,13 +200,14 @@ async def set_hyperparameter_extrinsic( params=[netuid], ) if subnet_owner != wallet.coldkeypub.ss58_address: - err_console.print( + err_msg = ( ":cross_mark: [red]This wallet doesn't own the specified subnet.[/red]" ) - return False + err_console.print(err_msg) + return False, err_msg - if not unlock_key(wallet).success: - return False + if not (ulw := unlock_key(wallet)).success: + return False, ulw.message arbitrary_extrinsic = False @@ -218,15 +219,14 @@ async def set_hyperparameter_extrinsic( ) extrinsic = parameter if not arbitrary_extrinsic: - err_console.print( - ":cross_mark: [red]Invalid hyperparameter specified.[/red]" - ) - return False + err_msg = ":cross_mark: [red]Invalid hyperparameter specified.[/red]" + err_console.print(err_msg) + return False, err_msg if sudo_ and prompt: if not Confirm.ask( "This hyperparam is only settable by root sudo users. If you are not, this will fail. Please confirm" ): - return False + return False, "This hyperparam is only settable by root sudo users" substrate = subtensor.substrate msg_value = value if not arbitrary_extrinsic else call_params @@ -254,10 +254,11 @@ async def set_hyperparameter_extrinsic( ] if len(value) < len(non_netuid_fields): - err_console.print( + err_msg = ( "Not enough values provided in the list for all parameters" ) - return False + err_console.print(err_msg) + return False, err_msg call_params.update( {name: val for name, val in zip(non_netuid_fields, value)} @@ -290,20 +291,20 @@ async def set_hyperparameter_extrinsic( ) if not success: err_console.print(f":cross_mark: [red]Failed[/red]: {err_msg}") - return False + return False, err_msg elif 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 + return True, "" # 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 + return True, "" async def _get_senate_members( @@ -619,25 +620,26 @@ async def sudo_set_hyperparameter( param_value: Optional[str], prompt: bool, json_output: bool, -): +) -> tuple[bool, str]: """Set subnet hyperparameters.""" is_allowed_value, value = allowed_value(param_name, param_value) if not is_allowed_value: - err_console.print( + err_msg = ( f"Hyperparameter [dark_orange]{param_name}[/dark_orange] value is not within bounds. " f"Value is {param_value} but must be {value}" ) - return False - success = await set_hyperparameter_extrinsic( + err_console.print(err_msg) + return False, err_msg + success, err_msg = await set_hyperparameter_extrinsic( subtensor, wallet, netuid, param_name, value, prompt=prompt ) if json_output: - return success + return success, err_msg if success: console.print("\n") print_verbose("Fetching hyperparameters") await get_hyperparameters(subtensor, netuid=netuid) - return success + return success, err_msg async def get_hyperparameters( diff --git a/tests/e2e_tests/test_hyperparams_setting.py b/tests/e2e_tests/test_hyperparams_setting.py new file mode 100644 index 000000000..03d8616c3 --- /dev/null +++ b/tests/e2e_tests/test_hyperparams_setting.py @@ -0,0 +1,116 @@ +import json + +from bittensor_cli.src import HYPERPARAMS + +""" +Verify commands: + +* btcli subnets create +* btcli sudo set +* btcli sudo get +""" + + +def test_hyperparams_setting(local_chain, wallet_setup): + netuid = 2 + wallet_path_alice = "//Alice" + # Create wallet for Alice + keypair_alice, wallet_alice, wallet_path_alice, exec_command_alice = wallet_setup( + wallet_path_alice + ) + + # Register a subnet with sudo as Alice + result = exec_command_alice( + command="subnets", + sub_command="create", + extra_args=[ + "--wallet-path", + wallet_path_alice, + "--network", + "ws://127.0.0.1:9945", + "--wallet-name", + wallet_alice.name, + "--wallet-hotkey", + wallet_alice.hotkey_str, + "--subnet-name", + "Test Subnet", + "--repo", + "https://github.com/username/repo", + "--contact", + "alice@opentensor.dev", + "--url", + "https://testsubnet.com", + "--discord", + "alice#1234", + "--description", + "A test subnet for e2e testing", + "--additional-info", + "Created by Alice", + "--logo-url", + "https://testsubnet.com/logo.png", + "--no-prompt", + "--json-output", + ], + ) + result_output = json.loads(result.stdout) + assert result_output["success"] is True + assert result_output["netuid"] == netuid + print(result_output) + + # Fetch the hyperparameters of the subnet + hyperparams = exec_command_alice( + command="sudo", + sub_command="get", + extra_args=[ + "--network", + "ws://127.0.0.1:9945", + "--netuid", + netuid, + "--json-out", + ], + ) + + # Parse all hyperparameters and single out max_burn in TAO + all_hyperparams = json.loads(hyperparams.stdout) + hp = {} + for hyperparam in all_hyperparams: + hp[hyperparam["hyperparameter"]] = hyperparam["value"] + for key, (_, sudo_only) in HYPERPARAMS.items(): + if key in hp.keys() and not sudo_only: + if isinstance(hp[key], bool): + new_val = not hp[key] + elif isinstance(hp[key], int): + if hp[key] < 100: + new_val = hp[key] + 1 + else: + new_val = hp[key] - 1 + else: + raise ValueError( + f"Unrecognized hyperparameter value type: {key}: {hp[key]}" + ) + cmd = exec_command_alice( + command="sudo", + sub_command="set", + extra_args=[ + "--wallet-path", + wallet_path_alice, + "--network", + "ws://127.0.0.1:9945", + "--wallet-name", + wallet_alice.name, + "--wallet-hotkey", + wallet_alice.hotkey_str, + "--netuid", + netuid, + "--json-out", + "--no-prompt", + "--param", + key, + "--value", + new_val, + ], + ) + cmd_json = json.loads(cmd.stdout) + assert cmd_json["success"] is True, (key, new_val, cmd.stdout, cmd_json) + print(f"Successfully set hyperparameter {key} to value {new_val}") + print("Successfully set hyperparameters")