diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index 058bc10314..59269b8e06 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -109,6 +109,7 @@ fixed_to_float, check_and_convert_to_balance, ) +from bittensor.utils import deprecated_message from bittensor.utils.btlogging import logging from bittensor.utils.liquidity import ( calculate_fees, @@ -1678,7 +1679,7 @@ async def get_current_weight_commit_info( block: Optional[int] = None, block_hash: Optional[str] = None, reuse_block: bool = False, - ) -> list: + ) -> list[tuple[str, str, int]]: """ Retrieves CRV3 weight commit information for a specific subnet. @@ -1689,9 +1690,17 @@ async def get_current_weight_commit_info( reuse_block: Whether to reuse the last-used block hash. Returns: - list: A list of commit details, where each entry is a dictionary with keys 'who', 'serialized_commit', and - 'reveal_round', or an empty list if no data is found. + A list of commit details, where each item contains: + - ss58_address: The address of the committer. + - commit_message: The commit message. + - reveal_round: The round when the commitment was revealed. + + The list may be empty if there are no commits found. """ + deprecated_message( + message="The method `get_current_weight_commit_info` is deprecated and will be removed in version 10.0.0. " + "Use `get_current_weight_commit_info_v2` instead." + ) block_hash = await self.determine_block_hash(block, block_hash, reuse_block) result = await self.substrate.query_map( module="SubtensorModule", @@ -1704,6 +1713,43 @@ async def get_current_weight_commit_info( commits = result.records[0][1] if result.records else [] return [WeightCommitInfo.from_vec_u8(commit) for commit in commits] + async def get_current_weight_commit_info_v2( + self, + netuid: int, + block: Optional[int] = None, + block_hash: Optional[str] = None, + reuse_block: bool = False, + ) -> list[tuple[str, int, str, int]]: + """ + Retrieves CRV3 weight commit information for a specific subnet. + + Arguments: + netuid: The unique identifier of the subnet. + block: The blockchain block number for the query. Default is ``None``. + block_hash: The hash of the block to retrieve the subnet unique identifiers from. + reuse_block: Whether to reuse the last-used block hash. + + Returns: + A list of commit details, where each item contains: + - ss58_address: The address of the committer. + - commit_block: The block number when the commitment was made. + - commit_message: The commit message. + - reveal_round: The round when the commitment was revealed. + + The list may be empty if there are no commits found. + """ + block_hash = await self.determine_block_hash(block, block_hash, reuse_block) + result = await self.substrate.query_map( + module="SubtensorModule", + storage_function="CRV3WeightCommitsV2", + params=[netuid], + block_hash=block_hash, + reuse_block_hash=reuse_block, + ) + + commits = result.records[0][1] if result.records else [] + return [WeightCommitInfo.from_vec_u8_v2(commit) for commit in commits] + async def get_delegate_by_hotkey( self, hotkey_ss58: str, diff --git a/bittensor/core/chain_data/weight_commit_info.py b/bittensor/core/chain_data/weight_commit_info.py index db253f291c..b8555eed68 100644 --- a/bittensor/core/chain_data/weight_commit_info.py +++ b/bittensor/core/chain_data/weight_commit_info.py @@ -1,5 +1,6 @@ from dataclasses import dataclass from bittensor.core.chain_data.utils import decode_account_id +from typing import Optional @dataclass @@ -8,12 +9,14 @@ class WeightCommitInfo: Data class representing weight commit information. Attributes: - ss58 (str): The SS58 address of the committer - commit_hex (str): The serialized weight commit data as hex string - reveal_round (int): The round number for reveal + ss58: The SS58 address of the committer + commit_block: The block number of the commitment. + commit_hex: The serialized weight commit data as hex string + reveal_round: The round number for reveal """ ss58: str + commit_block: Optional[int] commit_hex: str reveal_round: int @@ -27,11 +30,37 @@ def from_vec_u8(cls, data: tuple) -> tuple[str, str, int]: Returns: WeightCommitInfo: A new instance with the decoded data + + Note: + This method is used when querying a block or block hash where storage functions `CRV3WeightCommitsV2` does + not exist in Subtensor module. """ - account_id, commit_data, round_number = data + account_id, commit_block, commit_data, round_number = data account_id_ = account_id[0] if isinstance(account_id, tuple) else account_id commit_data = commit_data[0] if isinstance(commit_data, tuple) else commit_data commit_hex = "0x" + "".join(format(x, "02x") for x in commit_data) return decode_account_id(account_id_), commit_hex, round_number + + @classmethod + def from_vec_u8_v2(cls, data: tuple) -> tuple[str, int, str, int]: + """ + Creates a WeightCommitInfo instance + + Args: + data (tuple): Tuple containing ((AccountId,), (commit_block, ) (commit_data,), round_number) + + Returns: + WeightCommitInfo: A new instance with the decoded data + """ + account_id, commit_block, commit_data, round_number = data + + account_id_ = account_id[0] if isinstance(account_id, tuple) else account_id + commit_block = ( + commit_block[0] if isinstance(commit_block, tuple) else commit_block + ) + commit_data = commit_data[0] if isinstance(commit_data, tuple) else commit_data + commit_hex = "0x" + "".join(format(x, "02x") for x in commit_data) + + return decode_account_id(account_id_), commit_block, commit_hex, round_number diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index b64809ee15..eac6061f7a 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -11,7 +11,7 @@ from async_substrate_interface.types import ScaleObj from bittensor_drand import get_encrypted_commitment from numpy.typing import NDArray - +from bittensor.utils import deprecated_message from bittensor.core.async_subtensor import ProposalVoteData from bittensor.core.axon import Axon from bittensor.core.chain_data import ( @@ -1072,7 +1072,7 @@ def get_all_revealed_commitments( def get_current_weight_commit_info( self, netuid: int, block: Optional[int] = None - ) -> list: + ) -> list[tuple[str, str, int]]: """ Retrieves CRV3 weight commit information for a specific subnet. @@ -1081,9 +1081,18 @@ def get_current_weight_commit_info( block (Optional[int]): The blockchain block number for the query. Default is ``None``. Returns: - list: A list of commit details, where each entry is a dictionary with keys 'who', 'serialized_commit', and - 'reveal_round', or an empty list if no data is found. + A list of commit details, where each item contains: + - ss58_address: The address of the committer. + - commit_message: The commit message. + - reveal_round: The round when the commitment was revealed. + + The list may be empty if there are no commits found. + """ + deprecated_message( + message="The method `get_current_weight_commit_info` is deprecated and will be removed in version 10.0.0. " + "Use `get_current_weight_commit_info_v2` instead." + ) result = self.substrate.query_map( module="SubtensorModule", storage_function="CRV3WeightCommits", @@ -1094,6 +1103,35 @@ def get_current_weight_commit_info( commits = result.records[0][1] if result.records else [] return [WeightCommitInfo.from_vec_u8(commit) for commit in commits] + def get_current_weight_commit_info_v2( + self, netuid: int, block: Optional[int] = None + ) -> list[tuple[str, int, str, int]]: + """ + Retrieves CRV3 weight commit information for a specific subnet. + + Arguments: + netuid (int): The unique identifier of the subnet. + block (Optional[int]): The blockchain block number for the query. Default is ``None``. + + Returns: + A list of commit details, where each item contains: + - ss58_address: The address of the committer. + - commit_block: The block number when the commitment was made. + - commit_message: The commit message. + - reveal_round: The round when the commitment was revealed. + + The list may be empty if there are no commits found. + """ + result = self.substrate.query_map( + module="SubtensorModule", + storage_function="CRV3WeightCommitsV2", + params=[netuid], + block_hash=self.determine_block_hash(block), + ) + + commits = result.records[0][1] if result.records else [] + return [WeightCommitInfo.from_vec_u8_v2(commit) for commit in commits] + def get_delegate_by_hotkey( self, hotkey_ss58: str, block: Optional[int] = None ) -> Optional["DelegateInfo"]: diff --git a/bittensor/core/subtensor_api/commitments.py b/bittensor/core/subtensor_api/commitments.py index 6bdbb7f9f3..8a9c49bd30 100644 --- a/bittensor/core/subtensor_api/commitments.py +++ b/bittensor/core/subtensor_api/commitments.py @@ -12,6 +12,9 @@ def __init__(self, subtensor: Union["_Subtensor", "_AsyncSubtensor"]): self.get_all_revealed_commitments = subtensor.get_all_revealed_commitments self.get_commitment = subtensor.get_commitment self.get_current_weight_commit_info = subtensor.get_current_weight_commit_info + self.get_current_weight_commit_info_v2 = ( + subtensor.get_current_weight_commit_info_v2 + ) self.get_last_commitment_bonds_reset_block = ( subtensor.get_last_commitment_bonds_reset_block ) diff --git a/bittensor/core/subtensor_api/utils.py b/bittensor/core/subtensor_api/utils.py index 6aad488979..3f31d51b90 100644 --- a/bittensor/core/subtensor_api/utils.py +++ b/bittensor/core/subtensor_api/utils.py @@ -48,6 +48,9 @@ def add_legacy_methods(subtensor: "SubtensorApi"): subtensor.get_current_weight_commit_info = ( subtensor._subtensor.get_current_weight_commit_info ) + subtensor.get_current_weight_commit_info_v2 = ( + subtensor._subtensor.get_current_weight_commit_info_v2 + ) subtensor.get_delegate_by_hotkey = subtensor._subtensor.get_delegate_by_hotkey subtensor.get_delegate_identities = subtensor._subtensor.get_delegate_identities subtensor.get_delegate_take = subtensor._subtensor.get_delegate_take diff --git a/bittensor/utils/__init__.py b/bittensor/utils/__init__.py index 14fb383847..26da8b5480 100644 --- a/bittensor/utils/__init__.py +++ b/bittensor/utils/__init__.py @@ -1,6 +1,7 @@ import ast import decimal import hashlib +import warnings from collections import namedtuple from typing import Any, Literal, Union, Optional, TYPE_CHECKING from urllib.parse import urlparse @@ -438,3 +439,9 @@ def determine_chain_endpoint_and_network( return result return "unknown", network + + +def deprecated_message(message: str) -> None: + """Shows a deprecation warning message with the given message.""" + warnings.simplefilter("default", DeprecationWarning) + warnings.warn(message=message, category=DeprecationWarning, stacklevel=2) diff --git a/bittensor/utils/balance.py b/bittensor/utils/balance.py index b65fdaec82..07a8431e66 100644 --- a/bittensor/utils/balance.py +++ b/bittensor/utils/balance.py @@ -4,6 +4,7 @@ from scalecodec import ScaleType from bittensor.core import settings +from bittensor.utils import deprecated_message def _check_currencies(self, other): @@ -830,12 +831,9 @@ def check_and_convert_to_balance( This is used to support backwards compatibility while also providing a deprecation notice. """ if isinstance(amount, (float, int)): - warnings.simplefilter("default", DeprecationWarning) - warnings.warn( + deprecated_message( "Detected a non-balance amount. Converting to Balance from Tao for backwards compatibility." - "Please update your code to use tao(amount) or Balance.from_tao(amount) for the main release 9.0.0.", - category=DeprecationWarning, - stacklevel=2, + "Please update your code to use tao(amount) or Balance.from_tao(amount) for the main release 10.0.0." ) amount = tao(amount) return amount diff --git a/tests/e2e_tests/conftest.py b/tests/e2e_tests/conftest.py index c79446be26..c9ed635971 100644 --- a/tests/e2e_tests/conftest.py +++ b/tests/e2e_tests/conftest.py @@ -18,7 +18,10 @@ setup_wallet, ) -LOCALNET_IMAGE_NAME = os.getenv("LOCALNET_IMAGE_NAME") or "ghcr.io/opentensor/subtensor-localnet:devnet-ready" +LOCALNET_IMAGE_NAME = ( + os.getenv("LOCALNET_IMAGE_NAME") + or "ghcr.io/opentensor/subtensor-localnet:devnet-ready" +) CONTAINER_NAME_PREFIX = "test_local_chain_" diff --git a/tests/e2e_tests/test_commit_reveal_v3.py b/tests/e2e_tests/test_commit_reveal_v3.py index 719dbe5827..1cc2970e3b 100644 --- a/tests/e2e_tests/test_commit_reveal_v3.py +++ b/tests/e2e_tests/test_commit_reveal_v3.py @@ -119,6 +119,7 @@ async def test_commit_and_reveal_weights_cr3(local_chain, subtensor, alice_walle reporting_interval=1, ) current_block = subtensor.get_current_block() + expected_block = current_block latest_drand_round = subtensor.last_drand_round() upcoming_tempo = next_tempo(current_block, tempo) logging.console.info( @@ -160,12 +161,13 @@ async def test_commit_and_reveal_weights_cr3(local_chain, subtensor, alice_walle ) # Fetch current commits pending on the chain - commits_on_chain = subtensor.get_current_weight_commit_info(netuid=netuid) - address, commit, reveal_round = commits_on_chain[0] + commits_on_chain = subtensor.get_current_weight_commit_info_v2(netuid=netuid) + address, commit_block, commit, reveal_round = commits_on_chain[0] # Assert correct values are committed on the chain assert expected_reveal_round == reveal_round assert address == alice_wallet.hotkey.ss58_address + assert commit_block == expected_block + 1 # Ensure no weights are available as of now assert subtensor.weights(netuid=netuid) == [] @@ -199,7 +201,7 @@ async def test_commit_and_reveal_weights_cr3(local_chain, subtensor, alice_walle assert weight_vals[0] == revealed_weights[0][1] # Now that the commit has been revealed, there shouldn't be any pending commits - assert subtensor.get_current_weight_commit_info(netuid=netuid) == [] + assert subtensor.get_current_weight_commit_info_v2(netuid=netuid) == [] # Ensure the drand_round is always in the positive w.r.t expected when revealed assert latest_drand_round - expected_reveal_round >= 0, ( diff --git a/tests/unit_tests/test_subtensor_extended.py b/tests/unit_tests/test_subtensor_extended.py index 78851574cf..09fcdb6d97 100644 --- a/tests/unit_tests/test_subtensor_extended.py +++ b/tests/unit_tests/test_subtensor_extended.py @@ -424,13 +424,16 @@ def test_get_children_pending(mock_substrate, subtensor): ) -def test_get_current_weight_commit_info(mock_substrate, subtensor, fake_wallet, mocker): +def test_get_current_weight_commit_info_v2( + mock_substrate, subtensor, fake_wallet, mocker +): mock_substrate.query_map.return_value.records = [ ( mocker.ANY, [ ( bytearray(32), + 100, b"data", 123, ), @@ -438,13 +441,14 @@ def test_get_current_weight_commit_info(mock_substrate, subtensor, fake_wallet, ), ] - result = subtensor.get_current_weight_commit_info( + result = subtensor.get_current_weight_commit_info_v2( netuid=1, ) assert result == [ ( "5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM", + 100, "0x64617461", 123, ), @@ -452,7 +456,7 @@ def test_get_current_weight_commit_info(mock_substrate, subtensor, fake_wallet, mock_substrate.query_map.assert_called_once_with( module="SubtensorModule", - storage_function="CRV3WeightCommits", + storage_function="CRV3WeightCommitsV2", params=[1], block_hash=None, )