From 9d0783927ac9ff061ec60bfbaeaa22300dcc3d91 Mon Sep 17 00:00:00 2001 From: Benjamin Himes <37844818+thewhaleking@users.noreply.github.com> Date: Wed, 13 Nov 2024 21:51:36 +0200 Subject: [PATCH 01/15] Backmerge main to staging (#242) * Bumps version and adds changelog * Updates changelog * Updates changelog * Bump versions, add previous release notes. * Update changelog --------- Co-authored-by: ibraheem-opentensor Co-authored-by: ibraheem-opentensor <165814940+ibraheem-opentensor@users.noreply.github.com> --- CHANGELOG.md | 18 ++++++++++++++++-- bittensor_cli/__init__.py | 2 +- bittensor_cli/cli.py | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3eeac9b..604e5666 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,26 @@ # Changelog -## 8.3.0 /2024-11-06 +## 8.3.1 /2024-11-13 ## What's Changed +* Better handle incorrect file path for wallets. by @thewhaleking in https://github.com/opentensor/btcli/pull/230 +* Handle websockets version 14, verbose error output by @thewhaleking in https://github.com/opentensor/btcli/pull/236 +* Handles the new PasswordError from bt-wallet by @thewhaleking in https://github.com/opentensor/btcli/pull/232 + +**Full Changelog**: https://github.com/opentensor/btcli/compare/v8.3.0...v.8.3.1 +## 8.3.0 /2024-11-06 + +## What's Changed * Better handle incorrect password by @thewhaleking in https://github.com/opentensor/btcli/pull/187 * Fixes success path of pow register by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/189 * Adds `--all` flag to transfer by @thewhaleking in https://github.com/opentensor/btcli/pull/181 -* Various fixes by @thewhaleking in https://github.com/opentensor/btcli/pull/199 +* In `do_transfer`, we check the balance with coldkeypub.ss58, but then retrieve it from the dict with coldkey.ss58. Resolve this. by @thewhaleking in https://github.com/opentensor/btcli/pull/199 +* Handle KeyboardInterrupt in CLI to gracefully exit (no traceback) by @thewhaleking in https://github.com/opentensor/btcli/pull/199 +* Handle race conditions where self.metadata may not be set before finishing initialising runtime (this may need optimised in the future) by @thewhaleking in https://github.com/opentensor/btcli/pull/199 +* Error description output by @thewhaleking in https://github.com/opentensor/btcli/pull/199 +* Taostats link fixed by @thewhaleking in https://github.com/opentensor/btcli/pull/199 +* Fixes not showing confirmation if --no-prompt is specified on stake remove by @thewhaleking in https://github.com/opentensor/btcli/pull/199 * Fix wallets in overview by @thewhaleking in https://github.com/opentensor/btcli/pull/197 * fix handling null neurons by @thewhaleking in https://github.com/opentensor/btcli/pull/214 * Fix cuda pow registration by @thewhaleking in https://github.com/opentensor/btcli/pull/215 @@ -16,6 +29,7 @@ * Support hotkey names for include/exclude in st add/remove by @thewhaleking in https://github.com/opentensor/btcli/pull/216 * Subvortex network added by @thewhaleking in https://github.com/opentensor/btcli/pull/223 * Add prompt option to all commands which use Confirm prompts by @thewhaleking in https://github.com/opentensor/btcli/pull/227 +* fix: local subtensor port by @distributedstatemachine in https://github.com/opentensor/btcli/pull/228 * Update local subtensor port by @distributedstatemachine in https://github.com/opentensor/btcli/pull/228 **Full Changelog**: https://github.com/opentensor/btcli/compare/v8.2.0...v8.3.0 diff --git a/bittensor_cli/__init__.py b/bittensor_cli/__init__.py index 6eaa6edc..165a7ac2 100644 --- a/bittensor_cli/__init__.py +++ b/bittensor_cli/__init__.py @@ -18,6 +18,6 @@ from .cli import CLIManager -__version__ = "8.3.0" +__version__ = "8.3.1" __all__ = ["CLIManager", "__version__"] diff --git a/bittensor_cli/cli.py b/bittensor_cli/cli.py index 3a312d45..08f8cb08 100755 --- a/bittensor_cli/cli.py +++ b/bittensor_cli/cli.py @@ -58,7 +58,7 @@ class GitError(Exception): pass -__version__ = "8.3.0" +__version__ = "8.3.1" _core_version = re.match(r"^\d+\.\d+\.\d+", __version__).group(0) From 88f645d610d08ab942faecae0088d6d4f91c5bdf Mon Sep 17 00:00:00 2001 From: Benjamin Himes Date: Thu, 14 Nov 2024 17:14:35 +0200 Subject: [PATCH 02/15] Uses a more general-use hex_to_bytes function for converting rather than the try:except --- .../bittensor/async_substrate_interface.py | 7 ++--- .../src/bittensor/extrinsics/registration.py | 7 +++-- .../src/bittensor/subtensor_interface.py | 29 ++++--------------- bittensor_cli/src/bittensor/utils.py | 13 ++++++++- bittensor_cli/src/commands/subnets.py | 7 ++--- bittensor_cli/src/commands/wallets.py | 10 ++----- 6 files changed, 29 insertions(+), 44 deletions(-) diff --git a/bittensor_cli/src/bittensor/async_substrate_interface.py b/bittensor_cli/src/bittensor/async_substrate_interface.py index 08e0cc9b..82bfc9d0 100644 --- a/bittensor_cli/src/bittensor/async_substrate_interface.py +++ b/bittensor_cli/src/bittensor/async_substrate_interface.py @@ -22,6 +22,8 @@ from substrateinterface.storage import StorageKey import websockets +from bittensor_cli.src.bittensor.utils import hex_to_bytes + ResultHandler = Callable[[dict, Any], Awaitable[tuple[dict, bool]]] @@ -2564,10 +2566,7 @@ def concat_hash_len(key_hasher: str) -> int: item_key = None try: - try: - item_bytes = bytes.fromhex(item[1][2:]) - except ValueError: - item_bytes = bytes.fromhex(item[1]) + item_bytes = hex_to_bytes(item[1]) item_value = await self.decode_scale( type_string=value_type, diff --git a/bittensor_cli/src/bittensor/extrinsics/registration.py b/bittensor_cli/src/bittensor/extrinsics/registration.py index d73837d2..33c9c156 100644 --- a/bittensor_cli/src/bittensor/extrinsics/registration.py +++ b/bittensor_cli/src/bittensor/extrinsics/registration.py @@ -37,6 +37,7 @@ print_verbose, print_error, unlock_key, + hex_to_bytes, ) if typing.TYPE_CHECKING: @@ -863,7 +864,7 @@ async def _check_for_newest_block_and_update( block_number, difficulty, block_hash = await _get_block_with_retry( subtensor=subtensor, netuid=netuid ) - block_bytes = bytes.fromhex(block_hash[2:]) + block_bytes = hex_to_bytes(block_hash) update_curr_block( curr_diff, @@ -970,7 +971,7 @@ async def _block_solver( subtensor=subtensor, netuid=netuid ) - block_bytes = bytes.fromhex(block_hash[2:]) + block_bytes = hex_to_bytes(block_hash) old_block_number = block_number # Set to current block _update_curr_block( @@ -1249,7 +1250,7 @@ def _terminate_workers_and_wait_for_exit( @backoff.on_exception(backoff.constant, Exception, interval=1, max_tries=3) async def _get_block_with_retry( subtensor: "SubtensorInterface", netuid: int -) -> tuple[int, int, bytes]: +) -> tuple[int, int, str]: """ Gets the current block number, difficulty, and block hash from the substrate node. diff --git a/bittensor_cli/src/bittensor/subtensor_interface.py b/bittensor_cli/src/bittensor/subtensor_interface.py index b8cfb7af..54ca20b6 100644 --- a/bittensor_cli/src/bittensor/subtensor_interface.py +++ b/bittensor_cli/src/bittensor/subtensor_interface.py @@ -35,6 +35,7 @@ err_console, decode_hex_identity_dict, validate_chain_endpoint, + hex_to_bytes, ) @@ -213,12 +214,7 @@ async def get_delegates( block_hash=block_hash, ) if hex_bytes_result is not None: - try: - bytes_result = bytes.fromhex(hex_bytes_result[2:]) - except ValueError: - bytes_result = bytes.fromhex(hex_bytes_result) - - return DelegateInfo.list_from_vec_u8(bytes_result) + return DelegateInfo.list_from_vec_u8(hex_to_bytes(hex_bytes_result)) else: return [] @@ -254,12 +250,7 @@ async def get_stake_info_for_coldkey( if hex_bytes_result is None: return [] - try: - bytes_result = bytes.fromhex(hex_bytes_result[2:]) - except ValueError: - bytes_result = bytes.fromhex(hex_bytes_result) - - return StakeInfo.list_from_vec_u8(bytes_result) + return StakeInfo.list_from_vec_u8(hex_to_bytes(hex_bytes_result)) async def get_stake_for_coldkey_and_hotkey( self, hotkey_ss58: str, coldkey_ss58: str, block_hash: Optional[str] @@ -654,12 +645,7 @@ async def neurons_lite( if hex_bytes_result is None: return [] - try: - bytes_result = bytes.fromhex(hex_bytes_result[2:]) - except ValueError: - bytes_result = bytes.fromhex(hex_bytes_result) - - return NeuronInfoLite.list_from_vec_u8(bytes_result) + return NeuronInfoLite.list_from_vec_u8(hex_to_bytes(hex_bytes_result)) async def neuron_for_uid( self, uid: Optional[int], netuid: int, block_hash: Optional[str] = None @@ -988,12 +974,7 @@ async def get_subnet_hyperparameters( if hex_bytes_result is None: return [] - if hex_bytes_result.startswith("0x"): - bytes_result = bytes.fromhex(hex_bytes_result[2:]) - else: - bytes_result = bytes.fromhex(hex_bytes_result) - - return SubnetHyperparameters.from_vec_u8(bytes_result) + return SubnetHyperparameters.from_vec_u8(hex_to_bytes(hex_bytes_result)) async def get_vote_data( self, diff --git a/bittensor_cli/src/bittensor/utils.py b/bittensor_cli/src/bittensor/utils.py index a3954a85..69d26515 100644 --- a/bittensor_cli/src/bittensor/utils.py +++ b/bittensor_cli/src/bittensor/utils.py @@ -581,7 +581,7 @@ def decode_hex_identity_dict(info_dictionary) -> dict[str, Any]: def get_decoded(data: str) -> str: """Decodes a hex-encoded string.""" try: - return bytes.fromhex(data[2:]).decode() + return hex_to_bytes(data).decode() except UnicodeDecodeError: print(f"Could not decode: {key}: {item}") @@ -1016,3 +1016,14 @@ def unlock_key( if print_out: err_console.print(f":cross_mark: [red]{err_msg}[/red]") return UnlockStatus(False, err_msg) + + +def hex_to_bytes(hex_str: str) -> bytes: + """ + Converts a hex-encoded string into bytes. Handles 0x-prefixed and non-prefixed hex-encoded strings. + """ + if hex_str.startswith("0x"): + bytes_result = bytes.fromhex(hex_str[2:]) + else: + bytes_result = bytes.fromhex(hex_str) + return bytes_result diff --git a/bittensor_cli/src/commands/subnets.py b/bittensor_cli/src/commands/subnets.py index 1d4620b7..51ce3708 100644 --- a/bittensor_cli/src/commands/subnets.py +++ b/bittensor_cli/src/commands/subnets.py @@ -28,6 +28,7 @@ render_table, update_metadata_table, unlock_key, + hex_to_bytes, ) if TYPE_CHECKING: @@ -155,12 +156,8 @@ async def _get_all_subnets_info(): hex_bytes_result = await subtensor.query_runtime_api( runtime_api="SubnetInfoRuntimeApi", method="get_subnets_info", params=[] ) - try: - bytes_result = bytes.fromhex(hex_bytes_result[2:]) - except ValueError: - bytes_result = bytes.fromhex(hex_bytes_result) - return SubnetInfo.list_from_vec_u8(bytes_result) + return SubnetInfo.list_from_vec_u8(hex_to_bytes(hex_bytes_result)) if not reuse_last: subnets: list[SubnetInfo] diff --git a/bittensor_cli/src/commands/wallets.py b/bittensor_cli/src/commands/wallets.py index 69188053..322b9538 100644 --- a/bittensor_cli/src/commands/wallets.py +++ b/bittensor_cli/src/commands/wallets.py @@ -15,23 +15,19 @@ from fuzzywuzzy import fuzz from rich import box from rich.align import Align -from rich.prompt import Confirm, Prompt +from rich.prompt import Confirm from rich.table import Column, Table from rich.tree import Tree from rich.padding import Padding from rich.prompt import IntPrompt -from scalecodec import ScaleBytes -import scalecodec import typer -from bittensor_cli.src import TYPE_REGISTRY from bittensor_cli.src.bittensor import utils from bittensor_cli.src.bittensor.balances import Balance from bittensor_cli.src.bittensor.chain_data import ( DelegateInfo, NeuronInfoLite, StakeInfo, - custom_rpc_type_registry, decode_account_id, ) from bittensor_cli.src.bittensor.extrinsics.registration import ( @@ -46,7 +42,6 @@ RAO_PER_TAO, console, convert_blocks_to_time, - decode_scale_bytes, err_console, print_error, print_verbose, @@ -56,6 +51,7 @@ validate_coldkey_presence, retry_prompt, unlock_key, + hex_to_bytes, ) @@ -1176,7 +1172,7 @@ def _process_neurons_for_netuids( :return: netuids mapped to decoded neurons """ all_results = [ - (netuid, NeuronInfoLite.list_from_vec_u8(bytes.fromhex(result[2:]))) + (netuid, NeuronInfoLite.list_from_vec_u8(hex_to_bytes(result))) if result else (netuid, []) for netuid, result in netuids_with_all_neurons_hex_bytes From d65ca598755c21f68884a3679b7ceff59c2c6d0a Mon Sep 17 00:00:00 2001 From: Benjamin Himes Date: Fri, 22 Nov 2024 15:20:09 +0200 Subject: [PATCH 03/15] Upgrade websockets --- .../bittensor/async_substrate_interface.py | 37 ++++++++++--------- requirements.txt | 3 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/bittensor_cli/src/bittensor/async_substrate_interface.py b/bittensor_cli/src/bittensor/async_substrate_interface.py index 82bfc9d0..2dfd43e5 100644 --- a/bittensor_cli/src/bittensor/async_substrate_interface.py +++ b/bittensor_cli/src/bittensor/async_substrate_interface.py @@ -4,12 +4,11 @@ from collections import defaultdict from dataclasses import dataclass from hashlib import blake2b -from typing import Optional, Any, Union, Callable, Awaitable, cast +from typing import Optional, Any, Union, Callable, Awaitable, cast, TYPE_CHECKING from async_property import async_property from bt_decode import PortableRegistry, decode as decode_by_type_string, MetadataV15 from bittensor_wallet import Keypair -from packaging import version from scalecodec import GenericExtrinsic from scalecodec.base import ScaleBytes, ScaleType, RuntimeConfigurationObject from scalecodec.type_registry import load_type_registry_preset @@ -20,10 +19,14 @@ BlockNotFound, ) from substrateinterface.storage import StorageKey -import websockets +from websockets.asyncio.client import connect +from websockets.exceptions import ConnectionClosed from bittensor_cli.src.bittensor.utils import hex_to_bytes +if TYPE_CHECKING: + from websockets.asyncio.client import ClientConnection + ResultHandler = Callable[[dict, Any], Awaitable[tuple[dict, bool]]] @@ -627,7 +630,7 @@ def __init__( # TODO allow setting max concurrent connections and rpc subscriptions per connection # TODO reconnection logic self.ws_url = ws_url - self.ws: Optional[websockets.WebSocketClientProtocol] = None + self.ws: Optional[ClientConnection] = None self.id = 0 self.max_subscriptions = max_subscriptions self.max_connections = max_connections @@ -655,7 +658,7 @@ async def __aenter__(self): async def _connect(self): self.ws = await asyncio.wait_for( - websockets.connect(self.ws_url, **self._options), timeout=10 + connect(self.ws_url, **self._options), timeout=10 ) async def __aexit__(self, exc_type, exc_val, exc_tb): @@ -698,9 +701,7 @@ async def shutdown(self): async def _recv(self) -> None: try: - response = json.loads( - await cast(websockets.WebSocketClientProtocol, self.ws).recv() - ) + response = json.loads(await cast(ClientConnection, self.ws).recv()) async with self._lock: self._open_subscriptions -= 1 if "id" in response: @@ -709,7 +710,7 @@ async def _recv(self) -> None: self._received[response["params"]["subscription"]] = response else: raise KeyError(response) - except websockets.ConnectionClosed: + except ConnectionClosed: raise except KeyError as e: raise e @@ -720,7 +721,7 @@ async def _start_receiving(self): await self._recv() except asyncio.CancelledError: pass - except websockets.ConnectionClosed: + except ConnectionClosed: # TODO try reconnect, but only if it's needed raise @@ -737,7 +738,7 @@ async def send(self, payload: dict) -> int: try: await self.ws.send(json.dumps({**payload, **{"id": original_id}})) return original_id - except websockets.ConnectionClosed: + except ConnectionClosed: raise async def retrieve(self, item_id: int) -> Optional[dict]: @@ -774,13 +775,13 @@ def __init__( """ self.chain_endpoint = chain_endpoint self.__chain = chain_name - options = { - "max_size": 2**32, - "write_limit": 2**16, - } - if version.parse(websockets.__version__) < version.parse("14.0"): - options.update({"read_limit": 2**16}) - self.ws = Websocket(chain_endpoint, options=options) + self.ws = Websocket( + chain_endpoint, + options={ + "max_size": 2**32, + "write_limit": 2**16, + }, + ) self._lock = asyncio.Lock() self.last_block_hash: Optional[str] = None self.config = { diff --git a/requirements.txt b/requirements.txt index bb50a3a7..268d40ce 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,6 @@ fuzzywuzzy~=0.18.0 netaddr~=1.3.0 numpy>=2.0.1 Jinja2 -packaging pycryptodome # Crypto PyYAML~=6.0.1 pytest @@ -16,6 +15,6 @@ rich~=13.7 scalecodec==1.2.11 substrate-interface~=1.7.9 typer~=0.12 -websockets>=12.0 +websockets>=14.1 bittensor-wallet>=2.1.0 bt-decode==0.2.0a0 \ No newline at end of file From 4e5c3cb1bb3c95311bb0c5d51f6745208759813a Mon Sep 17 00:00:00 2001 From: Benjamin Himes Date: Fri, 22 Nov 2024 16:13:15 +0200 Subject: [PATCH 04/15] Better-improved the asyncio websocket connection. --- .../src/bittensor/async_substrate_interface.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/bittensor_cli/src/bittensor/async_substrate_interface.py b/bittensor_cli/src/bittensor/async_substrate_interface.py index 2dfd43e5..869de573 100644 --- a/bittensor_cli/src/bittensor/async_substrate_interface.py +++ b/bittensor_cli/src/bittensor/async_substrate_interface.py @@ -652,15 +652,12 @@ async def __aenter__(self): self._exit_task.cancel() if not self._initialized: self._initialized = True - await self._connect() + self.ws = await asyncio.wait_for( + connect(self.ws_url, **self._options), timeout=10 + ) self._receiving_task = asyncio.create_task(self._start_receiving()) return self - async def _connect(self): - self.ws = await asyncio.wait_for( - connect(self.ws_url, **self._options), timeout=10 - ) - async def __aexit__(self, exc_type, exc_val, exc_tb): async with self._lock: self._in_use -= 1 @@ -701,7 +698,7 @@ async def shutdown(self): async def _recv(self) -> None: try: - response = json.loads(await cast(ClientConnection, self.ws).recv()) + response = json.loads(await self.ws.recv()) async with self._lock: self._open_subscriptions -= 1 if "id" in response: From c79a81600d2af3233b3335218f49a93b8304dd05 Mon Sep 17 00:00:00 2001 From: Benjamin Himes Date: Fri, 22 Nov 2024 16:24:19 +0200 Subject: [PATCH 05/15] Synced with bittensor implementation. --- bittensor_cli/src/bittensor/async_substrate_interface.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bittensor_cli/src/bittensor/async_substrate_interface.py b/bittensor_cli/src/bittensor/async_substrate_interface.py index 869de573..d9ea3765 100644 --- a/bittensor_cli/src/bittensor/async_substrate_interface.py +++ b/bittensor_cli/src/bittensor/async_substrate_interface.py @@ -439,7 +439,7 @@ def add_item( self.block_hashes[block_hash] = runtime def retrieve( - self, block: Optional[int], block_hash: Optional[str] + self, block: Optional[int] = None, block_hash: Optional[str] = None ) -> Optional["Runtime"]: if block is not None: return self.blocks.get(block) @@ -630,7 +630,7 @@ def __init__( # TODO allow setting max concurrent connections and rpc subscriptions per connection # TODO reconnection logic self.ws_url = ws_url - self.ws: Optional[ClientConnection] = None + self.ws: Optional["ClientConnection"] = None self.id = 0 self.max_subscriptions = max_subscriptions self.max_connections = max_connections @@ -1135,7 +1135,7 @@ async def create_storage_key( ------- StorageKey """ - runtime = await self.init_runtime(block_hash=block_hash) + await self.init_runtime(block_hash=block_hash) return StorageKey.create_from_storage_function( pallet, @@ -1555,7 +1555,7 @@ async def _process_response( self, response: dict, subscription_id: Union[int, str], - value_scale_type: Optional[str], + value_scale_type: Optional[str] = None, storage_item: Optional[ScaleType] = None, runtime: Optional[Runtime] = None, result_handler: Optional[ResultHandler] = None, From 8932194f23fd6229de2b89d92890f807f131241e Mon Sep 17 00:00:00 2001 From: Benjamin Himes Date: Fri, 22 Nov 2024 16:52:34 +0200 Subject: [PATCH 06/15] Remove is_flag and flag_value deprecated Typer args --- bittensor_cli/cli.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/bittensor_cli/cli.py b/bittensor_cli/cli.py index 08f8cb08..26fff060 100755 --- a/bittensor_cli/cli.py +++ b/bittensor_cli/cli.py @@ -127,8 +127,6 @@ class Options: use_password = typer.Option( True, help="Set this to `True` to protect the generated Bittensor key with a password.", - is_flag=True, - flag_value=False, ) public_hex_key = typer.Option(None, help="The public key in hex format.") ss58_address = typer.Option( @@ -1843,8 +1841,6 @@ def wallet_regen_hotkey( use_password: bool = typer.Option( False, # Overriden to False help="Set to 'True' to protect the generated Bittensor key with a password.", - is_flag=True, - flag_value=True, ), quiet: bool = Options.quiet, verbose: bool = Options.verbose, @@ -1901,8 +1897,6 @@ def wallet_new_hotkey( use_password: bool = typer.Option( False, # Overriden to False help="Set to 'True' to protect the generated Bittensor key with a password.", - is_flag=True, - flag_value=True, ), quiet: bool = Options.quiet, verbose: bool = Options.verbose, From 63917abe375af14095b75bcf424212f62cc86f03 Mon Sep 17 00:00:00 2001 From: Benjamin Himes <37844818+thewhaleking@users.noreply.github.com> Date: Mon, 25 Nov 2024 14:27:18 +0200 Subject: [PATCH 07/15] Speed up faucet (#245) --- .../bittensor/async_substrate_interface.py | 7 ++---- .../src/bittensor/extrinsics/registration.py | 22 +++++++++---------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/bittensor_cli/src/bittensor/async_substrate_interface.py b/bittensor_cli/src/bittensor/async_substrate_interface.py index d9ea3765..af54b531 100644 --- a/bittensor_cli/src/bittensor/async_substrate_interface.py +++ b/bittensor_cli/src/bittensor/async_substrate_interface.py @@ -1769,7 +1769,6 @@ async def compose_call( call_params = {} await self.init_runtime(block_hash=block_hash) - call = self.runtime_config.create_scale_object( type_string="Call", metadata=self.metadata ) @@ -2087,7 +2086,8 @@ async def create_signed_extrinsic( :return: The signed Extrinsic """ - await self.init_runtime() + if not self.metadata: + await self.init_runtime() # Check requirements if not isinstance(call, GenericCall): @@ -2140,7 +2140,6 @@ async def create_signed_extrinsic( extrinsic = self.runtime_config.create_scale_object( type_string="Extrinsic", metadata=self.metadata ) - value = { "account_id": f"0x{keypair.public_key.hex()}", "signature": f"0x{signature.hex()}", @@ -2158,9 +2157,7 @@ async def create_signed_extrinsic( signature_cls = self.runtime_config.get_decoder_class("ExtrinsicSignature") if issubclass(signature_cls, self.runtime_config.get_decoder_class("Enum")): value["signature_version"] = signature_version - extrinsic.encode(value) - return extrinsic async def get_chain_finalised_head(self): diff --git a/bittensor_cli/src/bittensor/extrinsics/registration.py b/bittensor_cli/src/bittensor/extrinsics/registration.py index 33c9c156..84f761a8 100644 --- a/bittensor_cli/src/bittensor/extrinsics/registration.py +++ b/bittensor_cli/src/bittensor/extrinsics/registration.py @@ -18,7 +18,6 @@ from typing import Optional import subprocess -import backoff from bittensor_wallet import Wallet from Crypto.Hash import keccak import numpy as np @@ -688,7 +687,7 @@ async def run_faucet_extrinsic( tpb: int = 256, num_processes: Optional[int] = None, update_interval: Optional[int] = None, - log_verbose: bool = False, + log_verbose: bool = True, max_successes: int = 3, ) -> tuple[bool, str]: r"""Runs a continual POW to get a faucet of TAO on the test net. @@ -736,8 +735,12 @@ async def run_faucet_extrinsic( # Attempt rolling registration. attempts = 1 successes = 1 + pow_result: Optional[POWSolution] while True: try: + account_nonce = await subtensor.substrate.get_account_nonce( + wallet.coldkey.ss58_address + ) pow_result = None while pow_result is None or await pow_result.is_stale(subtensor=subtensor): # Solve latest POW. @@ -746,7 +749,7 @@ async def run_faucet_extrinsic( if prompt: err_console.print("CUDA is not available.") return False, "CUDA is not available." - pow_result: Optional[POWSolution] = await create_pow( + pow_result = await create_pow( subtensor, wallet, -1, @@ -759,7 +762,7 @@ async def run_faucet_extrinsic( log_verbose=log_verbose, ) else: - pow_result: Optional[POWSolution] = await create_pow( + pow_result = await create_pow( subtensor, wallet, -1, @@ -779,7 +782,7 @@ async def run_faucet_extrinsic( }, ) extrinsic = await subtensor.substrate.create_signed_extrinsic( - call=call, keypair=wallet.coldkey + call=call, keypair=wallet.coldkey, nonce=account_nonce ) response = await subtensor.substrate.submit_extrinsic( extrinsic, @@ -1246,8 +1249,6 @@ def _terminate_workers_and_wait_for_exit( worker.terminate() -# TODO verify this works with async -@backoff.on_exception(backoff.constant, Exception, interval=1, max_tries=3) async def _get_block_with_retry( subtensor: "SubtensorInterface", netuid: int ) -> tuple[int, int, str]: @@ -1262,10 +1263,9 @@ async def _get_block_with_retry( :raises Exception: If the block hash is None. :raises ValueError: If the difficulty is None. """ - block_number = await subtensor.substrate.get_block_number(None) - block_hash = await subtensor.substrate.get_block_hash( - block_number - ) # TODO check if I need to do all this + block = await subtensor.substrate.get_block() + block_hash = block["header"]["hash"] + block_number = block["header"]["number"] try: difficulty = ( 1_000_000 From 086dda51325a7a6ff954b83076c2cdb2d24f9d48 Mon Sep 17 00:00:00 2001 From: ibraheem-opentensor Date: Mon, 25 Nov 2024 15:10:19 -0800 Subject: [PATCH 08/15] Fixed overview message descripancy --- bittensor_cli/src/commands/wallets.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/bittensor_cli/src/commands/wallets.py b/bittensor_cli/src/commands/wallets.py index 322b9538..9a8b0bfa 100644 --- a/bittensor_cli/src/commands/wallets.py +++ b/bittensor_cli/src/commands/wallets.py @@ -656,8 +656,13 @@ async def overview( neurons ) + has_alerts = False alerts_table = Table(show_header=True, header_style="bold magenta") alerts_table.add_column("🥩 alert!") + alerts_table.add_row( + "[bold]Detected the following stake(s) associated with coldkey(s) that are not linked to any local hotkeys:[/bold]" + ) + alerts_table.add_row("") coldkeys_to_check = [] ck_stakes = await subtensor.get_total_stake_for_coldkey( @@ -680,12 +685,23 @@ async def overview( if difference == 0: continue # We have all our stake registered. + has_alerts = True coldkeys_to_check.append(coldkey_wallet) alerts_table.add_row( - "Found [light_goldenrod2]{}[/light_goldenrod2] stake with coldkey [bright_magenta]{}[/bright_magenta] that is not registered.".format( - abs(difference), coldkey_wallet.coldkeypub.ss58_address + "[light_goldenrod2]{}[/light_goldenrod2] stake associated with coldkey [bright_magenta]{}[/bright_magenta] (ss58: [bright_magenta]{}[/bright_magenta])".format( + abs(difference), + coldkey_wallet.name, + coldkey_wallet.coldkeypub.ss58_address, ) ) + if has_alerts: + alerts_table.add_row("") + alerts_table.add_row( + "[bold yellow]Note:[/bold yellow] This stake might be delegated, staked to another user's hotkey, or associated with a hotkey not present in your wallet." + ) + alerts_table.add_row( + "You can find out more by executing `[bold]btcli wallet inspect[/bold]` command." + ) if coldkeys_to_check: # We have some stake that is not with a registered hotkey. @@ -739,7 +755,7 @@ async def overview( grid = Table.grid(pad_edge=True) # If there are any alerts, add them to the grid - if len(alerts_table.rows) > 0: + if has_alerts: grid.add_row(alerts_table) # Add title From 31adc4cdf2918b5ed8a5a1f602aee2589b399c0e Mon Sep 17 00:00:00 2001 From: Benjamin Himes <37844818+thewhaleking@users.noreply.github.com> Date: Tue, 26 Nov 2024 21:01:39 +0200 Subject: [PATCH 09/15] Fix hyperparams setting. (#252) * Fix hyperparams setting. * Updates check for registration_allowed --------- Co-authored-by: ibraheem-opentensor --- bittensor_cli/cli.py | 10 ++++++++++ bittensor_cli/src/__init__.py | 22 +++++++++++++--------- bittensor_cli/src/commands/sudo.py | 7 ++++--- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/bittensor_cli/cli.py b/bittensor_cli/cli.py index 26fff060..55eb4098 100755 --- a/bittensor_cli/cli.py +++ b/bittensor_cli/cli.py @@ -3904,6 +3904,16 @@ def sudo_set( ) param_name = hyperparam_list[choice - 1] + if param_name in ["alpha_high", "alpha_low"]: + param_name = "alpha_values" + low_val = FloatPrompt.ask( + "Enter the new value for [dark_orange]alpha_low[/dark_orange]" + ) + high_val = FloatPrompt.ask( + "Enter the new value for [dark_orange]alpha_high[/dark_orange]" + ) + param_value = f"{low_val},{high_val}" + if not param_value: param_value = Prompt.ask( f"Enter the new value for [dark_orange]{param_name}[/dark_orange] in the VALUE column format" diff --git a/bittensor_cli/src/__init__.py b/bittensor_cli/src/__init__.py index 8cf6aeff..a5ca2170 100644 --- a/bittensor_cli/src/__init__.py +++ b/bittensor_cli/src/__init__.py @@ -318,28 +318,32 @@ class WalletValidationTypes(Enum): HYPERPARAMS = { - "serving_rate_limit": "sudo_set_serving_rate_limit", + "rho": "sudo_set_rho", + "kappa": "sudo_set_kappa", + "immunity_period": "sudo_set_immunity_period", + "min_allowed_weights": "sudo_set_min_allowed_weights", + "max_weights_limit": "sudo_set_max_weight_limit", + "tempo": "sudo_set_tempo", "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", + "adjustment_interval": "sudo_set_adjustment_interval", "activity_cutoff": "sudo_set_activity_cutoff", - "network_registration_allowed": "sudo_set_network_registration_allowed", - "network_pow_registration_allowed": "sudo_set_network_pow_registration_allowed", + "target_regs_per_interval": "sudo_set_target_registrations_per_interval", "min_burn": "sudo_set_min_burn", "max_burn": "sudo_set_max_burn", + "bonds_moving_avg": "sudo_set_bonds_moving_average", + "max_regs_per_block": "sudo_set_max_registrations_per_block", + "serving_rate_limit": "sudo_set_serving_rate_limit", + "max_validators": "sudo_set_max_allowed_validators", "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", + "registration_allowed": "sudo_set_network_registration_allowed", } # Help Panels for cli help diff --git a/bittensor_cli/src/commands/sudo.py b/bittensor_cli/src/commands/sudo.py index 5711a3c2..5c0057ce 100644 --- a/bittensor_cli/src/commands/sudo.py +++ b/bittensor_cli/src/commands/sudo.py @@ -178,19 +178,20 @@ async def sudo_set_hyperparameter( normalized_value: Union[str, bool] if param_name in [ - "network_registration_allowed", + "registration_allowed", "network_pow_registration_allowed", "commit_reveal_weights_enabled", "liquid_alpha_enabled", ]: - normalized_value = param_value.lower() in ["true", "1"] + normalized_value = param_value.lower() in ["true", "True", "1"] else: normalized_value = param_value is_allowed_value, value = allowed_value(param_name, normalized_value) if not is_allowed_value: err_console.print( - f"Hyperparameter {param_name} value is not within bounds. Value is {normalized_value} but must be {value}" + f"Hyperparameter [dark_orange]{param_name}[/dark_orange] value is not within bounds. " + f"Value is {normalized_value} but must be {value}" ) return From e7b91228b86e52d50e8ffd2e076f02d824d54c21 Mon Sep 17 00:00:00 2001 From: ibraheem-opentensor Date: Tue, 26 Nov 2024 13:37:33 -0800 Subject: [PATCH 10/15] Bumps version and updates changelog --- CHANGELOG.md | 12 ++++++++++++ bittensor_cli/__init__.py | 2 +- bittensor_cli/cli.py | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 604e5666..c2df305f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## 8.4.0 /2024-11-26 + +## What's Changed +* Use hex to bytes function by @thewhaleking in https://github.com/opentensor/btcli/pull/244 +* Remove deprecated Typer options by @thewhaleking in https://github.com/opentensor/btcli/pull/248 +* Upgrade websockets by @thewhaleking in https://github.com/opentensor/btcli/pull/247 +* Fast block improvements by @thewhaleking in https://github.com/opentensor/btcli/pull/245 +* Fixed overview message discrepancy by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/251 +* Fix hyperparams setting. by @thewhaleking in https://github.com/opentensor/btcli/pull/252 + +**Full Changelog**: https://github.com/opentensor/btcli/compare/v8.3.1...v8.4.0 + ## 8.3.1 /2024-11-13 ## What's Changed diff --git a/bittensor_cli/__init__.py b/bittensor_cli/__init__.py index 165a7ac2..f2e41a91 100644 --- a/bittensor_cli/__init__.py +++ b/bittensor_cli/__init__.py @@ -18,6 +18,6 @@ from .cli import CLIManager -__version__ = "8.3.1" +__version__ = "8.4.0" __all__ = ["CLIManager", "__version__"] diff --git a/bittensor_cli/cli.py b/bittensor_cli/cli.py index 55eb4098..2b6467f0 100755 --- a/bittensor_cli/cli.py +++ b/bittensor_cli/cli.py @@ -58,7 +58,7 @@ class GitError(Exception): pass -__version__ = "8.3.1" +__version__ = "8.4.0" _core_version = re.match(r"^\d+\.\d+\.\d+", __version__).group(0) From 36179ceff2c2fa99d2b29776ab10d3de32934b9a Mon Sep 17 00:00:00 2001 From: ibraheem-opentensor Date: Tue, 26 Nov 2024 13:49:58 -0800 Subject: [PATCH 11/15] Updates changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2df305f..41a9126a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 8.4.0 /2024-11-26 +## 8.4.0 /2024-11-27 ## What's Changed * Use hex to bytes function by @thewhaleking in https://github.com/opentensor/btcli/pull/244 From 3eef3b6490db81c629f4a6e33fd715c9d6e6e1e1 Mon Sep 17 00:00:00 2001 From: ibraheem-opentensor Date: Wed, 27 Nov 2024 10:43:23 -0800 Subject: [PATCH 12/15] Bumps btwallet to 2.1.2 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 268d40ce..83283c9c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,5 +16,5 @@ scalecodec==1.2.11 substrate-interface~=1.7.9 typer~=0.12 websockets>=14.1 -bittensor-wallet>=2.1.0 +bittensor-wallet>=2.1.2 bt-decode==0.2.0a0 \ No newline at end of file From 4bf0686e8f12fd0ba3d910d9c66df3e9578189e6 Mon Sep 17 00:00:00 2001 From: ibraheem-opentensor Date: Wed, 27 Nov 2024 12:35:14 -0800 Subject: [PATCH 13/15] Updates changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41a9126a..c351e84e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Fast block improvements by @thewhaleking in https://github.com/opentensor/btcli/pull/245 * Fixed overview message discrepancy by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/251 * Fix hyperparams setting. by @thewhaleking in https://github.com/opentensor/btcli/pull/252 +* Bumps btwallet to 2.1.2 by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/255 **Full Changelog**: https://github.com/opentensor/btcli/compare/v8.3.1...v8.4.0 From 9dd967ccf49e2861f8910110c9c4330a7f8809d8 Mon Sep 17 00:00:00 2001 From: ibraheem-opentensor Date: Wed, 27 Nov 2024 13:34:18 -0800 Subject: [PATCH 14/15] Bumps btwallet to 2.1.3 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 83283c9c..c35276f2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,5 +16,5 @@ scalecodec==1.2.11 substrate-interface~=1.7.9 typer~=0.12 websockets>=14.1 -bittensor-wallet>=2.1.2 +bittensor-wallet>=2.1.3 bt-decode==0.2.0a0 \ No newline at end of file From c60f5718a492a63863fae2614897c1ddf1a0aa17 Mon Sep 17 00:00:00 2001 From: ibraheem-opentensor Date: Wed, 27 Nov 2024 14:18:02 -0800 Subject: [PATCH 15/15] Updates changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c351e84e..034edbd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * Fixed overview message discrepancy by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/251 * Fix hyperparams setting. by @thewhaleking in https://github.com/opentensor/btcli/pull/252 * Bumps btwallet to 2.1.2 by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/255 +* Bumps btwallet to 2.1.3 by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/256 **Full Changelog**: https://github.com/opentensor/btcli/compare/v8.3.1...v8.4.0