Skip to content

Commit

Permalink
Merge pull request #239 from opentensor/release/8.3.1
Browse files Browse the repository at this point in the history
Release/8.3.1
  • Loading branch information
thewhaleking authored Nov 13, 2024
2 parents 0091513 + 886909d commit 66dcb25
Show file tree
Hide file tree
Showing 15 changed files with 120 additions and 117 deletions.
18 changes: 16 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion bittensor_cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
from .cli import CLIManager


__version__ = "8.3.0"
__version__ = "8.3.1"

__all__ = ["CLIManager", "__version__"]
8 changes: 7 additions & 1 deletion bittensor_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import re
import ssl
import sys
import traceback
from pathlib import Path
from typing import Coroutine, Optional
from dataclasses import fields
Expand Down Expand Up @@ -57,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)
Expand Down Expand Up @@ -840,13 +841,18 @@ async def _run():
return result
except (ConnectionRefusedError, ssl.SSLError):
err_console.print(f"Unable to connect to the chain: {self.subtensor}")
verbose_console.print(traceback.format_exc())
except (
ConnectionClosed,
SubstrateRequestException,
KeyboardInterrupt,
) as e:
if isinstance(e, SubstrateRequestException):
err_console.print(str(e))
verbose_console.print(traceback.format_exc())
except Exception as e:
err_console.print(f"An unknown error has occurred: {e}")
verbose_console.print(traceback.format_exc())
finally:
if initiated is False:
asyncio.create_task(cmd).cancel()
Expand Down
20 changes: 10 additions & 10 deletions bittensor_cli/src/bittensor/async_substrate_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
from hashlib import blake2b
from typing import Optional, Any, Union, Callable, Awaitable, cast

from bt_decode import PortableRegistry, decode as decode_by_type_string, MetadataV15
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
from scalecodec.types import GenericCall
from bittensor_wallet import Keypair
from substrateinterface.exceptions import (
SubstrateRequestException,
ExtrinsicNotFound,
Expand Down Expand Up @@ -771,14 +772,13 @@ def __init__(
"""
self.chain_endpoint = chain_endpoint
self.__chain = chain_name
self.ws = Websocket(
chain_endpoint,
options={
"max_size": 2**32,
"read_limit": 2**16,
"write_limit": 2**16,
},
)
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._lock = asyncio.Lock()
self.last_block_hash: Optional[str] = None
self.config = {
Expand Down
13 changes: 4 additions & 9 deletions bittensor_cli/src/bittensor/extrinsics/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import backoff
from bittensor_wallet import Wallet
from bittensor_wallet.errors import KeyFileError
from Crypto.Hash import keccak
import numpy as np
from rich.prompt import Confirm
Expand All @@ -37,6 +36,7 @@
get_human_readable,
print_verbose,
print_error,
unlock_key,
)

if typing.TYPE_CHECKING:
Expand Down Expand Up @@ -726,10 +726,8 @@ async def run_faucet_extrinsic(
return False, "Requires torch"

# Unlock coldkey
try:
wallet.unlock_coldkey()
except KeyFileError:
return False, "There was an error unlocking your coldkey"
if not (unlock_status := unlock_key(wallet, print_out=False)).success:
return False, unlock_status.message

# Get previous balance.
old_balance = await subtensor.get_balance(wallet.coldkeypub.ss58_address)
Expand Down Expand Up @@ -1639,10 +1637,7 @@ async def swap_hotkey_extrinsic(
)
return False

try:
wallet.unlock_coldkey()
except KeyFileError:
err_console.print("Error decrypting coldkey (possibly incorrect password)")
if not unlock_key(wallet).success:
return False

if prompt:
Expand Down
12 changes: 3 additions & 9 deletions bittensor_cli/src/bittensor/extrinsics/root.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
from typing import Union, List, TYPE_CHECKING

from bittensor_wallet import Wallet, Keypair
from bittensor_wallet.errors import KeyFileError
import numpy as np
from numpy.typing import NDArray
from rich.prompt import Confirm
Expand All @@ -37,6 +36,7 @@
u16_normalized_float,
print_verbose,
format_error_message,
unlock_key,
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -306,10 +306,7 @@ async def root_register_extrinsic(
the response is `True`.
"""

try:
wallet.unlock_coldkey()
except KeyFileError:
err_console.print("Error decrypting coldkey (possibly incorrect password)")
if not unlock_key(wallet).success:
return False

print_verbose(f"Checking if hotkey ({wallet.hotkey_str}) is registered on root")
Expand Down Expand Up @@ -427,10 +424,7 @@ async def _do_set_weights():
err_console.print("Your hotkey is not registered to the root network")
return False

try:
wallet.unlock_coldkey()
except KeyFileError:
err_console.print("Error decrypting coldkey (possibly incorrect password)")
if not unlock_key(wallet).success:
return False

# First convert types.
Expand Down
7 changes: 2 additions & 5 deletions bittensor_cli/src/bittensor/extrinsics/transfer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import asyncio

from bittensor_wallet import Wallet
from bittensor_wallet.errors import KeyFileError
from rich.prompt import Confirm
from substrateinterface.exceptions import SubstrateRequestException

Expand All @@ -16,6 +15,7 @@
get_explorer_url_for_network,
is_valid_bittensor_address_or_public_key,
print_error,
unlock_key,
)


Expand Down Expand Up @@ -115,10 +115,7 @@ async def do_transfer() -> tuple[bool, str, str]:
return False
console.print(f"[dark_orange]Initiating transfer on network: {subtensor.network}")
# Unlock wallet coldkey.
try:
wallet.unlock_coldkey()
except KeyFileError:
err_console.print("Error decrypting coldkey (possibly incorrect password)")
if not unlock_key(wallet).success:
return False

# Check balance.
Expand Down
54 changes: 48 additions & 6 deletions bittensor_cli/src/bittensor/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ast
from collections import namedtuple
import math
import os
import sqlite3
Expand All @@ -9,7 +10,7 @@

from bittensor_wallet import Wallet, Keypair
from bittensor_wallet.utils import SS58_FORMAT
from bittensor_wallet.errors import KeyFileError
from bittensor_wallet.errors import KeyFileError, PasswordError
from bittensor_wallet import utils
from jinja2 import Template
from markupsafe import Markup
Expand All @@ -35,6 +36,8 @@
err_console = Console(stderr=True)
verbose_console = Console(quiet=True)

UnlockStatus = namedtuple("UnlockStatus", ["success", "message"])


def print_console(message: str, colour: str, title: str, console: Console):
console.print(
Expand Down Expand Up @@ -238,11 +241,14 @@ def get_hotkey_wallets_for_wallet(
def get_coldkey_wallets_for_path(path: str) -> list[Wallet]:
"""Gets all wallets with coldkeys from a given path"""
wallet_path = Path(path).expanduser()
wallets = [
Wallet(name=directory.name, path=path)
for directory in wallet_path.iterdir()
if directory.is_dir()
]
try:
wallets = [
Wallet(name=directory.name, path=path)
for directory in wallet_path.iterdir()
if directory.is_dir()
]
except FileNotFoundError:
wallets = []
return wallets


Expand Down Expand Up @@ -974,3 +980,39 @@ def retry_prompt(
return var
else:
err_console.print(rejection_text)


def unlock_key(
wallet: Wallet, unlock_type="cold", print_out: bool = True
) -> "UnlockStatus":
"""
Attempts to decrypt a wallet's coldkey or hotkey
Args:
wallet: a Wallet object
unlock_type: the key type, 'cold' or 'hot'
print_out: whether to print out the error message to the err_console
Returns: UnlockStatus for success status of unlock, with error message if unsuccessful
"""
if unlock_type == "cold":
unlocker = "unlock_coldkey"
elif unlock_type == "hot":
unlocker = "unlock_hotkey"
else:
raise ValueError(
f"Invalid unlock type provided: {unlock_type}. Must be 'cold' or 'hot'."
)
try:
getattr(wallet, unlocker)()
return UnlockStatus(True, "")
except PasswordError:
err_msg = f"The password used to decrypt your {unlock_type.capitalize()}key Keyfile is invalid."
if print_out:
err_console.print(f":cross_mark: [red]{err_msg}[/red]")
return UnlockStatus(False, err_msg)
except KeyFileError:
err_msg = f"{unlock_type.capitalize()}key Keyfile is corrupt, non-writable, or non-readable, or non-existent."
if print_out:
err_console.print(f":cross_mark: [red]{err_msg}[/red]")
return UnlockStatus(False, err_msg)
30 changes: 6 additions & 24 deletions bittensor_cli/src/commands/root.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from typing import Optional, TYPE_CHECKING

from bittensor_wallet import Wallet
from bittensor_wallet.errors import KeyFileError
import numpy as np
from numpy.typing import NDArray
from rich import box
Expand Down Expand Up @@ -42,6 +41,7 @@
ss58_to_vec_u8,
update_metadata_table,
group_subnets,
unlock_key,
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -280,10 +280,7 @@ async def burned_register_extrinsic(
finalization/inclusion, the response is `True`.
"""

try:
wallet.unlock_coldkey()
except KeyFileError:
err_console.print("Error decrypting coldkey (possibly incorrect password)")
if not unlock_key(wallet).success:
return False

with console.status(
Expand Down Expand Up @@ -537,10 +534,7 @@ async def get_stake_for_coldkey_and_hotkey(
delegate_string = "delegate" if delegate else "undelegate"

# Decrypt key
try:
wallet.unlock_coldkey()
except KeyFileError:
err_console.print("Error decrypting coldkey (possibly incorrect password)")
if not unlock_key(wallet).success:
return False

print_verbose("Checking if hotkey is a delegate")
Expand Down Expand Up @@ -1098,11 +1092,7 @@ async def senate_vote(
return False

# Unlock the wallet.
try:
wallet.unlock_hotkey()
wallet.unlock_coldkey()
except KeyFileError:
err_console.print("Error decrypting coldkey (possibly incorrect password)")
if not unlock_key(wallet).success and unlock_key(wallet, "hot").success:
return False

console.print(f"Fetching proposals in [dark_orange]network: {subtensor.network}")
Expand Down Expand Up @@ -1322,11 +1312,7 @@ async def _do_set_take() -> bool:

console.print(f"Setting take on [dark_orange]network: {subtensor.network}")
# Unlock the wallet.
try:
wallet.unlock_hotkey()
wallet.unlock_coldkey()
except KeyFileError:
err_console.print("Error decrypting coldkey (possibly incorrect password)")
if not unlock_key(wallet).success and unlock_key(wallet, "hot").success:
return False

result_ = await _do_set_take()
Expand Down Expand Up @@ -1724,11 +1710,7 @@ async def nominate(wallet: Wallet, subtensor: SubtensorInterface, prompt: bool):

console.print(f"Nominating on [dark_orange]network: {subtensor.network}")
# Unlock the wallet.
try:
wallet.unlock_hotkey()
wallet.unlock_coldkey()
except KeyFileError:
err_console.print("Error decrypting coldkey (possibly incorrect password)")
if not unlock_key(wallet).success and unlock_key(wallet, "hot").success:
return False

print_verbose(f"Checking hotkey ({wallet.hotkey_str}) is a delegate")
Expand Down
Loading

0 comments on commit 66dcb25

Please sign in to comment.