From 2580614e37ca3efdb5fa70a2b7d8971690649bc4 Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Thu, 24 Oct 2024 16:40:32 -0400 Subject: [PATCH 01/12] add runtime apis to reg --- bittensor_cli/src/__init__.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/bittensor_cli/src/__init__.py b/bittensor_cli/src/__init__.py index 3ab18fe25..32ca0e0f5 100644 --- a/bittensor_cli/src/__init__.py +++ b/bittensor_cli/src/__init__.py @@ -278,10 +278,27 @@ class WalletValidationTypes(Enum): "params": [], "type": "Vec", }, + "get_subnet_info_v2": { + "params": [ + { + "name": "netuid", + "type": "u16", + }, + ], + "type": "Vec", + }, + "get_subnets_info_v2": { + "params": [], + "type": "Vec", + }, "get_all_dynamic_info": { "params": [], "type": "Vec", }, + "get_dynamic_info": { + "params": [{"name": "netuid", "type": "u16"}], + "type": "Vec", + }, } }, "SubnetRegistrationRuntimeApi": { From 80db62252635b9c23f8106f843d978087def55fa Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Thu, 24 Oct 2024 16:43:01 -0400 Subject: [PATCH 02/12] use runtime api for neuron --- .../src/bittensor/subtensor_interface.py | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/bittensor_cli/src/bittensor/subtensor_interface.py b/bittensor_cli/src/bittensor/subtensor_interface.py index 73259ba99..02c3271f6 100644 --- a/bittensor_cli/src/bittensor/subtensor_interface.py +++ b/bittensor_cli/src/bittensor/subtensor_interface.py @@ -730,17 +730,23 @@ async def neuron_for_uid( """ if uid is None: return NeuronInfo.get_null_neuron() - - params = [netuid, uid, block_hash] if block_hash else [netuid, uid] - json_body = await self.substrate.rpc_request( - method="neuronInfo_getNeuron", - params=params, # custom rpc method + + hex_bytes_result = await self.query_runtime_api( + runtime_api="NeuronInfoRuntimeApi", + method="get_neuron", + params=[netuid, uid], + block_hash=block_hash, ) - if not (result := json_body.get("result", None)): + + if not (result := hex_bytes_result): return NeuronInfo.get_null_neuron() - bytes_result = bytes(result) + if result.startswith("0x"): + bytes_result = bytes.fromhex(result[2:]) + else: + bytes_result = bytes.fromhex(result) + return NeuronInfo.from_vec_u8(bytes_result) async def get_delegated( From f3c7bd6dd845ca19a908b456566c73d01603228e Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Thu, 24 Oct 2024 16:44:06 -0400 Subject: [PATCH 03/12] get delegated runtime api --- .../src/bittensor/subtensor_interface.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/bittensor_cli/src/bittensor/subtensor_interface.py b/bittensor_cli/src/bittensor/subtensor_interface.py index 02c3271f6..de035864a 100644 --- a/bittensor_cli/src/bittensor/subtensor_interface.py +++ b/bittensor_cli/src/bittensor/subtensor_interface.py @@ -775,15 +775,23 @@ async def get_delegated( else (self.substrate.last_block_hash if reuse_block else None) ) encoded_coldkey = ss58_to_vec_u8(coldkey_ss58) - json_body = await self.substrate.rpc_request( - method="delegateInfo_getDelegated", - params=([block_hash, encoded_coldkey] if block_hash else [encoded_coldkey]), + + hex_bytes_result = await self.query_runtime_api( + runtime_api="DelegateInfoRuntimeApi", + method="get_delegated", + params=[encoded_coldkey], + block_hash=block_hash, ) - if not (result := json_body.get("result")): + if not (result := hex_bytes_result): return [] - return DelegateInfo.delegated_list_from_vec_u8(bytes(result)) + if result.startswith("0x"): + bytes_result = bytes.fromhex(result[2:]) + else: + bytes_result = bytes.fromhex(result) + + return DelegateInfo.delegated_list_from_vec_u8(bytes_result) async def query_identity( self, From e03d4796da9d45310f7af94a3166885cef16ea9c Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Thu, 24 Oct 2024 16:45:26 -0400 Subject: [PATCH 04/12] add todo --- bittensor_cli/src/bittensor/subtensor_interface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor_cli/src/bittensor/subtensor_interface.py b/bittensor_cli/src/bittensor/subtensor_interface.py index de035864a..e5d726478 100644 --- a/bittensor_cli/src/bittensor/subtensor_interface.py +++ b/bittensor_cli/src/bittensor/subtensor_interface.py @@ -1167,7 +1167,7 @@ async def get_delegates_by_netuid_light( A list of DelegateInfo objects detailing each delegate's characteristics. """ - + # TODO (Ben): doesn't exist params = [netuid] if not block_hash else [netuid, block_hash] json_body = await self.substrate.rpc_request( method="delegateInfo_getDelegatesLight", # custom rpc method From eafad578b29fc7908d8878719592e012463e0360 Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Thu, 24 Oct 2024 17:42:41 -0400 Subject: [PATCH 05/12] use runtime api for get subnet dynamic info --- .../src/bittensor/subtensor_interface.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/bittensor_cli/src/bittensor/subtensor_interface.py b/bittensor_cli/src/bittensor/subtensor_interface.py index e5d726478..28561e541 100644 --- a/bittensor_cli/src/bittensor/subtensor_interface.py +++ b/bittensor_cli/src/bittensor/subtensor_interface.py @@ -1184,10 +1184,22 @@ async def get_delegates_by_netuid_light( async def get_subnet_dynamic_info( self, netuid: int, block_hash: Optional[str] = None ) -> "DynamicInfo": - json = await self.substrate.rpc_request( - method="subnetInfo_getDynamicInfo", params=[netuid, block_hash] + hex_bytes_result = await self.query_runtime_api( + runtime_api="SubnetInfoRuntimeApi", + method="get_dynamic_info", + params=[netuid], + block_hash=block_hash, ) - subnets = DynamicInfo.from_vec_u8(json["result"]) + + if hex_bytes_result is None: + return None + + if hex_bytes_result.startswith("0x"): + bytes_result = bytes.fromhex(hex_bytes_result[2:]) + else: + bytes_result = bytes.fromhex(hex_bytes_result) + + subnets = DynamicInfo.from_vec_u8(bytes_result) return subnets async def get_stake_for_coldkey_and_hotkey_on_netuid( From 39fbaf242337dbe0b18bc6633097c3dbe2f6ccbc Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Thu, 24 Oct 2024 17:44:43 -0400 Subject: [PATCH 06/12] replace with runtime api --- .../src/bittensor/extrinsics/registration.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/bittensor_cli/src/bittensor/extrinsics/registration.py b/bittensor_cli/src/bittensor/extrinsics/registration.py index 112ce4fd5..86bad3c9f 100644 --- a/bittensor_cli/src/bittensor/extrinsics/registration.py +++ b/bittensor_cli/src/bittensor/extrinsics/registration.py @@ -493,17 +493,23 @@ async def get_neuron_for_pubkey_and_subnet(): ) if uid is None: return NeuronInfo.get_null_neuron() + - params = [netuid, uid] - json_body = await subtensor.substrate.rpc_request( - method="neuronInfo_getNeuron", - params=params, + hex_bytes_result = await subtensor.substrate.query_runtime_api( + runtime_api="NeuronInfoRuntimeApi", + method="get_neuron", + params=[netuid, uid], ) - if not (result := json_body.get("result", None)): + if not (result := hex_bytes_result): return NeuronInfo.get_null_neuron() + + if result.startswith("0x"): + bytes_result = bytes.fromhex(result[2:]) + else: + bytes_result = bytes.fromhex(result) - return NeuronInfo.from_vec_u8(bytes(result)) + return NeuronInfo.from_vec_u8(bytes_result) print_verbose("Checking subnet status") if not await subtensor.subnet_exists(netuid): From 292434d570080e101a5aa64ea8f30e3cfa1dd2e6 Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Thu, 24 Oct 2024 17:46:16 -0400 Subject: [PATCH 07/12] use runtime api here also --- bittensor_cli/src/commands/wallets.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/bittensor_cli/src/commands/wallets.py b/bittensor_cli/src/commands/wallets.py index daf17c259..1b0fe474b 100644 --- a/bittensor_cli/src/commands/wallets.py +++ b/bittensor_cli/src/commands/wallets.py @@ -1114,17 +1114,12 @@ async def _fetch_neuron_for_netuid( """ async def neurons_lite_for_uid(uid: int) -> dict[Any, Any]: - call_definition = TYPE_REGISTRY["runtime_api"]["NeuronInfoRuntimeApi"][ - "methods" - ]["get_neurons_lite"] - data = await subtensor.encode_params( - call_definition=call_definition, params=[uid] - ) block_hash = subtensor.substrate.last_block_hash - hex_bytes_result = await subtensor.substrate.rpc_request( - method="state_call", - params=["NeuronInfoRuntimeApi_get_neurons_lite", data, block_hash], - reuse_block_hash=True, + hex_bytes_result = await subtensor.query_runtime_api( + runtime_api="NeuronInfoRuntimeApi", + method="get_neurons_lite", + params=[uid], + block_hash=block_hash, ) return hex_bytes_result From 6087513c3c766ed00f3ece6999f3527abe7af88e Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Thu, 24 Oct 2024 17:50:13 -0400 Subject: [PATCH 08/12] replace with runtime api --- bittensor_cli/src/commands/subnets.py | 57 +++++++++++++++++++-------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/bittensor_cli/src/commands/subnets.py b/bittensor_cli/src/commands/subnets.py index 6a21c09f2..266f2fb7f 100644 --- a/bittensor_cli/src/commands/subnets.py +++ b/bittensor_cli/src/commands/subnets.py @@ -269,16 +269,22 @@ async def subnets_list( async def show(subtensor: "SubtensorInterface", netuid: int, prompt: bool = True): async def show_root(): all_subnets = await subtensor.get_all_subnet_dynamic_info() - root_state: "SubnetState" = SubnetState.from_vec_u8( - ( - await subtensor.substrate.rpc_request( - method="subnetInfo_getSubnetState", params=[0, None] - ) - )["result"] + + hex_bytes_result = await subtensor.query_runtime_api( + runtime_api="SubnetInfoRuntimeApi", + method="get_subnet_state", + params=[0], ) - if root_state is None: + if (bytes_result := hex_bytes_result) is None: err_console.print("The root subnet does not exist") return + + if bytes_result.startswith("0x"): + bytes_result = bytes.fromhex(bytes_result[2:]) + + root_state: "SubnetState" = SubnetState.from_vec_u8( + bytes_result + ) if len(root_state.hotkeys) == 0: err_console.print( "The root-subnet is currently empty with 0 UIDs registered." @@ -373,12 +379,20 @@ async def show_root(): async def show_subnet(netuid_: int): subnet_info = await subtensor.get_subnet_dynamic_info(netuid_) + hex_bytes_result = await subtensor.query_runtime_api( + runtime_api="SubnetInfoRuntimeApi", + method="get_subnet_state", + params=[netuid_], + ) + if (bytes_result := hex_bytes_result) is None: + err_console.print(f"Subnet {netuid_} does not exist") + return + + if bytes_result.startswith("0x"): + bytes_result = bytes.fromhex(bytes_result[2:]) + subnet_state: "SubnetState" = SubnetState.from_vec_u8( - ( - await subtensor.substrate.rpc_request( - method="subnetInfo_getSubnetState", params=[netuid_, None] - ) - )["result"] + bytes_result ) if subnet_info is None: err_console.print(f"Subnet {netuid_} does not exist") @@ -789,12 +803,21 @@ async def metagraph_cmd( ), subtensor.substrate.get_block_number(block_hash=block_hash), ) + + hex_bytes_result = await subtensor.query_runtime_api( + runtime_api="SubnetInfoRuntimeApi", + method="get_subnet_state", + params=[netuid], + ) + if not (bytes_result := hex_bytes_result): + err_console.print(f"Subnet {netuid} does not exist") + return + + if bytes_result.startswith("0x"): + bytes_result = bytes.fromhex(bytes_result[2:]) + subnet_state: "SubnetState" = SubnetState.from_vec_u8( - ( - await subtensor.substrate.rpc_request( - method="subnetInfo_getSubnetState", params=[netuid, None] - ) - )["result"] + bytes_result ) difficulty = int(difficulty_) From db27dc2bfa7dbe522ba74ef1ac33b78dcfc39203 Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Thu, 24 Oct 2024 19:57:30 -0400 Subject: [PATCH 09/12] add subnet state to reg --- bittensor_cli/src/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bittensor_cli/src/__init__.py b/bittensor_cli/src/__init__.py index 32ca0e0f5..9df23756e 100644 --- a/bittensor_cli/src/__init__.py +++ b/bittensor_cli/src/__init__.py @@ -299,6 +299,10 @@ class WalletValidationTypes(Enum): "params": [{"name": "netuid", "type": "u16"}], "type": "Vec", }, + "get_subnet_state": { + "params": [{"name": "netuid", "type": "u16"}], + "type": "Vec", + }, } }, "SubnetRegistrationRuntimeApi": { From d4978cff9b0935f4b9ea746e84ebbeacbafaa2f1 Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Thu, 24 Oct 2024 20:29:39 -0400 Subject: [PATCH 10/12] modify query_multiple --- bittensor_cli/src/bittensor/async_substrate_interface.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bittensor_cli/src/bittensor/async_substrate_interface.py b/bittensor_cli/src/bittensor/async_substrate_interface.py index 60ec9dce9..a6baf541a 100644 --- a/bittensor_cli/src/bittensor/async_substrate_interface.py +++ b/bittensor_cli/src/bittensor/async_substrate_interface.py @@ -4,7 +4,7 @@ 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, Iterable from bt_decode import PortableRegistry, decode as decode_by_type_string, MetadataV15 from async_property import async_property @@ -1792,7 +1792,7 @@ async def query_multiple( runtime = await self.init_runtime(block_hash=block_hash) preprocessed: tuple[Preprocessed] = await asyncio.gather( *[ - self._preprocess([x], block_hash, storage_function, module) + self._preprocess([x] if not isinstance(x, Iterable) else list(x), block_hash, storage_function, module) for x in params ] ) From 877df05cbc4552bb2efce542dbeeca665b65c012 Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Thu, 24 Oct 2024 20:29:48 -0400 Subject: [PATCH 11/12] fix total stake for hotkey --- bittensor_cli/src/bittensor/subtensor_interface.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bittensor_cli/src/bittensor/subtensor_interface.py b/bittensor_cli/src/bittensor/subtensor_interface.py index 28561e541..5de331d54 100644 --- a/bittensor_cli/src/bittensor/subtensor_interface.py +++ b/bittensor_cli/src/bittensor/subtensor_interface.py @@ -431,10 +431,11 @@ async def get_total_stake_for_hotkey( :return: {address: Balance objects} """ + netuids = await self.get_all_subnet_netuids(block_hash=block_hash) results = await self.substrate.query_multiple( - params=[s for s in ss58_addresses], + params=[p for p in zip(ss58_addresses, netuids)], module="SubtensorModule", - storage_function="TotalHotkeyStake", + storage_function="TotalHotkeyAlpha", block_hash=block_hash, reuse_block_hash=reuse_block, ) From 5b77906570313724a72f23c2ce90bbe8cad3d310 Mon Sep 17 00:00:00 2001 From: Cameron Fairchild Date: Thu, 24 Oct 2024 20:34:33 -0400 Subject: [PATCH 12/12] unwrap tuple --- bittensor_cli/src/bittensor/subtensor_interface.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bittensor_cli/src/bittensor/subtensor_interface.py b/bittensor_cli/src/bittensor/subtensor_interface.py index 5de331d54..500d281a2 100644 --- a/bittensor_cli/src/bittensor/subtensor_interface.py +++ b/bittensor_cli/src/bittensor/subtensor_interface.py @@ -432,14 +432,14 @@ async def get_total_stake_for_hotkey( :return: {address: Balance objects} """ netuids = await self.get_all_subnet_netuids(block_hash=block_hash) - results = await self.substrate.query_multiple( + results: dict[tuple[str, int], int] = await self.substrate.query_multiple( params=[p for p in zip(ss58_addresses, netuids)], module="SubtensorModule", storage_function="TotalHotkeyAlpha", block_hash=block_hash, reuse_block_hash=reuse_block, ) - return {k: Balance.from_rao(r or 0) for (k, r) in results.items()} + return {k[0]: Balance.from_rao(r or 0) for (k, r) in results.items()} async def current_take( self,