Skip to content

Commit b5893f2

Browse files
authored
Merge pull request #2624 from opentensor/feat/roman/add-metagraph-info-subnet_volume
Add `subnet_volume` field to `MetagraphInfo` and `DynamicInfo`
2 parents 39c4661 + 18a9fab commit b5893f2

File tree

9 files changed

+48
-22
lines changed

9 files changed

+48
-22
lines changed

bittensor/core/async_subtensor.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,7 +1305,7 @@ async def get_metagraph_info(
13051305
block: Optional[int] = None,
13061306
block_hash: Optional[str] = None,
13071307
reuse_block: bool = False,
1308-
) -> MetagraphInfo:
1308+
) -> Optional[MetagraphInfo]:
13091309
"""
13101310
Retrieves the MetagraphInfo dataclass from the node for a single subnet (netuid)
13111311
@@ -1330,7 +1330,10 @@ async def get_metagraph_info(
13301330
params=[netuid],
13311331
block_hash=block_hash,
13321332
)
1333-
return MetagraphInfo.from_dict(query.decode())
1333+
if query.value is None:
1334+
logging.error(f"Subnet {netuid} does not exist.")
1335+
return None
1336+
return MetagraphInfo.from_dict(query.value)
13341337

13351338
async def get_all_metagraphs_info(
13361339
self,

bittensor/core/chain_data/dynamic_info.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class DynamicInfo(InfoBase):
3636
pending_alpha_emission: Balance
3737
pending_root_emission: Balance
3838
network_registered_at: int
39+
subnet_volume: Balance
3940
subnet_identity: Optional[SubnetIdentity]
4041

4142
@classmethod
@@ -71,6 +72,7 @@ def _from_dict(cls, decoded: dict) -> "DynamicInfo":
7172
decoded["pending_root_emission"]
7273
).set_unit(0)
7374

75+
subnet_volume = Balance.from_rao(decoded["subnet_volume"]).set_unit(netuid)
7476
price = (
7577
Balance.from_tao(1.0)
7678
if netuid == 0
@@ -113,6 +115,7 @@ def _from_dict(cls, decoded: dict) -> "DynamicInfo":
113115
pending_root_emission=pending_root_emission,
114116
network_registered_at=int(decoded["network_registered_at"]),
115117
subnet_identity=subnet_identity,
118+
subnet_volume=subnet_volume,
116119
)
117120

118121
def tao_to_alpha(self, tao: Union[Balance, float, int]) -> Balance:

bittensor/core/chain_data/metagraph_info.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class MetagraphInfo(InfoBase):
6262
tao_in_emission: Balance # amount of tao injected per block
6363
pending_alpha_emission: Balance # pending alpha to be distributed
6464
pending_root_emission: Balance # pending tao for root divs to be distributed
65+
subnet_volume: Balance # volume of the subnet in TAO
6566

6667
# Hparams for epoch
6768
rho: int # subnet rho param
@@ -161,6 +162,7 @@ def _from_dict(cls, decoded: dict) -> "MetagraphInfo":
161162
decoded["pending_alpha_emission"], _netuid
162163
)
163164
decoded["pending_root_emission"] = _tbwu(decoded["pending_root_emission"])
165+
decoded["subnet_volume"] = _tbwu(decoded["subnet_volume"], _netuid)
164166

165167
# Hparams for epoch
166168
decoded["kappa"] = u16tf(decoded["kappa"])
@@ -231,6 +233,7 @@ class MetagraphInfoPool:
231233
alpha_out: Balance
232234
alpha_in: Balance
233235
tao_in: Balance
236+
subnet_volume: Balance
234237

235238

236239
@dataclass

bittensor/core/metagraph.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -931,7 +931,7 @@ def __copy__(self):
931931
setattr(new_instance, key, value)
932932
return new_instance
933933

934-
def _apply_metagraph_ingo_mixin(self, metagraph_info: "MetagraphInfo"):
934+
def _apply_metagraph_info_mixin(self, metagraph_info: "MetagraphInfo"):
935935
"""
936936
Updates the attributes of the current object with data from a provided MetagraphInfo instance.
937937
@@ -985,6 +985,7 @@ def _apply_metagraph_ingo_mixin(self, metagraph_info: "MetagraphInfo"):
985985
alpha_out=metagraph_info.alpha_out,
986986
alpha_in=metagraph_info.alpha_in,
987987
tao_in=metagraph_info.tao_in,
988+
subnet_volume=metagraph_info.subnet_volume,
988989
)
989990
self.emissions = MetagraphInfoEmissions(
990991
alpha_out_emission=metagraph_info.alpha_out_emission,
@@ -1612,7 +1613,8 @@ async def _get_all_stakes_from_chain(self):
16121613
async def _apply_metagraph_info(self):
16131614
"""Retrieves metagraph information for a specific subnet and applies it using a mixin."""
16141615
metagraph_info = await self.subtensor.get_metagraph_info(self.netuid)
1615-
self._apply_metagraph_ingo_mixin(metagraph_info=metagraph_info)
1616+
if metagraph_info:
1617+
self._apply_metagraph_info_mixin(metagraph_info=metagraph_info)
16161618

16171619

16181620
class Metagraph(NumpyOrTorch):
@@ -1900,7 +1902,8 @@ def _get_all_stakes_from_chain(self):
19001902
def _apply_metagraph_info(self):
19011903
"""Retrieves metagraph information for a specific subnet and applies it using a mixin."""
19021904
metagraph_info = self.subtensor.get_metagraph_info(self.netuid)
1903-
self._apply_metagraph_ingo_mixin(metagraph_info=metagraph_info)
1905+
if metagraph_info:
1906+
self._apply_metagraph_info_mixin(metagraph_info=metagraph_info)
19041907

19051908

19061909
async def async_metagraph(

bittensor/core/subtensor.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,18 +1002,42 @@ def get_minimum_required_stake(self) -> Balance:
10021002
def get_metagraph_info(
10031003
self, netuid: int, block: Optional[int] = None
10041004
) -> Optional[MetagraphInfo]:
1005+
"""
1006+
Retrieves the MetagraphInfo dataclass from the node for a single subnet (netuid)
1007+
1008+
Arguments:
1009+
netuid: The NetUID of the subnet.
1010+
block: the block number at which to retrieve the hyperparameter. Do not specify if using block_hash or
1011+
reuse_block
1012+
1013+
Returns:
1014+
MetagraphInfo dataclass
1015+
"""
10051016
block_hash = self.determine_block_hash(block)
10061017
query = self.substrate.runtime_call(
10071018
"SubnetInfoRuntimeApi",
10081019
"get_metagraph",
10091020
params=[netuid],
10101021
block_hash=block_hash,
10111022
)
1023+
if query.value is None:
1024+
logging.error(f"Subnet {netuid} does not exist.")
1025+
return None
10121026
return MetagraphInfo.from_dict(query.value)
10131027

10141028
def get_all_metagraphs_info(
10151029
self, block: Optional[int] = None
10161030
) -> list[MetagraphInfo]:
1031+
"""
1032+
Retrieves a list of MetagraphInfo objects for all subnets
1033+
1034+
Arguments:
1035+
block: the block number at which to retrieve the hyperparameter. Do not specify if using block_hash or
1036+
reuse_block
1037+
1038+
Returns:
1039+
MetagraphInfo dataclass
1040+
"""
10171041
block_hash = self.determine_block_hash(block)
10181042
query = self.substrate.runtime_call(
10191043
"SubnetInfoRuntimeApi",

requirements/prod.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ uvicorn
2323
websockets>=14.1
2424
bittensor-commit-reveal>=0.2.0
2525
bittensor-wallet>=3.0.0
26-
async-substrate-interface==1.0.0rc9
26+
async-substrate-interface==1.0.0rc10

tests/e2e_tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import threading
88

99
import pytest
10-
from substrateinterface import SubstrateInterface
10+
from async_substrate_interface import SubstrateInterface
1111

1212
from bittensor.utils.btlogging import logging
1313
from tests.e2e_tests.utils.e2e_test_utils import (

tests/helpers/integration_websocket_data.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6457,7 +6457,7 @@
64576457
},
64586458
'["SubnetInfoRuntimeApi_get_metagraph", "0100", null]': {
64596459
"jsonrpc": "2.0",
6460-
"result": "0x01000cd1018501d5010839039102000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dec302009101fac20200e400000000000000000028feff010000feff0300009101214e010100010102286bee025a620201000140025a620213ffffffffffffff3f02286bee0700e87648170091010404c80004009a990300cecc020082ee36000000000000000000000000000000000000000000",
6460+
"result": "0x00",
64616461
},
64626462
},
64636463
"state_getRuntimeVersion": {

tests/unit_tests/test_async_subtensor.py

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,9 +1583,6 @@ async def test_does_hotkey_exist_true(subtensor, mocker):
15831583
mocked_query = mocker.AsyncMock(value=fake_query_result)
15841584
subtensor.substrate.query = mocked_query
15851585

1586-
mocked_decode_account_id = mocker.Mock(return_value="another_account_id")
1587-
mocker.patch.object(async_subtensor, "decode_account_id", mocked_decode_account_id)
1588-
15891586
# Call
15901587
result = await subtensor.does_hotkey_exist(
15911588
hotkey_ss58=fake_hotkey_ss58, block_hash=fake_block_hash
@@ -1599,25 +1596,19 @@ async def test_does_hotkey_exist_true(subtensor, mocker):
15991596
block_hash=fake_block_hash,
16001597
reuse_block_hash=False,
16011598
)
1602-
mocked_decode_account_id.assert_called_once()
16031599
assert result is True
16041600

16051601

16061602
@pytest.mark.asyncio
16071603
async def test_does_hotkey_exist_false_for_specific_account(subtensor, mocker):
16081604
"""Tests does_hotkey_exist method when the hotkey exists but matches the specific account ID to ignore."""
16091605
# Preps
1610-
fake_hotkey_ss58 = "ignored_hotkey"
1611-
fake_query_result = ["ignored_account_id"]
1606+
fake_hotkey_ss58 = "fake_hotkey"
1607+
fake_query_result = "5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM"
16121608

1613-
mocked_query = mocker.AsyncMock(value=fake_query_result)
1614-
subtensor.substrate.query = mocked_query
1615-
1616-
# Mock the decode_account_id function to return the specific account ID that should be ignored
1617-
mocked_decode_account_id = mocker.Mock(
1618-
return_value="5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM"
1609+
mocked_query = mocker.patch.object(
1610+
subtensor.substrate, "query", return_value=fake_query_result
16191611
)
1620-
mocker.patch.object(async_subtensor, "decode_account_id", mocked_decode_account_id)
16211612

16221613
# Call
16231614
result = await subtensor.does_hotkey_exist(hotkey_ss58=fake_hotkey_ss58)
@@ -1630,7 +1621,6 @@ async def test_does_hotkey_exist_false_for_specific_account(subtensor, mocker):
16301621
block_hash=None,
16311622
reuse_block_hash=False,
16321623
)
1633-
mocked_decode_account_id.assert_called_once()
16341624
assert result is False
16351625

16361626

0 commit comments

Comments
 (0)