Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes broken Subtensor methods #2420

Merged
merged 11 commits into from
Nov 14, 2024
49 changes: 22 additions & 27 deletions bittensor/core/subtensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,13 @@
transfer_extrinsic,
)
from bittensor.core.metagraph import Metagraph
from bittensor.utils import networking, torch, ss58_to_vec_u8, u16_normalized_float
from bittensor.utils import (
networking,
torch,
ss58_to_vec_u8,
u16_normalized_float,
hex_to_bytes,
)
from bittensor.utils.balance import Balance
from bittensor.utils.btlogging import logging
from bittensor.utils.registration import legacy_torch_api_compat
Expand Down Expand Up @@ -1227,12 +1233,7 @@ 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))

# Community uses this method
# Returns network ImmunityPeriod hyper parameter.
Expand Down Expand Up @@ -1308,10 +1309,13 @@ def get_commitment(self, netuid: int, uid: int, block: Optional[int] = None) ->
hotkey = metagraph.hotkeys[uid] # type: ignore

metadata = get_metadata(self, netuid, hotkey, block)
commitment = metadata["info"]["fields"][0] # type: ignore
hex_data = commitment[list(commitment.keys())[0]][2:] # type: ignore
try:
commitment = metadata["info"]["fields"][0] # type: ignore
hex_data = commitment[list(commitment.keys())[0]][2:] # type: ignore
return bytes.fromhex(hex_data).decode()

return bytes.fromhex(hex_data).decode()
except TypeError:
return ""

# Community uses this via `bittensor.utils.weight_utils.process_weights_for_netuid` function.
def min_allowed_weights(
Expand Down Expand Up @@ -1367,7 +1371,7 @@ def get_prometheus_info(
Optional[bittensor.core.chain_data.prometheus_info.PrometheusInfo]: A PrometheusInfo object containing the prometheus information, or ``None`` if the prometheus information is not found.
"""
result = self.query_subtensor("Prometheus", block, [netuid, hotkey_ss58])
if result is not None and hasattr(result, "value"):
if result is not None and getattr(result, "value", None) is not None:
return PrometheusInfo(
ip=networking.int_to_ip(result.value["ip"]),
ip_type=result.value["ip_type"],
Expand Down Expand Up @@ -1407,17 +1411,13 @@ def get_all_subnets_info(self, block: Optional[int] = None) -> list[SubnetInfo]:

Gaining insights into the subnets' details assists in understanding the network's composition, the roles of different subnets, and their unique features.
"""
block_hash = None if block is None else self.substrate.get_block_hash(block)

json_body = self.substrate.rpc_request(
method="subnetInfo_getSubnetsInfo", # custom rpc method
params=[block_hash] if block_hash else [],
hex_bytes_result = self.query_runtime_api(
"SubnetInfoRuntimeApi", "get_subnets_info", params=[], block=block
)

if not (result := json_body.get("result", None)):
if not hex_bytes_result:
return []

return SubnetInfo.list_from_vec_u8(result)
else:
return SubnetInfo.list_from_vec_u8(hex_to_bytes(hex_bytes_result))

# Metagraph uses this method
def bonds(
Expand Down Expand Up @@ -1561,12 +1561,7 @@ def neurons_lite(
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 NeuronInfoLite.list_from_vec_u8(bytes_result) # type: ignore
return NeuronInfoLite.list_from_vec_u8(hex_to_bytes(hex_bytes_result)) # type: ignore

# Used in the `neurons` method which is used in metagraph.py
def weights(
Expand Down Expand Up @@ -1923,7 +1918,7 @@ def get_delegate_by_hotkey(
if not (result := json_body.get("result", None)):
return None

return DelegateInfo.from_vec_u8(result)
return DelegateInfo.from_vec_u8(bytes(result))

# Subnet 27 uses this method name
_do_serve_axon = do_serve_axon
11 changes: 11 additions & 0 deletions bittensor/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,3 +403,14 @@ def unlock_key(wallet: "Wallet", unlock_type="coldkey") -> "UnlockStatus":
except KeyFileError:
err_msg = f"{unlock_type.capitalize()} keyfile is corrupt, non-writable, or non-readable, or non-existent."
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
12 changes: 12 additions & 0 deletions tests/unit_tests/utils/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,15 @@ def test_unlock_key_errors(mocker, side_effect, response):
result = utils.unlock_key(wallet=mock_wallet)

assert result == response


@pytest.mark.parametrize(
"hex_str, response",
[
("5461796c6f72205377696674", b"Taylor Swift"),
("0x5461796c6f72205377696674", b"Taylor Swift"),
],
)
def test_hex_to_bytes(hex_str, response):
result = utils.hex_to_bytes(hex_str)
assert result == response
Loading