From 43ffc7a1e19873f21c986765654a233d8e7f2d95 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 18:10:15 -0700 Subject: [PATCH 001/100] improve `async/subtensor.sign_and_send_extrinsic` --- bittensor/core/async_subtensor.py | 9 ++++++--- bittensor/core/subtensor.py | 12 +++++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index 422fb0a6e4..d8e7d56748 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -3216,7 +3216,7 @@ async def sign_and_send_extrinsic( wait_for_finalization: bool = False, sign_with: str = "coldkey", use_nonce: bool = False, - period: Optional[int] = None, + period: Optional[int] = 64, # 96 seconds for non-fast-blocks and 2 seconds for fast-blocks nonce_key: str = "hotkey", raise_error: bool = False, ) -> tuple[bool, str]: @@ -3230,9 +3230,12 @@ async def sign_and_send_extrinsic( wait_for_finalization (bool): whether to wait until the extrinsic call is finalized on the chain sign_with: the wallet's keypair to use for the signing. Options are "coldkey", "hotkey", "coldkeypub" use_nonce: unique identifier for the transaction related with hot/coldkey. - period: the period of the transaction as ERA part for transaction. Means how many blocks the transaction will be valid for. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. nonce_key: the type on nonce to use. Options are "hotkey" or "coldkey". - raise_error: raises relevant exception rather than returning `False` if unsuccessful. + nonce_key: the type on nonce to use. Options are "hotkey" or "coldkey". + raise_error: raises a relevant exception rather than returning `False` if unsuccessful. Returns: (success, error message) diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 1268c481b6..517f751ca0 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -2642,7 +2642,7 @@ def sign_and_send_extrinsic( wait_for_finalization: bool = False, sign_with: str = "coldkey", use_nonce: bool = False, - period: Optional[int] = None, + period: Optional[int] = 64, # 96 seconds for non-fast-blocks and 2 seconds for fast-blocks nonce_key: str = "hotkey", raise_error: bool = False, ) -> tuple[bool, str]: @@ -2654,11 +2654,13 @@ def sign_and_send_extrinsic( wallet (bittensor_wallet.Wallet): the wallet whose coldkey will be used to sign the extrinsic wait_for_inclusion (bool): whether to wait until the extrinsic call is included on the chain wait_for_finalization (bool): whether to wait until the extrinsic call is finalized on the chain - sign_with: the wallet's keypair to use for the signing. Options are "coldkey", "hotkey", "coldkeypub" - use_nonce: unique identifier for the transaction related with hot/coldkey. - period: the period of the transaction as ERA part for transaction. Means how many blocks the transaction will be valid for. + sign_with (str): the wallet's keypair to use for the signing. Options are "coldkey", "hotkey", "coldkeypub" + use_nonce (bool): unique identifier for the transaction related with hot/coldkey. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. nonce_key: the type on nonce to use. Options are "hotkey" or "coldkey". - raise_error: raises relevant exception rather than returning `False` if unsuccessful. + raise_error: raises a relevant exception rather than returning `False` if unsuccessful. Returns: (success, error message) From 4d2450bb80d044992fbb4193db5a65c907d67be6 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 19:33:37 -0700 Subject: [PATCH 002/100] add extrinsics helper function `convert_and_normalize_weights_and_uids` --- bittensor/core/extrinsics/utils.py | 38 ++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/bittensor/core/extrinsics/utils.py b/bittensor/core/extrinsics/utils.py index 7cc2e3c4e0..4a58260936 100644 --- a/bittensor/core/extrinsics/utils.py +++ b/bittensor/core/extrinsics/utils.py @@ -1,12 +1,15 @@ """Module with helper functions for extrinsics.""" -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Union +import numpy as np from async_substrate_interface.errors import SubstrateRequestException +from numpy.typing import NDArray from bittensor.utils import format_error_message from bittensor.utils.balance import Balance from bittensor.utils.btlogging import logging +from bittensor.utils.weight_utils import convert_weights_and_uids_for_emit if TYPE_CHECKING: from bittensor_wallet import Wallet @@ -18,6 +21,7 @@ from bittensor.core.subtensor import Subtensor from bittensor.core.chain_data import StakeInfo from scalecodec.types import GenericExtrinsic + from bittensor.utils.registration import torch def submit_extrinsic( @@ -105,9 +109,9 @@ def get_old_stakes( """ Retrieve the previous staking balances for a wallet's hotkeys across given netuids. - This function searches through the provided staking data to find the stake amounts - for the specified hotkeys and netuids associated with the wallet's coldkey. If no match - is found for a particular hotkey and netuid combination, a default balance of zero is returned. + This function searches through the provided staking data to find the stake amounts for the specified hotkeys and + netuids associated with the wallet's coldkey. If no match is found for a particular hotkey and netuid combination, + a default balance of zero is returned. Args: wallet (Wallet): The wallet containing the coldkey to compare with stake data. @@ -129,3 +133,29 @@ def get_old_stakes( ) for hotkey_ss58, netuid in zip(hotkey_ss58s, netuids) ] + + +def convert_and_normalize_weights_and_uids( + uids: Union[NDArray[np.int64], "torch.LongTensor", list], + weights: Union[NDArray[np.float32], "torch.FloatTensor", list], +) -> tuple[list[int], list[int]]: + """Converts weights and uids to numpy arrays if they are not already. + + Arguments: + uids (Union[NDArray[np.int64], torch.LongTensor, list]): The ``uint64`` uids of destination neurons. + weights (Union[NDArray[np.float32], torch.FloatTensor, list]): The weights to set. These must be ``float`` s + and correspond to the passed ``uid`` s. + + Returns: + weight_uids, weight_vals: Bytes converted weights and uids + """ + if isinstance(uids, list): + uids = np.array(uids, dtype=np.int64) + if isinstance(weights, list): + weights = np.array(weights, dtype=np.float32) + + # Reformat and normalize. + weight_uids, weight_vals = convert_weights_and_uids_for_emit( + uids, weights + ) + return weight_uids, weight_vals From 463dd2aa62afbe37b3c1b2455cbc3f37ca99038c Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 19:34:43 -0700 Subject: [PATCH 003/100] use `convert_and_normalize_weights_and_uids` in set_weights.py --- bittensor/core/extrinsics/set_weights.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/bittensor/core/extrinsics/set_weights.py b/bittensor/core/extrinsics/set_weights.py index 908fb2b2a9..7e5714afa3 100644 --- a/bittensor/core/extrinsics/set_weights.py +++ b/bittensor/core/extrinsics/set_weights.py @@ -5,8 +5,9 @@ import numpy as np from numpy.typing import NDArray +from bittensor.core.extrinsics.utils import convert_and_normalize_weights_and_uids from bittensor.core.settings import version_as_int -from bittensor.utils import format_error_message, weight_utils +from bittensor.utils import format_error_message from bittensor.utils.btlogging import logging if TYPE_CHECKING: @@ -60,7 +61,7 @@ def _do_set_weights( }, ) next_nonce = subtensor.substrate.get_account_next_index(wallet.hotkey.ss58_address) - # Period dictates how long the extrinsic will stay as part of waiting pool + # Period dictates how long the extrinsic will stay as part of the waiting pool extrinsic = subtensor.substrate.create_signed_extrinsic( call=call, keypair=wallet.hotkey, @@ -93,7 +94,7 @@ def set_weights_extrinsic( wait_for_finalization: bool = False, period: int = 5, ) -> tuple[bool, str]: - """Sets the given weights and values on chain for wallet hotkey account. + """Sets the given weights and values on a chain for a wallet hotkey account. Args: subtensor (bittensor.core.async_subtensor.AsyncSubtensor): Bittensor subtensor object. @@ -113,16 +114,14 @@ def set_weights_extrinsic( success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. If we did not wait for finalization / inclusion, the response is ``True``. """ - # First convert types. + # Convert types. if isinstance(uids, list): uids = np.array(uids, dtype=np.int64) if isinstance(weights, list): weights = np.array(weights, dtype=np.float32) # Reformat and normalize. - weight_uids, weight_vals = weight_utils.convert_weights_and_uids_for_emit( - uids, weights - ) + weight_uids, weight_vals = convert_and_normalize_weights_and_uids(uids, weights) logging.info( f":satellite: [magenta]Setting weights on [/magenta][blue]{subtensor.network}[/blue] [magenta]...[/magenta]" From 58f3f151b8969526fd4dfe71592c4f1d4ccc816f Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 19:35:22 -0700 Subject: [PATCH 004/100] use `convert_and_normalize_weights_and_uids` in weights.py --- bittensor/core/extrinsics/asyncex/weights.py | 29 ++++++-------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/weights.py b/bittensor/core/extrinsics/asyncex/weights.py index 6e07b90adb..62f9ea31f1 100644 --- a/bittensor/core/extrinsics/asyncex/weights.py +++ b/bittensor/core/extrinsics/asyncex/weights.py @@ -5,9 +5,8 @@ import numpy as np from numpy.typing import NDArray -import bittensor.utils.weight_utils as weight_utils +from bittensor.core.extrinsics.utils import convert_and_normalize_weights_and_uids from bittensor.core.settings import version_as_int -from bittensor.utils import format_error_message from bittensor.utils.btlogging import logging if TYPE_CHECKING: @@ -119,7 +118,7 @@ async def _do_reveal_weights( version_key: int, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, -) -> tuple[bool, Optional[dict]]: +) -> tuple[bool, str]: """ Internal method to send a transaction to the Bittensor blockchain, revealing the weights for a specific subnet. This method constructs and submits the transaction, handling retries and blockchain communication. @@ -137,7 +136,7 @@ async def _do_reveal_weights( wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Returns: - tuple[bool, Optional[str]]: A tuple containing a success flag and an optional error message. + tuple[bool, str]: A tuple containing a success flag and an optional error message. This method ensures that the weight revelation is securely recorded on the Bittensor blockchain, providing transparency and accountability for the neuron's weight distribution. @@ -181,8 +180,7 @@ async def reveal_weights_extrinsic( This function is a wrapper around the `_do_reveal_weights` method. Args: - subtensor (bittensor.core.async_subtensor.AsyncSubtensor): The subtensor instance used for blockchain - interaction. + subtensor (bittensor.core.async_subtensor.AsyncSubtensor): The subtensor instance used for blockchain interaction. wallet (bittensor_wallet.Wallet): The wallet associated with the neuron revealing the weights. netuid (int): The unique identifier of the subnet. uids (list[int]): List of neuron UIDs for which weights are being revealed. @@ -217,7 +215,6 @@ async def reveal_weights_extrinsic( logging.info(success_message) return True, success_message - error_message = format_error_message(error_message) logging.error(f"Failed to reveal weights: {error_message}") return False, error_message @@ -232,7 +229,7 @@ async def _do_set_weights( wait_for_inclusion: bool = False, wait_for_finalization: bool = False, period: int = 5, -) -> tuple[bool, Optional[str]]: # (success, error_message) +) -> tuple[bool, str]: # (success, error_message) """ Internal method to send a transaction to the Bittensor blockchain, setting weights for specified neurons. This method constructs and submits the transaction, handling @@ -250,7 +247,7 @@ async def _do_set_weights( period (int, optional): The period in seconds to wait for extrinsic inclusion or finalization. Defaults to 5. Returns: - Tuple[bool, Optional[str]]: A tuple containing a success flag and an optional error message. + Tuple[bool, str]: A tuple containing a success flag and an optional error message. This method is vital for the dynamic weighting mechanism in Bittensor, where neurons adjust their trust in other neurons based on observed performance and contributions. @@ -289,7 +286,7 @@ async def set_weights_extrinsic( wait_for_finalization: bool = False, period: int = 5, ) -> tuple[bool, str]: - """Sets the given weights and values on chain for wallet hotkey account. + """Sets the given weights and values on a chain for a wallet hotkey account. Args: subtensor (bittensor.core.async_subtensor.AsyncSubtensor): Bittensor subtensor object. @@ -309,16 +306,8 @@ async def set_weights_extrinsic( success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. If we did not wait for finalization / inclusion, the response is ``True``. """ - # First convert types. - if isinstance(uids, list): - uids = np.array(uids, dtype=np.int64) - if isinstance(weights, list): - weights = np.array(weights, dtype=np.float32) - - # Reformat and normalize. - weight_uids, weight_vals = weight_utils.convert_weights_and_uids_for_emit( - uids, weights - ) + + weight_uids, weight_vals = convert_and_normalize_weights_and_uids(uids, weights) logging.info( f":satellite: [magenta]Setting weights on [/magenta][blue]{subtensor.network}[/blue] [magenta]...[/magenta]" From e1543dba4f6c31c9ab44f77fc48a907602de4a84 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 19:57:19 -0700 Subject: [PATCH 005/100] update commit_reveal extrinsics --- .../core/extrinsics/asyncex/commit_reveal.py | 44 +++++++++++-------- bittensor/core/extrinsics/commit_reveal.py | 41 ++++++++++------- 2 files changed, 49 insertions(+), 36 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/commit_reveal.py b/bittensor/core/extrinsics/asyncex/commit_reveal.py index 70c12fe0fb..7994bbbd76 100644 --- a/bittensor/core/extrinsics/asyncex/commit_reveal.py +++ b/bittensor/core/extrinsics/asyncex/commit_reveal.py @@ -6,9 +6,9 @@ from bittensor_drand import get_encrypted_commit from numpy.typing import NDArray +from bittensor.core.extrinsics.utils import convert_and_normalize_weights_and_uids from bittensor.core.settings import version_as_int from bittensor.utils.btlogging import logging -from bittensor.utils.weight_utils import convert_weights_and_uids_for_emit if TYPE_CHECKING: from bittensor_wallet import Wallet @@ -24,23 +24,26 @@ async def _do_commit_reveal_v3( reveal_round: int, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, -) -> tuple[bool, Optional[str]]: + period: Optional[int] = None, +) -> tuple[bool, str]: """ - Executes the commit-reveal phase 3 for a given netuid and commit, and optionally waits for extrinsic inclusion or - finalization. + Executes commit-reveal phase 3 for a given netuid and commit, and optionally waits for extrinsic inclusion or finalization. Arguments: subtensor: An instance of the AsyncSubtensor class. wallet: Wallet An instance of the Wallet class containing the user's keypair. netuid: int The network unique identifier. - commit bytes The commit data in bytes format. + commit: bytes The commit data in bytes format. reveal_round: int The round number for the reveal phase. wait_for_inclusion: bool, optional Flag indicating whether to wait for the extrinsic to be included in a block. wait_for_finalization: bool, optional Flag indicating whether to wait for the extrinsic to be finalized. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: - A tuple where the first element is a boolean indicating success or failure, and the second element is an - optional string containing error message if any. + A tuple where the first element is a boolean indicating success or failure, and the second element is a + string containing an error message if any. """ logging.info( f"Committing weights hash [blue]{commit.hex()}[/blue] for subnet #[blue]{netuid}[/blue] with " @@ -57,7 +60,12 @@ async def _do_commit_reveal_v3( }, ) return await subtensor.sign_and_send_extrinsic( - call, wallet, wait_for_inclusion, wait_for_finalization, sign_with="hotkey" + call=call, + wallet=wallet, + wait_for_inclusion=wait_for_inclusion, + wait_for_finalization=wait_for_finalization, + sign_with="hotkey", + period=period ) @@ -70,10 +78,11 @@ async def commit_reveal_v3_extrinsic( version_key: int = version_as_int, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, - block_time: float = 12.0, + block_time: Union[int, float] = 12.0, + period: Optional[int] = None, ) -> tuple[bool, str]: """ - Commits and reveals weights for given subtensor and wallet with provided uids and weights. + Commits and reveals weights for a given subtensor and wallet with provided uids and weights. Arguments: subtensor: The AsyncSubtensor instance. @@ -84,21 +93,17 @@ async def commit_reveal_v3_extrinsic( version_key: The version key to use for committing and revealing. Default is version_as_int. wait_for_inclusion: Whether to wait for the inclusion of the transaction. Default is False. wait_for_finalization: Whether to wait for the finalization of the transaction. Default is False. - block_time (float): The amount of seconds for block duration. Default is 12.0 seconds. + block_time (float): The number of seconds for block duration. Default is 12.0 seconds. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: A tuple where the first element is a boolean indicating success or failure, and the second element is a message associated with the result """ try: - # Convert uids and weights - if isinstance(uids, list): - uids = np.array(uids, dtype=np.int64) - if isinstance(weights, list): - weights = np.array(weights, dtype=np.float32) - - # Reformat and normalize. - uids, weights = convert_weights_and_uids_for_emit(uids, weights) + uids, weights = convert_and_normalize_weights_and_uids(uids, weights) current_block = await subtensor.substrate.get_block(None) subnet_hyperparameters = await subtensor.get_subnet_hyperparameters( @@ -127,6 +132,7 @@ async def commit_reveal_v3_extrinsic( reveal_round=reveal_round, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if success is not True: diff --git a/bittensor/core/extrinsics/commit_reveal.py b/bittensor/core/extrinsics/commit_reveal.py index be66a71ea3..73e62aaf8f 100644 --- a/bittensor/core/extrinsics/commit_reveal.py +++ b/bittensor/core/extrinsics/commit_reveal.py @@ -2,13 +2,13 @@ from typing import Union, TYPE_CHECKING, Optional -from bittensor_drand import get_encrypted_commit import numpy as np +from bittensor_drand import get_encrypted_commit from numpy.typing import NDArray +from bittensor.core.extrinsics.utils import convert_and_normalize_weights_and_uids from bittensor.core.settings import version_as_int from bittensor.utils.btlogging import logging -from bittensor.utils.weight_utils import convert_weights_and_uids_for_emit if TYPE_CHECKING: from bittensor_wallet import Wallet @@ -24,23 +24,27 @@ def _do_commit_reveal_v3( reveal_round: int, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> tuple[bool, Optional[str]]: """ - Executes the commit-reveal phase 3 for a given netuid and commit, and optionally waits for extrinsic inclusion or + Executes commit-reveal phase 3 for a given netuid and commit, and optionally waits for extrinsic inclusion or finalization. Arguments: subtensor: An instance of the Subtensor class. wallet: Wallet An instance of the Wallet class containing the user's keypair. netuid: int The network unique identifier. - commit bytes The commit data in bytes format. + commit: bytes The commit data in bytes format. reveal_round: int The round number for the reveal phase. wait_for_inclusion: bool, optional Flag indicating whether to wait for the extrinsic to be included in a block. wait_for_finalization: bool, optional Flag indicating whether to wait for the extrinsic to be finalized. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: A tuple where the first element is a boolean indicating success or failure, and the second element is an - optional string containing error message if any. + optional string containing an error message if any. """ logging.info( f"Committing weights hash [blue]{commit.hex()}[/blue] for subnet #[blue]{netuid}[/blue] with " @@ -57,7 +61,12 @@ def _do_commit_reveal_v3( }, ) return subtensor.sign_and_send_extrinsic( - call, wallet, wait_for_inclusion, wait_for_finalization, sign_with="hotkey" + call=call, + wallet=wallet, + wait_for_inclusion=wait_for_inclusion, + wait_for_finalization=wait_for_finalization, + sign_with="hotkey", + period=period ) @@ -70,10 +79,11 @@ def commit_reveal_v3_extrinsic( version_key: int = version_as_int, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, - block_time: float = 12.0, + block_time: Union[int, float] = 12.0, + period: Optional[int] = None, ) -> tuple[bool, str]: """ - Commits and reveals weights for given subtensor and wallet with provided uids and weights. + Commits and reveals weights for a given subtensor and wallet with provided uids and weights. Arguments: subtensor: The Subtensor instance. @@ -84,21 +94,17 @@ def commit_reveal_v3_extrinsic( version_key: The version key to use for committing and revealing. Default is version_as_int. wait_for_inclusion: Whether to wait for the inclusion of the transaction. Default is False. wait_for_finalization: Whether to wait for the finalization of the transaction. Default is False. - block_time (float): The amount of seconds for block duration. Default is 12.0 seconds. + block_time (float): The number of seconds for block duration. Default is 12.0 seconds. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If the + transaction is not included in a block within that number of blocks, it will expire and be rejected. You can + think of it as an expiration date for the transaction. Returns: tuple[bool, str]: A tuple where the first element is a boolean indicating success or failure, and the second element is a message associated with the result """ try: - # Convert uids and weights - if isinstance(uids, list): - uids = np.array(uids, dtype=np.int64) - if isinstance(weights, list): - weights = np.array(weights, dtype=np.float32) - - # Reformat and normalize. - uids, weights = convert_weights_and_uids_for_emit(uids, weights) + uids, weights = convert_and_normalize_weights_and_uids(uids, weights) current_block = subtensor.get_current_block() subnet_hyperparameters = subtensor.get_subnet_hyperparameters( @@ -127,6 +133,7 @@ def commit_reveal_v3_extrinsic( reveal_round=reveal_round, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if success is not True: From dbc23e3f1e943ab6669eb095880ec5d1a0da9436 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 19:57:59 -0700 Subject: [PATCH 006/100] update `bittensor.core.subtensor.Subtensor.set_weights` call --- bittensor/core/subtensor.py | 46 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 517f751ca0..b5c83fbfba 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -3216,7 +3216,7 @@ def set_weights( wait_for_finalization: bool = False, max_retries: int = 5, block_time: float = 12.0, - period: int = 5, + period: int = 8, ) -> tuple[bool, str]: """ Sets the inter-neuronal weights for the specified neuron. This process involves specifying the influence or @@ -3224,27 +3224,26 @@ def set_weights( decentralized learning architecture. Arguments: - wallet (bittensor_wallet.Wallet): The wallet associated with the neuron setting the weights. - netuid (int): The unique identifier of the subnet. - uids (Union[NDArray[np.int64], torch.LongTensor, list]): The list of neuron UIDs that the weights are being - set for. - weights (Union[NDArray[np.float32], torch.FloatTensor, list]): The corresponding weights to be set for each - UID. - version_key (int): Version key for compatibility with the network. Default is int representation of - Bittensor version. - wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``False``. - wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is - ``False``. - max_retries (int): The number of maximum attempts to set weights. Default is ``5``. - block_time (float): The amount of seconds for block duration. Default is 12.0 seconds. - period (int, optional): The period in seconds to wait for extrinsic inclusion or finalization. Defaults to 5. + wallet: The wallet associated with the neuron setting the weights. + netuid: The unique identifier of the subnet. + uids: The list of neuron UIDs that the weights are being set for. + weights: The corresponding weights to be set for each UID. + version_key: Version key for compatibility with the network. Default is int representation of a Bittensor version. + wait_for_inclusion: Waits for the transaction to be included in a block. Default is ``False``. + wait_for_finalization: Waits for the transaction to be finalized on the blockchain. Default is ``False``. + max_retries: The number of maximum attempts to set weights. Default is ``5``. + block_time: The number of seconds for block duration. Default is 12.0 seconds. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: - tuple[bool, str]: ``True`` if the setting of weights is successful, False otherwise. And `msg`, a string - value describing the success or potential error. + tuple: + ``True`` if the setting of weights is successful, False otherwise. + `msg` is a string value describing the success or potential error. This function is crucial in shaping the network's collective intelligence, where each neuron's learning and - contribution are influenced by the weights it sets towards others【81†source】. + contribution are influenced by the weights it sets towards others. """ def _blocks_weight_limit() -> bool: @@ -3268,7 +3267,8 @@ def _blocks_weight_limit() -> bool: while retries < max_retries and success is False and _blocks_weight_limit(): logging.info( - f"Committing weights for subnet #{netuid}. Attempt {retries + 1} of {max_retries}." + f"Committing weights for subnet [blue]{netuid}[/blue]. " + f"Attempt [blue]{retries + 1}[blue] of [green]{max_retries}[/green]." ) success, message = commit_reveal_v3_extrinsic( subtensor=self, @@ -3280,17 +3280,18 @@ def _blocks_weight_limit() -> bool: wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, block_time=block_time, + period=period, ) retries += 1 return success, message else: - # go with classic `set weights extrinsic` + # go with classic `set_weights_extrinsic` while retries < max_retries and success is False and _blocks_weight_limit(): try: logging.info( - f"Setting weights for subnet #[blue]{netuid}[/blue]. " - f"Attempt [blue]{retries + 1} of {max_retries}[/blue]." + f"Setting weights for subnet [blue]{netuid}[/blue]. " + f"Attempt [blue]{retries + 1}[/blue] of [green]{max_retries}[/green]." ) success, message = set_weights_extrinsic( subtensor=self, @@ -3305,7 +3306,6 @@ def _blocks_weight_limit() -> bool: ) except Exception as e: logging.error(f"Error setting weights: {e}") - finally: retries += 1 return success, message From c88822f0b53db9a2aab43dd4f1521338a351fa5e Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 19:58:59 -0700 Subject: [PATCH 007/100] update test related with `bittensor.core.subtensor.Subtensor.set_weights` call --- tests/unit_tests/test_subtensor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/test_subtensor.py b/tests/unit_tests/test_subtensor.py index ca6aad000d..2774d7ca4e 100644 --- a/tests/unit_tests/test_subtensor.py +++ b/tests/unit_tests/test_subtensor.py @@ -1203,7 +1203,7 @@ def test_set_weights(subtensor, mocker, fake_wallet): version_key=settings.version_as_int, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, - period=5, + period=8, ) assert result == expected_result @@ -3144,6 +3144,7 @@ def test_set_weights_with_commit_reveal_enabled(subtensor, fake_wallet, mocker): wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, block_time=12.0, + period=8, ) assert result == mocked_commit_reveal_v3_extrinsic.return_value From 1b98ea03fedab8ab5960f003b430df4e99663185 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 21:31:39 -0700 Subject: [PATCH 008/100] increase set_weights' period until 16 to avoid flaky behavior --- bittensor/core/subtensor.py | 6 +++--- tests/e2e_tests/test_commit_reveal_v3.py | 2 +- tests/e2e_tests/test_commit_weights.py | 16 ++++++++-------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index b5c83fbfba..1090c4162b 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -3139,7 +3139,7 @@ def root_set_weights( wait_for_finalization: bool = False, ) -> bool: """ - Set weights for root network. + Set weights for the root network. Arguments: wallet (bittensor_wallet.Wallet): bittensor wallet instance. @@ -3216,7 +3216,7 @@ def set_weights( wait_for_finalization: bool = False, max_retries: int = 5, block_time: float = 12.0, - period: int = 8, + period: int = 16, ) -> tuple[bool, str]: """ Sets the inter-neuronal weights for the specified neuron. This process involves specifying the influence or @@ -3235,7 +3235,7 @@ def set_weights( block_time: The number of seconds for block duration. Default is 12.0 seconds. period (int): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. - You can think of it as an expiration date for the transaction. + You can think of it as an expiration date for the transaction. Default is 16. Returns: tuple: diff --git a/tests/e2e_tests/test_commit_reveal_v3.py b/tests/e2e_tests/test_commit_reveal_v3.py index 106af50a96..4eff2ce052 100644 --- a/tests/e2e_tests/test_commit_reveal_v3.py +++ b/tests/e2e_tests/test_commit_reveal_v3.py @@ -22,7 +22,7 @@ async def test_commit_and_reveal_weights_cr3(local_chain, subtensor, alice_walle Steps: 1. Register a subnet through Alice 2. Register Alice's neuron and add stake - 3. Enable commit-reveal mechanism on the subnet + 3. Enable a commit-reveal mechanism on subnet 4. Lower weights rate limit 5. Change the tempo for subnet 1 5. Commit weights and ensure they are committed. diff --git a/tests/e2e_tests/test_commit_weights.py b/tests/e2e_tests/test_commit_weights.py index 5015208a1b..6d77895e76 100644 --- a/tests/e2e_tests/test_commit_weights.py +++ b/tests/e2e_tests/test_commit_weights.py @@ -19,14 +19,14 @@ async def test_commit_and_reveal_weights_legacy(local_chain, subtensor, alice_wa Steps: 1. Register a subnet through Alice - 2. Enable commit-reveal mechanism on the subnet + 2. Enable a commit-reveal mechanism on subnet 3. Lower the commit_reveal interval and rate limit 4. Commit weights and verify 5. Wait interval & reveal weights and verify Raises: AssertionError: If any of the checks or verifications fail """ - netuid = 2 + netuid = subtensor.get_total_subnets() # 2 print("Testing test_commit_and_reveal_weights") @@ -153,12 +153,12 @@ async def test_commit_and_reveal_weights_legacy(local_chain, subtensor, alice_wa @pytest.mark.asyncio async def test_commit_weights_uses_next_nonce(local_chain, subtensor, alice_wallet): """ - Tests that committing weights doesn't re-use a nonce in the transaction pool. + Tests that committing weights doesn't re-use nonce in the transaction pool. Steps: 1. Register a subnet through Alice 2. Register Alice's neuron and add stake - 3. Enable commit-reveal mechanism on the subnet + 3. Enable a commit-reveal mechanism on subnet 4. Lower the commit_reveal interval and rate limit 5. Commit weights three times 6. Assert that all commits succeeded @@ -166,7 +166,7 @@ async def test_commit_weights_uses_next_nonce(local_chain, subtensor, alice_wall AssertionError: If any of the checks or verifications fail """ subnet_tempo = 50 - netuid = 2 + netuid = subtensor.get_total_subnets() # 2 # Wait for 2 tempos to pass as CR3 only reveals weights after 2 tempos subtensor.wait_for_block(subnet_tempo * 2 + 1) @@ -226,7 +226,7 @@ async def test_commit_weights_uses_next_nonce(local_chain, subtensor, alice_wall # wait while weights_rate_limit changes applied. subtensor.wait_for_block(subnet_tempo + 1) - # create different commited data to avoid coming into pool black list with the error + # Create different commited data to avoid coming into the pool's blacklist with the error # Failed to commit weights: Subtensor returned `Custom type(1012)` error. This means: `Transaction is temporarily # banned`.Failed to commit weights: Subtensor returned `Custom type(1012)` error. This means: `Transaction is # temporarily banned`.` @@ -245,7 +245,7 @@ def get_weights_and_salt(counter: int): f"{subtensor.substrate.get_account_next_index(alice_wallet.hotkey.ss58_address)}[/orange]" ) - # 3 time doing call if nonce wasn't updated, then raise error + # 3 time doing call if nonce wasn't updated, then raise the error @retry.retry(exceptions=Exception, tries=3, delay=1) @execute_and_wait_for_next_nonce(subtensor=subtensor, wallet=alice_wallet) def send_commit(salt_, weight_uids_, weight_vals_): @@ -260,7 +260,7 @@ def send_commit(salt_, weight_uids_, weight_vals_): ) assert success is True, message - # send some amount of commit weights + # Send some number of commit weights AMOUNT_OF_COMMIT_WEIGHTS = 3 for call in range(AMOUNT_OF_COMMIT_WEIGHTS): weight_uids, weight_vals, salt = get_weights_and_salt(call) From b0e5238365bc74ba629741567423edd2bb169332 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 21:31:52 -0700 Subject: [PATCH 009/100] fix tests --- tests/unit_tests/test_subtensor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/test_subtensor.py b/tests/unit_tests/test_subtensor.py index 2774d7ca4e..f6bb50f619 100644 --- a/tests/unit_tests/test_subtensor.py +++ b/tests/unit_tests/test_subtensor.py @@ -1203,7 +1203,7 @@ def test_set_weights(subtensor, mocker, fake_wallet): version_key=settings.version_as_int, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, - period=8, + period=16, ) assert result == expected_result @@ -3144,7 +3144,7 @@ def test_set_weights_with_commit_reveal_enabled(subtensor, fake_wallet, mocker): wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, block_time=12.0, - period=8, + period=16, ) assert result == mocked_commit_reveal_v3_extrinsic.return_value From e32638c0b016ef39f72181280a1b65d9f1ad4722 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 21:40:02 -0700 Subject: [PATCH 010/100] fix commit reveal unit tests --- .../extrinsics/asyncex/test_commit_reveal.py | 10 ++++++---- tests/unit_tests/extrinsics/test_commit_reveal.py | 11 +++++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/tests/unit_tests/extrinsics/asyncex/test_commit_reveal.py b/tests/unit_tests/extrinsics/asyncex/test_commit_reveal.py index 7802ccf9bb..2b0b1f596d 100644 --- a/tests/unit_tests/extrinsics/asyncex/test_commit_reveal.py +++ b/tests/unit_tests/extrinsics/asyncex/test_commit_reveal.py @@ -163,7 +163,7 @@ async def test_commit_reveal_v3_extrinsic_success_with_torch( mocked_weights = mocker.Mock() mocked_convert_weights_and_uids_for_emit = mocker.patch.object( async_commit_reveal, - "convert_weights_and_uids_for_emit", + "convert_and_normalize_weights_and_uids", return_value=(mocked_uids, mocked_weights), ) mocked_get_subnet_reveal_period_epochs = mocker.patch.object( @@ -223,6 +223,7 @@ async def test_commit_reveal_v3_extrinsic_success_with_torch( reveal_round=fake_reveal_round, wait_for_inclusion=True, wait_for_finalization=True, + period=None ) @@ -238,7 +239,7 @@ async def test_commit_reveal_v3_extrinsic_success_with_numpy( mock_convert = mocker.patch.object( async_commit_reveal, - "convert_weights_and_uids_for_emit", + "convert_and_normalize_weights_and_uids", return_value=(fake_uids, fake_weights), ) mock_encode_drand = mocker.patch.object( @@ -288,7 +289,7 @@ async def test_commit_reveal_v3_extrinsic_response_false( # Mocks mocker.patch.object( async_commit_reveal, - "convert_weights_and_uids_for_emit", + "convert_and_normalize_weights_and_uids", return_value=(fake_uids, fake_weights), ) mocker.patch.object( @@ -328,6 +329,7 @@ async def test_commit_reveal_v3_extrinsic_response_false( reveal_round=fake_reveal_round, wait_for_inclusion=True, wait_for_finalization=True, + period=None ) @@ -341,7 +343,7 @@ async def test_commit_reveal_v3_extrinsic_exception(mocker, subtensor, fake_wall mocker.patch.object( async_commit_reveal, - "convert_weights_and_uids_for_emit", + "convert_and_normalize_weights_and_uids", side_effect=Exception("Test Error"), ) diff --git a/tests/unit_tests/extrinsics/test_commit_reveal.py b/tests/unit_tests/extrinsics/test_commit_reveal.py index 37b131e391..e254e88a0f 100644 --- a/tests/unit_tests/extrinsics/test_commit_reveal.py +++ b/tests/unit_tests/extrinsics/test_commit_reveal.py @@ -155,7 +155,7 @@ def test_commit_reveal_v3_extrinsic_success_with_torch( mocked_weights = mocker.Mock() mocked_convert_weights_and_uids_for_emit = mocker.patch.object( commit_reveal, - "convert_weights_and_uids_for_emit", + "convert_and_normalize_weights_and_uids", return_value=(mocked_uids, mocked_weights), ) mocker.patch.object(subtensor, "get_subnet_reveal_period_epochs") @@ -183,6 +183,7 @@ def test_commit_reveal_v3_extrinsic_success_with_torch( weights=fake_weights, wait_for_inclusion=True, wait_for_finalization=True, + period=None, ) # Asserts @@ -209,6 +210,7 @@ def test_commit_reveal_v3_extrinsic_success_with_torch( reveal_round=fake_reveal_round, wait_for_inclusion=True, wait_for_finalization=True, + period=None, ) @@ -223,7 +225,7 @@ def test_commit_reveal_v3_extrinsic_success_with_numpy( mock_convert = mocker.patch.object( commit_reveal, - "convert_weights_and_uids_for_emit", + "convert_and_normalize_weights_and_uids", return_value=(fake_uids, fake_weights), ) mock_encode_drand = mocker.patch.object( @@ -272,7 +274,7 @@ def test_commit_reveal_v3_extrinsic_response_false( # Mocks mocker.patch.object( commit_reveal, - "convert_weights_and_uids_for_emit", + "convert_and_normalize_weights_and_uids", return_value=(fake_uids, fake_weights), ) mocker.patch.object( @@ -312,6 +314,7 @@ def test_commit_reveal_v3_extrinsic_response_false( reveal_round=fake_reveal_round, wait_for_inclusion=True, wait_for_finalization=True, + period=None, ) @@ -324,7 +327,7 @@ def test_commit_reveal_v3_extrinsic_exception(mocker, subtensor, fake_wallet): mocker.patch.object( commit_reveal, - "convert_weights_and_uids_for_emit", + "convert_and_normalize_weights_and_uids", side_effect=Exception("Test Error"), ) From 71842ec093b62d4a8f214423942eb324256a2758 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 21:41:54 -0700 Subject: [PATCH 011/100] set default period as None. Better to control this argument via each call --- bittensor/core/async_subtensor.py | 2 +- bittensor/core/subtensor.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index d8e7d56748..d7bee8895c 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -3216,7 +3216,7 @@ async def sign_and_send_extrinsic( wait_for_finalization: bool = False, sign_with: str = "coldkey", use_nonce: bool = False, - period: Optional[int] = 64, # 96 seconds for non-fast-blocks and 2 seconds for fast-blocks + period: Optional[int] = None, nonce_key: str = "hotkey", raise_error: bool = False, ) -> tuple[bool, str]: diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 1090c4162b..42e60c950a 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -2642,7 +2642,7 @@ def sign_and_send_extrinsic( wait_for_finalization: bool = False, sign_with: str = "coldkey", use_nonce: bool = False, - period: Optional[int] = 64, # 96 seconds for non-fast-blocks and 2 seconds for fast-blocks + period: Optional[int] = None, nonce_key: str = "hotkey", raise_error: bool = False, ) -> tuple[bool, str]: From 7225ddc6644dff6bef9b6c950677159771933d9e Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 21:52:46 -0700 Subject: [PATCH 012/100] Add logic to control running localnet mode (non-/fast-blocks) to run e2e tests --- tests/e2e_tests/conftest.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/e2e_tests/conftest.py b/tests/e2e_tests/conftest.py index 0170cbd302..9eccd89f3f 100644 --- a/tests/e2e_tests/conftest.py +++ b/tests/e2e_tests/conftest.py @@ -57,7 +57,11 @@ def read_output(): def local_chain(request): """Determines whether to run the localnet.sh script in a subprocess or a Docker container.""" args = request.param if hasattr(request, "param") else None - params = "" if args is None else f"{args}" + + # passed env variable to control node mod (non-/fast-blocks) + non_fast_mode = os.getenv("NON_FAST_BLOCKS") == "1" + params = "" if args is None else f"{args}" + "True" if non_fast_mode is True else "False" + if shutil.which("docker") and not os.getenv("USE_DOCKER") == "0": yield from docker_runner(params) else: From 6aeadaea3e17069f75c435c1f6cd5374bd925979 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 22:25:51 -0700 Subject: [PATCH 013/100] update `commit_weights` extrinsics calls --- bittensor/core/async_subtensor.py | 18 ++++++++++++------ bittensor/core/subtensor.py | 26 ++++++++++++++++++-------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index d7bee8895c..6c58279425 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -3426,6 +3426,7 @@ async def commit_weights( wait_for_inclusion: bool = False, wait_for_finalization: bool = False, max_retries: int = 5, + period: Optional[int] = 16, ) -> tuple[bool, str]: """ Commits a hash of the neuron's weights to the Bittensor blockchain using the provided wallet. @@ -3438,15 +3439,19 @@ async def commit_weights( uids (np.ndarray): NumPy array of neuron UIDs for which weights are being committed. weights (np.ndarray): NumPy array of weight values corresponding to each UID. version_key (int): Version key for compatibility with the network. Default is ``int representation of - Bittensor version.``. + a Bittensor version.``. wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``False``. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``. max_retries (int): The number of maximum attempts to commit weights. Default is ``5``. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: - tuple[bool, str]: ``True`` if the weight commitment is successful, False otherwise. And `msg`, a string - value describing the success or potential error. + tuple[bool, str]: + `True` if the weight commitment is successful, False otherwise. + `msg` is a string value describing the success or potential error. This function allows neurons to create a tamper-proof record of their weight distribution at a specific point in time, enhancing transparency and accountability within the Bittensor network. @@ -3456,8 +3461,9 @@ async def commit_weights( message = "No attempt made. Perhaps it is too soon to commit weights!" logging.info( - f"Committing weights with params: netuid={netuid}, uids={uids}, weights={weights}, " - f"version_key={version_key}" + f"Committing weights with params: " + f"netuid=[blue]{netuid}[/blue], uids=[blue]{uids}[/blue], weights=[blue]{weights}[/blue], " + f"version_key=[blue]{version_key}[/blue]" ) # Generate the hash of the weights @@ -3479,12 +3485,12 @@ async def commit_weights( commit_hash=commit_hash, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if success: break except Exception as e: logging.error(f"Error committing weights: {e}") - finally: retries += 1 return success, message diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 42e60c950a..e45d032ae5 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -2509,8 +2509,11 @@ def wait_for_block(self, block: Optional[int] = None): bool: True if the target block was reached, False if timeout occurred. Example: - >>> subtensor.wait_for_block() # Waits for next block - >>> subtensor.wait_for_block(block=1234) # Waits for specific block + >>> import bittensor as bt + >>> subtensor = bt.subtensor(network="finney")) + + >>> subtensor.wait_for_block() # Waits for the next block + >>> subtensor.wait_for_block(block=1234) # Waits for a specific block """ def handler(block_data: dict): @@ -2519,6 +2522,7 @@ def handler(block_data: dict): ) if block_data["header"]["number"] >= target_block: return True + return False current_block = self.substrate.get_block() current_block_hash = current_block.get("header", {}).get("hash") @@ -2853,6 +2857,7 @@ def commit_weights( wait_for_inclusion: bool = False, wait_for_finalization: bool = False, max_retries: int = 5, + period: Optional[int] = 16, ) -> tuple[bool, str]: """ Commits a hash of the neuron's weights to the Bittensor blockchain using the provided wallet. @@ -2865,15 +2870,19 @@ def commit_weights( uids (np.ndarray): NumPy array of neuron UIDs for which weights are being committed. weights (np.ndarray): NumPy array of weight values corresponding to each UID. version_key (int): Version key for compatibility with the network. Default is ``int representation of - Bittensor version.``. + a Bittensor version.``. wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``False``. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``. max_retries (int): The number of maximum attempts to commit weights. Default is ``5``. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: - tuple[bool, str]: ``True`` if the weight commitment is successful, False otherwise. And `msg`, a string - value describing the success or potential error. + tuple[bool, str]: + `True` if the weight commitment is successful, False otherwise. + `msg` is a string value describing the success or potential error. This function allows neurons to create a tamper-proof record of their weight distribution at a specific point in time, enhancing transparency and accountability within the Bittensor network. @@ -2883,8 +2892,9 @@ def commit_weights( message = "No attempt made. Perhaps it is too soon to commit weights!" logging.info( - f"Committing weights with params: netuid={netuid}, uids={uids}, weights={weights}, " - f"version_key={version_key}" + f"Committing weights with params: " + f"netuid=[blue]{netuid}[/blue], uids=[blue]{uids}[/blue], weights=[blue]{weights}[/blue], " + f"version_key=[blue]{version_key}[/blue]" ) # Generate the hash of the weights @@ -2906,12 +2916,12 @@ def commit_weights( commit_hash=commit_hash, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if success: break except Exception as e: logging.error(f"Error committing weights: {e}") - finally: retries += 1 return success, message From fa9139bd068322ad7c7a86cc4520400248de5fdc Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 22:26:11 -0700 Subject: [PATCH 014/100] update `commit_weights` extrinsics --- bittensor/core/extrinsics/asyncex/weights.py | 13 +++++++++++-- bittensor/core/extrinsics/commit_weights.py | 10 ++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/weights.py b/bittensor/core/extrinsics/asyncex/weights.py index 62f9ea31f1..0a6bf0b9ce 100644 --- a/bittensor/core/extrinsics/asyncex/weights.py +++ b/bittensor/core/extrinsics/asyncex/weights.py @@ -22,19 +22,22 @@ async def _do_commit_weights( commit_hash: str, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> tuple[bool, Optional[str]]: """ Internal method to send a transaction to the Bittensor blockchain, committing the hash of a neuron's weights. This method constructs and submits the transaction, handling retries and blockchain communication. Args: - subtensor (bittensor.core.async_subtensor.AsyncSubtensor): The subtensor instance used for blockchain - interaction. + subtensor (bittensor.core.async_subtensor.AsyncSubtensor): The subtensor instance used for blockchain interaction. wallet (bittensor_wallet.Wallet): The wallet associated with the neuron committing the weights. netuid (int): The unique identifier of the subnet. commit_hash (str): The hash of the neuron's weights to be committed. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, Optional[str]]: A tuple containing a success flag and an optional error message. @@ -56,6 +59,7 @@ async def _do_commit_weights( wait_for_inclusion, wait_for_finalization, use_nonce=True, + period=period, nonce_key="hotkey", sign_with="hotkey", ) @@ -68,6 +72,7 @@ async def commit_weights_extrinsic( commit_hash: str, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Commits a hash of the neuron's weights to the Bittensor blockchain using the provided wallet. @@ -81,6 +86,9 @@ async def commit_weights_extrinsic( commit_hash (str): The hash of the neuron's weights to be committed. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: ``True`` if the weight commitment is successful, False otherwise. And `msg`, a string @@ -97,6 +105,7 @@ async def commit_weights_extrinsic( commit_hash=commit_hash, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if success: diff --git a/bittensor/core/extrinsics/commit_weights.py b/bittensor/core/extrinsics/commit_weights.py index 06e3295eb5..4b077eac30 100644 --- a/bittensor/core/extrinsics/commit_weights.py +++ b/bittensor/core/extrinsics/commit_weights.py @@ -17,6 +17,7 @@ def _do_commit_weights( commit_hash: str, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> tuple[bool, Optional[str]]: """ Internal method to send a transaction to the Bittensor blockchain, committing the hash of a neuron's weights. @@ -29,6 +30,9 @@ def _do_commit_weights( commit_hash (str): The hash of the neuron's weights to be committed. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, Optional[str]]: A tuple containing a success flag and an optional error message. @@ -50,6 +54,7 @@ def _do_commit_weights( wait_for_inclusion, wait_for_finalization, use_nonce=True, + period=period, sign_with="hotkey", nonce_key="hotkey", ) @@ -62,6 +67,7 @@ def commit_weights_extrinsic( commit_hash: str, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Commits a hash of the neuron's weights to the Bittensor blockchain using the provided wallet. @@ -74,6 +80,9 @@ def commit_weights_extrinsic( commit_hash (str): The hash of the neuron's weights to be committed. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: ``True`` if the weight commitment is successful, False otherwise. And `msg`, a string @@ -90,6 +99,7 @@ def commit_weights_extrinsic( commit_hash=commit_hash, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if success: From cf2a8cc70399cdf6e708d9b6207fba91e7cce90b Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 23:27:17 -0700 Subject: [PATCH 015/100] fix fast_blocks logic in conftest.py --- tests/e2e_tests/conftest.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/e2e_tests/conftest.py b/tests/e2e_tests/conftest.py index 9eccd89f3f..60d939fd86 100644 --- a/tests/e2e_tests/conftest.py +++ b/tests/e2e_tests/conftest.py @@ -59,8 +59,8 @@ def local_chain(request): args = request.param if hasattr(request, "param") else None # passed env variable to control node mod (non-/fast-blocks) - non_fast_mode = os.getenv("NON_FAST_BLOCKS") == "1" - params = "" if args is None else f"{args}" + "True" if non_fast_mode is True else "False" + fast_blocks = "True" if (os.getenv("FAST_BLOCKS") == "1") is True else "False" + params = f"{fast_blocks}" if args is None else f"{fast_blocks} {args} " if shutil.which("docker") and not os.getenv("USE_DOCKER") == "0": yield from docker_runner(params) @@ -69,7 +69,7 @@ def local_chain(request): if sys.platform.startswith("linux"): docker_command = ( "Install docker with command " - "[blue]sudo apt-get update && sudo apt-get install docker.io -y[/blue]" + "[blue]sudo apt-gat update && sudo apt-get install docker.io -y[/blue]" " or use documentation [blue]https://docs.docker.com/engine/install/[/blue]" ) elif sys.platform == "darwin": @@ -95,7 +95,7 @@ def legacy_runner(params): logging.warning("LOCALNET_SH_PATH env variable is not set, e2e test skipped.") pytest.skip("LOCALNET_SH_PATH environment variable is not set.") - # Check if param is None, and handle it accordingly + # Check if param is None and handle it accordingly args = "" if params is None else f"{params}" # Compile commands to send to process From 1751d481e62dffe87fbea7b2965a74f0c0e4e268 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 23:27:49 -0700 Subject: [PATCH 016/100] fix wait_for_block logic in subtensors --- bittensor/core/async_subtensor.py | 7 ++++--- bittensor/core/subtensor.py | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index 6c58279425..cf4d6f62e1 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -3024,7 +3024,7 @@ async def tx_rate_limit( Optional[int]: The transaction rate limit of the network, None if not available. The transaction rate limit is an essential parameter for ensuring the stability and scalability of the Bittensor - network. It helps in managing network load and preventing congestion, thereby maintaining efficient and + network. It helps in managing a network load and preventing congestion, thereby maintaining efficient and timely transaction processing. """ block_hash = await self.determine_block_hash(block, block_hash, reuse_block) @@ -3039,14 +3039,14 @@ async def wait_for_block(self, block: Optional[int] = None): waits for the next block. Args: - block (Optional[int]): The block number to wait for. If None, waits for next block. + block (Optional[int]): The block number to wait for. If None, waits for the next block. Returns: bool: True if the target block was reached, False if timeout occurred. Example: await subtensor.wait_for_block() # Waits for next block - await subtensor.wait_for_block(block=1234) # Waits for specific block + await subtensor.wait_for_block(block=1234) # Waits for a specific block """ async def handler(block_data: dict): @@ -3055,6 +3055,7 @@ async def handler(block_data: dict): ) if block_data["header"]["number"] >= target_block: return True + return None current_block = await self.substrate.get_block() current_block_hash = current_block.get("header", {}).get("hash") diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index e45d032ae5..618c89b3a2 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -2503,7 +2503,7 @@ def wait_for_block(self, block: Optional[int] = None): waits for the next block. Args: - block (Optional[int]): The block number to wait for. If None, waits for next block. + block (Optional[int]): The block number to wait for. If None, waits for the next block. Returns: bool: True if the target block was reached, False if timeout occurred. @@ -2522,7 +2522,7 @@ def handler(block_data: dict): ) if block_data["header"]["number"] >= target_block: return True - return False + return None current_block = self.substrate.get_block() current_block_hash = current_block.get("header", {}).get("hash") From e8ab07bbdcc2198d6f7c06cc851206ef4b5ad83d Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 23:40:43 -0700 Subject: [PATCH 017/100] update docstrings --- bittensor/core/extrinsics/asyncex/weights.py | 34 ++++++++++++-------- bittensor/core/extrinsics/commit_weights.py | 24 ++++++++------ 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/weights.py b/bittensor/core/extrinsics/asyncex/weights.py index 0a6bf0b9ce..ceb519311a 100644 --- a/bittensor/core/extrinsics/asyncex/weights.py +++ b/bittensor/core/extrinsics/asyncex/weights.py @@ -23,7 +23,7 @@ async def _do_commit_weights( wait_for_inclusion: bool = False, wait_for_finalization: bool = False, period: Optional[int] = None, -) -> tuple[bool, Optional[str]]: +) -> tuple[bool, str]: """ Internal method to send a transaction to the Bittensor blockchain, committing the hash of a neuron's weights. This method constructs and submits the transaction, handling retries and blockchain communication. @@ -40,7 +40,9 @@ async def _do_commit_weights( You can think of it as an expiration date for the transaction. Returns: - tuple[bool, Optional[str]]: A tuple containing a success flag and an optional error message. + tuple[bool, str]: + `True` if the weight commitment is successful, `False` otherwise. + `msg` is a string value describing the success or potential error. This method ensures that the weight commitment is securely recorded on the Bittensor blockchain, providing a verifiable record of the neuron's weight distribution at a specific point in time. @@ -91,8 +93,9 @@ async def commit_weights_extrinsic( You can think of it as an expiration date for the transaction. Returns: - tuple[bool, str]: ``True`` if the weight commitment is successful, False otherwise. And `msg`, a string - value describing the success or potential error. + tuple[bool, str]: + `True` if the weight commitment is successful, `False` otherwise. + `msg` is a string value describing the success or potential error. This function provides a user-friendly interface for committing weights to the Bittensor blockchain, ensuring proper error handling and user interaction when required. @@ -145,7 +148,9 @@ async def _do_reveal_weights( wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Returns: - tuple[bool, str]: A tuple containing a success flag and an optional error message. + tuple[bool, str]: + `True` if the weight commitment is successful, `False` otherwise. + `msg` is a string value describing the success or potential error. This method ensures that the weight revelation is securely recorded on the Bittensor blockchain, providing transparency and accountability for the neuron's weight distribution. @@ -200,8 +205,9 @@ async def reveal_weights_extrinsic( wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Returns: - tuple[bool, str]: ``True`` if the weight revelation is successful, False otherwise. And `msg`, a string value - describing the success or potential error. + tuple[bool, str]: + `True` if the weight commitment is successful, `False` otherwise. + `msg` is a string value describing the success or potential error. This function provides a user-friendly interface for revealing weights on the Bittensor blockchain, ensuring proper error handling and user interaction when required. @@ -240,9 +246,8 @@ async def _do_set_weights( period: int = 5, ) -> tuple[bool, str]: # (success, error_message) """ - Internal method to send a transaction to the Bittensor blockchain, setting weights - for specified neurons. This method constructs and submits the transaction, handling - retries and blockchain communication. + Internal method to send a transaction to the Bittensor blockchain, setting weights for specified neurons. This + method constructs and submits the transaction, handling retries and blockchain communication. Args: subtensor (subtensor.core.async_subtensor.AsyncSubtensor): Async Subtensor instance. @@ -256,7 +261,9 @@ async def _do_set_weights( period (int, optional): The period in seconds to wait for extrinsic inclusion or finalization. Defaults to 5. Returns: - Tuple[bool, str]: A tuple containing a success flag and an optional error message. + tuple[bool, str]: + `True` if the weight commitment is successful, `False` otherwise. + `msg` is a string value describing the success or potential error. This method is vital for the dynamic weighting mechanism in Bittensor, where neurons adjust their trust in other neurons based on observed performance and contributions. @@ -312,8 +319,9 @@ async def set_weights_extrinsic( period (int, optional): The period in seconds to wait for extrinsic inclusion or finalization. Defaults to 5. Returns: - success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. If we did not wait for - finalization / inclusion, the response is ``True``. + tuple[bool, str]: + `True` if the weight commitment is successful, `False` otherwise. + `msg` is a string value describing the success or potential error. """ weight_uids, weight_vals = convert_and_normalize_weights_and_uids(uids, weights) diff --git a/bittensor/core/extrinsics/commit_weights.py b/bittensor/core/extrinsics/commit_weights.py index 4b077eac30..3f8e2c2a6c 100644 --- a/bittensor/core/extrinsics/commit_weights.py +++ b/bittensor/core/extrinsics/commit_weights.py @@ -18,7 +18,7 @@ def _do_commit_weights( wait_for_inclusion: bool = False, wait_for_finalization: bool = False, period: Optional[int] = None, -) -> tuple[bool, Optional[str]]: +) -> tuple[bool, str]: """ Internal method to send a transaction to the Bittensor blockchain, committing the hash of a neuron's weights. This method constructs and submits the transaction, handling retries and blockchain communication. @@ -35,7 +35,9 @@ def _do_commit_weights( You can think of it as an expiration date for the transaction. Returns: - tuple[bool, Optional[str]]: A tuple containing a success flag and an optional error message. + tuple[bool, str]: + `True` if the weight commitment is successful, `False` otherwise. + `msg` is a string value describing the success or potential error. This method ensures that the weight commitment is securely recorded on the Bittensor blockchain, providing a verifiable record of the neuron's weight distribution at a specific point in time. @@ -85,8 +87,9 @@ def commit_weights_extrinsic( You can think of it as an expiration date for the transaction. Returns: - tuple[bool, str]: ``True`` if the weight commitment is successful, False otherwise. And `msg`, a string - value describing the success or potential error. + tuple[bool, str]: + `True` if the weight commitment is successful, `False` otherwise. + `msg` is a string value describing the success or potential error. This function provides a user-friendly interface for committing weights to the Bittensor blockchain, ensuring proper error handling and user interaction when required. @@ -121,7 +124,7 @@ def _do_reveal_weights( version_key: int, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, -) -> tuple[bool, Optional[dict]]: +) -> tuple[bool, str]: """ Internal method to send a transaction to the Bittensor blockchain, revealing the weights for a specific subnet. This method constructs and submits the transaction, handling retries and blockchain communication. @@ -138,7 +141,9 @@ def _do_reveal_weights( wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Returns: - tuple[bool, Optional[str]]: A tuple containing a success flag and an optional error message. + tuple[bool, str]: + `True` if the weight commitment is successful, `False` otherwise. + `msg` is a string value describing the success or potential error. This method ensures that the weight revelation is securely recorded on the Bittensor blockchain, providing transparency and accountability for the neuron's weight distribution. @@ -193,8 +198,9 @@ def reveal_weights_extrinsic( wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Returns: - tuple[bool, str]: ``True`` if the weight revelation is successful, False otherwise. And `msg`, a string value - describing the success or potential error. + tuple[bool, str]: + `True` if the weight commitment is successful, `False` otherwise. + `msg` is a string value describing the success or potential error. This function provides a user-friendly interface for revealing weights on the Bittensor blockchain, ensuring proper error handling and user interaction when required. @@ -217,6 +223,6 @@ def reveal_weights_extrinsic( logging.info(success_message) return True, success_message - error_message = format_error_message(error_message) + error_message = error_message logging.error(f"Failed to reveal weights: {error_message}") return False, error_message From 0213d0314118655ded79cbf230d27beff2668dd3 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 23:53:10 -0700 Subject: [PATCH 018/100] keep fast-blocks mode by default --- tests/e2e_tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e_tests/conftest.py b/tests/e2e_tests/conftest.py index 60d939fd86..a247b85a5a 100644 --- a/tests/e2e_tests/conftest.py +++ b/tests/e2e_tests/conftest.py @@ -59,7 +59,7 @@ def local_chain(request): args = request.param if hasattr(request, "param") else None # passed env variable to control node mod (non-/fast-blocks) - fast_blocks = "True" if (os.getenv("FAST_BLOCKS") == "1") is True else "False" + fast_blocks = "False" if (os.getenv("FAST_BLOCKS") == "0") is True else "True" params = f"{fast_blocks}" if args is None else f"{fast_blocks} {args} " if shutil.which("docker") and not os.getenv("USE_DOCKER") == "0": From 73e9fb25f0e75845f689aa6296b342a2516fc2bf Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 30 Apr 2025 23:59:46 -0700 Subject: [PATCH 019/100] update `reveal_weights_extrinsic` for both subtensors --- bittensor/core/extrinsics/asyncex/weights.py | 10 ++++++++++ bittensor/core/extrinsics/commit_weights.py | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/bittensor/core/extrinsics/asyncex/weights.py b/bittensor/core/extrinsics/asyncex/weights.py index ceb519311a..508703b31a 100644 --- a/bittensor/core/extrinsics/asyncex/weights.py +++ b/bittensor/core/extrinsics/asyncex/weights.py @@ -130,6 +130,7 @@ async def _do_reveal_weights( version_key: int, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Internal method to send a transaction to the Bittensor blockchain, revealing the weights for a specific subnet. @@ -146,6 +147,9 @@ async def _do_reveal_weights( version_key (int): Version key for compatibility with the network. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: @@ -173,6 +177,7 @@ async def _do_reveal_weights( wait_for_inclusion, wait_for_finalization, sign_with="hotkey", + period=period, nonce_key="hotkey", use_nonce=True, ) @@ -188,6 +193,7 @@ async def reveal_weights_extrinsic( version_key: int, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Reveals the weights for a specific subnet on the Bittensor blockchain using the provided wallet. @@ -203,6 +209,9 @@ async def reveal_weights_extrinsic( version_key (int): Version key for compatibility with the network. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: @@ -223,6 +232,7 @@ async def reveal_weights_extrinsic( version_key=version_key, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if success: diff --git a/bittensor/core/extrinsics/commit_weights.py b/bittensor/core/extrinsics/commit_weights.py index 3f8e2c2a6c..14223c2e1c 100644 --- a/bittensor/core/extrinsics/commit_weights.py +++ b/bittensor/core/extrinsics/commit_weights.py @@ -124,6 +124,7 @@ def _do_reveal_weights( version_key: int, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Internal method to send a transaction to the Bittensor blockchain, revealing the weights for a specific subnet. @@ -139,6 +140,9 @@ def _do_reveal_weights( version_key (int): Version key for compatibility with the network. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: @@ -166,6 +170,7 @@ def _do_reveal_weights( wait_for_inclusion, wait_for_finalization, use_nonce=True, + period=period, sign_with="hotkey", nonce_key="hotkey", ) @@ -181,6 +186,7 @@ def reveal_weights_extrinsic( version_key: int, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Reveals the weights for a specific subnet on the Bittensor blockchain using the provided wallet. @@ -196,6 +202,9 @@ def reveal_weights_extrinsic( version_key (int): Version key for compatibility with the network. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: @@ -216,6 +225,7 @@ def reveal_weights_extrinsic( version_key=version_key, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if success: From c8e7e99b190d4f398580f5715bb8ab8ad0fca083 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 00:01:52 -0700 Subject: [PATCH 020/100] update `Subtensor.reveal_weights` extrinsic call --- bittensor/core/subtensor.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 618c89b3a2..4b9ad102e4 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -3062,6 +3062,7 @@ def reveal_weights( wait_for_inclusion: bool = False, wait_for_finalization: bool = False, max_retries: int = 5, + period: Optional[int] = 16, ) -> tuple[bool, str]: """ Reveals the weights for a specific subnet on the Bittensor blockchain using the provided wallet. @@ -3074,11 +3075,14 @@ def reveal_weights( weights (np.ndarray): NumPy array of weight values corresponding to each UID. salt (np.ndarray): NumPy array of salt values corresponding to the hash function. version_key (int): Version key for compatibility with the network. Default is ``int representation of - Bittensor version``. + a Bittensor version``. wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``False``. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``. max_retries (int): The number of maximum attempts to reveal weights. Default is ``5``. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: ``True`` if the weight revelation is successful, False otherwise. And `msg`, a string @@ -3103,12 +3107,12 @@ def reveal_weights( version_key=version_key, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if success: break except Exception as e: logging.error(f"Error revealing weights: {e}") - finally: retries += 1 return success, message From 422eddf8ef93316af9014f7f490cfa6d83312730 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 00:08:56 -0700 Subject: [PATCH 021/100] fix related unit tests --- tests/unit_tests/extrinsics/asyncex/test_weights.py | 2 ++ tests/unit_tests/test_async_subtensor.py | 1 + tests/unit_tests/test_subtensor.py | 2 ++ 3 files changed, 5 insertions(+) diff --git a/tests/unit_tests/extrinsics/asyncex/test_weights.py b/tests/unit_tests/extrinsics/asyncex/test_weights.py index c01490055d..e02f006e9b 100644 --- a/tests/unit_tests/extrinsics/asyncex/test_weights.py +++ b/tests/unit_tests/extrinsics/asyncex/test_weights.py @@ -437,6 +437,7 @@ async def test_commit_weights_extrinsic_success(subtensor, fake_wallet, mocker): commit_hash=fake_commit_hash, wait_for_inclusion=True, wait_for_finalization=True, + period=None, ) assert result is True assert message == "✅ [green]Successfully committed weights.[green]" @@ -471,6 +472,7 @@ async def test_commit_weights_extrinsic_failure(subtensor, fake_wallet, mocker): commit_hash=fake_commit_hash, wait_for_inclusion=True, wait_for_finalization=True, + period=None, ) assert result is False assert message == "Commit failed." diff --git a/tests/unit_tests/test_async_subtensor.py b/tests/unit_tests/test_async_subtensor.py index bb6bb5b49f..c0fd7dbcc5 100644 --- a/tests/unit_tests/test_async_subtensor.py +++ b/tests/unit_tests/test_async_subtensor.py @@ -2853,6 +2853,7 @@ async def test_commit_weights_success(subtensor, fake_wallet, mocker): commit_hash="fake_commit_hash", wait_for_inclusion=False, wait_for_finalization=False, + period=16, ) assert result is True assert message == "Success" diff --git a/tests/unit_tests/test_subtensor.py b/tests/unit_tests/test_subtensor.py index f6bb50f619..c1ef86bbd2 100644 --- a/tests/unit_tests/test_subtensor.py +++ b/tests/unit_tests/test_subtensor.py @@ -1963,6 +1963,7 @@ def test_commit_weights(subtensor, fake_wallet, mocker): commit_hash=mocked_generate_weight_hash.return_value, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=16 ) assert result == expected_result @@ -2002,6 +2003,7 @@ def test_reveal_weights(subtensor, fake_wallet, mocker): salt=salt, wait_for_inclusion=False, wait_for_finalization=False, + period=16 ) From 662767ca5e4663ff21f3942f30e678025a0ea80f Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 00:11:14 -0700 Subject: [PATCH 022/100] fmt --- bittensor/core/extrinsics/asyncex/weights.py | 5 ----- bittensor/core/extrinsics/commit_weights.py | 1 - 2 files changed, 6 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/weights.py b/bittensor/core/extrinsics/asyncex/weights.py index 508703b31a..33c0e98b9d 100644 --- a/bittensor/core/extrinsics/asyncex/weights.py +++ b/bittensor/core/extrinsics/asyncex/weights.py @@ -100,7 +100,6 @@ async def commit_weights_extrinsic( This function provides a user-friendly interface for committing weights to the Bittensor blockchain, ensuring proper error handling and user interaction when required. """ - success, error_message = await _do_commit_weights( subtensor=subtensor, wallet=wallet, @@ -159,7 +158,6 @@ async def _do_reveal_weights( This method ensures that the weight revelation is securely recorded on the Bittensor blockchain, providing transparency and accountability for the neuron's weight distribution. """ - call = await subtensor.substrate.compose_call( call_module="SubtensorModule", call_function="reveal_weights", @@ -221,7 +219,6 @@ async def reveal_weights_extrinsic( This function provides a user-friendly interface for revealing weights on the Bittensor blockchain, ensuring proper error handling and user interaction when required. """ - success, error_message = await _do_reveal_weights( subtensor=subtensor, wallet=wallet, @@ -278,7 +275,6 @@ async def _do_set_weights( This method is vital for the dynamic weighting mechanism in Bittensor, where neurons adjust their trust in other neurons based on observed performance and contributions. """ - call = await subtensor.substrate.compose_call( call_module="SubtensorModule", call_function="set_weights", @@ -333,7 +329,6 @@ async def set_weights_extrinsic( `True` if the weight commitment is successful, `False` otherwise. `msg` is a string value describing the success or potential error. """ - weight_uids, weight_vals = convert_and_normalize_weights_and_uids(uids, weights) logging.info( diff --git a/bittensor/core/extrinsics/commit_weights.py b/bittensor/core/extrinsics/commit_weights.py index 14223c2e1c..c07878ac16 100644 --- a/bittensor/core/extrinsics/commit_weights.py +++ b/bittensor/core/extrinsics/commit_weights.py @@ -2,7 +2,6 @@ from typing import TYPE_CHECKING, Optional -from bittensor.utils import format_error_message from bittensor.utils.btlogging import logging if TYPE_CHECKING: From 84e71089327b42eb8bd1329b5d50f3255da85cdf Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 00:16:41 -0700 Subject: [PATCH 023/100] bittensor.core.extrinsics.move_stake.transfer_stake_extrinsic --- bittensor/core/extrinsics/move_stake.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bittensor/core/extrinsics/move_stake.py b/bittensor/core/extrinsics/move_stake.py index fdf9d406a8..3a1366b49b 100644 --- a/bittensor/core/extrinsics/move_stake.py +++ b/bittensor/core/extrinsics/move_stake.py @@ -17,6 +17,7 @@ def _get_stake_in_origin_and_dest( origin_netuid: int, destination_netuid: int, ) -> tuple[Balance, Balance]: + """Gets the current stake balances for both origin and destination addresses in their respective subnets.""" block = subtensor.get_current_block() stake_in_origin = subtensor.get_stake( coldkey_ss58=origin_coldkey_ss58, @@ -43,6 +44,7 @@ def transfer_stake_extrinsic( amount: Optional[Balance] = None, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: """ Transfers stake from one subnet to another while changing the coldkey owner. @@ -57,6 +59,9 @@ def transfer_stake_extrinsic( amount (Union[Balance, float, int]): Amount to transfer. wait_for_inclusion (bool): If true, waits for inclusion before returning. wait_for_finalization (bool): If true, waits for finalization before returning. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): True if the transfer was successful. @@ -113,6 +118,7 @@ def transfer_stake_extrinsic( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if success: From 81a5669169c73e50ec0a76e03c3bd9e35cbb8c12 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 00:16:51 -0700 Subject: [PATCH 024/100] bittensor.core.subtensor.Subtensor.transfer_stake --- bittensor/core/subtensor.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 4b9ad102e4..4c44d75ebc 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -3499,6 +3499,7 @@ def transfer_stake( amount: Balance, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: """ Transfers stake from one subnet to another while changing the coldkey owner. @@ -3512,6 +3513,9 @@ def transfer_stake( amount (Union[Balance, float, int]): Amount to transfer. wait_for_inclusion (bool): If true, waits for inclusion before returning. wait_for_finalization (bool): If true, waits for finalization before returning. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): True if the transfer was successful. @@ -3527,6 +3531,7 @@ def transfer_stake( amount=amount, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) def unstake( From 6dc3e0e2bbdfcb18d2867480f09b72652500993f Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 00:24:55 -0700 Subject: [PATCH 025/100] bittensor.core.extrinsics.move_stake.swap_stake_extrinsic --- bittensor/core/extrinsics/move_stake.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bittensor/core/extrinsics/move_stake.py b/bittensor/core/extrinsics/move_stake.py index 3a1366b49b..9bde9e8d48 100644 --- a/bittensor/core/extrinsics/move_stake.py +++ b/bittensor/core/extrinsics/move_stake.py @@ -166,6 +166,7 @@ def swap_stake_extrinsic( safe_staking: bool = False, allow_partial_stake: bool = False, rate_tolerance: float = 0.005, + period: Optional[int] = None, ) -> bool: """ Moves stake between subnets while keeping the same coldkey-hotkey pair ownership. @@ -181,7 +182,10 @@ def swap_stake_extrinsic( wait_for_finalization (bool): If true, waits for finalization before returning. safe_staking (bool): If true, enables price safety checks to protect against price impact. allow_partial_stake (bool): If true, allows partial stake swaps when the full amount would exceed the price tolerance. - rate_tolerance (float): Maximum allowed increase in price ratio (0.005 = 0.5%). + rate_tolerance (float): Maximum allowed increase in a price ratio (0.005 = 0.5%). + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): True if the swap was successful. @@ -261,6 +265,7 @@ def swap_stake_extrinsic( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if success: From 5ab22dffba2f4de98a23cf4a3995af996f00d9ca Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 00:25:04 -0700 Subject: [PATCH 026/100] bittensor.core.subtensor.Subtensor.swap_stake --- bittensor/core/subtensor.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 4c44d75ebc..49dfca3141 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -3402,6 +3402,7 @@ def swap_stake( safe_staking: bool = False, allow_partial_stake: bool = False, rate_tolerance: float = 0.005, + period: Optional[int] = None, ) -> bool: """ Moves stake between subnets while keeping the same coldkey-hotkey pair ownership. @@ -3424,6 +3425,9 @@ def swap_stake( rate_tolerance (float): The maximum allowed increase in the price ratio between subnets (origin_price/destination_price). For example, 0.005 = 0.5% maximum increase. Only used when safe_staking is True. Default is 0.005. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: @@ -3449,6 +3453,7 @@ def swap_stake( safe_staking=safe_staking, allow_partial_stake=allow_partial_stake, rate_tolerance=rate_tolerance, + period=period, ) def transfer( From 9050c204f164c96280acbcd537e0fbfebbfe195a Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 00:25:12 -0700 Subject: [PATCH 027/100] fix related tests --- tests/unit_tests/test_subtensor.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit_tests/test_subtensor.py b/tests/unit_tests/test_subtensor.py index c1ef86bbd2..bfc9b45d94 100644 --- a/tests/unit_tests/test_subtensor.py +++ b/tests/unit_tests/test_subtensor.py @@ -3021,6 +3021,7 @@ def test_swap_stake_success(mocker, subtensor, fake_wallet): safe_staking=False, allow_partial_stake=False, rate_tolerance=0.005, + period=None, ) assert result == mock_swap_stake_extrinsic.return_value @@ -3065,6 +3066,7 @@ def test_swap_stake_with_safe_staking(mocker, subtensor, fake_wallet): safe_staking=True, allow_partial_stake=True, rate_tolerance=fake_rate_tolerance, + period=None, ) assert result == mock_swap_stake_extrinsic.return_value From 0f56efc27bbcd90aadf36222977a30d1e5569428 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 00:29:20 -0700 Subject: [PATCH 028/100] bittensor.core.extrinsics.move_stake.move_stake_extrinsic --- bittensor/core/extrinsics/move_stake.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bittensor/core/extrinsics/move_stake.py b/bittensor/core/extrinsics/move_stake.py index 9bde9e8d48..a815c14dc0 100644 --- a/bittensor/core/extrinsics/move_stake.py +++ b/bittensor/core/extrinsics/move_stake.py @@ -316,6 +316,7 @@ def move_stake_extrinsic( amount: Optional[Balance] = None, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: """ Moves stake to a different hotkey and/or subnet while keeping the same coldkey owner. @@ -330,6 +331,9 @@ def move_stake_extrinsic( amount (Union[Balance, float]): Amount to move. wait_for_inclusion (bool): If true, waits for inclusion before returning. wait_for_finalization (bool): If true, waits for finalization before returning. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): True if the move was successful. @@ -375,6 +379,7 @@ def move_stake_extrinsic( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if success: From 474b2ee7b928e62a4c71d5138f1d5057f89a56f1 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 00:29:30 -0700 Subject: [PATCH 029/100] bittensor.core.subtensor.Subtensor.move_stake --- bittensor/core/subtensor.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 49dfca3141..b6cf393e8c 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -2936,6 +2936,7 @@ def move_stake( amount: Balance, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: """ Moves stake to a different hotkey and/or subnet. @@ -2949,6 +2950,9 @@ def move_stake( amount (Balance): Amount of stake to move. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): True if the stake movement was successful. @@ -2964,6 +2968,7 @@ def move_stake( amount=amount, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) def register( From d549aa2678a4e0716c43a3c7fcd7ac2000357015 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 00:32:17 -0700 Subject: [PATCH 030/100] bittensor/core/extrinsics/asyncex/move_stake.py --- .../core/extrinsics/asyncex/move_stake.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/bittensor/core/extrinsics/asyncex/move_stake.py b/bittensor/core/extrinsics/asyncex/move_stake.py index 6ab0b13028..ee21e00aeb 100644 --- a/bittensor/core/extrinsics/asyncex/move_stake.py +++ b/bittensor/core/extrinsics/asyncex/move_stake.py @@ -1,5 +1,5 @@ import asyncio -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from bittensor.utils.balance import Balance from bittensor.utils.btlogging import logging @@ -18,6 +18,7 @@ async def _get_stake_in_origin_and_dest( origin_netuid: int, destination_netuid: int, ) -> tuple[Balance, Balance]: + """Gets the current stake balances for both origin and destination addresses in their respective subnets.""" block_hash = await subtensor.substrate.get_chain_head() stake_in_origin, stake_in_destination = await asyncio.gather( subtensor.get_stake( @@ -46,6 +47,7 @@ async def transfer_stake_extrinsic( amount: Balance, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: """ Transfers stake from one coldkey to another in the Bittensor network. @@ -60,6 +62,9 @@ async def transfer_stake_extrinsic( amount (Balance): The amount of stake to transfer as a `Balance` object. wait_for_inclusion (bool): If True, waits for transaction inclusion in a block. Defaults to `True`. wait_for_finalization (bool): If True, waits for transaction finalization. Defaults to `False`. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: True if the transfer was successful, False otherwise. @@ -116,6 +121,7 @@ async def transfer_stake_extrinsic( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if success: @@ -163,6 +169,7 @@ async def swap_stake_extrinsic( safe_staking: bool = False, allow_partial_stake: bool = False, rate_tolerance: float = 0.005, + period: Optional[int] = None, ) -> bool: """ Swaps stake from one subnet to another for a given hotkey in the Bittensor network. @@ -179,6 +186,9 @@ async def swap_stake_extrinsic( safe_staking (bool): If true, enables price safety checks to protect against price impact. allow_partial_stake (bool): If true, allows partial stake swaps when the full amount would exceed the price tolerance. rate_tolerance (float): Maximum allowed increase in price ratio (0.005 = 0.5%). + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: True if the swap was successful, False otherwise. @@ -259,6 +269,7 @@ async def swap_stake_extrinsic( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if success: @@ -309,6 +320,7 @@ async def move_stake_extrinsic( amount: Balance, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: """ Moves stake from one hotkey to another within subnets in the Bittensor network. @@ -323,6 +335,9 @@ async def move_stake_extrinsic( amount (Balance): The amount of stake to move as a `Balance` object. wait_for_inclusion (bool): If True, waits for transaction inclusion in a block. Defaults to True. wait_for_finalization (bool): If True, waits for transaction finalization. Defaults to False. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: True if the move was successful, False otherwise. @@ -369,6 +384,7 @@ async def move_stake_extrinsic( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if success: From adeda3f2ce4cc57700e1f8c7685097cdca170a3a Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 00:35:05 -0700 Subject: [PATCH 031/100] related changes in bittensor/core/async_subtensor.py --- bittensor/core/async_subtensor.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index cf4d6f62e1..6f708cc899 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -3506,6 +3506,7 @@ async def move_stake( amount: Balance, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: """ Moves stake to a different hotkey and/or subnet. @@ -3519,6 +3520,9 @@ async def move_stake( amount (Balance): Amount of stake to move. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): True if the stake movement was successful. @@ -3534,6 +3538,7 @@ async def move_stake( amount=amount, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) async def register( @@ -4128,6 +4133,7 @@ async def swap_stake( safe_staking: bool = False, allow_partial_stake: bool = False, rate_tolerance: float = 0.005, + period: Optional[int] = None, ) -> bool: """ Moves stake between subnets while keeping the same coldkey-hotkey pair ownership. @@ -4150,6 +4156,9 @@ async def swap_stake( rate_tolerance (float): The maximum allowed increase in the price ratio between subnets (origin_price/destination_price). For example, 0.005 = 0.5% maximum increase. Only used when safe_staking is True. Default is 0.005. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): True if the extrinsic was successful. @@ -4174,6 +4183,7 @@ async def swap_stake( safe_staking=safe_staking, allow_partial_stake=allow_partial_stake, rate_tolerance=rate_tolerance, + period=period ) async def transfer_stake( @@ -4186,6 +4196,7 @@ async def transfer_stake( amount: Balance, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: """ Transfers stake from one subnet to another while changing the coldkey owner. @@ -4199,6 +4210,9 @@ async def transfer_stake( amount (Balance): Amount to transfer. wait_for_inclusion (bool): If true, waits for inclusion before returning. wait_for_finalization (bool): If true, waits for finalization before returning. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): True if the transfer was successful. @@ -4214,6 +4228,7 @@ async def transfer_stake( amount=amount, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) async def transfer( From c0eebe01fc1aa36322baeff474cc525f613f5b8e Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 11:58:32 -0700 Subject: [PATCH 032/100] update `bittensor/core/extrinsics/registration.py` --- bittensor/core/extrinsics/registration.py | 41 ++++++++++++++++++++--- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/bittensor/core/extrinsics/registration.py b/bittensor/core/extrinsics/registration.py index c1feea3a30..ed53319974 100644 --- a/bittensor/core/extrinsics/registration.py +++ b/bittensor/core/extrinsics/registration.py @@ -25,6 +25,7 @@ def _do_burned_register( wallet: "Wallet", wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Performs a burned register extrinsic call to the Subtensor chain. @@ -37,6 +38,9 @@ def _do_burned_register( wallet (bittensor_wallet.Wallet): The wallet to be registered. wait_for_inclusion (bool): Whether to wait for the transaction to be included in a block. Default is False. wait_for_finalization (bool): Whether to wait for the transaction to be finalized. Default is True. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: Tuple[bool, Optional[str]]: A tuple containing a boolean indicating success or failure, and an optional error @@ -57,6 +61,7 @@ def _do_burned_register( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) @@ -66,6 +71,7 @@ def burned_register_extrinsic( netuid: int, wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> bool: """Registers the wallet to chain by recycling TAO. @@ -77,6 +83,9 @@ def burned_register_extrinsic( returns ``False`` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. If we did not wait for @@ -120,6 +129,7 @@ def burned_register_extrinsic( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if not success: @@ -154,6 +164,7 @@ def _do_pow_register( pow_result: "POWSolution", wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> tuple[bool, Optional[str]]: """Sends a (POW) register extrinsic to the chain. @@ -164,6 +175,9 @@ def _do_pow_register( pow_result (POWSolution): The PoW result to register. wait_for_inclusion (bool): If ``True``, waits for the extrinsic to be included in a block. Default to `False`. wait_for_finalization (bool): If ``True``, waits for the extrinsic to be finalized. Default to `True`. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): ``True`` if the extrinsic was included in a block. @@ -188,6 +202,7 @@ def _do_pow_register( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) @@ -196,6 +211,7 @@ def register_subnet_extrinsic( wallet: "Wallet", wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> bool: """ Registers a new subnetwork on the Bittensor blockchain. @@ -205,6 +221,9 @@ def register_subnet_extrinsic( wallet (Wallet): The wallet to be used for subnet registration. wait_for_inclusion (bool): If set, waits for the extrinsic to enter a block before returning true. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning true. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: True if the subnet registration was successful, False otherwise. @@ -232,16 +251,20 @@ def register_subnet_extrinsic( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) + if not wait_for_finalization and not wait_for_inclusion: + return True + if success: logging.success( ":white_heavy_check_mark: [green]Successfully registered subnet[/green]" ) return True - else: - logging.error(f"Failed to register subnet: {message}") - return False + + logging.error(f"Failed to register subnet: {message}") + return False def register_extrinsic( @@ -258,6 +281,7 @@ def register_extrinsic( num_processes: Optional[int] = None, update_interval: Optional[int] = None, log_verbose: bool = False, + period: Optional[int] = None, ) -> bool: """Registers the wallet to the chain. @@ -277,6 +301,9 @@ def register_extrinsic( num_processes: The number of processes to use to register. update_interval: The number of nonces to solve between updates. log_verbose: If `True`, the registration process will log more information. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: `True` if extrinsic was finalized or included in the block. If we did not wait for finalization/inclusion, the @@ -366,7 +393,7 @@ def register_extrinsic( # pow successful, proceed to submit pow to chain for registration else: logging.info(":satellite: [magenta]Submitting POW...[/magenta]") - # check if pow result is still valid + # check if a pow result is still valid while not pow_result.is_stale(subtensor=subtensor): result: tuple[bool, Optional[str]] = _do_pow_register( subtensor=subtensor, @@ -375,6 +402,7 @@ def register_extrinsic( pow_result=pow_result, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) success, err_msg = result @@ -439,6 +467,7 @@ def set_subnet_identity_extrinsic( additional: str, wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Set the identity information for a given subnet. @@ -456,6 +485,9 @@ def set_subnet_identity_extrinsic( additional (str): Any additional metadata or information related to the subnet. wait_for_inclusion (bool): Whether to wait for the extrinsic inclusion in a block (default: False). wait_for_finalization (bool): Whether to wait for the extrinsic finalization in a block (default: True). + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: A tuple where the first element indicates success or failure (True/False), and the second @@ -487,6 +519,7 @@ def set_subnet_identity_extrinsic( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if not wait_for_finalization and not wait_for_inclusion: From 54e026120245dcf24c96aad9db2c71aa79832fa7 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 11:58:53 -0700 Subject: [PATCH 033/100] update `bittensor/core/extrinsics/asyncex/registration.py` --- .../core/extrinsics/asyncex/registration.py | 57 +++++++++++++------ 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/registration.py b/bittensor/core/extrinsics/asyncex/registration.py index cfdd78e6f5..0d5cff1692 100644 --- a/bittensor/core/extrinsics/asyncex/registration.py +++ b/bittensor/core/extrinsics/asyncex/registration.py @@ -26,6 +26,7 @@ async def _do_burned_register( wallet: "Wallet", wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Performs a burned register extrinsic call to the Subtensor chain. @@ -38,6 +39,9 @@ async def _do_burned_register( wallet (bittensor_wallet.Wallet): The wallet to be registered. wait_for_inclusion (bool): Whether to wait for the transaction to be included in a block. Default is False. wait_for_finalization (bool): Whether to wait for the transaction to be finalized. Default is True. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: Tuple[bool, Optional[str]]: A tuple containing a boolean indicating success or failure, and an optional error @@ -58,6 +62,7 @@ async def _do_burned_register( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) @@ -67,6 +72,7 @@ async def burned_register_extrinsic( netuid: int, wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> bool: """Registers the wallet to chain by recycling TAO. @@ -78,6 +84,9 @@ async def burned_register_extrinsic( returns ``False`` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. If we did not wait for @@ -98,7 +107,7 @@ async def burned_register_extrinsic( f":satellite: [magenta]Checking Account on subnet[/magenta] [blue]{netuid}[/blue][magenta] ...[/magenta]" ) - # We could do this as_completed because we don't actually need old_balance and recycle + # We could do this as_completed because we don't need old_balance and recycle # if neuron is null, but the complexity isn't worth it considering the small performance # gains we'd hypothetically receive in this situation neuron, old_balance, recycle_amount = await asyncio.gather( @@ -126,6 +135,7 @@ async def burned_register_extrinsic( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if not success: @@ -162,6 +172,7 @@ async def _do_pow_register( pow_result: "POWSolution", wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> tuple[bool, Optional[str]]: """Sends a (POW) register extrinsic to the chain. @@ -172,6 +183,9 @@ async def _do_pow_register( pow_result (POWSolution): The PoW result to register. wait_for_inclusion (bool): If ``True``, waits for the extrinsic to be included in a block. Default to `False`. wait_for_finalization (bool): If ``True``, waits for the extrinsic to be finalized. Default to `True`. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): ``True`` if the extrinsic was included in a block. @@ -196,6 +210,7 @@ async def _do_pow_register( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) @@ -213,6 +228,7 @@ async def register_extrinsic( num_processes: Optional[int] = None, update_interval: Optional[int] = None, log_verbose: bool = False, + period: Optional[int] = None, ) -> bool: """Registers the wallet to the chain. @@ -233,6 +249,9 @@ async def register_extrinsic( num_processes: The number of processes to use to register. update_interval: The number of nonces to solve between updates. log_verbose: If `True`, the registration process will log more information. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: `True` if extrinsic was finalized or included in the block. If we did not wait for finalization/inclusion, the @@ -321,7 +340,7 @@ async def register_extrinsic( # pow successful, proceed to submit pow to chain for registration else: logging.info(":satellite: [magenta]Submitting POW...[/magenta]") - # check if pow result is still valid + # check if a pow result is still valid while not await pow_result.is_stale_async(subtensor=subtensor): result: tuple[bool, Optional[str]] = await _do_pow_register( subtensor=subtensor, @@ -330,6 +349,7 @@ async def register_extrinsic( pow_result=pow_result, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) success, err_msg = result @@ -386,6 +406,7 @@ async def register_subnet_extrinsic( wallet: "Wallet", wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> bool: """ Registers a new subnetwork on the Bittensor blockchain asynchronously. @@ -395,6 +416,9 @@ async def register_subnet_extrinsic( wallet (Wallet): The wallet to be used for subnet registration. wait_for_inclusion (bool): If set, waits for the extrinsic to enter a block before returning true. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning true. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: True if the subnet registration was successful, False otherwise. @@ -417,29 +441,25 @@ async def register_subnet_extrinsic( }, ) - extrinsic = await subtensor.substrate.create_signed_extrinsic( - call=call, keypair=wallet.coldkey - ) - - response = await subtensor.substrate.submit_extrinsic( - extrinsic, + success, message = await subtensor.sign_and_send_extrinsic( + call=call, + wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if not wait_for_finalization and not wait_for_inclusion: return True - if not await response.is_success: - logging.error( - f"Failed to register subnet: {format_error_message(await response.error_message)}" + if success: + logging.success( + ":white_heavy_check_mark: [green]Successfully registered subnet[/green]" ) - return False + return True - logging.success( - ":white_heavy_check_mark: [green]Successfully registered subnet[/green]" - ) - return True + logging.error(f"Failed to register subnet: {message}") + return False async def set_subnet_identity_extrinsic( @@ -455,6 +475,7 @@ async def set_subnet_identity_extrinsic( additional: str, wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Set the identity information for a given subnet. @@ -472,6 +493,9 @@ async def set_subnet_identity_extrinsic( additional (str): Any additional metadata or information related to the subnet. wait_for_inclusion (bool): Whether to wait for the extrinsic inclusion in a block (default: False). wait_for_finalization (bool): Whether to wait for the extrinsic finalization in a block (default: True). + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: A tuple where the first element indicates success or failure (True/False), and the second @@ -503,6 +527,7 @@ async def set_subnet_identity_extrinsic( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if not wait_for_finalization and not wait_for_inclusion: From 04cc497719a6a6f36ad8a645d767ecc72148efa6 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 11:59:31 -0700 Subject: [PATCH 034/100] update `bittensor/core/async_subtensor.py` --- bittensor/core/async_subtensor.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index b9ef190488..98c09b26e5 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -3382,6 +3382,7 @@ async def burned_register( netuid: int, wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> bool: """ Registers a neuron on the Bittensor network by recycling TAO. This method of registration involves recycling @@ -3394,6 +3395,9 @@ async def burned_register( `False`. wait_for_finalization (bool, optional): Waits for the transaction to be finalized on the blockchain. Defaults to `True`. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: ``True`` if the registration is successful, False otherwise. @@ -3413,6 +3417,7 @@ async def burned_register( netuid=netuid, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period ) async def commit_weights( @@ -3554,6 +3559,7 @@ async def register( num_processes: Optional[int] = None, update_interval: Optional[int] = None, log_verbose: bool = False, + period: Optional[int] = None, ): """ Registers a neuron on the Bittensor network using the provided wallet. @@ -3576,6 +3582,9 @@ async def register( num_processes (Optional[int]): The number of processes to use to register. Default to `None`. update_interval (Optional[int]): The number of nonces to solve between updates. Default to `None`. log_verbose (bool): If ``true``, the registration process will log more information. Default to `False`. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: ``True`` if the registration is successful, False otherwise. @@ -3597,6 +3606,7 @@ async def register( dev_id=dev_id, output_in_place=output_in_place, log_verbose=log_verbose, + period=period, ) async def register_subnet( @@ -3604,6 +3614,7 @@ async def register_subnet( wallet: "Wallet", wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> bool: """ Registers a new subnetwork on the Bittensor network. @@ -3614,6 +3625,9 @@ async def register_subnet( false if the extrinsic fails to enter the block within the timeout. Default is False. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning true, or returns false if the extrinsic fails to be finalized within the timeout. Default is True. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: True if the subnet registration was successful, False otherwise. @@ -3624,6 +3638,7 @@ async def register_subnet( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) async def reveal_weights( @@ -3907,6 +3922,7 @@ async def set_subnet_identity( subnet_identity: SubnetIdentity, wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Sets the identity of a subnet for a specific wallet and network. @@ -3918,6 +3934,9 @@ async def set_subnet_identity( repository, contact, URL, discord, description, and any additional metadata. wait_for_inclusion (bool): Indicates if the function should wait for the transaction to be included in the block. wait_for_finalization (bool): Indicates if the function should wait for the transaction to reach finalization. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: A tuple where the first element is a boolean indicating success or failure of the @@ -3936,6 +3955,7 @@ async def set_subnet_identity( additional=subnet_identity.additional, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) async def set_weights( @@ -3964,12 +3984,12 @@ async def set_weights( weights (Union[NDArray[np.float32], torch.FloatTensor, list]): The corresponding weights to be set for each UID. version_key (int): Version key for compatibility with the network. Default is int representation of - Bittensor version. + a Bittensor version. wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``False``. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``. max_retries (int): The number of maximum attempts to set weights. Default is ``5``. - block_time (float): The amount of seconds for block duration. Default is 12.0 seconds. + block_time (float): The number of seconds for block duration. Default is 12.0 seconds. period (int, optional): The period in seconds to wait for extrinsic inclusion or finalization. Defaults to 5. Returns: From f131a7cdc3abafb5fcc6d0852e73ab01c5113f1f Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 11:59:40 -0700 Subject: [PATCH 035/100] update `bittensor/core/subtensor.py` --- bittensor/core/subtensor.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 57e6d42eea..9b08a25221 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -2812,6 +2812,7 @@ def burned_register( netuid: int, wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> bool: """ Registers a neuron on the Bittensor network by recycling TAO. This method of registration involves recycling @@ -2824,6 +2825,9 @@ def burned_register( `False`. wait_for_finalization (bool, optional): Waits for the transaction to be finalized on the blockchain. Defaults to `True`. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: ``True`` if the registration is successful, False otherwise. @@ -2843,6 +2847,7 @@ def burned_register( netuid=netuid, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) def commit_weights( @@ -2984,6 +2989,7 @@ def register( num_processes: Optional[int] = None, update_interval: Optional[int] = None, log_verbose: bool = False, + period: Optional[int] = None, ) -> bool: """ Registers a neuron on the Bittensor network using the provided wallet. @@ -3006,6 +3012,9 @@ def register( num_processes (Optional[int]): The number of processes to use to register. Default to `None`. update_interval (Optional[int]): The number of nonces to solve between updates. Default to `None`. log_verbose (bool): If ``true``, the registration process will log more information. Default to `False`. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: ``True`` if the registration is successful, False otherwise. @@ -3027,6 +3036,7 @@ def register( dev_id=dev_id, output_in_place=output_in_place, log_verbose=log_verbose, + period=period, ) def register_subnet( @@ -3034,6 +3044,7 @@ def register_subnet( wallet: "Wallet", wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> bool: """ Registers a new subnetwork on the Bittensor network. @@ -3044,6 +3055,9 @@ def register_subnet( false if the extrinsic fails to enter the block within the timeout. Default is False. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning true, or returns false if the extrinsic fails to be finalized within the timeout. Default is True. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: True if the subnet registration was successful, False otherwise. @@ -3053,6 +3067,7 @@ def register_subnet( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) def reveal_weights( @@ -3192,6 +3207,7 @@ def set_subnet_identity( subnet_identity: SubnetIdentity, wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Sets the identity of a subnet for a specific wallet and network. @@ -3203,6 +3219,9 @@ def set_subnet_identity( repository, contact, URL, discord, description, and any additional metadata. wait_for_inclusion (bool): Indicates if the function should wait for the transaction to be included in the block. wait_for_finalization (bool): Indicates if the function should wait for the transaction to reach finalization. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: A tuple where the first element is a boolean indicating success or failure of the @@ -3221,6 +3240,7 @@ def set_subnet_identity( additional=subnet_identity.additional, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) def set_weights( From 0e743f71cc15c21a93d5f51fd520f55343119b63 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 11:59:54 -0700 Subject: [PATCH 036/100] fix related tests --- tests/e2e_tests/test_axon.py | 2 +- tests/e2e_tests/test_set_subnet_identity_extrinsic.py | 2 +- tests/unit_tests/extrinsics/asyncex/test_registration.py | 3 +++ tests/unit_tests/extrinsics/test_registration.py | 2 ++ tests/unit_tests/test_async_subtensor.py | 2 ++ tests/unit_tests/test_subtensor.py | 1 + 6 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/e2e_tests/test_axon.py b/tests/e2e_tests/test_axon.py index 0a139eb457..613027c691 100644 --- a/tests/e2e_tests/test_axon.py +++ b/tests/e2e_tests/test_axon.py @@ -13,7 +13,7 @@ async def test_axon(subtensor, templates, alice_wallet): Steps: 1. Register a subnet and register Alice 2. Check if metagraph.axon is updated and check axon attributes - 3. Run Alice as a miner on the subnet + 3. Run Alice as a miner on subnet 4. Check the metagraph again after running the miner and verify all attributes Raises: AssertionError: If any of the checks or verifications fail diff --git a/tests/e2e_tests/test_set_subnet_identity_extrinsic.py b/tests/e2e_tests/test_set_subnet_identity_extrinsic.py index 60d91fa3d1..11c8d76d7e 100644 --- a/tests/e2e_tests/test_set_subnet_identity_extrinsic.py +++ b/tests/e2e_tests/test_set_subnet_identity_extrinsic.py @@ -10,7 +10,7 @@ async def test_set_subnet_identity_extrinsic_happy_pass(subtensor, alice_wallet) "[magenta]Testing `set_subnet_identity_extrinsic` with success result.[/magenta]" ) - netuid = 2 + netuid = subtensor.get_total_subnets() # 2 # Register a subnet, netuid 2 assert subtensor.register_subnet(alice_wallet), "Subnet wasn't created" diff --git a/tests/unit_tests/extrinsics/asyncex/test_registration.py b/tests/unit_tests/extrinsics/asyncex/test_registration.py index b53fd946e0..66d1c667f0 100644 --- a/tests/unit_tests/extrinsics/asyncex/test_registration.py +++ b/tests/unit_tests/extrinsics/asyncex/test_registration.py @@ -450,6 +450,7 @@ async def is_stale_side_effect(*_, **__): pow_result=fake_pow_result, wait_for_inclusion=True, wait_for_finalization=True, + period=None, ) assert result is False @@ -510,6 +511,7 @@ async def test_set_subnet_identity_extrinsic_is_success(subtensor, fake_wallet, wallet=fake_wallet, wait_for_inclusion=False, wait_for_finalization=True, + period=None, ) assert result == (True, "Identities for subnet 123 are set.") @@ -574,6 +576,7 @@ async def test_set_subnet_identity_extrinsic_is_failed(subtensor, fake_wallet, m wallet=fake_wallet, wait_for_inclusion=True, wait_for_finalization=True, + period=None, ) assert result == ( diff --git a/tests/unit_tests/extrinsics/test_registration.py b/tests/unit_tests/extrinsics/test_registration.py index b2d816d4dd..77c6a0d3aa 100644 --- a/tests/unit_tests/extrinsics/test_registration.py +++ b/tests/unit_tests/extrinsics/test_registration.py @@ -286,6 +286,7 @@ def test_set_subnet_identity_extrinsic_is_success(mock_subtensor, mock_wallet, m wallet=mock_wallet, wait_for_inclusion=False, wait_for_finalization=True, + period=None, ) assert result == (True, "Identities for subnet 123 are set.") @@ -347,6 +348,7 @@ def test_set_subnet_identity_extrinsic_is_failed(mock_subtensor, mock_wallet, mo wallet=mock_wallet, wait_for_inclusion=False, wait_for_finalization=True, + period=None, ) assert result == ( diff --git a/tests/unit_tests/test_async_subtensor.py b/tests/unit_tests/test_async_subtensor.py index c0fd7dbcc5..1c409a6658 100644 --- a/tests/unit_tests/test_async_subtensor.py +++ b/tests/unit_tests/test_async_subtensor.py @@ -2551,6 +2551,7 @@ async def test_register_success(subtensor, fake_wallet, mocker): wait_for_finalization=True, wait_for_inclusion=False, wallet=fake_wallet, + period=None, ) assert result == mocked_register_extrinsic.return_value @@ -2956,6 +2957,7 @@ async def test_set_subnet_identity(mocker, subtensor, fake_wallet): additional=fake_subnet_identity.additional, wait_for_finalization=True, wait_for_inclusion=False, + period=None, ) assert result == mocked_extrinsic.return_value diff --git a/tests/unit_tests/test_subtensor.py b/tests/unit_tests/test_subtensor.py index bfc9b45d94..9160ae4c2a 100644 --- a/tests/unit_tests/test_subtensor.py +++ b/tests/unit_tests/test_subtensor.py @@ -3206,6 +3206,7 @@ def test_set_subnet_identity(mocker, subtensor, fake_wallet): additional=fake_subnet_identity.additional, wait_for_finalization=True, wait_for_inclusion=False, + period=None, ) assert result == mocked_extrinsic.return_value From 904b4cd980efb85fb44108c531e3952788a8a2d2 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 12:00:08 -0700 Subject: [PATCH 037/100] optimize imports in utils --- bittensor/core/extrinsics/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bittensor/core/extrinsics/utils.py b/bittensor/core/extrinsics/utils.py index 1ee776895b..e0d2cb8e4f 100644 --- a/bittensor/core/extrinsics/utils.py +++ b/bittensor/core/extrinsics/utils.py @@ -1,8 +1,10 @@ """Module with helper functions for extrinsics.""" from typing import TYPE_CHECKING, Union + import numpy as np from numpy.typing import NDArray + from bittensor.utils.balance import Balance from bittensor.utils.weight_utils import convert_weights_and_uids_for_emit From f813b9c7347b09f189dee20423ae4b42e963ef61 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 16:42:48 -0700 Subject: [PATCH 038/100] update `bittensor/core/extrinsics/root.py` --- bittensor/core/extrinsics/root.py | 67 ++++++++++++++++--------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/bittensor/core/extrinsics/root.py b/bittensor/core/extrinsics/root.py index 43fd65a5a1..7272eae296 100644 --- a/bittensor/core/extrinsics/root.py +++ b/bittensor/core/extrinsics/root.py @@ -1,5 +1,5 @@ import time -from typing import Union, TYPE_CHECKING +from typing import Optional, Union, TYPE_CHECKING import numpy as np from numpy.typing import NDArray @@ -16,6 +16,7 @@ from bittensor.utils.weight_utils import ( normalize_max_weight, convert_weights_and_uids_for_emit, + convert_netuids_and_weights ) if TYPE_CHECKING: @@ -50,8 +51,9 @@ def root_register_extrinsic( wallet: "Wallet", wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> bool: - """Registers the wallet to root network. + """Registers the wallet to the root network. Arguments: subtensor (bittensor.core.subtensor.Subtensor): The Subtensor object @@ -60,6 +62,9 @@ def root_register_extrinsic( `False` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning `True`, or returns `False` if the extrinsic fails to be finalized within the timeout. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: `True` if extrinsic was finalized or included in the block. If we did not wait for finalization/inclusion, the @@ -118,6 +123,7 @@ def root_register_extrinsic( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if not success: @@ -152,7 +158,7 @@ def _do_set_root_weights( version_key: int = 0, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, - period: int = 5, + period: Optional[int] = 8, ) -> tuple[bool, str]: """ Sets the root weights on the Subnet for the given wallet hotkey account. @@ -172,7 +178,9 @@ def _do_set_root_weights( False. wait_for_finalization (bool, optional): If True, waits for the extrinsic to be finalized on the chain. Defaults to False. - period (int, optional): The period in seconds to wait for extrinsic inclusion or finalization. Defaults to 5. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple: Returns a tuple containing a boolean indicating success and a message describing the result of the @@ -190,28 +198,23 @@ def _do_set_root_weights( }, ) - next_nonce = subtensor.substrate.get_account_next_index(wallet.hotkey.ss58_address) - - # Period dictates how long the extrinsic will stay as part of waiting pool - extrinsic = subtensor.substrate.create_signed_extrinsic( + success, message = subtensor.sign_and_send_extrinsic( call=call, - keypair=wallet.coldkey, - era={"period": period}, - nonce=next_nonce, - ) - response = subtensor.substrate.submit_extrinsic( - extrinsic=extrinsic, + wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + use_nonce=True, + period=period, ) + # We only wait here if we expect finalization. if not wait_for_finalization and not wait_for_inclusion: return True, "Not waiting for finalization or inclusion." - if response.is_success: + if success: return True, "Successfully set weights." - return False, format_error_message(response.error_message) + return False, message def set_root_weights_extrinsic( @@ -222,20 +225,24 @@ def set_root_weights_extrinsic( version_key: int = 0, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: - """Sets the given weights and values on chain for wallet hotkey account. + """Sets the given weights and values on a chain for a wallet hotkey account. Arguments: subtensor (bittensor.core.subtensor.Subtensor): The Subtensor object wallet (bittensor_wallet.Wallet): Bittensor wallet object. netuids (Union[NDArray[np.int64], list[int]]): The `netuid` of the subnet to set weights for. - weights (Union[NDArray[np.float32], list[float]]): Weights to set. These must be `float` s and must correspond + weights (Union[NDArray[np.float32], list[float]]): Weights to set. These must be `float's and must correspond to the passed `netuid` s. version_key (int): The version key of the validator. wait_for_inclusion (bool): If set, waits for the extrinsic to enter a block before returning `True`, or returns `False` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning True`, or returns `False` if the extrinsic fails to be finalized within the timeout. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: `True` if extrinsic was finalized or included in the block. If we did not wait for finalization/inclusion, the @@ -253,13 +260,10 @@ def set_root_weights_extrinsic( logging.error(unlock.message) return False - # First convert types. - if isinstance(netuids, list): - netuids = np.array(netuids, dtype=np.int64) - if isinstance(weights, list): - weights = np.array(weights, dtype=np.float32) + # Convert types. + netuids, weights = convert_netuids_and_weights(netuids, weights) - logging.debug("Fetching weight limits") + logging.debug("[magenta]Fetching weight limits ...[/magenta]") min_allowed_weights, max_weight_limit = _get_limits(subtensor) # Get non zero values. @@ -273,7 +277,7 @@ def set_root_weights_extrinsic( ) # Normalize the weights to max value. - logging.info("Normalizing weights") + logging.info("[magenta]Normalizing weights ...[/magenta]") formatted_weights = normalize_max_weight(x=weights, limit=max_weight_limit) logging.info( f"Raw weights -> Normalized weights: [blue]{weights}[/blue] -> [green]{formatted_weights}[/green]" @@ -283,7 +287,7 @@ def set_root_weights_extrinsic( logging.info(":satellite: [magenta]Setting root weights...[magenta]") weight_uids, weight_vals = convert_weights_and_uids_for_emit(netuids, weights) - success, error_message = _do_set_root_weights( + success, message = _do_set_root_weights( subtensor=subtensor, wallet=wallet, netuids=weight_uids, @@ -291,18 +295,15 @@ def set_root_weights_extrinsic( version_key=version_key, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) - if not wait_for_finalization and not wait_for_inclusion: - return True - if success is True: logging.info(":white_heavy_check_mark: [green]Finalized[/green]") return True - else: - fmt_err = error_message - logging.error(f":cross_mark: [red]Failed error:[/red] {fmt_err}") - return False + + logging.error(f":cross_mark: [red]Failed error:[/red] {message}") + return False except SubstrateRequestException as e: fmt_err = format_error_message(e) From 7fe6084342e3c57ec32095ab054316289006437b Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 16:43:04 -0700 Subject: [PATCH 039/100] update `bittensor/core/extrinsics/asyncex/root.py` --- bittensor/core/extrinsics/asyncex/root.py | 66 +++++++++++------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/root.py b/bittensor/core/extrinsics/asyncex/root.py index 6c30f631eb..0170da5236 100644 --- a/bittensor/core/extrinsics/asyncex/root.py +++ b/bittensor/core/extrinsics/asyncex/root.py @@ -1,7 +1,6 @@ import asyncio -from typing import Union, TYPE_CHECKING +from typing import Optional, Union, TYPE_CHECKING -from bittensor_wallet import Wallet import numpy as np from numpy.typing import NDArray @@ -12,9 +11,11 @@ from bittensor.utils.weight_utils import ( normalize_max_weight, convert_weights_and_uids_for_emit, + convert_netuids_and_weights ) if TYPE_CHECKING: + from bittensor_wallet import Wallet from bittensor.core.async_subtensor import AsyncSubtensor @@ -47,8 +48,9 @@ async def root_register_extrinsic( wallet: "Wallet", wait_for_inclusion: bool = True, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> bool: - """Registers the wallet to root network. + """Registers the wallet to the root network. Arguments: subtensor (bittensor.core.async_subtensor.AsyncSubtensor): The AsyncSubtensor object @@ -57,6 +59,9 @@ async def root_register_extrinsic( `False` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning `True`, or returns `False` if the extrinsic fails to be finalized within the timeout. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: `True` if extrinsic was finalized or included in the block. If we did not wait for finalization/inclusion, @@ -112,15 +117,16 @@ async def root_register_extrinsic( call_function="root_register", call_params={"hotkey": wallet.hotkey.ss58_address}, ) - success, err_msg = await subtensor.sign_and_send_extrinsic( + success, message = await subtensor.sign_and_send_extrinsic( call, wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if not success: - logging.error(f":cross_mark: [red]Failed error:[/red] {err_msg}") + logging.error(f":cross_mark: [red]Failed error:[/red] {message}") await asyncio.sleep(0.5) return False @@ -151,7 +157,7 @@ async def _do_set_root_weights( version_key: int = 0, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, - period: int = 5, + period: Optional[int] = 8, ) -> tuple[bool, str]: """ Sets the root weights on the Subnet for the given wallet hotkey account. @@ -171,7 +177,9 @@ async def _do_set_root_weights( False. wait_for_finalization (bool, optional): If True, waits for the extrinsic to be finalized on the chain. Defaults to False. - period (int, optional): The period in seconds to wait for extrinsic inclusion or finalization. Defaults to 5. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple: Returns a tuple containing a boolean indicating success and a message describing the result of the @@ -189,30 +197,23 @@ async def _do_set_root_weights( }, ) - next_nonce = await subtensor.substrate.get_account_next_index( - wallet.hotkey.ss58_address - ) - - # Period dictates how long the extrinsic will stay as part of waiting pool - extrinsic = await subtensor.substrate.create_signed_extrinsic( + success, message = await subtensor.sign_and_send_extrinsic( call=call, - keypair=wallet.coldkey, - era={"period": period}, - nonce=next_nonce, - ) - response = await subtensor.substrate.submit_extrinsic( - extrinsic=extrinsic, + wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + use_nonce=True, + period=period, ) + # We only wait here if we expect finalization. if not wait_for_finalization and not wait_for_inclusion: return True, "Not waiting for finalization or inclusion." - if await response.is_success: + if success: return True, "Successfully set weights." - return False, format_error_message(await response.error_message) + return False, message async def set_root_weights_extrinsic( @@ -223,20 +224,24 @@ async def set_root_weights_extrinsic( version_key: int = 0, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: - """Sets the given weights and values on chain for wallet hotkey account. + """Sets the given weights and values on a chain for a wallet hotkey account. Arguments: subtensor (bittensor.core.async_subtensor.AsyncSubtensor): The AsyncSubtensor object wallet (bittensor_wallet.Wallet): Bittensor wallet object. netuids (Union[NDArray[np.int64], list[int]]): The `netuid` of the subnet to set weights for. - weights (Union[NDArray[np.float32], list[float]]): Weights to set. These must be `float` s and must correspond + weights (Union[NDArray[np.float32], list[Float]]): Weights to set. These must be `Float`s and must correspond to the passed `netuid` s. version_key (int): The version key of the validator. wait_for_inclusion (bool): If set, waits for the extrinsic to enter a block before returning `True`, or returns `False` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning ` True`, or returns `False` if the extrinsic fails to be finalized within the timeout. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: `True` if extrinsic was finalized or included in the block. If we did not wait for finalization/inclusion, the @@ -254,13 +259,10 @@ async def set_root_weights_extrinsic( logging.error(unlock.message) return False - # First convert types. - if isinstance(netuids, list): - netuids = np.array(netuids, dtype=np.int64) - if isinstance(weights, list): - weights = np.array(weights, dtype=np.float32) + # Convert types. + netuids, weights = convert_netuids_and_weights(netuids, weights) - logging.debug("Fetching weight limits") + logging.debug("[magenta]Fetching weight limits ...[/magenta]") min_allowed_weights, max_weight_limit = await _get_limits(subtensor) # Get non zero values. @@ -274,7 +276,7 @@ async def set_root_weights_extrinsic( ) # Normalize the weights to max value. - logging.info("Normalizing weights") + logging.info("[magenta]Normalizing weights ...[/magenta]") formatted_weights = normalize_max_weight(x=weights, limit=max_weight_limit) logging.info( f"Raw weights -> Normalized weights: [blue]{weights}[/blue] -> [green]{formatted_weights}[/green]" @@ -292,11 +294,9 @@ async def set_root_weights_extrinsic( version_key=version_key, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) - if not wait_for_finalization and not wait_for_inclusion: - return True - if success is True: logging.info(":white_heavy_check_mark: [green]Finalized[/green]") return True From 1aed64081ed44ae11480cb2fcc855d532aa9a929 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 16:46:08 -0700 Subject: [PATCH 040/100] refactoring related with `bittensor.utils.weight_utils.convert_and_normalize_weights_and_uids` --- .../core/extrinsics/asyncex/commit_reveal.py | 2 +- bittensor/core/extrinsics/asyncex/weights.py | 2 +- bittensor/core/extrinsics/commit_reveal.py | 2 +- bittensor/core/extrinsics/set_weights.py | 2 +- bittensor/core/extrinsics/utils.py | 26 ---------- bittensor/utils/weight_utils.py | 50 ++++++++++++++++++- 6 files changed, 52 insertions(+), 32 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/commit_reveal.py b/bittensor/core/extrinsics/asyncex/commit_reveal.py index 7994bbbd76..74d2de5c3a 100644 --- a/bittensor/core/extrinsics/asyncex/commit_reveal.py +++ b/bittensor/core/extrinsics/asyncex/commit_reveal.py @@ -6,9 +6,9 @@ from bittensor_drand import get_encrypted_commit from numpy.typing import NDArray -from bittensor.core.extrinsics.utils import convert_and_normalize_weights_and_uids from bittensor.core.settings import version_as_int from bittensor.utils.btlogging import logging +from bittensor.utils.weight_utils import convert_and_normalize_weights_and_uids if TYPE_CHECKING: from bittensor_wallet import Wallet diff --git a/bittensor/core/extrinsics/asyncex/weights.py b/bittensor/core/extrinsics/asyncex/weights.py index 33c0e98b9d..ef5cbfdba9 100644 --- a/bittensor/core/extrinsics/asyncex/weights.py +++ b/bittensor/core/extrinsics/asyncex/weights.py @@ -5,9 +5,9 @@ import numpy as np from numpy.typing import NDArray -from bittensor.core.extrinsics.utils import convert_and_normalize_weights_and_uids from bittensor.core.settings import version_as_int from bittensor.utils.btlogging import logging +from bittensor.utils.weight_utils import convert_and_normalize_weights_and_uids if TYPE_CHECKING: from bittensor_wallet import Wallet diff --git a/bittensor/core/extrinsics/commit_reveal.py b/bittensor/core/extrinsics/commit_reveal.py index 73e62aaf8f..ed7e57fc4f 100644 --- a/bittensor/core/extrinsics/commit_reveal.py +++ b/bittensor/core/extrinsics/commit_reveal.py @@ -6,9 +6,9 @@ from bittensor_drand import get_encrypted_commit from numpy.typing import NDArray -from bittensor.core.extrinsics.utils import convert_and_normalize_weights_and_uids from bittensor.core.settings import version_as_int from bittensor.utils.btlogging import logging +from bittensor.utils.weight_utils import convert_and_normalize_weights_and_uids if TYPE_CHECKING: from bittensor_wallet import Wallet diff --git a/bittensor/core/extrinsics/set_weights.py b/bittensor/core/extrinsics/set_weights.py index 7e5714afa3..90f4cff32d 100644 --- a/bittensor/core/extrinsics/set_weights.py +++ b/bittensor/core/extrinsics/set_weights.py @@ -5,10 +5,10 @@ import numpy as np from numpy.typing import NDArray -from bittensor.core.extrinsics.utils import convert_and_normalize_weights_and_uids from bittensor.core.settings import version_as_int from bittensor.utils import format_error_message from bittensor.utils.btlogging import logging +from bittensor.utils.weight_utils import convert_and_normalize_weights_and_uids if TYPE_CHECKING: from bittensor.core.subtensor import Subtensor diff --git a/bittensor/core/extrinsics/utils.py b/bittensor/core/extrinsics/utils.py index e0d2cb8e4f..a23126d1c8 100644 --- a/bittensor/core/extrinsics/utils.py +++ b/bittensor/core/extrinsics/utils.py @@ -47,29 +47,3 @@ def get_old_stakes( ) for hotkey_ss58, netuid in zip(hotkey_ss58s, netuids) ] - - -def convert_and_normalize_weights_and_uids( - uids: Union[NDArray[np.int64], "torch.LongTensor", list], - weights: Union[NDArray[np.float32], "torch.FloatTensor", list], -) -> tuple[list[int], list[int]]: - """Converts weights and uids to numpy arrays if they are not already. - - Arguments: - uids (Union[NDArray[np.int64], torch.LongTensor, list]): The ``uint64`` uids of destination neurons. - weights (Union[NDArray[np.float32], torch.FloatTensor, list]): The weights to set. These must be ``float`` s - and correspond to the passed ``uid`` s. - - Returns: - weight_uids, weight_vals: Bytes converted weights and uids - """ - if isinstance(uids, list): - uids = np.array(uids, dtype=np.int64) - if isinstance(weights, list): - weights = np.array(weights, dtype=np.float32) - - # Reformat and normalize. - weight_uids, weight_vals = convert_weights_and_uids_for_emit( - uids, weights - ) - return weight_uids, weight_vals diff --git a/bittensor/utils/weight_utils.py b/bittensor/utils/weight_utils.py index 5c98b1f383..4939b7bb4e 100644 --- a/bittensor/utils/weight_utils.py +++ b/bittensor/utils/weight_utils.py @@ -190,7 +190,7 @@ def convert_weights_and_uids_for_emit( f"Passed weights and uids must have the same length, got {len(uids)} and {len(weights)}" ) if sum(weights) == 0: - return [], [] # Nothing to set on chain. + return [], [] # Nothing to set on a chain. else: max_weight = float(max(weights)) weights = [ @@ -249,7 +249,7 @@ def process_weights_for_netuid( logging.debug(f"subtensor: {subtensor}") logging.debug(f"metagraph: {metagraph}") - # Get latest metagraph from chain if metagraph is None. + # Get latest metagraph from a chain if metagraph is None. if metagraph is None: metagraph = subtensor.metagraph(netuid) @@ -440,3 +440,49 @@ def generate_weight_hash( commit_hash = "0x" + blake2b_hash.hexdigest() return commit_hash + + +def convert_netuids_and_weights( + netuids: Union[NDArray[np.int64], list], + weights: Union[NDArray[np.float32], list], +) -> tuple[np.ndarray, np.ndarray]: + """Converts netuids and weights to numpy arrays if they are not already. + + Arguments: + netuids (Union[NDArray[np.int64], list]): The uint64 uids of destination neurons. + weights (Union[NDArray[np.float32], list]): The weights to set. These must be floated. + + Returns: + tuple[ndarray, ndarray]: Bytes converted netuids and weights. + """ + if isinstance(netuids, list): + netuids = np.array(netuids, dtype=np.int64) + if isinstance(weights, list): + weights = np.array(weights, dtype=np.float32) + return netuids, weights + + +def convert_and_normalize_weights_and_uids( + uids: Union[NDArray[np.int64], "torch.LongTensor", list], + weights: Union[NDArray[np.float32], "torch.FloatTensor", list], +) -> tuple[list[int], list[int]]: + """Converts weights and uids to numpy arrays if they are not already. + + Arguments: + uids (Union[NDArray[np.int64], torch.LongTensor, list]): The ``uint64`` uids of destination neurons. + weights (Union[NDArray[np.float32], torch.FloatTensor, list]): The weights to set. These must be ``float`` s + and correspond to the passed ``uid`` s. + + Returns: + weight_uids, weight_vals: Bytes converted weights and uids + """ + if isinstance(uids, list): + uids = np.array(uids, dtype=np.int64) + if isinstance(weights, list): + weights = np.array(weights, dtype=np.float32) + + # Reformat and normalize. + weight_uids, weight_vals = convert_weights_and_uids_for_emit( + uids, weights + ) + return weight_uids, weight_vals From fb050f8f4a728a420e80d5f50ec17724f2b5a50f Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 16:48:14 -0700 Subject: [PATCH 041/100] update extrinsics related calls --- bittensor/core/async_subtensor.py | 18 +++++++++++++++--- bittensor/core/subtensor.py | 11 +++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index 98c09b26e5..c0f146dd6d 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -3398,6 +3398,9 @@ async def burned_register( period (int): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: ``True`` if the registration is successful, False otherwise. @@ -3409,6 +3412,7 @@ async def burned_register( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) return await burned_register_extrinsic( @@ -3706,19 +3710,21 @@ async def reveal_weights( async def root_register( self, wallet: "Wallet", - block_hash: Optional[str] = None, wait_for_inclusion: bool = True, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> bool: """ Register neuron by recycling some TAO. Arguments: wallet (bittensor_wallet.Wallet): Bittensor wallet instance. - block_hash (Optional[str]): The hash of the blockchain block for the query. wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``False``. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: `True` if registration was successful, otherwise `False`. @@ -3729,6 +3735,7 @@ async def root_register( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) async def root_set_weights( @@ -3739,9 +3746,10 @@ async def root_set_weights( version_key: int = 0, wait_for_inclusion: bool = True, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> bool: """ - Set weights for root network. + Set weights for the root network. Arguments: wallet (bittensor_wallet.Wallet): bittensor wallet instance. @@ -3752,6 +3760,9 @@ async def root_set_weights( ``False``. wait_for_finalization (bool, optional): Waits for the transaction to be finalized on the blockchain. Defaults to ``False``. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: `True` if the setting of weights is successful, `False` otherwise. @@ -3768,6 +3779,7 @@ async def root_set_weights( version_key=version_key, wait_for_finalization=wait_for_finalization, wait_for_inclusion=wait_for_inclusion, + period=period, ) async def set_children( diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 9b08a25221..43130913f5 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -2839,6 +2839,7 @@ def burned_register( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) return burned_register_extrinsic( @@ -3141,6 +3142,7 @@ def root_register( wallet: "Wallet", wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> bool: """ Register neuron by recycling some TAO. @@ -3150,6 +3152,9 @@ def root_register( wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``False``. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: `True` if registration was successful, otherwise `False`. @@ -3160,6 +3165,7 @@ def root_register( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) def root_set_weights( @@ -3170,6 +3176,7 @@ def root_set_weights( version_key: int = 0, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: """ Set weights for the root network. @@ -3183,6 +3190,9 @@ def root_set_weights( ``False``. wait_for_finalization (bool, optional): Waits for the transaction to be finalized on the blockchain. Defaults to ``False``. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: `True` if the setting of weights is successful, `False` otherwise. @@ -3198,6 +3208,7 @@ def root_set_weights( version_key=version_key, wait_for_finalization=wait_for_finalization, wait_for_inclusion=wait_for_inclusion, + period=period, ) def set_subnet_identity( From d7b156f4439e74e5df7e6c0de8fdf3ad29d63323 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 16:50:22 -0700 Subject: [PATCH 042/100] fix related tests --- .../extrinsics/asyncex/test_root.py | 60 ++++++------------- tests/unit_tests/extrinsics/test_root.py | 1 + tests/unit_tests/test_async_subtensor.py | 1 + tests/unit_tests/test_subtensor_extended.py | 53 ---------------- 4 files changed, 20 insertions(+), 95 deletions(-) diff --git a/tests/unit_tests/extrinsics/asyncex/test_root.py b/tests/unit_tests/extrinsics/asyncex/test_root.py index ecca5a9847..ca221b2cd4 100644 --- a/tests/unit_tests/extrinsics/asyncex/test_root.py +++ b/tests/unit_tests/extrinsics/asyncex/test_root.py @@ -332,7 +332,7 @@ async def test_do_set_root_weights_success(subtensor, fake_wallet, mocker): fake_weights = [0.1, 0.2, 0.7] fake_call = mocker.AsyncMock() - fake_extrinsic = mocker.AsyncMock() + fake_extrinsic = True, "Successfully set weights." fake_response = mocker.Mock() fake_response.is_success = mocker.AsyncMock(return_value=True)() @@ -340,10 +340,7 @@ async def test_do_set_root_weights_success(subtensor, fake_wallet, mocker): mocker.patch.object(subtensor.substrate, "compose_call", return_value=fake_call) mocker.patch.object( - subtensor.substrate, "create_signed_extrinsic", return_value=fake_extrinsic - ) - mocker.patch.object( - subtensor.substrate, "submit_extrinsic", return_value=fake_response + subtensor, "sign_and_send_extrinsic", return_value=fake_extrinsic ) # Call @@ -369,14 +366,13 @@ async def test_do_set_root_weights_success(subtensor, fake_wallet, mocker): "hotkey": "fake_hotkey_address", }, ) - subtensor.substrate.create_signed_extrinsic.assert_called_once_with( + subtensor.sign_and_send_extrinsic.assert_called_once_with( call=fake_call, - keypair=fake_wallet.coldkey, - era={"period": 5}, - nonce=subtensor.substrate.get_account_next_index.return_value, - ) - subtensor.substrate.submit_extrinsic.assert_called_once_with( - extrinsic=fake_extrinsic, wait_for_inclusion=True, wait_for_finalization=True + wallet=fake_wallet, + wait_for_inclusion=True, + wait_for_finalization=True, + use_nonce=True, + period=8, ) assert result is True assert message == "Successfully set weights." @@ -391,29 +387,9 @@ async def test_do_set_root_weights_failure(subtensor, fake_wallet, mocker): fake_weights = [0.1, 0.2, 0.7] fake_call = mocker.AsyncMock() - fake_extrinsic = mocker.AsyncMock() - fake_response = mocker.Mock() - - async def fake_is_success(): - return False - - fake_response.is_success = fake_is_success() - fake_response.process_events = mocker.AsyncMock() - fake_response.error_message = mocker.AsyncMock()() mocker.patch.object(subtensor.substrate, "compose_call", return_value=fake_call) - mocker.patch.object( - subtensor.substrate, "create_signed_extrinsic", return_value=fake_extrinsic - ) - mocker.patch.object( - subtensor.substrate, "submit_extrinsic", return_value=fake_response - ) - - mocked_format_error_message = mocker.patch.object( - async_root, - "format_error_message", - return_value="Transaction failed", - ) + mocker.patch.object(subtensor, "sign_and_send_extrinsic", return_value=(False, "Transaction failed")) # Call result, message = await async_root._do_set_root_weights( @@ -428,7 +404,6 @@ async def fake_is_success(): # Asserts assert result is False - assert message == mocked_format_error_message.return_value @pytest.mark.asyncio @@ -441,14 +416,10 @@ async def test_do_set_root_weights_no_waiting(subtensor, fake_wallet, mocker): fake_call = mocker.AsyncMock() fake_extrinsic = mocker.AsyncMock() - fake_response = mocker.Mock() mocker.patch.object(subtensor.substrate, "compose_call", return_value=fake_call) mocker.patch.object( - subtensor.substrate, "create_signed_extrinsic", return_value=fake_extrinsic - ) - mocker.patch.object( - subtensor.substrate, "submit_extrinsic", return_value=fake_response + subtensor, "sign_and_send_extrinsic", return_value=(True, "Not waiting for finalization or inclusion.") ) # Call @@ -464,9 +435,13 @@ async def test_do_set_root_weights_no_waiting(subtensor, fake_wallet, mocker): # Asserts subtensor.substrate.compose_call.assert_called_once() - subtensor.substrate.create_signed_extrinsic.assert_called_once() - subtensor.substrate.submit_extrinsic.assert_called_once_with( - extrinsic=fake_extrinsic, wait_for_inclusion=False, wait_for_finalization=False + subtensor.sign_and_send_extrinsic.assert_called_once_with( + call=subtensor.substrate.compose_call.return_value, + wallet=fake_wallet, + wait_for_inclusion=False, + wait_for_finalization=False, + use_nonce=True, + period=8, ) assert result is True assert message == "Not waiting for finalization or inclusion." @@ -674,5 +649,6 @@ async def test_set_root_weights_extrinsic_request_exception( version_key=0, wait_for_inclusion=True, wait_for_finalization=True, + period=None, ) mocked_format_error_message.assert_called_once() diff --git a/tests/unit_tests/extrinsics/test_root.py b/tests/unit_tests/extrinsics/test_root.py index a22d456a2e..9324613fe8 100644 --- a/tests/unit_tests/extrinsics/test_root.py +++ b/tests/unit_tests/extrinsics/test_root.py @@ -103,6 +103,7 @@ def test_root_register_extrinsic( wallet=mock_wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=None ) diff --git a/tests/unit_tests/test_async_subtensor.py b/tests/unit_tests/test_async_subtensor.py index 1c409a6658..ddf5148b8c 100644 --- a/tests/unit_tests/test_async_subtensor.py +++ b/tests/unit_tests/test_async_subtensor.py @@ -2804,6 +2804,7 @@ async def test_root_set_weights_success(subtensor, fake_wallet, mocker): version_key=0, wait_for_finalization=True, wait_for_inclusion=True, + period=None, ) assert result == mocked_set_root_weights_extrinsic.return_value diff --git a/tests/unit_tests/test_subtensor_extended.py b/tests/unit_tests/test_subtensor_extended.py index ec67747f97..45f65f24db 100644 --- a/tests/unit_tests/test_subtensor_extended.py +++ b/tests/unit_tests/test_subtensor_extended.py @@ -1291,59 +1291,6 @@ def test_root_register_is_already_registered( mock_substrate.submit_extrinsic.assert_not_called() -def test_root_set_weights(mock_substrate, subtensor, fake_wallet, mocker): - MIN_ALLOWED_WEIGHTS = 0 - MAX_WEIGHTS_LIMIT = 1 - - mock_substrate.query.return_value = 1 - mocker.patch.object( - subtensor, - "get_hyperparameter", - autospec=True, - side_effect=[ - MIN_ALLOWED_WEIGHTS, - MAX_WEIGHTS_LIMIT, - ], - ) - - subtensor.root_set_weights( - fake_wallet, - netuids=[1, 2], - weights=[0.5, 0.5], - ) - - subtensor.get_hyperparameter.assert_has_calls( - [ - mocker.call("MinAllowedWeights", netuid=0), - mocker.call("MaxWeightsLimit", netuid=0), - ] - ) - mock_substrate.query.assert_called_once_with( - "SubtensorModule", - "Uids", - [0, fake_wallet.hotkey.ss58_address], - ) - - assert_submit_signed_extrinsic( - mock_substrate, - fake_wallet.coldkey, - call_module="SubtensorModule", - call_function="set_root_weights", - call_params={ - "dests": [1, 2], - "weights": [65535, 65535], - "netuid": 0, - "version_key": 0, - "hotkey": fake_wallet.hotkey.ss58_address, - }, - era={ - "period": 5, - }, - nonce=mock_substrate.get_account_next_index.return_value, - wait_for_finalization=False, - ) - - def test_root_set_weights_no_uid(mock_substrate, subtensor, fake_wallet, mocker): mock_substrate.query.return_value = None From dba73aa117c91b4ef37a6a59f79e60916582b1a7 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 18:29:37 -0700 Subject: [PATCH 043/100] update `bittensor/core/extrinsics/serving.py` --- bittensor/core/extrinsics/serving.py | 84 +++++++++++++++------------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/bittensor/core/extrinsics/serving.py b/bittensor/core/extrinsics/serving.py index aaed6ad38f..a9309cfe24 100644 --- a/bittensor/core/extrinsics/serving.py +++ b/bittensor/core/extrinsics/serving.py @@ -2,14 +2,13 @@ from bittensor.core.errors import MetadataError from bittensor.core.settings import version_as_int +from bittensor.core.types import AxonServeCallParams from bittensor.utils import ( - format_error_message, networking as net, unlock_key, Certificate, ) from bittensor.utils.btlogging import logging -from bittensor.core.types import AxonServeCallParams if TYPE_CHECKING: from bittensor_wallet import Wallet @@ -23,7 +22,8 @@ def do_serve_axon( call_params: "AxonServeCallParams", wait_for_inclusion: bool = False, wait_for_finalization: bool = True, -) -> tuple[bool, Optional[dict]]: + period: Optional[int] = None, +) -> tuple[bool, str]: """ Internal method to submit a serve axon transaction to the Bittensor blockchain. This method creates and submits a transaction, enabling a neuron's ``Axon`` to serve requests on the network. @@ -34,6 +34,9 @@ def do_serve_axon( call_params (bittensor.core.types.AxonServeCallParams): Parameters required for the serve axon call. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, Optional[str]]: A tuple containing a success flag and an optional error message. @@ -51,21 +54,15 @@ def do_serve_axon( call_function=call_function, call_params=call_params.dict(), ) - extrinsic = subtensor.substrate.create_signed_extrinsic( - call=call, keypair=wallet.hotkey - ) - response = subtensor.substrate.submit_extrinsic( - extrinsic=extrinsic, + + success, message = subtensor.sign_and_send_extrinsic( + call=call, + wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) - if wait_for_inclusion or wait_for_finalization: - if response.is_success: - return True, None - - return False, response.error_message - - return True, None + return success, message def serve_extrinsic( @@ -80,6 +77,7 @@ def serve_extrinsic( wait_for_inclusion: bool = False, wait_for_finalization=True, certificate: Optional[Certificate] = None, + period: Optional[int] = None, ) -> bool: """Subscribes a Bittensor endpoint to the subtensor chain. @@ -98,6 +96,9 @@ def serve_extrinsic( ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. certificate (bittensor.utils.Certificate): Certificate to use for TLS. If ``None``, no TLS will be used. Defaults to ``None``. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. If we did not wait for @@ -130,33 +131,33 @@ def serve_extrinsic( neuron_up_to_date = not neuron.is_null and params == neuron if neuron_up_to_date: logging.debug( - f"Axon already served on: AxonInfo({wallet.hotkey.ss58_address},{ip}:{port}) " + f"Axon already served on: [blue]AxonInfo({wallet.hotkey.ss58_address}, {ip}:{port})[/blue]" ) return True logging.debug( - f"Serving axon with: AxonInfo({wallet.hotkey.ss58_address},{ip}:{port}) -> {subtensor.network}:{netuid}" + f"Serving axon with: [blue]AxonInfo({wallet.hotkey.ss58_address}, {ip}:{port})[/blue] -> " + f"[green]{subtensor.network}:{netuid}[/green]" ) - success, error_message = do_serve_axon( + success, message = do_serve_axon( subtensor=subtensor, wallet=wallet, call_params=params, wait_for_finalization=wait_for_finalization, wait_for_inclusion=wait_for_inclusion, + period=period, ) - if wait_for_inclusion or wait_for_finalization: - if success is True: - logging.debug( - f"Axon served with: AxonInfo({wallet.hotkey.ss58_address},{ip}:{port}) on {subtensor.network}:{netuid} " - ) - return True - else: - logging.error(f"Failed: {format_error_message(error_message)}") - return False - else: + if success: + logging.debug( + f"Axon served with: [blue]AxonInfo({wallet.hotkey.ss58_address}, {ip}:{port})[/blue] on " + f"[green]{subtensor.network}:{netuid}[/green]" + ) return True + logging.error(f"Failed: {message}") + return False + def serve_axon_extrinsic( subtensor: "Subtensor", @@ -165,6 +166,7 @@ def serve_axon_extrinsic( wait_for_inclusion: bool = False, wait_for_finalization: bool = True, certificate: Optional["Certificate"] = None, + period: Optional[int] = None, ) -> bool: """Serves the axon to the network. @@ -178,6 +180,9 @@ def serve_axon_extrinsic( ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. certificate (bittensor.utils.Certificate): Certificate to use for TLS. If ``None``, no TLS will be used. Defaults to ``None``. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. If we did not wait for @@ -213,6 +218,7 @@ def serve_axon_extrinsic( wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, certificate=certificate, + period=period, ) return serve_success @@ -225,6 +231,7 @@ def publish_metadata( data: Union[bytes, dict], wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> bool: """ Publishes metadata on the Bittensor network using the specified wallet and network identifier. @@ -242,12 +249,15 @@ def publish_metadata( block before returning. Defaults to ``False``. wait_for_finalization (bool, optional): If ``True``, the function will wait for the extrinsic to be finalized on the chain before returning. Defaults to ``True``. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: ``True`` if the metadata was successfully published (and finalized if specified). ``False`` otherwise. Raises: - MetadataError: If there is an error in submitting the extrinsic or if the response from the blockchain indicates + MetadataError: If there is an error in submitting the extrinsic, or if the response from the blockchain indicates failure. """ @@ -264,21 +274,17 @@ def publish_metadata( }, ) - extrinsic = subtensor.substrate.create_signed_extrinsic( - call=call, keypair=wallet.hotkey - ) - response = subtensor.substrate.submit_extrinsic( - extrinsic=extrinsic, + success, message = subtensor.sign_and_send_extrinsic( + call=call, + wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) - # We only wait here if we expect finalization. - if not wait_for_finalization and not wait_for_inclusion: - return True - if response.is_success: + if success: return True - raise MetadataError(format_error_message(response.error_message)) + raise MetadataError(message) def get_metadata( From 904f9b2ff443381b814293081be8c901d78c9a2c Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 18:29:56 -0700 Subject: [PATCH 044/100] update `bittensor/core/extrinsics/asyncex/serving.py` --- bittensor/core/extrinsics/asyncex/serving.py | 85 +++++++++++--------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/serving.py b/bittensor/core/extrinsics/asyncex/serving.py index 558b58cae5..aafde7dd02 100644 --- a/bittensor/core/extrinsics/asyncex/serving.py +++ b/bittensor/core/extrinsics/asyncex/serving.py @@ -3,14 +3,13 @@ from bittensor.core.errors import MetadataError from bittensor.core.settings import version_as_int +from bittensor.core.types import AxonServeCallParams from bittensor.utils import ( - format_error_message, networking as net, unlock_key, Certificate, ) from bittensor.utils.btlogging import logging -from bittensor.core.types import AxonServeCallParams if TYPE_CHECKING: from bittensor.core.axon import Axon @@ -24,7 +23,8 @@ async def do_serve_axon( call_params: "AxonServeCallParams", wait_for_inclusion: bool = False, wait_for_finalization: bool = True, -) -> tuple[bool, Optional[dict]]: + period: Optional[int] = None, +) -> tuple[bool, str]: """ Internal method to submit a serve axon transaction to the Bittensor blockchain. This method creates and submits a transaction, enabling a neuron's ``Axon`` to serve requests on the network. @@ -35,9 +35,12 @@ async def do_serve_axon( call_params (bittensor.core.types.AxonServeCallParams): Parameters required for the serve axon call. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: - tuple[bool, Optional[str]]: A tuple containing a success flag and an optional error message. + tuple[bool, str]: A tuple containing a success flag and an optional error message. This function is crucial for initializing and announcing a neuron's ``Axon`` service on the network, enhancing the decentralized computation capabilities of Bittensor. @@ -53,21 +56,14 @@ async def do_serve_axon( call_function=call_function, call_params=call_params.dict(), ) - extrinsic = await subtensor.substrate.create_signed_extrinsic( - call=call, keypair=wallet.hotkey - ) - response = await subtensor.substrate.submit_extrinsic( - extrinsic=extrinsic, + success, message = await subtensor.sign_and_send_extrinsic( + call, + wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) - if wait_for_inclusion or wait_for_finalization: - if await response.is_success: - return True, None - - return False, await response.error_message - - return True, None + return success, message async def serve_extrinsic( @@ -82,6 +78,7 @@ async def serve_extrinsic( wait_for_inclusion: bool = False, wait_for_finalization=True, certificate: Optional[Certificate] = None, + period: Optional[int] = None, ) -> bool: """Subscribes a Bittensor endpoint to the subtensor chain. @@ -100,6 +97,9 @@ async def serve_extrinsic( ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. certificate (bittensor.utils.Certificate): Certificate to use for TLS. If ``None``, no TLS will be used. Defaults to ``None``. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. If we did not wait for @@ -132,33 +132,33 @@ async def serve_extrinsic( neuron_up_to_date = not neuron.is_null and params == neuron if neuron_up_to_date: logging.debug( - f"Axon already served on: AxonInfo({wallet.hotkey.ss58_address},{ip}:{port}) " + f"Axon already served on: [blue]AxonInfo({wallet.hotkey.ss58_address}, {ip}:{port})[/blue]" ) return True logging.debug( - f"Serving axon with: AxonInfo({wallet.hotkey.ss58_address},{ip}:{port}) -> {subtensor.network}:{netuid}" + f"Serving axon with: [blue]AxonInfo({wallet.hotkey.ss58_address}, {ip}:{port})[/blue] -> " + f"[green]{subtensor.network}:{netuid}[/green]" ) - success, error_message = await do_serve_axon( + success, message = do_serve_axon( subtensor=subtensor, wallet=wallet, call_params=params, wait_for_finalization=wait_for_finalization, wait_for_inclusion=wait_for_inclusion, + period=period, ) - if wait_for_inclusion or wait_for_finalization: - if success is True: - logging.debug( - f"Axon served with: AxonInfo({wallet.hotkey.ss58_address},{ip}:{port}) on {subtensor.network}:{netuid} " - ) - return True - else: - logging.error(f"Failed: {format_error_message(error_message)}") - return False - else: + if success: + logging.debug( + f"Axon served with: [blue]AxonInfo({wallet.hotkey.ss58_address}, {ip}:{port})[/blue] on " + f"[green]{subtensor.network}:{netuid}[/green]" + ) return True + logging.error(f"Failed: {message}") + return False + async def serve_axon_extrinsic( subtensor: "AsyncSubtensor", @@ -167,6 +167,7 @@ async def serve_axon_extrinsic( wait_for_inclusion: bool = False, wait_for_finalization: bool = True, certificate: Optional[Certificate] = None, + period: Optional[int] = None, ) -> bool: """Serves the axon to the network. @@ -180,6 +181,9 @@ async def serve_axon_extrinsic( ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. certificate (bittensor.utils.Certificate): Certificate to use for TLS. If ``None``, no TLS will be used. Defaults to ``None``. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. If we did not wait for @@ -217,6 +221,7 @@ async def serve_axon_extrinsic( wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, certificate=certificate, + period=period ) return serve_success @@ -229,6 +234,7 @@ async def publish_metadata( data: Union[bytes, dict], wait_for_inclusion: bool = False, wait_for_finalization: bool = True, + period: Optional[int] = None, ) -> bool: """ Publishes metadata on the Bittensor network using the specified wallet and network identifier. @@ -246,12 +252,15 @@ async def publish_metadata( block before returning. Defaults to ``False``. wait_for_finalization (bool, optional): If ``True``, the function will wait for the extrinsic to be finalized on the chain before returning. Defaults to ``True``. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: ``True`` if the metadata was successfully published (and finalized if specified). ``False`` otherwise. Raises: - MetadataError: If there is an error in submitting the extrinsic or if the response from the blockchain indicates + MetadataError: If there is an error in submitting the extrinsic, or if the response from the blockchain indicates failure. """ @@ -269,21 +278,17 @@ async def publish_metadata( }, ) - extrinsic = await substrate.create_signed_extrinsic( - call=call, keypair=wallet.hotkey - ) - response = await substrate.submit_extrinsic( - extrinsic=extrinsic, + success, message = await subtensor.sign_and_send_extrinsic( + call=call, + wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) - # We only wait here if we expect finalization. - if not wait_for_finalization and not wait_for_inclusion: - return True - if await response.is_success: + if success: return True - raise MetadataError(format_error_message(await response.error_message)) + raise MetadataError(message) async def get_metadata( From 9a27b6ac34b696889d6e3e33851f4bbe391c3210 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 18:30:50 -0700 Subject: [PATCH 045/100] related subtensors updates --- bittensor/core/async_subtensor.py | 20 ++++++++++++++++++-- bittensor/core/subtensor.py | 25 ++++++++++++++++++++----- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index c0f146dd6d..451706fd1f 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -653,7 +653,7 @@ async def bonds( return b_map - async def commit(self, wallet: "Wallet", netuid: int, data: str) -> bool: + async def commit(self, wallet: "Wallet", netuid: int, data: str, period: Optional[int] = None) -> bool: """ Commits arbitrary data to the Bittensor network by publishing metadata. @@ -661,6 +661,12 @@ async def commit(self, wallet: "Wallet", netuid: int, data: str) -> bool: wallet (bittensor_wallet.Wallet): The wallet associated with the neuron committing the data. netuid (int): The unique identifier of the subnetwork. data (str): The data to be committed to the network. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. + + Return: + bool: `True` if the commit was successful, `False` otherwise. """ return await publish_metadata( subtensor=self, @@ -2850,6 +2856,7 @@ async def set_reveal_commitment( data: str, blocks_until_reveal: int = 360, block_time: Union[int, float] = 12, + period: Optional[int] = None ) -> tuple[bool, int]: """ Commits arbitrary data to the Bittensor network by publishing metadata. @@ -2859,8 +2866,11 @@ async def set_reveal_commitment( netuid (int): The unique identifier of the subnetwork. data (str): The data to be committed to the network. blocks_until_reveal (int): The number of blocks from now after which the data will be revealed. Defaults to `360`. - Then amount of blocks in one epoch. + The number of blocks in one epoch. block_time (Union[int, float]): The number of seconds between each block. Defaults to `12`. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: `True` if the commitment was successful, `False` otherwise. @@ -2881,6 +2891,7 @@ async def set_reveal_commitment( netuid=netuid, data_type=f"TimelockEncrypted", data=data_, + period=period ), reveal_round async def subnet( @@ -4093,6 +4104,7 @@ async def serve_axon( wait_for_inclusion: bool = False, wait_for_finalization: bool = True, certificate: Optional[Certificate] = None, + period: Optional[int] = None, ) -> bool: """ Registers an ``Axon`` serving endpoint on the Bittensor network for a specific neuron. This function is used to @@ -4106,6 +4118,9 @@ async def serve_axon( ``True``. certificate (bittensor.utils.Certificate): Certificate to use for TLS. If ``None``, no TLS will be used. Defaults to ``None``. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: ``True`` if the Axon serve registration is successful, False otherwise. @@ -4120,6 +4135,7 @@ async def serve_axon( wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, certificate=certificate, + period=period, ) async def start_call( diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 43130913f5..ac8e1b0710 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -452,7 +452,7 @@ def bonds( return b_map - def commit(self, wallet, netuid: int, data: str) -> bool: + def commit(self, wallet, netuid: int, data: str, period: Optional[int] = None) -> bool: """ Commits arbitrary data to the Bittensor network by publishing metadata. @@ -460,6 +460,12 @@ def commit(self, wallet, netuid: int, data: str) -> bool: wallet (bittensor_wallet.Wallet): The wallet associated with the neuron committing the data. netuid (int): The unique identifier of the subnetwork. data (str): The data to be committed to the network. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. + + Returns: + bool: `True` if the commitment was successful, `False` otherwise. """ return publish_metadata( subtensor=self, @@ -467,6 +473,7 @@ def commit(self, wallet, netuid: int, data: str) -> bool: netuid=netuid, data_type=f"Raw{len(data)}", data=data.encode(), + period=period, ) # add explicit alias @@ -476,7 +483,7 @@ def commit_reveal_enabled( self, netuid: int, block: Optional[int] = None ) -> Optional[bool]: """ - Check if commit-reveal mechanism is enabled for a given network at a specific block. + Check if a commit-reveal mechanism is enabled for a given network at a specific block. Arguments: netuid: The network identifier for which to check the commit-reveal mechanism. @@ -2368,6 +2375,7 @@ def set_reveal_commitment( data: str, blocks_until_reveal: int = 360, block_time: Union[int, float] = 12, + period: Optional[int] = None, ) -> tuple[bool, int]: """ Commits arbitrary data to the Bittensor network by publishing metadata. @@ -2377,9 +2385,11 @@ def set_reveal_commitment( netuid (int): The unique identifier of the subnetwork. data (str): The data to be committed to the network. blocks_until_reveal (int): The number of blocks from now after which the data will be revealed. Defaults to `360`. - Then amount of blocks in one epoch. + Then number of blocks in one epoch. block_time (Union[int, float]): The number of seconds between each block. Defaults to `12`. - + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: `True` if the commitment was successful, `False` otherwise. @@ -2399,6 +2409,7 @@ def set_reveal_commitment( netuid=netuid, data_type=f"TimelockEncrypted", data=data_, + period=period, ), reveal_round def subnet(self, netuid: int, block: Optional[int] = None) -> Optional[DynamicInfo]: @@ -3366,6 +3377,7 @@ def serve_axon( wait_for_inclusion: bool = False, wait_for_finalization: bool = True, certificate: Optional[Certificate] = None, + period: Optional[int] = None, ) -> bool: """ Registers an ``Axon`` serving endpoint on the Bittensor network for a specific neuron. This function is used to @@ -3379,6 +3391,9 @@ def serve_axon( ``True``. certificate (bittensor.utils.Certificate): Certificate to use for TLS. If ``None``, no TLS will be used. Defaults to ``None``. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: ``True`` if the Axon serve registration is successful, False otherwise. @@ -3393,6 +3408,7 @@ def serve_axon( wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, certificate=certificate, + period=period, ) def start_call( @@ -3464,7 +3480,6 @@ def swap_stake( the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. - Returns: success (bool): True if the extrinsic was successful. From e5d2264cc83b46d406522f23ede67245816d5c1e Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 18:31:43 -0700 Subject: [PATCH 046/100] fix tests --- tests/unit_tests/extrinsics/test_serving.py | 15 ++----- tests/unit_tests/test_subtensor.py | 48 +++++++++------------ 2 files changed, 23 insertions(+), 40 deletions(-) diff --git a/tests/unit_tests/extrinsics/test_serving.py b/tests/unit_tests/extrinsics/test_serving.py index 8fd01ef6ef..027199ca81 100644 --- a/tests/unit_tests/extrinsics/test_serving.py +++ b/tests/unit_tests/extrinsics/test_serving.py @@ -321,7 +321,7 @@ def test_serve_axon_extrinsic( 1, "Sha256", b"mock_bytes_data", - True, + (True, ""), True, "happy-path-wait", ), @@ -331,7 +331,7 @@ def test_serve_axon_extrinsic( 1, "Sha256", b"mock_bytes_data", - True, + (True, ""), True, "happy-path-no-wait", ), @@ -353,16 +353,7 @@ def test_publish_metadata( # Arrange with ( patch.object(mock_subtensor.substrate, "compose_call"), - patch.object(mock_subtensor.substrate, "create_signed_extrinsic"), - patch.object( - mock_subtensor.substrate, - "submit_extrinsic", - return_value=MagicMock( - is_success=response_success, - process_events=MagicMock(), - error_message="error", - ), - ), + patch.object(mock_subtensor, "sign_and_send_extrinsic", return_value=response_success), ): # Act result = serving.publish_metadata( diff --git a/tests/unit_tests/test_subtensor.py b/tests/unit_tests/test_subtensor.py index 9160ae4c2a..1eba075158 100644 --- a/tests/unit_tests/test_subtensor.py +++ b/tests/unit_tests/test_subtensor.py @@ -1234,6 +1234,7 @@ def test_serve_axon(subtensor, mocker): wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, certificate=fake_certificate, + period=None, ) assert result == mocked_serve_axon_extrinsic.return_value @@ -1252,7 +1253,7 @@ def test_get_block_hash(subtensor, mocker): def test_commit(subtensor, fake_wallet, mocker): - """Test successful commit call.""" + """Test a successful commit call.""" # Preps fake_netuid = 1 fake_data = "some data to network" @@ -1268,6 +1269,7 @@ def test_commit(subtensor, fake_wallet, mocker): netuid=fake_netuid, data_type=f"Raw{len(fake_data)}", data=fake_data.encode(), + period=None ) assert result is mocked_publish_metadata.return_value @@ -1466,7 +1468,7 @@ def test_do_serve_axon_is_success( fake_wait_for_inclusion = True fake_wait_for_finalization = True - subtensor.substrate.submit_extrinsic.return_value.is_success = True + mocker.patch.object(subtensor, "sign_and_send_extrinsic", return_value=(True, "")) # Call result = do_serve_axon( @@ -1484,20 +1486,16 @@ def test_do_serve_axon_is_success( call_params=fake_call_params, ) - subtensor.substrate.create_signed_extrinsic.assert_called_once_with( + subtensor.sign_and_send_extrinsic.assert_called_once_with( call=subtensor.substrate.compose_call.return_value, - keypair=fake_wallet.hotkey, - ) - - subtensor.substrate.submit_extrinsic.assert_called_once_with( - extrinsic=subtensor.substrate.create_signed_extrinsic.return_value, + wallet=fake_wallet, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, + period=None ) - # subtensor.substrate.submit_extrinsic.return_value.process_events.assert_called_once() assert result[0] is True - assert result[1] is None + assert result[1] is "" def test_do_serve_axon_is_not_success(subtensor, fake_wallet, mocker, fake_call_params): @@ -1506,7 +1504,7 @@ def test_do_serve_axon_is_not_success(subtensor, fake_wallet, mocker, fake_call_ fake_wait_for_inclusion = True fake_wait_for_finalization = True - subtensor.substrate.submit_extrinsic.return_value.is_success = None + mocker.patch.object(subtensor, "sign_and_send_extrinsic", return_value=(False, None)) # Call result = do_serve_axon( @@ -1524,21 +1522,15 @@ def test_do_serve_axon_is_not_success(subtensor, fake_wallet, mocker, fake_call_ call_params=fake_call_params, ) - subtensor.substrate.create_signed_extrinsic.assert_called_once_with( + subtensor.sign_and_send_extrinsic.assert_called_once_with( call=subtensor.substrate.compose_call.return_value, - keypair=fake_wallet.hotkey, - ) - - subtensor.substrate.submit_extrinsic.assert_called_once_with( - extrinsic=subtensor.substrate.create_signed_extrinsic.return_value, + wallet=fake_wallet, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, + period=None ) - assert result == ( - False, - subtensor.substrate.submit_extrinsic.return_value.error_message, - ) + assert result == (False, None) def test_do_serve_axon_no_waits(subtensor, fake_wallet, mocker, fake_call_params): @@ -1547,6 +1539,9 @@ def test_do_serve_axon_no_waits(subtensor, fake_wallet, mocker, fake_call_params fake_wait_for_inclusion = False fake_wait_for_finalization = False + mocked_sign_and_send_extrinsic = mocker.Mock(return_value=(True, "")) + mocker.patch.object(subtensor, "sign_and_send_extrinsic", new=mocked_sign_and_send_extrinsic) + # Call result = do_serve_axon( subtensor=subtensor, @@ -1563,17 +1558,14 @@ def test_do_serve_axon_no_waits(subtensor, fake_wallet, mocker, fake_call_params call_params=fake_call_params, ) - subtensor.substrate.create_signed_extrinsic.assert_called_once_with( + mocked_sign_and_send_extrinsic.assert_called_once_with( call=subtensor.substrate.compose_call.return_value, - keypair=fake_wallet.hotkey, - ) - - subtensor.substrate.submit_extrinsic.assert_called_once_with( - extrinsic=subtensor.substrate.create_signed_extrinsic.return_value, + wallet=fake_wallet, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, + period=None ) - assert result == (True, None) + assert result == (True, "") def test_immunity_period(subtensor, mocker): From a36ecb16013521aa9479c3e23a04995addd1093f Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 20:45:24 -0700 Subject: [PATCH 047/100] update `bittensor/core/extrinsics/asyncex/weights.py` --- bittensor/core/extrinsics/asyncex/weights.py | 34 ++++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/weights.py b/bittensor/core/extrinsics/asyncex/weights.py index ef5cbfdba9..37693927a1 100644 --- a/bittensor/core/extrinsics/asyncex/weights.py +++ b/bittensor/core/extrinsics/asyncex/weights.py @@ -250,7 +250,7 @@ async def _do_set_weights( version_key: int = version_as_int, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, - period: int = 5, + period: Optional[int] = None, ) -> tuple[bool, str]: # (success, error_message) """ Internal method to send a transaction to the Bittensor blockchain, setting weights for specified neurons. This @@ -265,7 +265,9 @@ async def _do_set_weights( version_key (int, optional): Version key for compatibility with the network. wait_for_inclusion (bool, optional): Waits for the transaction to be included in a block. wait_for_finalization (bool, optional): Waits for the transaction to be finalized on the blockchain. - period (int, optional): The period in seconds to wait for extrinsic inclusion or finalization. Defaults to 5. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: @@ -285,7 +287,7 @@ async def _do_set_weights( "version_key": version_key, }, ) - return await subtensor.sign_and_send_extrinsic( + success, message = await subtensor.sign_and_send_extrinsic( call, wallet, wait_for_inclusion, @@ -296,6 +298,14 @@ async def _do_set_weights( sign_with="hotkey", ) + # We only wait here if we expect finalization. + if not wait_for_finalization and not wait_for_inclusion: + return True, "Not waiting for finalization or inclusion." + + if success: + return success, "Successfully set weights." + return success, message + async def set_weights_extrinsic( subtensor: "AsyncSubtensor", @@ -306,7 +316,7 @@ async def set_weights_extrinsic( version_key: int = 0, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, - period: int = 5, + period: Optional[int] = 8, ) -> tuple[bool, str]: """Sets the given weights and values on a chain for a wallet hotkey account. @@ -322,7 +332,9 @@ async def set_weights_extrinsic( returns ``False`` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. - period (int, optional): The period in seconds to wait for extrinsic inclusion or finalization. Defaults to 5. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: @@ -332,10 +344,12 @@ async def set_weights_extrinsic( weight_uids, weight_vals = convert_and_normalize_weights_and_uids(uids, weights) logging.info( - f":satellite: [magenta]Setting weights on [/magenta][blue]{subtensor.network}[/blue] [magenta]...[/magenta]" + f":satellite: [magenta]Setting weights on [/magenta]" + f"[blue]{subtensor.network}[/blue] " + f"[magenta]...[/magenta]" ) try: - success, error_message = await _do_set_weights( + success, message = await _do_set_weights( subtensor=subtensor, wallet=wallet, netuid=netuid, @@ -348,15 +362,15 @@ async def set_weights_extrinsic( ) if not wait_for_finalization and not wait_for_inclusion: - return True, "Not waiting for finalization or inclusion." + return True, message if success is True: message = "Successfully set weights and Finalized." logging.success(f":white_heavy_check_mark: [green]{message}[/green]") return True, message - logging.error(f"[red]Failed[/red] set weights. Error: {error_message}") - return False, error_message + logging.error(f"[red]Failed[/red] set weights. Error: {message}") + return False, message except Exception as error: logging.error(f":cross_mark: [red]Failed[/red] set weights. Error: {error}") From a2418b1a02968dc58709ec9ada3db9f348ac6087 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 20:45:40 -0700 Subject: [PATCH 048/100] update `bittensor/core/extrinsics/set_weights.py` --- bittensor/core/extrinsics/set_weights.py | 59 +++++++++++------------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/bittensor/core/extrinsics/set_weights.py b/bittensor/core/extrinsics/set_weights.py index 90f4cff32d..6b30b78c5d 100644 --- a/bittensor/core/extrinsics/set_weights.py +++ b/bittensor/core/extrinsics/set_weights.py @@ -8,7 +8,7 @@ from bittensor.core.settings import version_as_int from bittensor.utils import format_error_message from bittensor.utils.btlogging import logging -from bittensor.utils.weight_utils import convert_and_normalize_weights_and_uids +from bittensor.utils.weight_utils import convert_and_normalize_weights_and_uids, convert_netuids_and_weights if TYPE_CHECKING: from bittensor.core.subtensor import Subtensor @@ -25,8 +25,8 @@ def _do_set_weights( version_key: int = version_as_int, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, - period: int = 5, -) -> tuple[bool, Optional[str]]: # (success, error_message) + period: Optional[int] = None, +) -> tuple[bool, str]: """ Internal method to send a transaction to the Bittensor blockchain, setting weights for specified neurons. This method constructs and submits the transaction, handling @@ -41,10 +41,12 @@ def _do_set_weights( version_key (int, optional): Version key for compatibility with the network. wait_for_inclusion (bool, optional): Waits for the transaction to be included in a block. wait_for_finalization (bool, optional): Waits for the transaction to be finalized on the blockchain. - period (int, optional): The period in seconds to wait for extrinsic inclusion or finalization. Defaults to 5. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: - Tuple[bool, Optional[str]]: A tuple containing a success flag and an optional error message. + Tuple[bool, str]: A tuple containing a success flag and an optional error message. This method is vital for the dynamic weighting mechanism in Bittensor, where neurons adjust their trust in other neurons based on observed performance and contributions. @@ -60,27 +62,17 @@ def _do_set_weights( "version_key": version_key, }, ) - next_nonce = subtensor.substrate.get_account_next_index(wallet.hotkey.ss58_address) - # Period dictates how long the extrinsic will stay as part of the waiting pool - extrinsic = subtensor.substrate.create_signed_extrinsic( + success, message = subtensor.sign_and_send_extrinsic( call=call, - keypair=wallet.hotkey, - era={"period": period}, - nonce=next_nonce, - ) - response = subtensor.substrate.submit_extrinsic( - extrinsic=extrinsic, + wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, + use_nonce=True, + nonce_key="hotkey", + sign_with="hotkey", ) - # We only wait here if we expect finalization. - if not wait_for_finalization and not wait_for_inclusion: - return True, "Not waiting for finalization or inclusion." - - if response.is_success: - return True, "Successfully set weights." - - return False, format_error_message(response.error_message) + return success, message def set_weights_extrinsic( @@ -92,7 +84,7 @@ def set_weights_extrinsic( version_key: int = 0, wait_for_inclusion: bool = False, wait_for_finalization: bool = False, - period: int = 5, + period: Optional[int] = 8, ) -> tuple[bool, str]: """Sets the given weights and values on a chain for a wallet hotkey account. @@ -108,26 +100,27 @@ def set_weights_extrinsic( returns ``False`` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. - period (int, optional): The period in seconds to wait for extrinsic inclusion or finalization. Defaults to 5. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. If we did not wait for finalization / inclusion, the response is ``True``. """ # Convert types. - if isinstance(uids, list): - uids = np.array(uids, dtype=np.int64) - if isinstance(weights, list): - weights = np.array(weights, dtype=np.float32) + uids, weights = convert_netuids_and_weights(uids, weights) # Reformat and normalize. weight_uids, weight_vals = convert_and_normalize_weights_and_uids(uids, weights) logging.info( - f":satellite: [magenta]Setting weights on [/magenta][blue]{subtensor.network}[/blue] [magenta]...[/magenta]" + f":satellite: [magenta]Setting weights on [/magenta]" + f"[blue]{subtensor.network}[/blue] " + f"[magenta]...[/magenta]" ) try: - success, error_message = _do_set_weights( + success, message = _do_set_weights( subtensor=subtensor, wallet=wallet, netuid=netuid, @@ -140,15 +133,15 @@ def set_weights_extrinsic( ) if not wait_for_finalization and not wait_for_inclusion: - return True, "Not waiting for finalization or inclusion." + return True, message if success is True: message = "Successfully set weights and Finalized." logging.success(f":white_heavy_check_mark: [green]{message}[/green]") return True, message - logging.error(f"[red]Failed[/red] set weights. Error: {error_message}") - return False, error_message + logging.error(f"[red]Failed[/red] set weights. Error: {message}") + return False, message except Exception as error: logging.error(f":cross_mark: [red]Failed[/red] set weights. Error: {error}") From cc5344ca6d49ab4162476447777636335d69596c Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 21:07:23 -0700 Subject: [PATCH 049/100] rename `convert_uids_and_weights` --- bittensor/core/extrinsics/asyncex/root.py | 6 ++--- bittensor/core/extrinsics/root.py | 4 ++-- bittensor/core/extrinsics/set_weights.py | 5 ++--- bittensor/utils/weight_utils.py | 27 +++++++++-------------- 4 files changed, 17 insertions(+), 25 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/root.py b/bittensor/core/extrinsics/asyncex/root.py index 0170da5236..852f004daf 100644 --- a/bittensor/core/extrinsics/asyncex/root.py +++ b/bittensor/core/extrinsics/asyncex/root.py @@ -11,7 +11,7 @@ from bittensor.utils.weight_utils import ( normalize_max_weight, convert_weights_and_uids_for_emit, - convert_netuids_and_weights + convert_uids_and_weights ) if TYPE_CHECKING: @@ -208,7 +208,7 @@ async def _do_set_root_weights( # We only wait here if we expect finalization. if not wait_for_finalization and not wait_for_inclusion: - return True, "Not waiting for finalization or inclusion." + return True, message if success: return True, "Successfully set weights." @@ -260,7 +260,7 @@ async def set_root_weights_extrinsic( return False # Convert types. - netuids, weights = convert_netuids_and_weights(netuids, weights) + netuids, weights = convert_uids_and_weights(netuids, weights) logging.debug("[magenta]Fetching weight limits ...[/magenta]") min_allowed_weights, max_weight_limit = await _get_limits(subtensor) diff --git a/bittensor/core/extrinsics/root.py b/bittensor/core/extrinsics/root.py index 7272eae296..cc944a7c62 100644 --- a/bittensor/core/extrinsics/root.py +++ b/bittensor/core/extrinsics/root.py @@ -16,7 +16,7 @@ from bittensor.utils.weight_utils import ( normalize_max_weight, convert_weights_and_uids_for_emit, - convert_netuids_and_weights + convert_uids_and_weights ) if TYPE_CHECKING: @@ -261,7 +261,7 @@ def set_root_weights_extrinsic( return False # Convert types. - netuids, weights = convert_netuids_and_weights(netuids, weights) + netuids, weights = convert_uids_and_weights(netuids, weights) logging.debug("[magenta]Fetching weight limits ...[/magenta]") min_allowed_weights, max_weight_limit = _get_limits(subtensor) diff --git a/bittensor/core/extrinsics/set_weights.py b/bittensor/core/extrinsics/set_weights.py index 6b30b78c5d..eea4ddbb0e 100644 --- a/bittensor/core/extrinsics/set_weights.py +++ b/bittensor/core/extrinsics/set_weights.py @@ -6,9 +6,8 @@ from numpy.typing import NDArray from bittensor.core.settings import version_as_int -from bittensor.utils import format_error_message from bittensor.utils.btlogging import logging -from bittensor.utils.weight_utils import convert_and_normalize_weights_and_uids, convert_netuids_and_weights +from bittensor.utils.weight_utils import convert_and_normalize_weights_and_uids, convert_uids_and_weights if TYPE_CHECKING: from bittensor.core.subtensor import Subtensor @@ -109,7 +108,7 @@ def set_weights_extrinsic( finalization / inclusion, the response is ``True``. """ # Convert types. - uids, weights = convert_netuids_and_weights(uids, weights) + uids, weights = convert_uids_and_weights(uids, weights) # Reformat and normalize. weight_uids, weight_vals = convert_and_normalize_weights_and_uids(uids, weights) diff --git a/bittensor/utils/weight_utils.py b/bittensor/utils/weight_utils.py index 4939b7bb4e..3a24f5fcc2 100644 --- a/bittensor/utils/weight_utils.py +++ b/bittensor/utils/weight_utils.py @@ -442,29 +442,29 @@ def generate_weight_hash( return commit_hash -def convert_netuids_and_weights( - netuids: Union[NDArray[np.int64], list], +def convert_uids_and_weights( + uids: Union[NDArray[np.int64], list], weights: Union[NDArray[np.float32], list], ) -> tuple[np.ndarray, np.ndarray]: """Converts netuids and weights to numpy arrays if they are not already. Arguments: - netuids (Union[NDArray[np.int64], list]): The uint64 uids of destination neurons. + uids (Union[NDArray[np.int64], list]): The uint64 uids of destination neurons. weights (Union[NDArray[np.float32], list]): The weights to set. These must be floated. Returns: tuple[ndarray, ndarray]: Bytes converted netuids and weights. """ - if isinstance(netuids, list): - netuids = np.array(netuids, dtype=np.int64) + if isinstance(uids, list): + uids = np.array(uids, dtype=np.int64) if isinstance(weights, list): weights = np.array(weights, dtype=np.float32) - return netuids, weights + return uids, weights def convert_and_normalize_weights_and_uids( - uids: Union[NDArray[np.int64], "torch.LongTensor", list], - weights: Union[NDArray[np.float32], "torch.FloatTensor", list], + uids: Union[NDArray[np.int64], "torch.LongTensor", list], + weights: Union[NDArray[np.float32], "torch.FloatTensor", list], ) -> tuple[list[int], list[int]]: """Converts weights and uids to numpy arrays if they are not already. @@ -476,13 +476,6 @@ def convert_and_normalize_weights_and_uids( Returns: weight_uids, weight_vals: Bytes converted weights and uids """ - if isinstance(uids, list): - uids = np.array(uids, dtype=np.int64) - if isinstance(weights, list): - weights = np.array(weights, dtype=np.float32) - # Reformat and normalize. - weight_uids, weight_vals = convert_weights_and_uids_for_emit( - uids, weights - ) - return weight_uids, weight_vals + # Reformat and normalize and return + return convert_weights_and_uids_for_emit(*convert_uids_and_weights(uids, weights)) From ca92a81f52cda9bb5becb93e27ddaa65d699d105 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 21:07:51 -0700 Subject: [PATCH 050/100] refactoring --- bittensor/core/extrinsics/asyncex/registration.py | 8 ++++---- bittensor/core/extrinsics/commit_reveal.py | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/registration.py b/bittensor/core/extrinsics/asyncex/registration.py index 0d5cff1692..54da2f3a9a 100644 --- a/bittensor/core/extrinsics/asyncex/registration.py +++ b/bittensor/core/extrinsics/asyncex/registration.py @@ -522,7 +522,7 @@ async def set_subnet_identity_extrinsic( }, ) - success, error_message = await subtensor.sign_and_send_extrinsic( + success, message = await subtensor.sign_and_send_extrinsic( call=call, wallet=wallet, wait_for_inclusion=wait_for_inclusion, @@ -531,7 +531,7 @@ async def set_subnet_identity_extrinsic( ) if not wait_for_finalization and not wait_for_inclusion: - return True, f"Identities for subnet {netuid} are sent to the chain." + return True, message if success: logging.success( @@ -540,6 +540,6 @@ async def set_subnet_identity_extrinsic( return True, f"Identities for subnet {netuid} are set." logging.error( - f":cross_mark: Failed to set identity for subnet [blue]{netuid}[/blue]: {error_message}" + f":cross_mark: Failed to set identity for subnet [blue]{netuid}[/blue]: {message}" ) - return False, f"Failed to set identity for subnet {netuid}: {error_message}" + return False, f"Failed to set identity for subnet {netuid}: {message}" diff --git a/bittensor/core/extrinsics/commit_reveal.py b/bittensor/core/extrinsics/commit_reveal.py index ed7e57fc4f..532e1dba83 100644 --- a/bittensor/core/extrinsics/commit_reveal.py +++ b/bittensor/core/extrinsics/commit_reveal.py @@ -25,7 +25,7 @@ def _do_commit_reveal_v3( wait_for_inclusion: bool = False, wait_for_finalization: bool = False, period: Optional[int] = None, -) -> tuple[bool, Optional[str]]: +) -> tuple[bool, str]: """ Executes commit-reveal phase 3 for a given netuid and commit, and optionally waits for extrinsic inclusion or finalization. @@ -43,8 +43,8 @@ def _do_commit_reveal_v3( You can think of it as an expiration date for the transaction. Returns: - A tuple where the first element is a boolean indicating success or failure, and the second element is an - optional string containing an error message if any. + A tuple where the first element is a boolean indicating success or failure, and the second element is a string + containing an error message if any. """ logging.info( f"Committing weights hash [blue]{commit.hex()}[/blue] for subnet #[blue]{netuid}[/blue] with " From 3ee11a6e94f2391666518edb4577cede4c13d997 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 21:08:09 -0700 Subject: [PATCH 051/100] improve `sign_and_send_extrinsic` calls --- bittensor/core/async_subtensor.py | 4 +++- bittensor/core/subtensor.py | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index 451706fd1f..e0749df2a5 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -3279,7 +3279,9 @@ async def sign_and_send_extrinsic( ) # We only wait here if we expect finalization. if not wait_for_finalization and not wait_for_inclusion: - return True, "" + message = "Not waiting for finalization or inclusion." + logging.debug(message) + return True, message if await response.is_success: return True, "" diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index ac8e1b0710..8236571bd7 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -2708,7 +2708,9 @@ def sign_and_send_extrinsic( ) # We only wait here if we expect finalization. if not wait_for_finalization and not wait_for_inclusion: - return True, "" + message = f"Not waiting for finalization or inclusion. Extrinsic: {extrinsic}" + logging.debug(message) + return True, message if response.is_success: return True, "" @@ -3276,7 +3278,7 @@ def set_weights( wait_for_finalization: bool = False, max_retries: int = 5, block_time: float = 12.0, - period: int = 16, + period: Optional[int] = 16, ) -> tuple[bool, str]: """ Sets the inter-neuronal weights for the specified neuron. This process involves specifying the influence or From f34befd4f10adff477e397f3d58cae2153f0c1d8 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 21:08:15 -0700 Subject: [PATCH 052/100] fix tests --- .../extrinsics/asyncex/test_commit_reveal.py | 2 +- .../extrinsics/asyncex/test_registration.py | 2 +- .../extrinsics/asyncex/test_weights.py | 22 +++-- .../extrinsics/test_commit_reveal.py | 18 ++-- .../unit_tests/extrinsics/test_set_weights.py | 88 ++++--------------- tests/unit_tests/test_async_subtensor.py | 2 +- 6 files changed, 42 insertions(+), 92 deletions(-) diff --git a/tests/unit_tests/extrinsics/asyncex/test_commit_reveal.py b/tests/unit_tests/extrinsics/asyncex/test_commit_reveal.py index 2b0b1f596d..a81f540f2b 100644 --- a/tests/unit_tests/extrinsics/asyncex/test_commit_reveal.py +++ b/tests/unit_tests/extrinsics/asyncex/test_commit_reveal.py @@ -82,7 +82,7 @@ async def test_do_commit_reveal_v3_success(mocker, subtensor, fake_wallet): wait_for_inclusion=False, wait_for_finalization=False, ) - assert result == (True, "") + assert result == (True, "Not waiting for finalization or inclusion.") @pytest.mark.asyncio diff --git a/tests/unit_tests/extrinsics/asyncex/test_registration.py b/tests/unit_tests/extrinsics/asyncex/test_registration.py index 66d1c667f0..322c132045 100644 --- a/tests/unit_tests/extrinsics/asyncex/test_registration.py +++ b/tests/unit_tests/extrinsics/asyncex/test_registration.py @@ -185,7 +185,7 @@ async def test_do_pow_register_no_waiting(subtensor, fake_wallet, mocker): fake_extrinsic, wait_for_inclusion=False, wait_for_finalization=False ) assert result is True - assert error_message == "" + assert error_message == "Not waiting for finalization or inclusion." @pytest.mark.asyncio diff --git a/tests/unit_tests/extrinsics/asyncex/test_weights.py b/tests/unit_tests/extrinsics/asyncex/test_weights.py index e02f006e9b..ef6900f62f 100644 --- a/tests/unit_tests/extrinsics/asyncex/test_weights.py +++ b/tests/unit_tests/extrinsics/asyncex/test_weights.py @@ -43,7 +43,7 @@ async def fake_is_success(): # Asserts assert result is True - assert message == "" + assert message == "Successfully set weights." @pytest.mark.asyncio @@ -131,7 +131,7 @@ async def test_do_set_weights_no_waiting(subtensor, fake_wallet, mocker): # Asserts assert result is True - assert message == "" + assert message == "Not waiting for finalization or inclusion." @pytest.mark.asyncio @@ -141,12 +141,14 @@ async def test_set_weights_extrinsic_success_with_finalization( """Tests set_weights_extrinsic when weights are successfully set with finalization.""" # Preps fake_netuid = 1 - fake_uids = [1, 2, 3] - fake_weights = [0.1, 0.2, 0.7] + fake_uids = mocker.Mock() + fake_weights = mocker.Mock() mocked_do_set_weights = mocker.patch.object( async_weights, "_do_set_weights", return_value=(True, "") ) + mocker_converter = mocker.patch.object(async_weights, "convert_and_normalize_weights_and_uids") + mocker_converter.return_value = (mocker.Mock(), mocker.Mock()) # Call result, message = await async_weights.set_weights_extrinsic( @@ -160,16 +162,18 @@ async def test_set_weights_extrinsic_success_with_finalization( ) # Asserts + mocker_converter.assert_called_once_with(fake_uids, fake_weights) + mocked_do_set_weights.assert_called_once_with( subtensor=subtensor, wallet=fake_wallet, netuid=fake_netuid, - uids=mocker.ANY, - vals=mocker.ANY, + uids=mocker_converter.return_value[0], + vals=mocker_converter.return_value[1], version_key=0, wait_for_finalization=True, wait_for_inclusion=True, - period=5, + period=8, ) assert result is True assert message == "Successfully set weights and Finalized." @@ -184,7 +188,7 @@ async def test_set_weights_extrinsic_no_waiting(subtensor, fake_wallet, mocker): fake_weights = [0.1, 0.2, 0.7] mocked_do_set_weights = mocker.patch.object( - async_weights, "_do_set_weights", return_value=(True, "") + async_weights, "_do_set_weights", return_value=(True, "Not waiting for finalization or inclusion.") ) # Call @@ -380,7 +384,7 @@ async def test_do_commit_weights_no_waiting(subtensor, fake_wallet, mocker): # Asserts assert result is True - assert message == "" + assert message == "Not waiting for finalization or inclusion." @pytest.mark.asyncio diff --git a/tests/unit_tests/extrinsics/test_commit_reveal.py b/tests/unit_tests/extrinsics/test_commit_reveal.py index e254e88a0f..3891b97dae 100644 --- a/tests/unit_tests/extrinsics/test_commit_reveal.py +++ b/tests/unit_tests/extrinsics/test_commit_reveal.py @@ -48,11 +48,8 @@ def test_do_commit_reveal_v3_success(mocker, subtensor, fake_wallet): fake_reveal_round = 1 mocked_compose_call = mocker.patch.object(subtensor.substrate, "compose_call") - mocked_create_signed_extrinsic = mocker.patch.object( - subtensor.substrate, "create_signed_extrinsic" - ) - mocked_submit_extrinsic = mocker.patch.object( - subtensor.substrate, "submit_extrinsic" + mocked_sign_and_send_extrinsic = mocker.patch.object( + subtensor, "sign_and_send_extrinsic", return_value=(True, "") ) # Call @@ -74,14 +71,15 @@ def test_do_commit_reveal_v3_success(mocker, subtensor, fake_wallet): "reveal_round": fake_reveal_round, }, ) - mocked_create_signed_extrinsic.assert_called_once_with( - call=mocked_compose_call.return_value, keypair=fake_wallet.hotkey - ) - mocked_submit_extrinsic.assert_called_once_with( - mocked_create_signed_extrinsic.return_value, + mocked_sign_and_send_extrinsic.assert_called_once_with( + call=mocked_compose_call.return_value, + wallet=fake_wallet, wait_for_inclusion=False, wait_for_finalization=False, + sign_with="hotkey", + period=None, ) + assert result == (True, "") diff --git a/tests/unit_tests/extrinsics/test_set_weights.py b/tests/unit_tests/extrinsics/test_set_weights.py index d3ebfd71c8..645395ab8a 100644 --- a/tests/unit_tests/extrinsics/test_set_weights.py +++ b/tests/unit_tests/extrinsics/test_set_weights.py @@ -68,16 +68,16 @@ def test_set_weights_extrinsic( expected_success, expected_message, ): - uids_tensor = torch.tensor(uids, dtype=torch.int64) - weights_tensor = torch.tensor(weights, dtype=torch.float32) + # uids_tensor = torch.tensor(uids, dtype=torch.int64) + # weights_tensor = torch.tensor(weights, dtype=torch.float32) with ( patch( "bittensor.utils.weight_utils.convert_weights_and_uids_for_emit", - return_value=(uids_tensor, weights_tensor), + return_value=(uids, weights), ), patch( "bittensor.core.extrinsics.set_weights._do_set_weights", - return_value=(expected_success, "Mock error message"), + return_value=(expected_success, expected_message), ), ): result, message = set_weights_extrinsic( @@ -105,6 +105,7 @@ def test_do_set_weights_is_success(mock_subtensor, fake_wallet, mocker): fake_wait_for_finalization = True mock_subtensor.substrate.submit_extrinsic.return_value.is_success = True + mocker.patch.object(mock_subtensor, "sign_and_send_extrinsic", return_value=(True, "")) # Call result = _do_set_weights( @@ -130,68 +131,17 @@ def test_do_set_weights_is_success(mock_subtensor, fake_wallet, mocker): }, ) - mock_subtensor.substrate.create_signed_extrinsic.assert_called_once() - _, kwargs = mock_subtensor.substrate.create_signed_extrinsic.call_args - assert kwargs["call"] == mock_subtensor.substrate.compose_call.return_value - assert kwargs["keypair"] == fake_wallet.hotkey - assert kwargs["era"] == {"period": 5} - - assert result == (True, "Successfully set weights.") - - -def test_do_set_weights_is_not_success(mock_subtensor, fake_wallet, mocker): - """Unsuccessful _do_set_weights call.""" - # Prep - fake_uids = [1, 2, 3] - fake_vals = [4, 5, 6] - fake_netuid = 1 - fake_wait_for_inclusion = True - fake_wait_for_finalization = True - - mock_subtensor.substrate.submit_extrinsic.return_value.is_success = False - mocked_format_error_message = mocker.MagicMock() - subtensor_module.format_error_message = mocked_format_error_message - - # Call - result = _do_set_weights( - subtensor=mock_subtensor, + mock_subtensor.sign_and_send_extrinsic.assert_called_once_with( + call=mock_subtensor.substrate.compose_call.return_value, wallet=fake_wallet, - uids=fake_uids, - vals=fake_vals, - netuid=fake_netuid, - version_key=version_as_int, - wait_for_inclusion=fake_wait_for_inclusion, - wait_for_finalization=fake_wait_for_finalization, - ) - - # Asserts - mock_subtensor.substrate.compose_call.assert_called_once_with( - call_module="SubtensorModule", - call_function="set_weights", - call_params={ - "dests": fake_uids, - "weights": fake_vals, - "netuid": fake_netuid, - "version_key": version_as_int, - }, - ) - - mock_subtensor.substrate.create_signed_extrinsic.assert_called_once() - _, kwargs = mock_subtensor.substrate.create_signed_extrinsic.call_args - assert kwargs["call"] == mock_subtensor.substrate.compose_call.return_value - assert kwargs["keypair"] == fake_wallet.hotkey - assert kwargs["era"] == {"period": 5} - - mock_subtensor.substrate.submit_extrinsic.assert_called_once_with( - extrinsic=mock_subtensor.substrate.create_signed_extrinsic.return_value, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, + nonce_key="hotkey", + sign_with="hotkey", + use_nonce=True, + period=None ) - - assert result == ( - False, - "Subtensor returned `UnknownError(UnknownType)` error. This means: `Unknown Description`.", - ) + assert result == (True, "") def test_do_set_weights_no_waits(mock_subtensor, fake_wallet, mocker): @@ -203,6 +153,8 @@ def test_do_set_weights_no_waits(mock_subtensor, fake_wallet, mocker): fake_wait_for_inclusion = False fake_wait_for_finalization = False + mocker.patch.object(mock_subtensor, "sign_and_send_extrinsic", return_value=(True, "Not waiting for finalization or inclusion.")) + # Call result = _do_set_weights( subtensor=mock_subtensor, @@ -227,15 +179,11 @@ def test_do_set_weights_no_waits(mock_subtensor, fake_wallet, mocker): }, ) - mock_subtensor.substrate.create_signed_extrinsic.assert_called_once() - _, kwargs = mock_subtensor.substrate.create_signed_extrinsic.call_args - assert kwargs["call"] == mock_subtensor.substrate.compose_call.return_value - assert kwargs["keypair"] == fake_wallet.hotkey - assert kwargs["era"] == {"period": 5} - - mock_subtensor.substrate.submit_extrinsic.assert_called_once_with( - extrinsic=mock_subtensor.substrate.create_signed_extrinsic.return_value, + mock_subtensor.sign_and_send_extrinsic( + call=mock_subtensor.substrate.compose_call.return_value, + wallet=fake_wallet, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, + period=None ) assert result == (True, "Not waiting for finalization or inclusion.") diff --git a/tests/unit_tests/test_async_subtensor.py b/tests/unit_tests/test_async_subtensor.py index ddf5148b8c..1d84ba9470 100644 --- a/tests/unit_tests/test_async_subtensor.py +++ b/tests/unit_tests/test_async_subtensor.py @@ -1821,7 +1821,7 @@ async def test_sign_and_send_extrinsic_success_without_inclusion_finalization( wait_for_inclusion=False, wait_for_finalization=False, ) - assert result == (True, "") + assert result == (True, "Not waiting for finalization or inclusion.") @pytest.mark.asyncio From 42341a16c6014a822370399d2537c28d29a5602d Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 21:14:36 -0700 Subject: [PATCH 053/100] opps with set_weights (fixed) + tests --- bittensor/core/async_subtensor.py | 15 +++++++++------ bittensor/core/subtensor.py | 2 +- tests/unit_tests/test_async_subtensor.py | 4 ++-- tests/unit_tests/test_subtensor.py | 4 ++-- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index e0749df2a5..eb0fab0c5b 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -3994,7 +3994,7 @@ async def set_weights( wait_for_finalization: bool = False, max_retries: int = 5, block_time: float = 12.0, - period: int = 5, + period: Optional[int] = 8, ): """ Sets the inter-neuronal weights for the specified neuron. This process involves specifying the influence or @@ -4015,7 +4015,9 @@ async def set_weights( ``False``. max_retries (int): The number of maximum attempts to set weights. Default is ``5``. block_time (float): The number of seconds for block duration. Default is 12.0 seconds. - period (int, optional): The period in seconds to wait for extrinsic inclusion or finalization. Defaults to 5. + period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Default is 16. Returns: tuple[bool, str]: ``True`` if the setting of weights is successful, False otherwise. And `msg`, a string @@ -4034,6 +4036,7 @@ async def _blocks_weight_limit() -> bool: retries = 0 success = False + message = "No attempt made. Perhaps it is too soon to set weights!" if ( uid := await self.get_uid_for_hotkey_on_subnet( wallet.hotkey.ss58_address, netuid @@ -4046,7 +4049,7 @@ async def _blocks_weight_limit() -> bool: if (await self.commit_reveal_enabled(netuid=netuid)) is True: # go with `commit reveal v3` extrinsic - message = "No attempt made. Perhaps it is too soon to commit weights!" + while ( retries < max_retries and success is False @@ -4065,12 +4068,13 @@ async def _blocks_weight_limit() -> bool: wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, block_time=block_time, + period=period, ) retries += 1 return success, message else: # go with classic `set weights extrinsic` - message = "No attempt made. Perhaps it is too soon to set weights!" + while ( retries < max_retries and success is False @@ -4079,7 +4083,7 @@ async def _blocks_weight_limit() -> bool: try: logging.info( f"Setting weights for subnet #[blue]{netuid}[/blue]. " - f"Attempt [blue]{retries + 1} of {max_retries}[/blue]." + f"Attempt [blue]{retries + 1}[/blue] of [green]{max_retries}[/green]." ) success, message = await set_weights_extrinsic( subtensor=self, @@ -4094,7 +4098,6 @@ async def _blocks_weight_limit() -> bool: ) except Exception as e: logging.error(f"Error setting weights: {e}") - finally: retries += 1 return success, message diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 8236571bd7..dc57fd3059 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -3278,7 +3278,7 @@ def set_weights( wait_for_finalization: bool = False, max_retries: int = 5, block_time: float = 12.0, - period: Optional[int] = 16, + period: Optional[int] = 8, ) -> tuple[bool, str]: """ Sets the inter-neuronal weights for the specified neuron. This process involves specifying the influence or diff --git a/tests/unit_tests/test_async_subtensor.py b/tests/unit_tests/test_async_subtensor.py index 1d84ba9470..e8f4f3817f 100644 --- a/tests/unit_tests/test_async_subtensor.py +++ b/tests/unit_tests/test_async_subtensor.py @@ -2667,7 +2667,7 @@ async def test_set_delegate_take_decrease( @pytest.mark.asyncio async def test_set_weights_success(subtensor, fake_wallet, mocker): - """Tests set_weights with successful weight setting on the first try.""" + """Tests set_weights with the successful weight setting on the first try.""" # Preps fake_netuid = 1 fake_uids = [1, 2, 3] @@ -2716,7 +2716,7 @@ async def test_set_weights_success(subtensor, fake_wallet, mocker): wait_for_finalization=False, wait_for_inclusion=False, weights=fake_weights, - period=5, + period=8, ) mocked_weights_rate_limit.assert_called_once_with(fake_netuid) assert result is True diff --git a/tests/unit_tests/test_subtensor.py b/tests/unit_tests/test_subtensor.py index 1eba075158..f5de2b33ff 100644 --- a/tests/unit_tests/test_subtensor.py +++ b/tests/unit_tests/test_subtensor.py @@ -1203,7 +1203,7 @@ def test_set_weights(subtensor, mocker, fake_wallet): version_key=settings.version_as_int, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, - period=16, + period=8, ) assert result == expected_result @@ -3140,7 +3140,7 @@ def test_set_weights_with_commit_reveal_enabled(subtensor, fake_wallet, mocker): wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, block_time=12.0, - period=16, + period=8, ) assert result == mocked_commit_reveal_v3_extrinsic.return_value From 45d4bec772d5c03a30ebd69290490c187373e70f Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 21:33:34 -0700 Subject: [PATCH 054/100] refactor --- tests/e2e_tests/test_staking.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/e2e_tests/test_staking.py b/tests/e2e_tests/test_staking.py index dddd9d1af1..95d056b20b 100644 --- a/tests/e2e_tests/test_staking.py +++ b/tests/e2e_tests/test_staking.py @@ -162,8 +162,8 @@ def test_single_operation(subtensor, alice_wallet, bob_wallet): } success = subtensor.unstake( - alice_wallet, - bob_wallet.hotkey.ss58_address, + wallet=alice_wallet, + hotkey_ss58=bob_wallet.hotkey.ss58_address, netuid=alice_subnet_netuid, amount=stake_bob, wait_for_inclusion=True, @@ -173,8 +173,8 @@ def test_single_operation(subtensor, alice_wallet, bob_wallet): assert success is True stake = subtensor.get_stake( - alice_wallet.coldkey.ss58_address, - bob_wallet.hotkey.ss58_address, + coldkey_ss58=alice_wallet.coldkey.ss58_address, + hotkey_ss58=bob_wallet.hotkey.ss58_address, netuid=alice_subnet_netuid, ) From 7d508c6718e4c6d705cf467e79eca451772f5fac Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 21:53:12 -0700 Subject: [PATCH 055/100] update `bittensor/core/extrinsics/asyncex/staking.py` --- bittensor/core/extrinsics/asyncex/staking.py | 35 ++++++++++---------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/staking.py b/bittensor/core/extrinsics/asyncex/staking.py index ddaa1bd240..0dcd9345a7 100644 --- a/bittensor/core/extrinsics/asyncex/staking.py +++ b/bittensor/core/extrinsics/asyncex/staking.py @@ -1,11 +1,11 @@ import asyncio from typing import Optional, Sequence, TYPE_CHECKING - +from async_substrate_interface.errors import SubstrateRequestException from bittensor.core.errors import StakeError, NotRegisteredError +from bittensor.core.extrinsics.utils import get_old_stakes from bittensor.utils import unlock_key from bittensor.utils.balance import Balance from bittensor.utils.btlogging import logging -from bittensor.core.extrinsics.utils import get_old_stakes if TYPE_CHECKING: from bittensor_wallet import Wallet @@ -24,6 +24,7 @@ async def add_stake_extrinsic( safe_staking: bool = False, allow_partial_stake: bool = False, rate_tolerance: float = 0.005, + period: Optional[int] = None, ) -> bool: """ Adds the specified amount of stake to passed hotkey `uid`. @@ -42,10 +43,16 @@ async def add_stake_extrinsic( safe_staking: If set, uses safe staking logic allow_partial_stake: If set, allows partial stake rate_tolerance: The rate tolerance for safe staking + period: The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success: Flag is `True` if extrinsic was finalized or included in the block. If we did not wait for finalization/inclusion, the response is `True`. + + Raises: + SubstrateRequestException: Raised if the extrinsic fails to be included in the block within the timeout. """ # Decrypt keys, @@ -147,13 +154,14 @@ async def add_stake_extrinsic( call_params=call_params, ) staking_response, err_msg = await subtensor.sign_and_send_extrinsic( - call, - wallet, - wait_for_inclusion, - wait_for_finalization, + call=call, + wallet=wallet, + wait_for_inclusion=wait_for_inclusion, + wait_for_finalization=wait_for_finalization, nonce_key="coldkeypub", sign_with="coldkey", use_nonce=True, + period=period, ) if staking_response is True: # If we successfully staked. # We only wait here if we expect finalization. @@ -163,8 +171,8 @@ async def add_stake_extrinsic( logging.success(":white_heavy_check_mark: [green]Finalized[/green]") logging.info( - f":satellite: [magenta]Checking Balance on:[/magenta] [blue]{subtensor.network}[/blue] " - "[magenta]...[/magenta]" + f":satellite: [magenta]Checking Balance on:[/magenta] " + f"[blue]{subtensor.network}[/blue] [magenta]...[/magenta]" ) new_block_hash = await subtensor.substrate.get_chain_head() new_balance, new_stake = await asyncio.gather( @@ -195,15 +203,8 @@ async def add_stake_extrinsic( logging.error(f":cross_mark: [red]Failed: {err_msg}.[/red]") return False - except NotRegisteredError: - logging.error( - ":cross_mark: [red]Hotkey: {} is not registered.[/red]".format( - wallet.hotkey_str - ) - ) - return False - except StakeError as e: - logging.error(f":cross_mark: [red]Stake Error: {e}[/red]") + except SubstrateRequestException as e: + logging.error(f":cross_mark: [red]Add Stake Error: {e}[/red]") return False From 3e9db4656ec7841f73093e49acefd17388802d12 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 21:53:37 -0700 Subject: [PATCH 056/100] update `bittensor/core/extrinsics/staking.py` --- bittensor/core/extrinsics/staking.py | 43 +++++++++++++++------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/bittensor/core/extrinsics/staking.py b/bittensor/core/extrinsics/staking.py index 3a011bdf9b..288f4a39e5 100644 --- a/bittensor/core/extrinsics/staking.py +++ b/bittensor/core/extrinsics/staking.py @@ -1,5 +1,7 @@ from typing import Optional, TYPE_CHECKING, Sequence +from async_substrate_interface.errors import SubstrateRequestException + from bittensor.core.errors import StakeError, NotRegisteredError from bittensor.core.extrinsics.utils import get_old_stakes from bittensor.utils import unlock_key @@ -22,6 +24,7 @@ def add_stake_extrinsic( safe_staking: bool = False, allow_partial_stake: bool = False, rate_tolerance: float = 0.005, + period: Optional[int] = None, ) -> bool: """ Adds the specified amount of stake to passed hotkey `uid`. @@ -39,10 +42,16 @@ def add_stake_extrinsic( safe_staking (bool): If true, enables price safety checks allow_partial_stake (bool): If true, allows partial unstaking if price tolerance exceeded rate_tolerance (float): Maximum allowed price increase percentage (0.005 = 0.5%) + period: The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success: Flag is `True` if extrinsic was finalized or included in the block. If we did not wait for finalization/inclusion, the response is `True`. + + Raises: + SubstrateRequestException: Raised if the extrinsic fails to be included in the block within the timeout. """ # Decrypt keys, @@ -143,16 +152,17 @@ def add_stake_extrinsic( call_params=call_params, ) - staking_response, err_msg = subtensor.sign_and_send_extrinsic( - call, - wallet, - wait_for_inclusion, - wait_for_finalization, + success, message = subtensor.sign_and_send_extrinsic( + call=call, + wallet=wallet, + wait_for_inclusion=wait_for_inclusion, + wait_for_finalization=wait_for_finalization, use_nonce=True, sign_with="coldkey", nonce_key="coldkeypub", + period=period, ) - if staking_response is True: # If we successfully staked. + if success is True: # If we successfully staked. # We only wait here if we expect finalization. if not wait_for_finalization and not wait_for_inclusion: return True @@ -160,8 +170,8 @@ def add_stake_extrinsic( logging.success(":white_heavy_check_mark: [green]Finalized[/green]") logging.info( - f":satellite: [magenta]Checking Balance on:[/magenta] [blue]{subtensor.network}[/blue] " - "[magenta]...[/magenta]" + f":satellite: [magenta]Checking Balance on:[/magenta] " + f"[blue]{subtensor.network}[/blue] [magenta]...[/magenta]" ) new_block = subtensor.get_current_block() new_balance = subtensor.get_balance( @@ -181,24 +191,16 @@ def add_stake_extrinsic( ) return True else: - if safe_staking and "Custom error: 8" in err_msg: + if safe_staking and "Custom error: 8" in message: logging.error( ":cross_mark: [red]Failed[/red]: Price exceeded tolerance limit. Either increase price tolerance or enable partial staking." ) else: - logging.error(f":cross_mark: [red]Failed: {err_msg}.[/red]") + logging.error(f":cross_mark: [red]Failed: {message}.[/red]") return False - # TODO I don't think these are used. Maybe should just catch SubstrateRequestException? - except NotRegisteredError: - logging.error( - ":cross_mark: [red]Hotkey: {} is not registered.[/red]".format( - wallet.hotkey_str - ) - ) - return False - except StakeError as e: - logging.error(f":cross_mark: [red]Stake Error: {e}[/red]") + except SubstrateRequestException as e: + logging.error(f":cross_mark: [red]Add Stake Error: {e}[/red]") return False @@ -217,6 +219,7 @@ def add_stake_multiple_extrinsic( subtensor: The initialized SubtensorInterface object. wallet: Bittensor wallet object for the coldkey. hotkey_ss58s: List of hotkeys to stake to. + netuids: List of netuids to stake to. amounts: List of amounts to stake. If `None`, stake all to the first hotkey. wait_for_inclusion: If set, waits for the extrinsic to enter a block before returning `True`, or returns `False` if the extrinsic fails to enter the block within the timeout. From 93c051e6c39644bc515aea0ddb0052b7af016180 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 22:05:34 -0700 Subject: [PATCH 057/100] update `bittensor.core.extrinsics.staking.add_stake_multiple_extrinsic` --- bittensor/core/extrinsics/staking.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/bittensor/core/extrinsics/staking.py b/bittensor/core/extrinsics/staking.py index 288f4a39e5..8b99743c81 100644 --- a/bittensor/core/extrinsics/staking.py +++ b/bittensor/core/extrinsics/staking.py @@ -32,7 +32,7 @@ def add_stake_extrinsic( Arguments: subtensor: the Subtensor object to use wallet: Bittensor wallet object. - hotkey_ss58: The `ss58` address of the hotkey account to stake to defaults to the wallet's hotkey. + hotkey_ss58: The `ss58` address of the hotkey account to stake to default to the wallet's hotkey. netuid (Optional[int]): Subnet unique ID. amount: Amount to stake as Bittensor balance, `None` if staking all. wait_for_inclusion: If set, waits for the extrinsic to enter a block before returning `True`, or returns @@ -212,8 +212,9 @@ def add_stake_multiple_extrinsic( amounts: Optional[list[Balance]] = None, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: - """Adds stake to each ``hotkey_ss58`` in the list, using each amount, from a common coldkey. + """Adds a stake to each ``hotkey_ss58`` in the list, using each amount, from a common coldkey. Arguments: subtensor: The initialized SubtensorInterface object. @@ -225,6 +226,9 @@ def add_stake_multiple_extrinsic( if the extrinsic fails to enter the block within the timeout. wait_for_finalization: If set, waits for the extrinsic to be finalized on the chain before returning `True`, or returns `False` if the extrinsic fails to be finalized within the timeout. + period: The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success: `True` if extrinsic was finalized or included in the block. `True` if any wallet was staked. If we did @@ -330,17 +334,18 @@ def add_stake_multiple_extrinsic( "netuid": netuid, }, ) - staking_response, err_msg = subtensor.sign_and_send_extrinsic( - call, - wallet, - wait_for_inclusion, - wait_for_finalization, + success, message = subtensor.sign_and_send_extrinsic( + call=call, + wallet=wallet, + wait_for_inclusion=wait_for_inclusion, + wait_for_finalization=wait_for_finalization, use_nonce=True, nonce_key="coldkeypub", sign_with="coldkey", + period=period, ) - if staking_response is True: # If we successfully staked. + if success is True: # If we successfully staked. # We only wait here if we expect finalization. if not wait_for_finalization and not wait_for_inclusion: @@ -377,7 +382,7 @@ def add_stake_multiple_extrinsic( break else: - logging.error(f":cross_mark: [red]Failed[/red]: {err_msg}") + logging.error(f":cross_mark: [red]Failed[/red]: {message}") continue except NotRegisteredError: From 76e89078872ce5aed3b97622df9ac09148df9961 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 22:05:47 -0700 Subject: [PATCH 058/100] update `bittensor.core.extrinsics.asyncex.staking.add_stake_multiple_extrinsic` --- bittensor/core/extrinsics/asyncex/staking.py | 21 ++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/staking.py b/bittensor/core/extrinsics/asyncex/staking.py index 0dcd9345a7..f06eb8dced 100644 --- a/bittensor/core/extrinsics/asyncex/staking.py +++ b/bittensor/core/extrinsics/asyncex/staking.py @@ -217,8 +217,9 @@ async def add_stake_multiple_extrinsic( amounts: Optional[list[Balance]] = None, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: - """Adds stake to each ``hotkey_ss58`` in the list, using each amount, from a common coldkey. + """Adds a stake to each ``hotkey_ss58`` in the list, using each amount, from a common coldkey. Arguments: subtensor: The initialized SubtensorInterface object. @@ -231,6 +232,9 @@ async def add_stake_multiple_extrinsic( if the extrinsic fails to enter the block within the timeout. wait_for_finalization: If set, waits for the extrinsic to be finalized on the chain before returning `True`, or returns `False` if the extrinsic fails to be finalized within the timeout. + period: The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success: `True` if extrinsic was finalized or included in the block. `True` if any wallet was staked. If we did @@ -342,17 +346,18 @@ async def add_stake_multiple_extrinsic( "netuid": netuid, }, ) - staking_response, err_msg = await subtensor.sign_and_send_extrinsic( - call, - wallet, - wait_for_inclusion, - wait_for_finalization, + success, message = await subtensor.sign_and_send_extrinsic( + call=call, + wallet=wallet, + wait_for_inclusion=wait_for_inclusion, + wait_for_finalization=wait_for_finalization, nonce_key="coldkeypub", sign_with="coldkey", use_nonce=True, + period=period, ) - if staking_response is True: # If we successfully staked. + if success is True: # If we successfully staked. # We only wait here if we expect finalization. if not wait_for_finalization and not wait_for_inclusion: @@ -392,7 +397,7 @@ async def add_stake_multiple_extrinsic( break else: - logging.error(f":cross_mark: [red]Failed: {err_msg}.[/red]") + logging.error(f":cross_mark: [red]Failed: {message}.[/red]") continue except NotRegisteredError: From 268f95cf519abb32c3639a4894fa5e2689cc5534 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 22:06:08 -0700 Subject: [PATCH 059/100] fix tests --- tests/e2e_tests/test_staking.py | 1 + tests/unit_tests/extrinsics/test_staking.py | 26 +++++++++++---------- tests/unit_tests/test_subtensor.py | 3 +++ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/tests/e2e_tests/test_staking.py b/tests/e2e_tests/test_staking.py index 95d056b20b..3307956095 100644 --- a/tests/e2e_tests/test_staking.py +++ b/tests/e2e_tests/test_staking.py @@ -55,6 +55,7 @@ def test_single_operation(subtensor, alice_wallet, bob_wallet): amount=Balance.from_tao(1), wait_for_inclusion=True, wait_for_finalization=True, + period=16 ) assert success is True diff --git a/tests/unit_tests/extrinsics/test_staking.py b/tests/unit_tests/extrinsics/test_staking.py index 899054006f..517280d461 100644 --- a/tests/unit_tests/extrinsics/test_staking.py +++ b/tests/unit_tests/extrinsics/test_staking.py @@ -13,7 +13,7 @@ def test_add_stake_extrinsic(mocker): "sign_and_send_extrinsic.return_value": (True, ""), } ) - fake_wallet = mocker.Mock( + fake_wallet_ = mocker.Mock( **{ "coldkeypub.ss58_address": "hotkey_owner", } @@ -27,7 +27,7 @@ def test_add_stake_extrinsic(mocker): # Call result = staking.add_stake_extrinsic( subtensor=fake_subtensor, - wallet=fake_wallet, + wallet=fake_wallet_, hotkey_ss58=hotkey_ss58, netuid=fake_netuid, amount=amount, @@ -44,13 +44,14 @@ def test_add_stake_extrinsic(mocker): call_params={"hotkey": "hotkey", "amount_staked": 9, "netuid": 1}, ) fake_subtensor.sign_and_send_extrinsic.assert_called_once_with( - fake_subtensor.substrate.compose_call.return_value, - fake_wallet, - True, - True, + call=fake_subtensor.substrate.compose_call.return_value, + wallet=fake_wallet_, + wait_for_inclusion=True, + wait_for_finalization=True, nonce_key="coldkeypub", sign_with="coldkey", use_nonce=True, + period=None ) @@ -85,7 +86,7 @@ def test_add_stake_multiple_extrinsic(mocker): mocker.patch.object( staking, "get_old_stakes", return_value=[Balance(1.1), Balance(0.3)] ) - fake_wallet = mocker.Mock( + fake_wallet_ = mocker.Mock( **{ "coldkeypub.ss58_address": "hotkey_owner", } @@ -99,7 +100,7 @@ def test_add_stake_multiple_extrinsic(mocker): # Call result = staking.add_stake_multiple_extrinsic( subtensor=fake_subtensor, - wallet=fake_wallet, + wallet=fake_wallet_, hotkey_ss58s=hotkey_ss58s, netuids=netuids, amounts=amounts, @@ -131,11 +132,12 @@ def test_add_stake_multiple_extrinsic(mocker): }, ) fake_subtensor.sign_and_send_extrinsic.assert_called_with( - fake_subtensor.substrate.compose_call.return_value, - fake_wallet, - True, - True, + call=fake_subtensor.substrate.compose_call.return_value, + wallet=fake_wallet_, + wait_for_inclusion=True, + wait_for_finalization=True, nonce_key="coldkeypub", sign_with="coldkey", use_nonce=True, + period=None ) diff --git a/tests/unit_tests/test_subtensor.py b/tests/unit_tests/test_subtensor.py index f5de2b33ff..fbd67014a2 100644 --- a/tests/unit_tests/test_subtensor.py +++ b/tests/unit_tests/test_subtensor.py @@ -2826,6 +2826,7 @@ def test_add_stake_success(mocker, fake_wallet, subtensor): safe_staking=False, allow_partial_stake=False, rate_tolerance=0.005, + period=None, ) assert result == mock_add_stake_extrinsic.return_value @@ -2865,6 +2866,7 @@ def test_add_stake_with_safe_staking(mocker, fake_wallet, subtensor): safe_staking=True, allow_partial_stake=False, rate_tolerance=fake_rate_tolerance, + period=None, ) assert result == mock_add_stake_extrinsic.return_value @@ -2898,6 +2900,7 @@ def test_add_stake_multiple_success(mocker, fake_wallet, subtensor): amounts=fake_amount, wait_for_inclusion=True, wait_for_finalization=False, + period=None, ) assert result == mock_add_stake_multiple_extrinsic.return_value From 6a872d3b64c0e2f2cc8f83147c77ef26429d7d51 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 22:06:27 -0700 Subject: [PATCH 060/100] update subtensor calls --- bittensor/core/async_subtensor.py | 40 +++++++++++++--------- bittensor/core/subtensor.py | 57 +++++++++++++++++++------------ 2 files changed, 59 insertions(+), 38 deletions(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index eb0fab0c5b..b9442daa4d 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -661,7 +661,7 @@ async def commit(self, wallet: "Wallet", netuid: int, data: str, period: Optiona wallet (bittensor_wallet.Wallet): The wallet associated with the neuron committing the data. netuid (int): The unique identifier of the subnetwork. data (str): The data to be committed to the network. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -2868,7 +2868,7 @@ async def set_reveal_commitment( blocks_until_reveal (int): The number of blocks from now after which the data will be revealed. Defaults to `360`. The number of blocks in one epoch. block_time (Union[int, float]): The number of seconds between each block. Defaults to `12`. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -3241,7 +3241,7 @@ async def sign_and_send_extrinsic( wait_for_finalization (bool): whether to wait until the extrinsic call is finalized on the chain sign_with: the wallet's keypair to use for the signing. Options are "coldkey", "hotkey", "coldkeypub" use_nonce: unique identifier for the transaction related with hot/coldkey. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. nonce_key: the type on nonce to use. Options are "hotkey" or "coldkey". @@ -3250,6 +3250,9 @@ async def sign_and_send_extrinsic( Returns: (success, error message) + + Raises: + SubstrateRequestException: Substrate request exception. """ possible_keys = ("coldkey", "hotkey", "coldkeypub") if sign_with not in possible_keys: @@ -3310,6 +3313,7 @@ async def add_stake( safe_staking: bool = False, allow_partial_stake: bool = False, rate_tolerance: float = 0.005, + period: Optional[int] = None, ) -> bool: """ Adds the specified amount of stake to a neuron identified by the hotkey ``SS58`` address. @@ -3330,6 +3334,9 @@ async def add_stake( exceed the threshold. Default is False. rate_tolerance (float): The maximum allowed price change ratio when staking. For example, 0.005 = 0.5% maximum price increase. Only used when safe_staking is True. Default is 0.005. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's + submitted. If the transaction is not included in a block within that number of blocks, it will expire + and be rejected. You can think of it as an expiration date for the transaction. Returns: bool: ``True`` if the staking is successful, False otherwise. @@ -3350,6 +3357,7 @@ async def add_stake( safe_staking=safe_staking, allow_partial_stake=allow_partial_stake, rate_tolerance=rate_tolerance, + period=period, ) async def add_stake_multiple( @@ -3408,10 +3416,10 @@ async def burned_register( `False`. wait_for_finalization (bool, optional): Waits for the transaction to be finalized on the blockchain. Defaults to `True`. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -3466,7 +3474,7 @@ async def commit_weights( wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``. max_retries (int): The number of maximum attempts to commit weights. Default is ``5``. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -3541,7 +3549,7 @@ async def move_stake( amount (Balance): Amount of stake to move. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -3599,7 +3607,7 @@ async def register( num_processes (Optional[int]): The number of processes to use to register. Default to `None`. update_interval (Optional[int]): The number of nonces to solve between updates. Default to `None`. log_verbose (bool): If ``true``, the registration process will log more information. Default to `False`. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -3642,7 +3650,7 @@ async def register_subnet( false if the extrinsic fails to enter the block within the timeout. Default is False. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning true, or returns false if the extrinsic fails to be finalized within the timeout. Default is True. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -3735,7 +3743,7 @@ async def root_register( wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``False``. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -3773,7 +3781,7 @@ async def root_set_weights( ``False``. wait_for_finalization (bool, optional): Waits for the transaction to be finalized on the blockchain. Defaults to ``False``. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -3959,7 +3967,7 @@ async def set_subnet_identity( repository, contact, URL, discord, description, and any additional metadata. wait_for_inclusion (bool): Indicates if the function should wait for the transaction to be included in the block. wait_for_finalization (bool): Indicates if the function should wait for the transaction to reach finalization. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -4015,7 +4023,7 @@ async def set_weights( ``False``. max_retries (int): The number of maximum attempts to set weights. Default is ``5``. block_time (float): The number of seconds for block duration. Default is 12.0 seconds. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. Default is 16. @@ -4123,7 +4131,7 @@ async def serve_axon( ``True``. certificate (bittensor.utils.Certificate): Certificate to use for TLS. If ``None``, no TLS will be used. Defaults to ``None``. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -4208,7 +4216,7 @@ async def swap_stake( rate_tolerance (float): The maximum allowed increase in the price ratio between subnets (origin_price/destination_price). For example, 0.005 = 0.5% maximum increase. Only used when safe_staking is True. Default is 0.005. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -4262,7 +4270,7 @@ async def transfer_stake( amount (Balance): Amount to transfer. wait_for_inclusion (bool): If true, waits for inclusion before returning. wait_for_finalization (bool): If true, waits for finalization before returning. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index dc57fd3059..33eef30a03 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -460,9 +460,9 @@ def commit(self, wallet, netuid: int, data: str, period: Optional[int] = None) - wallet (bittensor_wallet.Wallet): The wallet associated with the neuron committing the data. netuid (int): The unique identifier of the subnetwork. data (str): The data to be committed to the network. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If - the transaction is not included in a block within that number of blocks, it will expire and be rejected. - You can think of it as an expiration date for the transaction. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's + submitted. If the transaction is not included in a block within that number of blocks, it will expire + and be rejected. You can think of it as an expiration date for the transaction. Returns: bool: `True` if the commitment was successful, `False` otherwise. @@ -2384,12 +2384,12 @@ def set_reveal_commitment( wallet (bittensor_wallet.Wallet): The wallet associated with the neuron committing the data. netuid (int): The unique identifier of the subnetwork. data (str): The data to be committed to the network. - blocks_until_reveal (int): The number of blocks from now after which the data will be revealed. Defaults to `360`. - Then number of blocks in one epoch. + blocks_until_reveal (int): The number of blocks from now after which the data will be revealed. Defaults to + `360`. Then number of blocks in one epoch. block_time (Union[int, float]): The number of seconds between each block. Defaults to `12`. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If - the transaction is not included in a block within that number of blocks, it will expire and be rejected. - You can think of it as an expiration date for the transaction. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's + submitted. If the transaction is not included in a block within that number of blocks, it will expire + and be rejected. You can think of it as an expiration date for the transaction. Returns: bool: `True` if the commitment was successful, `False` otherwise. @@ -2670,7 +2670,7 @@ def sign_and_send_extrinsic( wait_for_finalization (bool): whether to wait until the extrinsic call is finalized on the chain sign_with (str): the wallet's keypair to use for the signing. Options are "coldkey", "hotkey", "coldkeypub" use_nonce (bool): unique identifier for the transaction related with hot/coldkey. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. nonce_key: the type on nonce to use. Options are "hotkey" or "coldkey". @@ -2678,6 +2678,9 @@ def sign_and_send_extrinsic( Returns: (success, error message) + + Raises: + SubstrateRequestException: Substrate request exception. """ possible_keys = ("coldkey", "hotkey", "coldkeypub") if sign_with not in possible_keys: @@ -2739,6 +2742,7 @@ def add_stake( safe_staking: bool = False, allow_partial_stake: bool = False, rate_tolerance: float = 0.005, + period: Optional[int] = None, ) -> bool: """ Adds the specified amount of stake to a neuron identified by the hotkey ``SS58`` address. @@ -2759,6 +2763,9 @@ def add_stake( exceed the tolerance. Default is False. rate_tolerance (float): The maximum allowed price change ratio when staking. For example, 0.005 = 0.5% maximum price increase. Only used when safe_staking is True. Default is 0.005. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's + submitted. If the transaction is not included in a block within that number of blocks, it will expire + and be rejected. You can think of it as an expiration date for the transaction. Returns: bool: True if the staking is successful, False otherwise. @@ -2780,6 +2787,7 @@ def add_stake( safe_staking=safe_staking, allow_partial_stake=allow_partial_stake, rate_tolerance=rate_tolerance, + period=period, ) def add_stake_multiple( @@ -2790,6 +2798,7 @@ def add_stake_multiple( amounts: Optional[list[Balance]] = None, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: """ Adds stakes to multiple neurons identified by their hotkey SS58 addresses. @@ -2802,6 +2811,9 @@ def add_stake_multiple( amounts (list[Balance]): Corresponding amounts of TAO to stake for each hotkey. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: ``True`` if the staking is successful for all specified neurons, False otherwise. @@ -2817,6 +2829,7 @@ def add_stake_multiple( amounts=amounts, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) def burned_register( @@ -2838,7 +2851,7 @@ def burned_register( `False`. wait_for_finalization (bool, optional): Waits for the transaction to be finalized on the blockchain. Defaults to `True`. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -2893,7 +2906,7 @@ def commit_weights( wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``. max_retries (int): The number of maximum attempts to commit weights. Default is ``5``. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -2968,7 +2981,7 @@ def move_stake( amount (Balance): Amount of stake to move. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -3026,7 +3039,7 @@ def register( num_processes (Optional[int]): The number of processes to use to register. Default to `None`. update_interval (Optional[int]): The number of nonces to solve between updates. Default to `None`. log_verbose (bool): If ``true``, the registration process will log more information. Default to `False`. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -3069,7 +3082,7 @@ def register_subnet( false if the extrinsic fails to enter the block within the timeout. Default is False. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning true, or returns false if the extrinsic fails to be finalized within the timeout. Default is True. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -3113,7 +3126,7 @@ def reveal_weights( wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``. max_retries (int): The number of maximum attempts to reveal weights. Default is ``5``. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -3165,7 +3178,7 @@ def root_register( wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``False``. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -3203,7 +3216,7 @@ def root_set_weights( ``False``. wait_for_finalization (bool, optional): Waits for the transaction to be finalized on the blockchain. Defaults to ``False``. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -3243,7 +3256,7 @@ def set_subnet_identity( repository, contact, URL, discord, description, and any additional metadata. wait_for_inclusion (bool): Indicates if the function should wait for the transaction to be included in the block. wait_for_finalization (bool): Indicates if the function should wait for the transaction to reach finalization. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -3295,7 +3308,7 @@ def set_weights( wait_for_finalization: Waits for the transaction to be finalized on the blockchain. Default is ``False``. max_retries: The number of maximum attempts to set weights. Default is ``5``. block_time: The number of seconds for block duration. Default is 12.0 seconds. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. Default is 16. @@ -3393,7 +3406,7 @@ def serve_axon( ``True``. certificate (bittensor.utils.Certificate): Certificate to use for TLS. If ``None``, no TLS will be used. Defaults to ``None``. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -3478,7 +3491,7 @@ def swap_stake( rate_tolerance (float): The maximum allowed increase in the price ratio between subnets (origin_price/destination_price). For example, 0.005 = 0.5% maximum increase. Only used when safe_staking is True. Default is 0.005. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -3570,7 +3583,7 @@ def transfer_stake( amount (Union[Balance, float, int]): Amount to transfer. wait_for_inclusion (bool): If true, waits for inclusion before returning. wait_for_finalization (bool): If true, waits for finalization before returning. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. From eff87f2ad1d88c6a9f5659f8a45011b6e9412efb Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 22:06:33 -0700 Subject: [PATCH 061/100] refactoring --- bittensor/core/extrinsics/asyncex/commit_reveal.py | 4 ++-- bittensor/core/extrinsics/asyncex/move_stake.py | 8 ++++---- bittensor/core/extrinsics/asyncex/registration.py | 12 ++++++------ bittensor/core/extrinsics/asyncex/root.py | 6 +++--- bittensor/core/extrinsics/asyncex/serving.py | 8 ++++---- bittensor/core/extrinsics/asyncex/weights.py | 12 ++++++------ bittensor/core/extrinsics/commit_reveal.py | 8 ++++---- bittensor/core/extrinsics/commit_weights.py | 8 ++++---- bittensor/core/extrinsics/move_stake.py | 6 +++--- bittensor/core/extrinsics/registration.py | 12 ++++++------ bittensor/core/extrinsics/root.py | 6 +++--- bittensor/core/extrinsics/serving.py | 8 ++++---- bittensor/core/extrinsics/set_weights.py | 6 +++--- 13 files changed, 52 insertions(+), 52 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/commit_reveal.py b/bittensor/core/extrinsics/asyncex/commit_reveal.py index 74d2de5c3a..6c4ea6f138 100644 --- a/bittensor/core/extrinsics/asyncex/commit_reveal.py +++ b/bittensor/core/extrinsics/asyncex/commit_reveal.py @@ -37,7 +37,7 @@ async def _do_commit_reveal_v3( reveal_round: int The round number for the reveal phase. wait_for_inclusion: bool, optional Flag indicating whether to wait for the extrinsic to be included in a block. wait_for_finalization: bool, optional Flag indicating whether to wait for the extrinsic to be finalized. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -94,7 +94,7 @@ async def commit_reveal_v3_extrinsic( wait_for_inclusion: Whether to wait for the inclusion of the transaction. Default is False. wait_for_finalization: Whether to wait for the finalization of the transaction. Default is False. block_time (float): The number of seconds for block duration. Default is 12.0 seconds. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. diff --git a/bittensor/core/extrinsics/asyncex/move_stake.py b/bittensor/core/extrinsics/asyncex/move_stake.py index ee21e00aeb..8848e3f4e2 100644 --- a/bittensor/core/extrinsics/asyncex/move_stake.py +++ b/bittensor/core/extrinsics/asyncex/move_stake.py @@ -62,7 +62,7 @@ async def transfer_stake_extrinsic( amount (Balance): The amount of stake to transfer as a `Balance` object. wait_for_inclusion (bool): If True, waits for transaction inclusion in a block. Defaults to `True`. wait_for_finalization (bool): If True, waits for transaction finalization. Defaults to `False`. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -185,8 +185,8 @@ async def swap_stake_extrinsic( wait_for_finalization (bool): If True, waits for transaction finalization. Defaults to False. safe_staking (bool): If true, enables price safety checks to protect against price impact. allow_partial_stake (bool): If true, allows partial stake swaps when the full amount would exceed the price tolerance. - rate_tolerance (float): Maximum allowed increase in price ratio (0.005 = 0.5%). - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + rate_tolerance (float): Maximum allowed increase in a price ratio (0.005 = 0.5%). + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -335,7 +335,7 @@ async def move_stake_extrinsic( amount (Balance): The amount of stake to move as a `Balance` object. wait_for_inclusion (bool): If True, waits for transaction inclusion in a block. Defaults to True. wait_for_finalization (bool): If True, waits for transaction finalization. Defaults to False. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. diff --git a/bittensor/core/extrinsics/asyncex/registration.py b/bittensor/core/extrinsics/asyncex/registration.py index 54da2f3a9a..e3663f8f64 100644 --- a/bittensor/core/extrinsics/asyncex/registration.py +++ b/bittensor/core/extrinsics/asyncex/registration.py @@ -39,7 +39,7 @@ async def _do_burned_register( wallet (bittensor_wallet.Wallet): The wallet to be registered. wait_for_inclusion (bool): Whether to wait for the transaction to be included in a block. Default is False. wait_for_finalization (bool): Whether to wait for the transaction to be finalized. Default is True. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -84,7 +84,7 @@ async def burned_register_extrinsic( returns ``False`` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -183,7 +183,7 @@ async def _do_pow_register( pow_result (POWSolution): The PoW result to register. wait_for_inclusion (bool): If ``True``, waits for the extrinsic to be included in a block. Default to `False`. wait_for_finalization (bool): If ``True``, waits for the extrinsic to be finalized. Default to `True`. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -249,7 +249,7 @@ async def register_extrinsic( num_processes: The number of processes to use to register. update_interval: The number of nonces to solve between updates. log_verbose: If `True`, the registration process will log more information. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -416,7 +416,7 @@ async def register_subnet_extrinsic( wallet (Wallet): The wallet to be used for subnet registration. wait_for_inclusion (bool): If set, waits for the extrinsic to enter a block before returning true. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning true. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -493,7 +493,7 @@ async def set_subnet_identity_extrinsic( additional (str): Any additional metadata or information related to the subnet. wait_for_inclusion (bool): Whether to wait for the extrinsic inclusion in a block (default: False). wait_for_finalization (bool): Whether to wait for the extrinsic finalization in a block (default: True). - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. diff --git a/bittensor/core/extrinsics/asyncex/root.py b/bittensor/core/extrinsics/asyncex/root.py index 852f004daf..74eb15689d 100644 --- a/bittensor/core/extrinsics/asyncex/root.py +++ b/bittensor/core/extrinsics/asyncex/root.py @@ -59,7 +59,7 @@ async def root_register_extrinsic( `False` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning `True`, or returns `False` if the extrinsic fails to be finalized within the timeout. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -177,7 +177,7 @@ async def _do_set_root_weights( False. wait_for_finalization (bool, optional): If True, waits for the extrinsic to be finalized on the chain. Defaults to False. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -239,7 +239,7 @@ async def set_root_weights_extrinsic( `False` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning ` True`, or returns `False` if the extrinsic fails to be finalized within the timeout. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. diff --git a/bittensor/core/extrinsics/asyncex/serving.py b/bittensor/core/extrinsics/asyncex/serving.py index aafde7dd02..007be2a12b 100644 --- a/bittensor/core/extrinsics/asyncex/serving.py +++ b/bittensor/core/extrinsics/asyncex/serving.py @@ -35,7 +35,7 @@ async def do_serve_axon( call_params (bittensor.core.types.AxonServeCallParams): Parameters required for the serve axon call. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -97,7 +97,7 @@ async def serve_extrinsic( ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. certificate (bittensor.utils.Certificate): Certificate to use for TLS. If ``None``, no TLS will be used. Defaults to ``None``. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -181,7 +181,7 @@ async def serve_axon_extrinsic( ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. certificate (bittensor.utils.Certificate): Certificate to use for TLS. If ``None``, no TLS will be used. Defaults to ``None``. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -252,7 +252,7 @@ async def publish_metadata( block before returning. Defaults to ``False``. wait_for_finalization (bool, optional): If ``True``, the function will wait for the extrinsic to be finalized on the chain before returning. Defaults to ``True``. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. diff --git a/bittensor/core/extrinsics/asyncex/weights.py b/bittensor/core/extrinsics/asyncex/weights.py index 37693927a1..7f04ffd7bd 100644 --- a/bittensor/core/extrinsics/asyncex/weights.py +++ b/bittensor/core/extrinsics/asyncex/weights.py @@ -35,7 +35,7 @@ async def _do_commit_weights( commit_hash (str): The hash of the neuron's weights to be committed. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -88,7 +88,7 @@ async def commit_weights_extrinsic( commit_hash (str): The hash of the neuron's weights to be committed. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -146,7 +146,7 @@ async def _do_reveal_weights( version_key (int): Version key for compatibility with the network. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -207,7 +207,7 @@ async def reveal_weights_extrinsic( version_key (int): Version key for compatibility with the network. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -265,7 +265,7 @@ async def _do_set_weights( version_key (int, optional): Version key for compatibility with the network. wait_for_inclusion (bool, optional): Waits for the transaction to be included in a block. wait_for_finalization (bool, optional): Waits for the transaction to be finalized on the blockchain. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -332,7 +332,7 @@ async def set_weights_extrinsic( returns ``False`` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. diff --git a/bittensor/core/extrinsics/commit_reveal.py b/bittensor/core/extrinsics/commit_reveal.py index 532e1dba83..28f6c112fe 100644 --- a/bittensor/core/extrinsics/commit_reveal.py +++ b/bittensor/core/extrinsics/commit_reveal.py @@ -38,7 +38,7 @@ def _do_commit_reveal_v3( reveal_round: int The round number for the reveal phase. wait_for_inclusion: bool, optional Flag indicating whether to wait for the extrinsic to be included in a block. wait_for_finalization: bool, optional Flag indicating whether to wait for the extrinsic to be finalized. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -95,9 +95,9 @@ def commit_reveal_v3_extrinsic( wait_for_inclusion: Whether to wait for the inclusion of the transaction. Default is False. wait_for_finalization: Whether to wait for the finalization of the transaction. Default is False. block_time (float): The number of seconds for block duration. Default is 12.0 seconds. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If the - transaction is not included in a block within that number of blocks, it will expire and be rejected. You can - think of it as an expiration date for the transaction. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. + If the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: A tuple where the first element is a boolean indicating success or failure, and the second diff --git a/bittensor/core/extrinsics/commit_weights.py b/bittensor/core/extrinsics/commit_weights.py index c07878ac16..e139907b65 100644 --- a/bittensor/core/extrinsics/commit_weights.py +++ b/bittensor/core/extrinsics/commit_weights.py @@ -29,7 +29,7 @@ def _do_commit_weights( commit_hash (str): The hash of the neuron's weights to be committed. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -81,7 +81,7 @@ def commit_weights_extrinsic( commit_hash (str): The hash of the neuron's weights to be committed. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -139,7 +139,7 @@ def _do_reveal_weights( version_key (int): Version key for compatibility with the network. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -201,7 +201,7 @@ def reveal_weights_extrinsic( version_key (int): Version key for compatibility with the network. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. diff --git a/bittensor/core/extrinsics/move_stake.py b/bittensor/core/extrinsics/move_stake.py index a815c14dc0..58e651b3e9 100644 --- a/bittensor/core/extrinsics/move_stake.py +++ b/bittensor/core/extrinsics/move_stake.py @@ -59,7 +59,7 @@ def transfer_stake_extrinsic( amount (Union[Balance, float, int]): Amount to transfer. wait_for_inclusion (bool): If true, waits for inclusion before returning. wait_for_finalization (bool): If true, waits for finalization before returning. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -183,7 +183,7 @@ def swap_stake_extrinsic( safe_staking (bool): If true, enables price safety checks to protect against price impact. allow_partial_stake (bool): If true, allows partial stake swaps when the full amount would exceed the price tolerance. rate_tolerance (float): Maximum allowed increase in a price ratio (0.005 = 0.5%). - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -331,7 +331,7 @@ def move_stake_extrinsic( amount (Union[Balance, float]): Amount to move. wait_for_inclusion (bool): If true, waits for inclusion before returning. wait_for_finalization (bool): If true, waits for finalization before returning. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. diff --git a/bittensor/core/extrinsics/registration.py b/bittensor/core/extrinsics/registration.py index ed53319974..9acd2f0f8d 100644 --- a/bittensor/core/extrinsics/registration.py +++ b/bittensor/core/extrinsics/registration.py @@ -38,7 +38,7 @@ def _do_burned_register( wallet (bittensor_wallet.Wallet): The wallet to be registered. wait_for_inclusion (bool): Whether to wait for the transaction to be included in a block. Default is False. wait_for_finalization (bool): Whether to wait for the transaction to be finalized. Default is True. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -83,7 +83,7 @@ def burned_register_extrinsic( returns ``False`` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -175,7 +175,7 @@ def _do_pow_register( pow_result (POWSolution): The PoW result to register. wait_for_inclusion (bool): If ``True``, waits for the extrinsic to be included in a block. Default to `False`. wait_for_finalization (bool): If ``True``, waits for the extrinsic to be finalized. Default to `True`. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -221,7 +221,7 @@ def register_subnet_extrinsic( wallet (Wallet): The wallet to be used for subnet registration. wait_for_inclusion (bool): If set, waits for the extrinsic to enter a block before returning true. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning true. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -301,7 +301,7 @@ def register_extrinsic( num_processes: The number of processes to use to register. update_interval: The number of nonces to solve between updates. log_verbose: If `True`, the registration process will log more information. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -485,7 +485,7 @@ def set_subnet_identity_extrinsic( additional (str): Any additional metadata or information related to the subnet. wait_for_inclusion (bool): Whether to wait for the extrinsic inclusion in a block (default: False). wait_for_finalization (bool): Whether to wait for the extrinsic finalization in a block (default: True). - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. diff --git a/bittensor/core/extrinsics/root.py b/bittensor/core/extrinsics/root.py index cc944a7c62..3545909493 100644 --- a/bittensor/core/extrinsics/root.py +++ b/bittensor/core/extrinsics/root.py @@ -62,7 +62,7 @@ def root_register_extrinsic( `False` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning `True`, or returns `False` if the extrinsic fails to be finalized within the timeout. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -178,7 +178,7 @@ def _do_set_root_weights( False. wait_for_finalization (bool, optional): If True, waits for the extrinsic to be finalized on the chain. Defaults to False. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -240,7 +240,7 @@ def set_root_weights_extrinsic( `False` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning True`, or returns `False` if the extrinsic fails to be finalized within the timeout. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. diff --git a/bittensor/core/extrinsics/serving.py b/bittensor/core/extrinsics/serving.py index a9309cfe24..d004fd7dba 100644 --- a/bittensor/core/extrinsics/serving.py +++ b/bittensor/core/extrinsics/serving.py @@ -34,7 +34,7 @@ def do_serve_axon( call_params (bittensor.core.types.AxonServeCallParams): Parameters required for the serve axon call. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -96,7 +96,7 @@ def serve_extrinsic( ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. certificate (bittensor.utils.Certificate): Certificate to use for TLS. If ``None``, no TLS will be used. Defaults to ``None``. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -180,7 +180,7 @@ def serve_axon_extrinsic( ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. certificate (bittensor.utils.Certificate): Certificate to use for TLS. If ``None``, no TLS will be used. Defaults to ``None``. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -249,7 +249,7 @@ def publish_metadata( block before returning. Defaults to ``False``. wait_for_finalization (bool, optional): If ``True``, the function will wait for the extrinsic to be finalized on the chain before returning. Defaults to ``True``. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. diff --git a/bittensor/core/extrinsics/set_weights.py b/bittensor/core/extrinsics/set_weights.py index eea4ddbb0e..bfa912419c 100644 --- a/bittensor/core/extrinsics/set_weights.py +++ b/bittensor/core/extrinsics/set_weights.py @@ -40,7 +40,7 @@ def _do_set_weights( version_key (int, optional): Version key for compatibility with the network. wait_for_inclusion (bool, optional): Waits for the transaction to be included in a block. wait_for_finalization (bool, optional): Waits for the transaction to be finalized on the blockchain. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. @@ -99,8 +99,8 @@ def set_weights_extrinsic( returns ``False`` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. - period (int): The number of blocks during which the transaction will remain valid after it's submitted. If - the transaction is not included in a block within that number of blocks, it will expire and be rejected. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. + If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. Returns: From 838c9bc7e54bc4b61fa49473f58ed45fa3c34267 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 22:27:19 -0700 Subject: [PATCH 062/100] update start_call extrinsics --- .../core/extrinsics/asyncex/start_call.py | 22 +++++----- bittensor/core/extrinsics/start_call.py | 44 +++++++++---------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/start_call.py b/bittensor/core/extrinsics/asyncex/start_call.py index bc0089ddb9..3790995524 100644 --- a/bittensor/core/extrinsics/asyncex/start_call.py +++ b/bittensor/core/extrinsics/asyncex/start_call.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from bittensor.utils import unlock_key, format_error_message from bittensor.utils.btlogging import logging @@ -14,6 +14,7 @@ async def start_call_extrinsic( netuid: int, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Submits a start_call extrinsic to the blockchain, to trigger the start call process for a subnet (used to start a @@ -25,6 +26,9 @@ async def start_call_extrinsic( netuid (int): The UID of the target subnet for which the call is being initiated. wait_for_inclusion (bool, optional): Whether to wait for the extrinsic to be included in a block. Defaults to True. wait_for_finalization (bool, optional): Whether to wait for finalization of the extrinsic. Defaults to False. + period: The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: Tuple[bool, str]: @@ -41,21 +45,19 @@ async def start_call_extrinsic( call_function="start_call", call_params={"netuid": netuid}, ) - signed_ext = await substrate.create_signed_extrinsic( - call=start_call, - keypair=wallet.coldkey, - ) - response = await substrate.submit_extrinsic( - extrinsic=signed_ext, + success, message = await subtensor.sign_and_send_extrinsic( + call=start_call, + wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period ) if not wait_for_finalization and not wait_for_inclusion: - return True, "Not waiting for finalization or inclusion." + return True, message - if await response.is_success: + if success: return True, "Success with `start_call` response." - return False, format_error_message(await response.error_message) + return True, message diff --git a/bittensor/core/extrinsics/start_call.py b/bittensor/core/extrinsics/start_call.py index d3a1d423ce..ac6229e802 100644 --- a/bittensor/core/extrinsics/start_call.py +++ b/bittensor/core/extrinsics/start_call.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from bittensor.utils import unlock_key, format_error_message from bittensor.utils.btlogging import logging @@ -14,6 +14,7 @@ def start_call_extrinsic( netuid: int, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Submits a start_call extrinsic to the blockchain, to trigger the start call process for a subnet (used to start a @@ -25,6 +26,9 @@ def start_call_extrinsic( netuid (int): The UID of the target subnet for which the call is being initiated. wait_for_inclusion (bool, optional): Whether to wait for the extrinsic to be included in a block. Defaults to True. wait_for_finalization (bool, optional): Whether to wait for finalization of the extrinsic. Defaults to False. + period: The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: Tuple[bool, str]: @@ -35,28 +39,24 @@ def start_call_extrinsic( logging.error(unlock.message) return False, unlock.message - with subtensor.substrate as substrate: - start_call = substrate.compose_call( - call_module="SubtensorModule", - call_function="start_call", - call_params={"netuid": netuid}, - ) + start_call = subtensor.substrate.compose_call( + call_module="SubtensorModule", + call_function="start_call", + call_params={"netuid": netuid}, + ) - signed_ext = substrate.create_signed_extrinsic( - call=start_call, - keypair=wallet.coldkey, - ) + success, message = subtensor.sign_and_send_extrinsic( + call=start_call, + wallet=wallet, + wait_for_inclusion=wait_for_inclusion, + wait_for_finalization=wait_for_finalization, + period=period + ) - response = substrate.submit_extrinsic( - extrinsic=signed_ext, - wait_for_inclusion=wait_for_inclusion, - wait_for_finalization=wait_for_finalization, - ) + if not wait_for_finalization and not wait_for_inclusion: + return True, message - if not wait_for_finalization and not wait_for_inclusion: - return True, "Not waiting for finalization or inclusion." + if success: + return True, "Success with `start_call` response." - if response.is_success: - return True, "Success with `start_call` response." - - return False, format_error_message(response.error_message) + return True, message From 179b3dd6c5a4fdc60d7a352cfc2cfc3cee222185 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 22:27:33 -0700 Subject: [PATCH 063/100] update subtensors start_call extrinsics --- bittensor/core/async_subtensor.py | 5 +++++ bittensor/core/subtensor.py | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index b9442daa4d..28e6a9a522 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -4157,6 +4157,7 @@ async def start_call( netuid: int, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Submits a start_call extrinsic to the blockchain, to trigger the start call process for a subnet (used to start a @@ -4167,6 +4168,9 @@ async def start_call( netuid (int): The UID of the target subnet for which the call is being initiated. wait_for_inclusion (bool, optional): Whether to wait for the extrinsic to be included in a block. Defaults to True. wait_for_finalization (bool, optional): Whether to wait for finalization of the extrinsic. Defaults to False. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: Tuple[bool, str]: @@ -4179,6 +4183,7 @@ async def start_call( netuid=netuid, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) async def swap_stake( diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 33eef30a03..56f930bb6d 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -3432,6 +3432,7 @@ def start_call( netuid: int, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Submits a start_call extrinsic to the blockchain, to trigger the start call process for a subnet (used to start a @@ -3442,6 +3443,9 @@ def start_call( netuid (int): The UID of the target subnet for which the call is being initiated. wait_for_inclusion (bool, optional): Whether to wait for the extrinsic to be included in a block. Defaults to True. wait_for_finalization (bool, optional): Whether to wait for finalization of the extrinsic. Defaults to False. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: Tuple[bool, str]: @@ -3454,6 +3458,7 @@ def start_call( netuid=netuid, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) def swap_stake( From 76384c9da53734d31870d73e1e77e41f0838abb8 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 22:27:39 -0700 Subject: [PATCH 064/100] fix tests --- .../extrinsics/asyncex/test_start_call.py | 20 ++++++----------- .../unit_tests/extrinsics/test_start_call.py | 22 +++++++------------ tests/unit_tests/test_async_subtensor.py | 1 + tests/unit_tests/test_subtensor.py | 1 + 4 files changed, 17 insertions(+), 27 deletions(-) diff --git a/tests/unit_tests/extrinsics/asyncex/test_start_call.py b/tests/unit_tests/extrinsics/asyncex/test_start_call.py index 63083cd094..ebb5c327a9 100644 --- a/tests/unit_tests/extrinsics/asyncex/test_start_call.py +++ b/tests/unit_tests/extrinsics/asyncex/test_start_call.py @@ -5,18 +5,15 @@ @pytest.mark.asyncio async def test_start_call_extrinsics(subtensor, mocker, fake_wallet): """Test that start_call_extrinsic correctly constructs and submits the extrinsic.""" - # Preps netuid = 123 wallet = fake_wallet wallet.name = "fake_wallet" wallet.coldkey = "fake_coldkey" - substrate = subtensor.substrate.__aenter__.return_value - substrate.compose_call.return_value = "mock_call" - substrate.create_signed_extrinsic.return_value = "signed_ext" - substrate.submit_extrinsic.return_value = mocker.MagicMock( - is_success=mocker.AsyncMock(return_value=True)(), error_message="" + substrate.compose_call = mocker.AsyncMock() + mocked_sign_and_send_extrinsic = mocker.patch.object( + subtensor, "sign_and_send_extrinsic", return_value=(True, "") ) # Call @@ -33,15 +30,12 @@ async def test_start_call_extrinsics(subtensor, mocker, fake_wallet): call_params={"netuid": netuid}, ) - substrate.create_signed_extrinsic.assert_awaited_once_with( - call="mock_call", - keypair=wallet.coldkey, - ) - - substrate.submit_extrinsic.assert_awaited_once_with( - extrinsic="signed_ext", + mocked_sign_and_send_extrinsic.assert_awaited_once_with( + call=substrate.compose_call.return_value, + wallet=wallet, wait_for_inclusion=True, wait_for_finalization=False, + period=None ) assert success is True diff --git a/tests/unit_tests/extrinsics/test_start_call.py b/tests/unit_tests/extrinsics/test_start_call.py index ccc14581ee..658f0883f7 100644 --- a/tests/unit_tests/extrinsics/test_start_call.py +++ b/tests/unit_tests/extrinsics/test_start_call.py @@ -3,18 +3,15 @@ def test_start_call_extrinsics(subtensor, mocker, fake_wallet): """Test that start_call_extrinsic correctly constructs and submits the extrinsic.""" - # Preps netuid = 123 wallet = fake_wallet wallet.name = "fake_wallet" wallet.coldkey = "fake_coldkey" - substrate = subtensor.substrate.__enter__.return_value - substrate.compose_call.return_value = "mock_call" - substrate.create_signed_extrinsic.return_value = "signed_ext" - substrate.submit_extrinsic.return_value = mocker.MagicMock( - is_success=True, error_message="" + subtensor.substrate.compose_call = mocker.Mock() + mocked_sign_and_send_extrinsic = mocker.patch.object( + subtensor, "sign_and_send_extrinsic", return_value=(True, "") ) # Call @@ -25,21 +22,18 @@ def test_start_call_extrinsics(subtensor, mocker, fake_wallet): ) # Assertions - substrate.compose_call.assert_called_once_with( + subtensor.substrate.compose_call.assert_called_once_with( call_module="SubtensorModule", call_function="start_call", call_params={"netuid": netuid}, ) - substrate.create_signed_extrinsic.assert_called_once_with( - call="mock_call", - keypair=wallet.coldkey, - ) - - substrate.submit_extrinsic.assert_called_once_with( - extrinsic="signed_ext", + mocked_sign_and_send_extrinsic.assert_called_once_with( + call=subtensor.substrate.compose_call.return_value, + wallet=wallet, wait_for_inclusion=True, wait_for_finalization=False, + period=None ) assert success is True diff --git a/tests/unit_tests/test_async_subtensor.py b/tests/unit_tests/test_async_subtensor.py index e8f4f3817f..892836e2d8 100644 --- a/tests/unit_tests/test_async_subtensor.py +++ b/tests/unit_tests/test_async_subtensor.py @@ -3064,6 +3064,7 @@ async def test_start_call(subtensor, mocker): netuid=netuid, wait_for_inclusion=True, wait_for_finalization=False, + period=None, ) assert result == mocked_extrinsic.return_value diff --git a/tests/unit_tests/test_subtensor.py b/tests/unit_tests/test_subtensor.py index fbd67014a2..e3588178c5 100644 --- a/tests/unit_tests/test_subtensor.py +++ b/tests/unit_tests/test_subtensor.py @@ -3391,6 +3391,7 @@ def test_start_call(subtensor, mocker): netuid=netuid, wait_for_inclusion=True, wait_for_finalization=False, + period=None, ) assert result == mocked_extrinsic.return_value From 30953e1f3472c60c66fbfd1bb01d74d51bf1434f Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 22:48:58 -0700 Subject: [PATCH 065/100] extrinsics `increase_take_extrinsic` and `decrease_take_extrinsic` --- bittensor/core/extrinsics/asyncex/take.py | 49 ++++++++++++++++++++--- bittensor/core/extrinsics/take.py | 42 ++++++++++++++++++- 2 files changed, 84 insertions(+), 7 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/take.py b/bittensor/core/extrinsics/asyncex/take.py index 6a51239bc0..543d4e72da 100644 --- a/bittensor/core/extrinsics/asyncex/take.py +++ b/bittensor/core/extrinsics/asyncex/take.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from bittensor_wallet.bittensor_wallet import Wallet @@ -16,7 +16,26 @@ async def increase_take_extrinsic( wait_for_inclusion: bool = True, wait_for_finalization: bool = True, raise_error: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str]: + """Sets the delegate 'take' percentage for a neuron identified by its hotkey. + + Args: + subtensor (Subtensor): Blockchain connection. + wallet (Wallet): The wallet to sign the extrinsic. + hotkey_ss58 (str): SS58 address of the hotkey to set take for. + take (int): The percentage of rewards that the delegate claims from nominators. + wait_for_inclusion (bool, optional): Wait for inclusion before returning. Defaults to True. + wait_for_finalization (bool, optional): Wait for finalization before returning. Defaults to True. + raise_error (bool, optional): Raise error on failure. Defaults to False. + period: The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. + + Returns: + tuple[bool, str]: Success flag and status message. + """ + unlock = unlock_key(wallet, raise_error=raise_error) if not unlock.success: @@ -32,10 +51,11 @@ async def increase_take_extrinsic( ) return await subtensor.sign_and_send_extrinsic( - call, - wallet, + call=call, + wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, raise_error=raise_error, ) @@ -48,7 +68,25 @@ async def decrease_take_extrinsic( wait_for_inclusion: bool = True, wait_for_finalization: bool = True, raise_error: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str]: + """Sets the delegate 'take' percentage for a neuron identified by its hotkey. + + Args: + subtensor (Subtensor): Blockchain connection. + wallet (Wallet): The wallet to sign the extrinsic. + hotkey_ss58 (str): SS58 address of the hotkey to set take for. + take (int): The percentage of rewards that the delegate claims from nominators. + wait_for_inclusion (bool, optional): Wait for inclusion before returning. Defaults to True. + wait_for_finalization (bool, optional): Wait for finalization before returning. Defaults to True. + raise_error (bool, optional): Raise error on failure. Defaults to False. + period: The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. + + Returns: + tuple[bool, str]: Success flag and status message. + """ unlock = unlock_key(wallet, raise_error=raise_error) if not unlock.success: @@ -64,9 +102,10 @@ async def decrease_take_extrinsic( ) return await subtensor.sign_and_send_extrinsic( - call, - wallet, + call=call, + wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, raise_error=raise_error, ) diff --git a/bittensor/core/extrinsics/take.py b/bittensor/core/extrinsics/take.py index 1ac6e96040..4a18ec0748 100644 --- a/bittensor/core/extrinsics/take.py +++ b/bittensor/core/extrinsics/take.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from bittensor_wallet.bittensor_wallet import Wallet @@ -16,7 +16,25 @@ def increase_take_extrinsic( wait_for_inclusion: bool = True, wait_for_finalization: bool = True, raise_error: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str]: + """Sets the delegate 'take' percentage for a neuron identified by its hotkey. + + Args: + subtensor (Subtensor): Blockchain connection. + wallet (Wallet): The wallet to sign the extrinsic. + hotkey_ss58 (str): SS58 address of the hotkey to set take for. + take (int): The percentage of rewards that the delegate claims from nominators. + wait_for_inclusion (bool, optional): Wait for inclusion before returning. Defaults to True. + wait_for_finalization (bool, optional): Wait for finalization before returning. Defaults to True. + raise_error (bool, optional): Raise error on failure. Defaults to False. + period: The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. + + Returns: + tuple[bool, str]: Success flag and status message. + """ unlock = unlock_key(wallet, raise_error=raise_error) if not unlock.success: @@ -36,6 +54,7 @@ def increase_take_extrinsic( wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, raise_error=raise_error, ) @@ -48,7 +67,25 @@ def decrease_take_extrinsic( wait_for_inclusion: bool = True, wait_for_finalization: bool = True, raise_error: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str]: + """Sets the delegate 'take' percentage for a neuron identified by its hotkey. + + Args: + subtensor (Subtensor): Blockchain connection. + wallet (Wallet): The wallet to sign the extrinsic. + hotkey_ss58 (str): SS58 address of the hotkey to set take for. + take (int): The percentage of rewards that the delegate claims from nominators. + wait_for_inclusion (bool, optional): Wait for inclusion before returning. Defaults to True. + wait_for_finalization (bool, optional): Wait for finalization before returning. Defaults to True. + raise_error (bool, optional): Raise error on failure. Defaults to False. + period: The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. + + Returns: + tuple[bool, str]: Success flag and status message. + """ unlock = unlock_key(wallet, raise_error=raise_error) if not unlock.success: @@ -67,6 +104,7 @@ def decrease_take_extrinsic( call, wallet, wait_for_inclusion=wait_for_inclusion, - wait_for_finalization=wait_for_finalization, raise_error=raise_error, + wait_for_finalization=wait_for_finalization, + period=period, ) From 9563c0402b5a2ac5379fddb442d996c9bf2a8146 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 22:49:13 -0700 Subject: [PATCH 066/100] related subtensors calls --- bittensor/core/async_subtensor.py | 12 +- bittensor/core/subtensor.py | 296 +++++++++++++++--------------- 2 files changed, 160 insertions(+), 148 deletions(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index 28e6a9a522..c10be33b69 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -3880,6 +3880,7 @@ async def set_delegate_take( wait_for_inclusion: bool = True, wait_for_finalization: bool = True, raise_error: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Sets the delegate 'take' percentage for a neuron identified by its hotkey. @@ -3891,7 +3892,10 @@ async def set_delegate_take( take (float): Percentage reward for the delegate. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. - raise_error: Raises relevant exception rather than returning `False` if unsuccessful. + raise_error: Raises a relevant exception rather than returning `False` if unsuccessful. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: A tuple where the first element is a boolean indicating success or failure of the @@ -3901,8 +3905,8 @@ async def set_delegate_take( DelegateTakeTooHigh: Delegate take is too high. DelegateTakeTooLow: Delegate take is too low. DelegateTxRateLimitExceeded: A transactor exceeded the rate limit for delegate transaction. - HotKeyAccountNotExists: The hotkey does not exists. - NonAssociatedColdKey: Request to stake, unstake or subscribe is made by a coldkey that is not associated with the hotkey account. + HotKeyAccountNotExists: The hotkey does not exist. + NonAssociatedColdKey: Request to stake, unstake, or subscribe is made by a coldkey that is not associated with the hotkey account. bittensor_wallet.errors.PasswordError: Decryption failed or wrong password for decryption provided. bittensor_wallet.errors.KeyFileError: Failed to decode keyfile data. @@ -3931,6 +3935,7 @@ async def set_delegate_take( wait_for_finalization=wait_for_finalization, wait_for_inclusion=wait_for_inclusion, raise_error=raise_error, + period=period ) else: success, error = await decrease_take_extrinsic( @@ -3941,6 +3946,7 @@ async def set_delegate_take( wait_for_finalization=wait_for_finalization, wait_for_inclusion=wait_for_inclusion, raise_error=raise_error, + period=period ) if success: diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 56f930bb6d..685b715ed8 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -1931,151 +1931,6 @@ def immunity_period( ) return None if call is None else int(call) - def set_children( - self, - wallet: "Wallet", - hotkey: str, - netuid: int, - children: list[tuple[float, str]], - wait_for_inclusion: bool = True, - wait_for_finalization: bool = True, - raise_error: bool = False, - ) -> tuple[bool, str]: - """ - Allows a coldkey to set children keys. - - Arguments: - wallet (bittensor_wallet.Wallet): bittensor wallet instance. - hotkey (str): The ``SS58`` address of the neuron's hotkey. - netuid (int): The netuid value. - children (list[tuple[float, str]]): A list of children with their proportions. - wait_for_inclusion (bool): Waits for the transaction to be included in a block. - wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. - raise_error: Raises relevant exception rather than returning `False` if unsuccessful. - - Returns: - tuple[bool, str]: A tuple where the first element is a boolean indicating success or failure of the - operation, and the second element is a message providing additional information. - - Raises: - DuplicateChild: There are duplicates in the list of children. - InvalidChild: Child is the hotkey. - NonAssociatedColdKey: The coldkey does not own the hotkey or the child is the same as the hotkey. - NotEnoughStakeToSetChildkeys: Parent key doesn't have minimum own stake. - ProportionOverflow: The sum of the proportions does exceed uint64. - RegistrationNotPermittedOnRootSubnet: Attempting to register a child on the root network. - SubNetworkDoesNotExist: Attempting to register to a non-existent network. - TooManyChildren: Too many children in request. - TxRateLimitExceeded: Hotkey hit the rate limit. - bittensor_wallet.errors.KeyFileError: Failed to decode keyfile data. - bittensor_wallet.errors.PasswordError: Decryption failed or wrong password for decryption provided. - """ - - unlock = unlock_key(wallet, raise_error=raise_error) - - if not unlock.success: - return False, unlock.message - - call = self.substrate.compose_call( - call_module="SubtensorModule", - call_function="set_children", - call_params={ - "children": [ - ( - float_to_u64(proportion), - child_hotkey, - ) - for proportion, child_hotkey in children - ], - "hotkey": hotkey, - "netuid": netuid, - }, - ) - - return self.sign_and_send_extrinsic( - call, - wallet, - wait_for_inclusion, - wait_for_finalization, - raise_error=raise_error, - ) - - def set_delegate_take( - self, - wallet: "Wallet", - hotkey_ss58: str, - take: float, - wait_for_inclusion: bool = True, - wait_for_finalization: bool = True, - raise_error: bool = False, - ) -> tuple[bool, str]: - """ - Sets the delegate 'take' percentage for a nueron identified by its hotkey. - The 'take' represents the percentage of rewards that the delegate claims from its nominators' stakes. - - Arguments: - wallet (bittensor_wallet.Wallet): bittensor wallet instance. - hotkey_ss58 (str): The ``SS58`` address of the neuron's hotkey. - take (float): Percentage reward for the delegate. - wait_for_inclusion (bool): Waits for the transaction to be included in a block. - wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. - raise_error: Raises relevant exception rather than returning `False` if unsuccessful. - - Returns: - tuple[bool, str]: A tuple where the first element is a boolean indicating success or failure of the - operation, and the second element is a message providing additional information. - - Raises: - DelegateTakeTooHigh: Delegate take is too high. - DelegateTakeTooLow: Delegate take is too low. - DelegateTxRateLimitExceeded: A transactor exceeded the rate limit for delegate transaction. - HotKeyAccountNotExists: The hotkey does not exists. - NonAssociatedColdKey: Request to stake, unstake or subscribe is made by a coldkey that is not associated with the hotkey account. - bittensor_wallet.errors.PasswordError: Decryption failed or wrong password for decryption provided. - bittensor_wallet.errors.KeyFileError: Failed to decode keyfile data. - - The delegate take is a critical parameter in the network's incentive structure, influencing the distribution of - rewards among neurons and their nominators. - """ - - # u16 representation of the take - take_u16 = int(take * 0xFFFF) - - current_take = self.get_delegate_take(hotkey_ss58) - current_take_u16 = int(current_take * 0xFFFF) - - if current_take_u16 == take_u16: - logging.info(":white_heavy_check_mark: [green]Already Set[/green]") - return True, "" - - logging.info(f"Updating {hotkey_ss58} take: current={current_take} new={take}") - - if current_take_u16 < take_u16: - success, error = increase_take_extrinsic( - self, - wallet, - hotkey_ss58, - take_u16, - wait_for_finalization=wait_for_finalization, - wait_for_inclusion=wait_for_inclusion, - raise_error=raise_error, - ) - else: - success, error = decrease_take_extrinsic( - self, - wallet, - hotkey_ss58, - take_u16, - wait_for_finalization=wait_for_finalization, - wait_for_inclusion=wait_for_inclusion, - raise_error=raise_error, - ) - - if success: - logging.info(":white_heavy_check_mark: [green]Take Updated[/green]") - - return success, error - def is_hotkey_delegate(self, hotkey_ss58: str, block: Optional[int] = None) -> bool: """ Determines whether a given hotkey (public key) is a delegate on the Bittensor network. This function checks if @@ -3237,6 +3092,157 @@ def root_set_weights( period=period, ) + def set_children( + self, + wallet: "Wallet", + hotkey: str, + netuid: int, + children: list[tuple[float, str]], + wait_for_inclusion: bool = True, + wait_for_finalization: bool = True, + raise_error: bool = False, + ) -> tuple[bool, str]: + """ + Allows a coldkey to set children keys. + + Arguments: + wallet (bittensor_wallet.Wallet): bittensor wallet instance. + hotkey (str): The ``SS58`` address of the neuron's hotkey. + netuid (int): The netuid value. + children (list[tuple[float, str]]): A list of children with their proportions. + wait_for_inclusion (bool): Waits for the transaction to be included in a block. + wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. + raise_error: Raises relevant exception rather than returning `False` if unsuccessful. + + Returns: + tuple[bool, str]: A tuple where the first element is a boolean indicating success or failure of the + operation, and the second element is a message providing additional information. + + Raises: + DuplicateChild: There are duplicates in the list of children. + InvalidChild: Child is the hotkey. + NonAssociatedColdKey: The coldkey does not own the hotkey or the child is the same as the hotkey. + NotEnoughStakeToSetChildkeys: Parent key doesn't have minimum own stake. + ProportionOverflow: The sum of the proportions does exceed uint64. + RegistrationNotPermittedOnRootSubnet: Attempting to register a child on the root network. + SubNetworkDoesNotExist: Attempting to register to a non-existent network. + TooManyChildren: Too many children in request. + TxRateLimitExceeded: Hotkey hit the rate limit. + bittensor_wallet.errors.KeyFileError: Failed to decode keyfile data. + bittensor_wallet.errors.PasswordError: Decryption failed or wrong password for decryption provided. + """ + + unlock = unlock_key(wallet, raise_error=raise_error) + + if not unlock.success: + return False, unlock.message + + call = self.substrate.compose_call( + call_module="SubtensorModule", + call_function="set_children", + call_params={ + "children": [ + ( + float_to_u64(proportion), + child_hotkey, + ) + for proportion, child_hotkey in children + ], + "hotkey": hotkey, + "netuid": netuid, + }, + ) + + return self.sign_and_send_extrinsic( + call, + wallet, + wait_for_inclusion, + wait_for_finalization, + raise_error=raise_error, + ) + + def set_delegate_take( + self, + wallet: "Wallet", + hotkey_ss58: str, + take: float, + wait_for_inclusion: bool = True, + wait_for_finalization: bool = True, + raise_error: bool = False, + period: Optional[int] = None, + ) -> tuple[bool, str]: + """ + Sets the delegate 'take' percentage for a neuron identified by its hotkey. + The 'take' represents the percentage of rewards that the delegate claims from its nominators' stakes. + + Arguments: + wallet (bittensor_wallet.Wallet): bittensor wallet instance. + hotkey_ss58 (str): The ``SS58`` address of the neuron's hotkey. + take (float): Percentage reward for the delegate. + wait_for_inclusion (bool): Waits for the transaction to be included in a block. + wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. + raise_error: Raises a relevant exception rather than returning `False` if unsuccessful. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. + + Returns: + tuple[bool, str]: A tuple where the first element is a boolean indicating success or failure of the + operation, and the second element is a message providing additional information. + + Raises: + DelegateTakeTooHigh: Delegate take is too high. + DelegateTakeTooLow: Delegate take is too low. + DelegateTxRateLimitExceeded: A transactor exceeded the rate limit for delegate transaction. + HotKeyAccountNotExists: The hotkey does not exist. + NonAssociatedColdKey: Request to stake, unstake, or subscribe is made by a coldkey that is not associated with the hotkey account. + bittensor_wallet.errors.PasswordError: Decryption failed or wrong password for decryption provided. + bittensor_wallet.errors.KeyFileError: Failed to decode keyfile data. + + The delegate take is a critical parameter in the network's incentive structure, influencing the distribution of + rewards among neurons and their nominators. + """ + + # u16 representation of the take + take_u16 = int(take * 0xFFFF) + + current_take = self.get_delegate_take(hotkey_ss58) + current_take_u16 = int(current_take * 0xFFFF) + + if current_take_u16 == take_u16: + logging.info(":white_heavy_check_mark: [green]Already Set[/green]") + return True, "" + + logging.info(f"Updating {hotkey_ss58} take: current={current_take} new={take}") + + if current_take_u16 < take_u16: + success, error = increase_take_extrinsic( + self, + wallet, + hotkey_ss58, + take_u16, + wait_for_finalization=wait_for_finalization, + wait_for_inclusion=wait_for_inclusion, + raise_error=raise_error, + period=period + ) + else: + success, error = decrease_take_extrinsic( + self, + wallet, + hotkey_ss58, + take_u16, + wait_for_finalization=wait_for_finalization, + wait_for_inclusion=wait_for_inclusion, + raise_error=raise_error, + period=period + ) + + if success: + logging.info(":white_heavy_check_mark: [green]Take Updated[/green]") + + return success, error + def set_subnet_identity( self, wallet: "Wallet", From 363ba28d2d5d78066e3b423f02b25453cc1d7bee Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 23:18:03 -0700 Subject: [PATCH 067/100] refactoring --- bittensor/core/extrinsics/take.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bittensor/core/extrinsics/take.py b/bittensor/core/extrinsics/take.py index 4a18ec0748..20f4de2f8f 100644 --- a/bittensor/core/extrinsics/take.py +++ b/bittensor/core/extrinsics/take.py @@ -79,8 +79,8 @@ def decrease_take_extrinsic( wait_for_inclusion (bool, optional): Wait for inclusion before returning. Defaults to True. wait_for_finalization (bool, optional): Wait for finalization before returning. Defaults to True. raise_error (bool, optional): Raise error on failure. Defaults to False. - period: The number of blocks during which the transaction will remain valid after it's submitted. If - the transaction is not included in a block within that number of blocks, it will expire and be rejected. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. + If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. Returns: From d1f0a9079219af03a9b64d1c85f8d29d098e3044 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 23:18:21 -0700 Subject: [PATCH 068/100] transfer extrinsics --- bittensor/core/extrinsics/asyncex/transfer.py | 42 +++++++++------ bittensor/core/extrinsics/transfer.py | 53 +++++++++++-------- 2 files changed, 57 insertions(+), 38 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/transfer.py b/bittensor/core/extrinsics/asyncex/transfer.py index 1347c44260..a1c781310c 100644 --- a/bittensor/core/extrinsics/asyncex/transfer.py +++ b/bittensor/core/extrinsics/asyncex/transfer.py @@ -1,9 +1,8 @@ import asyncio -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from bittensor.core.settings import NETWORK_EXPLORER_MAP from bittensor.utils import ( - format_error_message, get_explorer_url_for_network, is_valid_bittensor_address_or_public_key, unlock_key, @@ -23,6 +22,7 @@ async def _do_transfer( amount: "Balance", wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str, str]: """ Makes transfer from wallet to destination public key address. @@ -34,8 +34,11 @@ async def _do_transfer( amount (bittensor.utils.balance.Balance): Amount to stake as Bittensor balance. wait_for_inclusion (bool): If set, waits for the extrinsic to enter a block before returning `True`, or returns `False` if the extrinsic fails to enter the block within the timeout. - wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning + wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning `True`, or returns `False` if the extrinsic fails to be finalized within the timeout. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. + If the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success, block hash, formatted error message @@ -45,24 +48,25 @@ async def _do_transfer( call_function="transfer_allow_death", call_params={"dest": destination, "value": amount.rao}, ) - extrinsic = await subtensor.substrate.create_signed_extrinsic( - call=call, keypair=wallet.coldkey - ) - response = await subtensor.substrate.submit_extrinsic( - extrinsic=extrinsic, + + success, message = await subtensor.sign_and_send_extrinsic( + call=call, + wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) + # We only wait here if we expect finalization. if not wait_for_finalization and not wait_for_inclusion: - return True, "", "Success, extrinsic submitted without waiting." + return True, "", message # Otherwise continue with finalization. - if await response.is_success: - block_hash_ = response.block_hash + if success: + block_hash_ = await subtensor.get_block_hash() return True, block_hash_, "Success with response." - return False, "", format_error_message(await response.error_message) + return False, "", message async def transfer_extrinsic( @@ -74,6 +78,7 @@ async def transfer_extrinsic( wait_for_inclusion: bool = True, wait_for_finalization: bool = False, keep_alive: bool = True, + period: Optional[int] = None, ) -> bool: """Transfers funds from this wallet to the destination public key address. @@ -85,9 +90,12 @@ async def transfer_extrinsic( transfer_all (bool): Whether to transfer all funds from this wallet to the destination address. wait_for_inclusion (bool): If set, waits for the extrinsic to enter a block before returning `True`, or returns `False` if the extrinsic fails to enter the block within the timeout. - wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning + wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning `True`, or returns `False` if the extrinsic fails to be finalized within the timeout. keep_alive (bool): If set, keeps the account alive by keeping the balance above the existential deposit. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. + If the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): Flag is `True` if extrinsic was finalized or included in the block. If we did not wait for @@ -100,6 +108,7 @@ async def transfer_extrinsic( f":cross_mark: [red]Invalid destination SS58 address[/red]: {destination}" ) return False + logging.info(f"Initiating transfer on network: {subtensor.network}") # Unlock wallet coldkey. if not (unlock := unlock_key(wallet)).success: @@ -148,6 +157,7 @@ async def transfer_extrinsic( amount=amount, wait_for_finalization=wait_for_finalization, wait_for_inclusion=wait_for_inclusion, + period=period, ) if success: @@ -173,6 +183,6 @@ async def transfer_extrinsic( f"Balance: [blue]{account_balance}[/blue] :arrow_right: [green]{new_balance}[/green]" ) return True - else: - logging.error(f":cross_mark: [red]Failed[/red]: {err_msg}") - return False + + logging.error(f":cross_mark: [red]Failed[/red]: {err_msg}") + return False diff --git a/bittensor/core/extrinsics/transfer.py b/bittensor/core/extrinsics/transfer.py index badc4d7cf9..03624097d0 100644 --- a/bittensor/core/extrinsics/transfer.py +++ b/bittensor/core/extrinsics/transfer.py @@ -1,13 +1,12 @@ -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from bittensor.core.settings import NETWORK_EXPLORER_MAP -from bittensor.utils.balance import Balance from bittensor.utils import ( is_valid_bittensor_address_or_public_key, unlock_key, get_explorer_url_for_network, - format_error_message, ) +from bittensor.utils.balance import Balance from bittensor.utils.btlogging import logging if TYPE_CHECKING: @@ -22,6 +21,7 @@ def _do_transfer( amount: Balance, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str, str]: """ Makes transfer from wallet to destination public key address. @@ -33,8 +33,11 @@ def _do_transfer( amount (bittensor.utils.balance.Balance): Amount to stake as Bittensor balance. wait_for_inclusion (bool): If set, waits for the extrinsic to enter a block before returning `True`, or returns `False` if the extrinsic fails to enter the block within the timeout. - wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning + wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning `True`, or returns `False` if the extrinsic fails to be finalized within the timeout. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. + If the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success, block hash, formatted error message @@ -44,24 +47,25 @@ def _do_transfer( call_function="transfer_allow_death", call_params={"dest": destination, "value": amount.rao}, ) - extrinsic = subtensor.substrate.create_signed_extrinsic( - call=call, keypair=wallet.coldkey - ) - response = subtensor.substrate.submit_extrinsic( - extrinsic=extrinsic, + + success, message = subtensor.sign_and_send_extrinsic( + call=call, + wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) + # We only wait here if we expect finalization. if not wait_for_finalization and not wait_for_inclusion: - return True, "", "Success, extrinsic submitted without waiting." + return True, "", message # Otherwise continue with finalization. - if response.is_success: - block_hash_ = response.block_hash + if success: + block_hash_ = subtensor.get_block_hash() return True, block_hash_, "Success with response." - return False, "", format_error_message(response.error_message) + return False, "", message def transfer_extrinsic( @@ -73,6 +77,7 @@ def transfer_extrinsic( wait_for_inclusion: bool = True, wait_for_finalization: bool = False, keep_alive: bool = True, + period: Optional[int] = None, ) -> bool: """Transfers funds from this wallet to the destination public key address. @@ -84,21 +89,24 @@ def transfer_extrinsic( transfer_all (bool): Whether to transfer all funds from this wallet to the destination address. wait_for_inclusion (bool): If set, waits for the extrinsic to enter a block before returning `True`, or returns `False` if the extrinsic fails to enter the block within the timeout. - wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning + wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning `True`, or returns `False` if the extrinsic fails to be finalized within the timeout. keep_alive (bool): If set, keeps the account alive by keeping the balance above the existential deposit. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. + If the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): Flag is `True` if extrinsic was finalized or included in the block. If we did not wait for finalization / inclusion, the response is `True`, regardless of its inclusion. """ - destination = dest # Validate destination address. - if not is_valid_bittensor_address_or_public_key(destination): + if not is_valid_bittensor_address_or_public_key(dest): logging.error( - f":cross_mark: [red]Invalid destination SS58 address[/red]: {destination}" + f":cross_mark: [red]Invalid destination SS58 address[/red]: {dest}" ) return False + logging.info(f"Initiating transfer on network: {subtensor.network}") # Unlock wallet coldkey. if not (unlock := unlock_key(wallet)).success: @@ -119,7 +127,7 @@ def transfer_extrinsic( else: existential_deposit = subtensor.get_existential_deposit(block=block) - fee = subtensor.get_transfer_fee(wallet=wallet, dest=destination, value=amount) + fee = subtensor.get_transfer_fee(wallet=wallet, dest=dest, value=amount) # Check if we have enough balance. if transfer_all is True: @@ -139,10 +147,11 @@ def transfer_extrinsic( success, block_hash, err_msg = _do_transfer( subtensor=subtensor, wallet=wallet, - destination=destination, + destination=dest, amount=amount, wait_for_finalization=wait_for_finalization, wait_for_inclusion=wait_for_inclusion, + period=period, ) if success: @@ -168,6 +177,6 @@ def transfer_extrinsic( f"Balance: [blue]{account_balance}[/blue] :arrow_right: [green]{new_balance}[/green]" ) return True - else: - logging.error(f":cross_mark: [red]Failed[/red]: {err_msg}") - return False + + logging.error(f":cross_mark: [red]Failed[/red]: {err_msg}") + return False From ac9685c087232737e9621bc745cd60fbb7aeb9a4 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 23:19:50 -0700 Subject: [PATCH 069/100] transfer extrinsics calls in subtensors --- bittensor/core/async_subtensor.py | 10 +++++++--- bittensor/core/subtensor.py | 11 ++++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index c10be33b69..2b11192dcf 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -3283,7 +3283,7 @@ async def sign_and_send_extrinsic( # We only wait here if we expect finalization. if not wait_for_finalization and not wait_for_inclusion: message = "Not waiting for finalization or inclusion." - logging.debug(message) + logging.debug(f"{message}. Extrinsic: {extrinsic}") return True, message if await response.is_success: @@ -4311,6 +4311,7 @@ async def transfer( wait_for_inclusion: bool = True, wait_for_finalization: bool = False, keep_alive: bool = True, + period: Optional[int] = None, ) -> bool: """ Transfer token of amount to destination. @@ -4318,13 +4319,15 @@ async def transfer( Arguments: wallet (bittensor_wallet.Wallet): Source wallet for the transfer. dest (str): Destination address for the transfer. - amount (float): Amount of tokens to transfer. + amount (float): Number of tokens to transfer. transfer_all (bool): Flag to transfer all tokens. Default is ``False``. wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``True``. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``. keep_alive (bool): Flag to keep the connection alive. Default is ``True``. - + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: `True` if the transferring was successful, otherwise `False`. """ @@ -4338,6 +4341,7 @@ async def transfer( wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, keep_alive=keep_alive, + period=period, ) async def unstake( diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 685b715ed8..460fdfd6b8 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -2566,8 +2566,8 @@ def sign_and_send_extrinsic( ) # We only wait here if we expect finalization. if not wait_for_finalization and not wait_for_inclusion: - message = f"Not waiting for finalization or inclusion. Extrinsic: {extrinsic}" - logging.debug(message) + message = f"Not waiting for finalization or inclusion." + logging.debug(f"{message}. Extrinsic: {extrinsic}") return True, message if response.is_success: @@ -3541,6 +3541,7 @@ def transfer( wait_for_finalization: bool = False, transfer_all: bool = False, keep_alive: bool = True, + period: Optional[int] = None, ) -> bool: """ Transfer token of amount to destination. @@ -3548,12 +3549,15 @@ def transfer( Arguments: wallet (bittensor_wallet.Wallet): Source wallet for the transfer. dest (str): Destination address for the transfer. - amount (float): Amount of tokens to transfer. + amount (float): Number of tokens to transfer. transfer_all (bool): Flag to transfer all tokens. Default is ``False``. wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``True``. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``. keep_alive (bool): Flag to keep the connection alive. Default is ``True``. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: `True` if the transferring was successful, otherwise `False`. @@ -3568,6 +3572,7 @@ def transfer( wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, keep_alive=keep_alive, + period=period, ) def transfer_stake( From 770a50acb1e92984d2a5e30a86492f21e38cf078 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 23:19:57 -0700 Subject: [PATCH 070/100] fixed tests --- .../extrinsics/asyncex/test_transfer.py | 91 ++++++------------- tests/unit_tests/extrinsics/test_transfer.py | 15 +-- 2 files changed, 33 insertions(+), 73 deletions(-) diff --git a/tests/unit_tests/extrinsics/asyncex/test_transfer.py b/tests/unit_tests/extrinsics/asyncex/test_transfer.py index 0fa70a8e75..1abd2fe15c 100644 --- a/tests/unit_tests/extrinsics/asyncex/test_transfer.py +++ b/tests/unit_tests/extrinsics/asyncex/test_transfer.py @@ -9,22 +9,13 @@ async def test_do_transfer_success(subtensor, fake_wallet, mocker): # Preps fake_destination = "destination_address" fake_amount = mocker.Mock(autospec=Balance, rao=1000) + fake_block_hash = "fake_block_hash" - fake_call = mocker.AsyncMock() - fake_extrinsic = mocker.AsyncMock() - fake_response = mocker.Mock() - - fake_response.is_success = mocker.AsyncMock(return_value=True)() - fake_response.process_events = mocker.AsyncMock() - fake_response.block_hash = "fake_block_hash" - - mocker.patch.object(subtensor.substrate, "compose_call", return_value=fake_call) - mocker.patch.object( - subtensor.substrate, "create_signed_extrinsic", return_value=fake_extrinsic - ) + mocker.patch.object(subtensor.substrate, "compose_call") mocker.patch.object( - subtensor.substrate, "submit_extrinsic", return_value=fake_response + subtensor, "sign_and_send_extrinsic", new=mocker.AsyncMock(return_value=(True, "")) ) + mocker.patch.object(subtensor, "get_block_hash", return_value=fake_block_hash) # Call success, block_hash, error_message = await async_transfer._do_transfer( @@ -37,18 +28,18 @@ async def test_do_transfer_success(subtensor, fake_wallet, mocker): ) # Asserts - subtensor.substrate.compose_call.assert_called_once_with( + subtensor.substrate.compose_call.assert_awaited_once_with( call_module="Balances", call_function="transfer_allow_death", call_params={"dest": fake_destination, "value": fake_amount.rao}, ) - subtensor.substrate.create_signed_extrinsic.assert_called_once_with( - call=subtensor.substrate.compose_call.return_value, keypair=fake_wallet.coldkey - ) - subtensor.substrate.submit_extrinsic.assert_called_once_with( - extrinsic=subtensor.substrate.create_signed_extrinsic.return_value, + + subtensor.sign_and_send_extrinsic.assert_awaited_once_with( + call=subtensor.substrate.compose_call.return_value, + wallet=fake_wallet, wait_for_inclusion=True, wait_for_finalization=True, + period=None, ) assert success is True assert block_hash == "fake_block_hash" @@ -61,28 +52,13 @@ async def test_do_transfer_failure(subtensor, fake_wallet, mocker): # Preps fake_destination = "destination_address" fake_amount = mocker.Mock(autospec=Balance, rao=1000) + fake_block_hash = "fake_block_hash" - fake_call = mocker.AsyncMock() - fake_extrinsic = mocker.AsyncMock() - fake_response = mocker.Mock() - - fake_response.is_success = mocker.AsyncMock(return_value=False)() - fake_response.process_events = mocker.AsyncMock() - fake_response.error_message = mocker.AsyncMock(return_value="Fake error message")() - - mocker.patch.object(subtensor.substrate, "compose_call", return_value=fake_call) + mocker.patch.object(subtensor.substrate, "compose_call") mocker.patch.object( - subtensor.substrate, "create_signed_extrinsic", return_value=fake_extrinsic - ) - mocker.patch.object( - subtensor.substrate, "submit_extrinsic", return_value=fake_response - ) - - mocked_format_error_message = mocker.patch.object( - async_transfer, - "format_error_message", - return_value="Formatted error message", + subtensor, "sign_and_send_extrinsic", new=mocker.AsyncMock(return_value=(False, "Formatted error message")) ) + mocker.patch.object(subtensor, "get_block_hash", return_value=fake_block_hash) # Call success, block_hash, error_message = await async_transfer._do_transfer( @@ -95,22 +71,21 @@ async def test_do_transfer_failure(subtensor, fake_wallet, mocker): ) # Asserts - subtensor.substrate.compose_call.assert_called_once_with( + subtensor.substrate.compose_call.assert_awaited_once_with( call_module="Balances", call_function="transfer_allow_death", call_params={"dest": fake_destination, "value": fake_amount.rao}, ) - subtensor.substrate.create_signed_extrinsic.assert_called_once_with( - call=subtensor.substrate.compose_call.return_value, keypair=fake_wallet.coldkey - ) - subtensor.substrate.submit_extrinsic.assert_called_once_with( - extrinsic=subtensor.substrate.create_signed_extrinsic.return_value, + + subtensor.sign_and_send_extrinsic.assert_awaited_once_with( + call=subtensor.substrate.compose_call.return_value, + wallet=fake_wallet, wait_for_inclusion=True, wait_for_finalization=True, + period=None, ) assert success is False assert block_hash == "" - mocked_format_error_message.assert_called_once_with("Fake error message") assert error_message == "Formatted error message" @@ -120,19 +95,13 @@ async def test_do_transfer_no_waiting(subtensor, fake_wallet, mocker): # Preps fake_destination = "destination_address" fake_amount = mocker.Mock(autospec=Balance, rao=1000) + fake_block_hash = "fake_block_hash" - fake_call = mocker.AsyncMock() - fake_extrinsic = mocker.AsyncMock() - - mocker.patch.object(subtensor.substrate, "compose_call", return_value=fake_call) + mocker.patch.object(subtensor.substrate, "compose_call") mocker.patch.object( - subtensor.substrate, "create_signed_extrinsic", return_value=fake_extrinsic - ) - mocker.patch.object( - subtensor.substrate, - "submit_extrinsic", - return_value=mocker.Mock(), + subtensor, "sign_and_send_extrinsic", new=mocker.AsyncMock(return_value=(False, "Success, extrinsic submitted without waiting.")) ) + mocker.patch.object(subtensor, "get_block_hash", return_value=fake_block_hash) # Call success, block_hash, error_message = await async_transfer._do_transfer( @@ -145,18 +114,18 @@ async def test_do_transfer_no_waiting(subtensor, fake_wallet, mocker): ) # Asserts - subtensor.substrate.compose_call.assert_called_once_with( + subtensor.substrate.compose_call.assert_awaited_once_with( call_module="Balances", call_function="transfer_allow_death", call_params={"dest": fake_destination, "value": fake_amount.rao}, ) - subtensor.substrate.create_signed_extrinsic.assert_called_once_with( - call=subtensor.substrate.compose_call.return_value, keypair=fake_wallet.coldkey - ) - subtensor.substrate.submit_extrinsic.assert_called_once_with( - extrinsic=subtensor.substrate.create_signed_extrinsic.return_value, + + subtensor.sign_and_send_extrinsic.assert_awaited_once_with( + call=subtensor.substrate.compose_call.return_value, + wallet=fake_wallet, wait_for_inclusion=False, wait_for_finalization=False, + period=None, ) assert success is True assert block_hash == "" diff --git a/tests/unit_tests/extrinsics/test_transfer.py b/tests/unit_tests/extrinsics/test_transfer.py index 9424352a55..097156ba49 100644 --- a/tests/unit_tests/extrinsics/test_transfer.py +++ b/tests/unit_tests/extrinsics/test_transfer.py @@ -39,7 +39,7 @@ def test_do_transfer_is_success_true(subtensor, fake_wallet, mocker): # subtensor.substrate.submit_extrinsic.return_value.process_events.assert_called_once() assert result == ( True, - subtensor.substrate.submit_extrinsic.return_value.block_hash, + subtensor.substrate.get_chain_head.return_value, "Success with response.", ) @@ -54,12 +54,6 @@ def test_do_transfer_is_success_false(subtensor, fake_wallet, mocker): subtensor.substrate.submit_extrinsic.return_value.is_success = False - mocked_format_error_message = mocker.Mock() - mocker.patch( - "bittensor.core.extrinsics.transfer.format_error_message", - mocked_format_error_message, - ) - # Call result = _do_transfer( subtensor, @@ -84,14 +78,11 @@ def test_do_transfer_is_success_false(subtensor, fake_wallet, mocker): wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, ) - mocked_format_error_message.assert_called_once_with( - subtensor.substrate.submit_extrinsic.return_value.error_message - ) assert result == ( False, "", - mocked_format_error_message.return_value, + "Subtensor returned `UnknownError(UnknownType)` error. This means: `Unknown Description`.", ) @@ -127,4 +118,4 @@ def test_do_transfer_no_waits(subtensor, fake_wallet, mocker): wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, ) - assert result == (True, "", "Success, extrinsic submitted without waiting.") + assert result == (True, "", "Not waiting for finalization or inclusion.") From 889670202913f093d48d2f1d377cf8c0556ad645 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 23:35:46 -0700 Subject: [PATCH 071/100] replace error + formatting error for staking --- bittensor/core/extrinsics/asyncex/staking.py | 15 +++++---------- bittensor/core/extrinsics/staking.py | 15 +++++---------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/staking.py b/bittensor/core/extrinsics/asyncex/staking.py index f06eb8dced..e0e33e2e9c 100644 --- a/bittensor/core/extrinsics/asyncex/staking.py +++ b/bittensor/core/extrinsics/asyncex/staking.py @@ -3,7 +3,7 @@ from async_substrate_interface.errors import SubstrateRequestException from bittensor.core.errors import StakeError, NotRegisteredError from bittensor.core.extrinsics.utils import get_old_stakes -from bittensor.utils import unlock_key +from bittensor.utils import unlock_key, format_error_message from bittensor.utils.balance import Balance from bittensor.utils.btlogging import logging @@ -203,8 +203,8 @@ async def add_stake_extrinsic( logging.error(f":cross_mark: [red]Failed: {err_msg}.[/red]") return False - except SubstrateRequestException as e: - logging.error(f":cross_mark: [red]Add Stake Error: {e}[/red]") + except SubstrateRequestException as error: + logging.error(f":cross_mark: [red]Add Stake Error: {format_error_message(error)}[/red]") return False @@ -400,13 +400,8 @@ async def add_stake_multiple_extrinsic( logging.error(f":cross_mark: [red]Failed: {message}.[/red]") continue - except NotRegisteredError: - logging.error( - f":cross_mark: [red]Hotkey: {hotkey_ss58} is not registered.[/red]" - ) - continue - except StakeError as e: - logging.error(f":cross_mark: [red]Stake Error: {e}[/red]") + except SubstrateRequestException as error: + logging.error(f":cross_mark: [red]Add Stake Multiple error: {format_error_message(error)}[/red]") continue if successful_stakes != 0: diff --git a/bittensor/core/extrinsics/staking.py b/bittensor/core/extrinsics/staking.py index 8b99743c81..ae883a72ee 100644 --- a/bittensor/core/extrinsics/staking.py +++ b/bittensor/core/extrinsics/staking.py @@ -4,7 +4,7 @@ from bittensor.core.errors import StakeError, NotRegisteredError from bittensor.core.extrinsics.utils import get_old_stakes -from bittensor.utils import unlock_key +from bittensor.utils import unlock_key, format_error_message from bittensor.utils.balance import Balance from bittensor.utils.btlogging import logging @@ -199,8 +199,8 @@ def add_stake_extrinsic( logging.error(f":cross_mark: [red]Failed: {message}.[/red]") return False - except SubstrateRequestException as e: - logging.error(f":cross_mark: [red]Add Stake Error: {e}[/red]") + except SubstrateRequestException as error: + logging.error(f":cross_mark: [red]Add Stake Error: {format_error_message((error))}[/red]") return False @@ -385,13 +385,8 @@ def add_stake_multiple_extrinsic( logging.error(f":cross_mark: [red]Failed[/red]: {message}") continue - except NotRegisteredError: - logging.error( - f":cross_mark: [red]Hotkey: {hotkey_ss58} is not registered.[/red]" - ) - continue - except StakeError as e: - logging.error(f":cross_mark: [red]Stake Error: {e}[/red]") + except SubstrateRequestException as error: + logging.error(f":cross_mark: [red]Add Stake Multiple error: {format_error_message(error)}[/red]") continue if successful_stakes != 0: From de076c999ea577129dbfc5a0c0840846f45c1d1e Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 23:46:22 -0700 Subject: [PATCH 072/100] update unstaking extrinsics --- .../core/extrinsics/asyncex/unstaking.py | 45 +++++++------- bittensor/core/extrinsics/unstaking.py | 60 ++++++++++--------- 2 files changed, 54 insertions(+), 51 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/unstaking.py b/bittensor/core/extrinsics/asyncex/unstaking.py index 54fb43c79d..8e322e4c05 100644 --- a/bittensor/core/extrinsics/asyncex/unstaking.py +++ b/bittensor/core/extrinsics/asyncex/unstaking.py @@ -1,11 +1,12 @@ import asyncio from typing import Optional, TYPE_CHECKING -from bittensor.core.errors import StakeError, NotRegisteredError -from bittensor.utils import unlock_key +from async_substrate_interface.errors import SubstrateRequestException + +from bittensor.core.extrinsics.utils import get_old_stakes +from bittensor.utils import unlock_key, format_error_message from bittensor.utils.balance import Balance from bittensor.utils.btlogging import logging -from bittensor.core.extrinsics.utils import get_old_stakes if TYPE_CHECKING: from bittensor_wallet import Wallet @@ -23,6 +24,7 @@ async def unstake_extrinsic( safe_staking: bool = False, allow_partial_stake: bool = False, rate_tolerance: float = 0.005, + period: Optional[int] = None, ) -> bool: """Removes stake into the wallet coldkey from the specified hotkey ``uid``. @@ -40,6 +42,9 @@ async def unstake_extrinsic( safe_staking: If true, enables price safety checks allow_partial_stake: If true, allows partial unstaking if price tolerance exceeded rate_tolerance: Maximum allowed price decrease percentage (0.005 = 0.5%) + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. + If the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. If we did not wait for @@ -133,7 +138,7 @@ async def unstake_extrinsic( call_function=call_function, call_params=call_params, ) - staking_response, err_msg = await subtensor.sign_and_send_extrinsic( + success, message = await subtensor.sign_and_send_extrinsic( call, wallet, wait_for_inclusion, @@ -141,9 +146,10 @@ async def unstake_extrinsic( nonce_key="coldkeypub", sign_with="coldkey", use_nonce=True, + period=period, ) - if staking_response is True: # If we successfully unstaked. + if success is True: # If we successfully unstaked. # We only wait here if we expect finalization. if not wait_for_finalization and not wait_for_inclusion: return True @@ -174,21 +180,16 @@ async def unstake_extrinsic( ) return True else: - if safe_staking and "Custom error: 8" in err_msg: + if safe_staking and "Custom error: 8" in message: logging.error( ":cross_mark: [red]Failed[/red]: Price exceeded tolerance limit. Either increase price tolerance or enable partial staking." ) else: - logging.error(f":cross_mark: [red]Failed: {err_msg}.[/red]") + logging.error(f":cross_mark: [red]Failed: {message}.[/red]") return False - except NotRegisteredError: - logging.error( - f":cross_mark: [red]Hotkey: {wallet.hotkey_str} is not registered.[/red]" - ) - return False - except StakeError as e: - logging.error(f":cross_mark: [red]Stake Error: {e}[/red]") + except SubstrateRequestException as error: + logging.error(f":cross_mark: [red]Unstake filed with error: {format_error_message(error)}[/red]") return False @@ -200,6 +201,7 @@ async def unstake_multiple_extrinsic( amounts: Optional[list[Balance]] = None, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: """Removes stake from each ``hotkey_ss58`` in the list, using each amount, to a common coldkey. @@ -213,6 +215,9 @@ async def unstake_multiple_extrinsic( returns ``False`` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. + If the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. Flag is ``True`` if any @@ -317,6 +322,7 @@ async def unstake_multiple_extrinsic( nonce_key="coldkeypub", sign_with="coldkey", use_nonce=True, + period=period, ) if staking_response is True: # If we successfully unstaked. @@ -347,14 +353,9 @@ async def unstake_multiple_extrinsic( logging.error(f":cross_mark: [red]Failed: {err_msg}.[/red]") continue - except NotRegisteredError: - logging.error( - f":cross_mark: [red]Hotkey[/red] [blue]{hotkey_ss58}[/blue] [red]is not registered.[/red]" - ) - continue - except StakeError as e: - logging.error(f":cross_mark: [red]Stake Error: {e}[/red]") - continue + except SubstrateRequestException as error: + logging.error(f":cross_mark: [red]Multiple unstake filed with error: {format_error_message(error)}[/red]") + return False if successful_unstakes != 0: logging.info( diff --git a/bittensor/core/extrinsics/unstaking.py b/bittensor/core/extrinsics/unstaking.py index f49362a4db..f4bb46f425 100644 --- a/bittensor/core/extrinsics/unstaking.py +++ b/bittensor/core/extrinsics/unstaking.py @@ -1,8 +1,9 @@ from typing import Optional, TYPE_CHECKING -from bittensor.core.errors import StakeError, NotRegisteredError +from async_substrate_interface.errors import SubstrateRequestException + from bittensor.core.extrinsics.utils import get_old_stakes -from bittensor.utils import unlock_key +from bittensor.utils import unlock_key, format_error_message from bittensor.utils.balance import Balance from bittensor.utils.btlogging import logging @@ -22,6 +23,7 @@ def unstake_extrinsic( safe_staking: bool = False, allow_partial_stake: bool = False, rate_tolerance: float = 0.005, + period: Optional[int] = None, ) -> bool: """Removes stake into the wallet coldkey from the specified hotkey ``uid``. @@ -39,6 +41,9 @@ def unstake_extrinsic( safe_staking: If true, enables price safety checks allow_partial_stake: If true, allows partial unstaking if price tolerance exceeded rate_tolerance: Maximum allowed price decrease percentage (0.005 = 0.5%) + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. + If the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. If we did not wait for @@ -64,6 +69,7 @@ def unstake_extrinsic( block=block, ) + # Covert to bittensor.Balance if amount is None: # Unstake it all. logging.warning( @@ -131,17 +137,18 @@ def unstake_extrinsic( call_params=call_params, ) - staking_response, err_msg = subtensor.sign_and_send_extrinsic( - call, - wallet, - wait_for_inclusion, - wait_for_finalization, + success, message = subtensor.sign_and_send_extrinsic( + call=call, + wallet=wallet, + wait_for_inclusion=wait_for_inclusion, + wait_for_finalization=wait_for_finalization, nonce_key="coldkeypub", sign_with="coldkey", use_nonce=True, + period=period, ) - if staking_response is True: # If we successfully unstaked. + if success is True: # If we successfully unstaked. # We only wait here if we expect finalization. if not wait_for_finalization and not wait_for_inclusion: return True @@ -170,21 +177,16 @@ def unstake_extrinsic( ) return True else: - if safe_staking and "Custom error: 8" in err_msg: + if safe_staking and "Custom error: 8" in message: logging.error( ":cross_mark: [red]Failed[/red]: Price exceeded tolerance limit. Either increase price tolerance or enable partial staking." ) else: - logging.error(f":cross_mark: [red]Failed: {err_msg}.[/red]") + logging.error(f":cross_mark: [red]Failed: {message}.[/red]") return False - except NotRegisteredError: - logging.error( - f":cross_mark: [red]Hotkey: {wallet.hotkey_str} is not registered.[/red]" - ) - return False - except StakeError as e: - logging.error(f":cross_mark: [red]Stake Error: {e}[/red]") + except SubstrateRequestException as error: + logging.error(f":cross_mark: [red]Unstake filed with error: {format_error_message(error)}[/red]") return False @@ -196,6 +198,7 @@ def unstake_multiple_extrinsic( amounts: Optional[list[Balance]] = None, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: """Removes stake from each ``hotkey_ss58`` in the list, using each amount, to a common coldkey. @@ -209,6 +212,9 @@ def unstake_multiple_extrinsic( returns ``False`` if the extrinsic fails to enter the block within the timeout. wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning ``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. + If the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. Flag is ``True`` if any @@ -298,13 +304,14 @@ def unstake_multiple_extrinsic( }, ) staking_response, err_msg = subtensor.sign_and_send_extrinsic( - call, - wallet, - wait_for_inclusion, - wait_for_finalization, + call=call, + wallet=wallet, + wait_for_inclusion=wait_for_inclusion, + wait_for_finalization=wait_for_finalization, nonce_key="coldkeypub", sign_with="coldkey", use_nonce=True, + period=period, ) if staking_response is True: # If we successfully unstaked. @@ -334,14 +341,9 @@ def unstake_multiple_extrinsic( logging.error(f":cross_mark: [red]Failed: {err_msg}.[/red]") continue - except NotRegisteredError: - logging.error( - f":cross_mark: [red]Hotkey[/red] [blue]{hotkey_ss58}[/blue] [red]is not registered.[/red]" - ) - continue - except StakeError as e: - logging.error(":cross_mark: [red]Stake Error: {}[/red]".format(e)) - continue + except SubstrateRequestException as error: + logging.error(f":cross_mark: [red]Multiple unstake filed with error: {format_error_message(error)}[/red]") + return False if successful_unstakes != 0: logging.info( From 1bd2e4e2f0da93e74c6fe4b2680af5ec6399cb09 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 23:46:46 -0700 Subject: [PATCH 073/100] update subtensor unstaking calls --- bittensor/core/async_subtensor.py | 10 ++++++++++ bittensor/core/subtensor.py | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index 2b11192dcf..c93007aa50 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -4355,6 +4355,7 @@ async def unstake( safe_staking: bool = False, allow_partial_stake: bool = False, rate_tolerance: float = 0.005, + period: Optional[int] = None, ) -> bool: """ Removes a specified amount of stake from a single hotkey account. This function is critical for adjusting @@ -4375,6 +4376,9 @@ async def unstake( exceed the threshold. Default is False. rate_tolerance (float): The maximum allowed price change ratio when unstaking. For example, 0.005 = 0.5% maximum price decrease. Only used when safe_staking is True. Default is 0.005. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: ``True`` if the unstaking process is successful, False otherwise. @@ -4394,6 +4398,7 @@ async def unstake( safe_staking=safe_staking, allow_partial_stake=allow_partial_stake, rate_tolerance=rate_tolerance, + period=period, ) async def unstake_multiple( @@ -4404,6 +4409,7 @@ async def unstake_multiple( amounts: Optional[list[Balance]] = None, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: """ Performs batch unstaking from multiple hotkey accounts, allowing a neuron to reduce its staked amounts @@ -4418,6 +4424,9 @@ async def unstake_multiple( unstakes all available stakes. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: ``True`` if the batch unstaking is successful, False otherwise. @@ -4433,6 +4442,7 @@ async def unstake_multiple( amounts=amounts, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 460fdfd6b8..c6cbd34373 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -3631,6 +3631,7 @@ def unstake( safe_staking: bool = False, allow_partial_stake: bool = False, rate_tolerance: float = 0.005, + period: Optional[int] = None, ) -> bool: """ Removes a specified amount of stake from a single hotkey account. This function is critical for adjusting @@ -3651,6 +3652,9 @@ def unstake( exceed the tolerance. Default is False. rate_tolerance (float): The maximum allowed price change ratio when unstaking. For example, 0.005 = 0.5% maximum price decrease. Only used when safe_staking is True. Default is 0.005. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: ``True`` if the unstaking process is successful, False otherwise. @@ -3671,6 +3675,7 @@ def unstake( safe_staking=safe_staking, allow_partial_stake=allow_partial_stake, rate_tolerance=rate_tolerance, + period=period, ) def unstake_multiple( @@ -3681,6 +3686,7 @@ def unstake_multiple( amounts: Optional[list[Balance]] = None, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + period: Optional[int] = None, ) -> bool: """ Performs batch unstaking from multiple hotkey accounts, allowing a neuron to reduce its staked amounts @@ -3695,6 +3701,9 @@ def unstake_multiple( unstakes all available stakes. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: bool: ``True`` if the batch unstaking is successful, False otherwise. @@ -3710,4 +3719,5 @@ def unstake_multiple( amounts=amounts, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) From ef80b8b66c07276d4387e9ee9ca9b6bbf8ff2c7a Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 23:46:54 -0700 Subject: [PATCH 074/100] fix related tests --- tests/unit_tests/extrinsics/test_unstaking.py | 18 ++++++++++-------- tests/unit_tests/test_async_subtensor.py | 1 + tests/unit_tests/test_subtensor.py | 4 ++++ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/tests/unit_tests/extrinsics/test_unstaking.py b/tests/unit_tests/extrinsics/test_unstaking.py index 224fe4b640..2fdf0cbe47 100644 --- a/tests/unit_tests/extrinsics/test_unstaking.py +++ b/tests/unit_tests/extrinsics/test_unstaking.py @@ -43,13 +43,14 @@ def test_unstake_extrinsic(fake_wallet, mocker): }, ) fake_subtensor.sign_and_send_extrinsic.assert_called_once_with( - fake_subtensor.substrate.compose_call.return_value, - fake_wallet, - True, - True, + call=fake_subtensor.substrate.compose_call.return_value, + wallet=fake_wallet, + wait_for_inclusion=True, + wait_for_finalization=True, sign_with="coldkey", nonce_key="coldkeypub", use_nonce=True, + period=None, ) @@ -109,11 +110,12 @@ def test_unstake_multiple_extrinsic(fake_wallet, mocker): }, ) fake_subtensor.sign_and_send_extrinsic.assert_called_with( - fake_subtensor.substrate.compose_call.return_value, - fake_wallet, - True, - True, + call=fake_subtensor.substrate.compose_call.return_value, + wallet=fake_wallet, + wait_for_inclusion=True, + wait_for_finalization=True, sign_with="coldkey", nonce_key="coldkeypub", use_nonce=True, + period=None, ) diff --git a/tests/unit_tests/test_async_subtensor.py b/tests/unit_tests/test_async_subtensor.py index 892836e2d8..b61df6dfaa 100644 --- a/tests/unit_tests/test_async_subtensor.py +++ b/tests/unit_tests/test_async_subtensor.py @@ -2518,6 +2518,7 @@ async def test_transfer_success(subtensor, fake_wallet, mocker): wait_for_inclusion=True, wait_for_finalization=False, keep_alive=True, + period=None, ) assert result == mocked_transfer_extrinsic.return_value diff --git a/tests/unit_tests/test_subtensor.py b/tests/unit_tests/test_subtensor.py index e3588178c5..03b45a35fe 100644 --- a/tests/unit_tests/test_subtensor.py +++ b/tests/unit_tests/test_subtensor.py @@ -1327,6 +1327,7 @@ def test_transfer(subtensor, fake_wallet, mocker): wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, keep_alive=True, + period=None, ) assert result == mocked_transfer_extrinsic.return_value @@ -2937,6 +2938,7 @@ def test_unstake_success(mocker, subtensor, fake_wallet): safe_staking=False, allow_partial_stake=False, rate_tolerance=0.005, + period=None, ) assert result == mock_unstake_extrinsic.return_value @@ -2973,6 +2975,7 @@ def test_unstake_with_safe_staking(mocker, subtensor, fake_wallet): safe_staking=True, allow_partial_stake=True, rate_tolerance=fake_rate_tolerance, + period=None, ) assert result == mock_unstake_extrinsic.return_value @@ -3095,6 +3098,7 @@ def test_unstake_multiple_success(mocker, subtensor, fake_wallet): amounts=fake_amounts, wait_for_inclusion=True, wait_for_finalization=False, + period=None, ) assert result == mock_unstake_multiple_extrinsic.return_value From bf7c9bbf24ce39e56c9660bcb5c1f78158379afa Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 1 May 2025 23:47:18 -0700 Subject: [PATCH 075/100] del unused imports --- bittensor/core/extrinsics/asyncex/staking.py | 3 ++- bittensor/core/extrinsics/staking.py | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/staking.py b/bittensor/core/extrinsics/asyncex/staking.py index e0e33e2e9c..c148fa86f9 100644 --- a/bittensor/core/extrinsics/asyncex/staking.py +++ b/bittensor/core/extrinsics/asyncex/staking.py @@ -1,7 +1,8 @@ import asyncio from typing import Optional, Sequence, TYPE_CHECKING + from async_substrate_interface.errors import SubstrateRequestException -from bittensor.core.errors import StakeError, NotRegisteredError + from bittensor.core.extrinsics.utils import get_old_stakes from bittensor.utils import unlock_key, format_error_message from bittensor.utils.balance import Balance diff --git a/bittensor/core/extrinsics/staking.py b/bittensor/core/extrinsics/staking.py index ae883a72ee..86014c5b07 100644 --- a/bittensor/core/extrinsics/staking.py +++ b/bittensor/core/extrinsics/staking.py @@ -2,7 +2,6 @@ from async_substrate_interface.errors import SubstrateRequestException -from bittensor.core.errors import StakeError, NotRegisteredError from bittensor.core.extrinsics.utils import get_old_stakes from bittensor.utils import unlock_key, format_error_message from bittensor.utils.balance import Balance From d7a6ef17c3cce04d4427fc00428deca96d48d9d3 Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 2 May 2025 00:44:36 -0700 Subject: [PATCH 076/100] fix a bunch of unit test's inner calls --- .../core/extrinsics/asyncex/move_stake.py | 10 +- bittensor/core/extrinsics/asyncex/root.py | 2 +- bittensor/core/extrinsics/asyncex/serving.py | 2 +- .../core/extrinsics/asyncex/unstaking.py | 16 ++-- bittensor/core/extrinsics/asyncex/weights.py | 24 ++--- bittensor/core/extrinsics/commit_weights.py | 16 ++-- bittensor/core/extrinsics/move_stake.py | 8 +- bittensor/core/extrinsics/root.py | 4 +- bittensor/core/extrinsics/take.py | 8 +- bittensor/core/extrinsics/utils.py | 7 +- .../extrinsics/asyncex/test_registration.py | 93 ++++++------------- .../extrinsics/test_commit_weights.py | 56 ++++------- tests/unit_tests/extrinsics/test_root.py | 4 +- tests/unit_tests/extrinsics/test_transfer.py | 49 +++++----- 14 files changed, 115 insertions(+), 184 deletions(-) diff --git a/bittensor/core/extrinsics/asyncex/move_stake.py b/bittensor/core/extrinsics/asyncex/move_stake.py index 8848e3f4e2..8cfd5a2604 100644 --- a/bittensor/core/extrinsics/asyncex/move_stake.py +++ b/bittensor/core/extrinsics/asyncex/move_stake.py @@ -82,7 +82,7 @@ async def transfer_stake_extrinsic( # Check sufficient stake stake_in_origin, stake_in_destination = await _get_stake_in_origin_and_dest( - subtensor, + subtensor=subtensor, origin_hotkey_ss58=hotkey_ss58, destination_hotkey_ss58=hotkey_ss58, origin_coldkey_ss58=wallet.coldkeypub.ss58_address, @@ -132,7 +132,7 @@ async def transfer_stake_extrinsic( # Get updated stakes origin_stake, dest_stake = await _get_stake_in_origin_and_dest( - subtensor, + subtensor=subtensor, origin_hotkey_ss58=hotkey_ss58, destination_hotkey_ss58=hotkey_ss58, origin_coldkey_ss58=wallet.coldkeypub.ss58_address, @@ -205,7 +205,7 @@ async def swap_stake_extrinsic( # Check sufficient stake stake_in_origin, stake_in_destination = await _get_stake_in_origin_and_dest( - subtensor, + subtensor=subtensor, origin_hotkey_ss58=hotkey_ss58, destination_hotkey_ss58=hotkey_ss58, origin_coldkey_ss58=wallet.coldkeypub.ss58_address, @@ -346,7 +346,7 @@ async def move_stake_extrinsic( # Check sufficient stake stake_in_origin, stake_in_destination = await _get_stake_in_origin_and_dest( - subtensor, + subtensor=subtensor, origin_hotkey_ss58=origin_hotkey, destination_hotkey_ss58=destination_hotkey, origin_coldkey_ss58=wallet.coldkeypub.ss58_address, @@ -395,7 +395,7 @@ async def move_stake_extrinsic( # Get updated stakes origin_stake, dest_stake = await _get_stake_in_origin_and_dest( - subtensor, + subtensor=subtensor, origin_hotkey_ss58=origin_hotkey, destination_hotkey_ss58=destination_hotkey, origin_coldkey_ss58=wallet.coldkeypub.ss58_address, diff --git a/bittensor/core/extrinsics/asyncex/root.py b/bittensor/core/extrinsics/asyncex/root.py index 74eb15689d..4641676e36 100644 --- a/bittensor/core/extrinsics/asyncex/root.py +++ b/bittensor/core/extrinsics/asyncex/root.py @@ -118,7 +118,7 @@ async def root_register_extrinsic( call_params={"hotkey": wallet.hotkey.ss58_address}, ) success, message = await subtensor.sign_and_send_extrinsic( - call, + call=call, wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, diff --git a/bittensor/core/extrinsics/asyncex/serving.py b/bittensor/core/extrinsics/asyncex/serving.py index 007be2a12b..c86a681b08 100644 --- a/bittensor/core/extrinsics/asyncex/serving.py +++ b/bittensor/core/extrinsics/asyncex/serving.py @@ -57,7 +57,7 @@ async def do_serve_axon( call_params=call_params.dict(), ) success, message = await subtensor.sign_and_send_extrinsic( - call, + call=call, wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, diff --git a/bittensor/core/extrinsics/asyncex/unstaking.py b/bittensor/core/extrinsics/asyncex/unstaking.py index 8e322e4c05..b114dc7e23 100644 --- a/bittensor/core/extrinsics/asyncex/unstaking.py +++ b/bittensor/core/extrinsics/asyncex/unstaking.py @@ -139,10 +139,10 @@ async def unstake_extrinsic( call_params=call_params, ) success, message = await subtensor.sign_and_send_extrinsic( - call, - wallet, - wait_for_inclusion, - wait_for_finalization, + call=call, + wallet=wallet, + wait_for_inclusion=wait_for_inclusion, + wait_for_finalization=wait_for_finalization, nonce_key="coldkeypub", sign_with="coldkey", use_nonce=True, @@ -315,10 +315,10 @@ async def unstake_multiple_extrinsic( ) staking_response, err_msg = await subtensor.sign_and_send_extrinsic( - call, - wallet, - wait_for_inclusion, - wait_for_finalization, + call=call, + wallet=wallet, + wait_for_inclusion=wait_for_inclusion, + wait_for_finalization=wait_for_finalization, nonce_key="coldkeypub", sign_with="coldkey", use_nonce=True, diff --git a/bittensor/core/extrinsics/asyncex/weights.py b/bittensor/core/extrinsics/asyncex/weights.py index 7f04ffd7bd..4b3d5cd56d 100644 --- a/bittensor/core/extrinsics/asyncex/weights.py +++ b/bittensor/core/extrinsics/asyncex/weights.py @@ -56,10 +56,10 @@ async def _do_commit_weights( }, ) return await subtensor.sign_and_send_extrinsic( - call, - wallet, - wait_for_inclusion, - wait_for_finalization, + call=call, + wallet=wallet, + wait_for_inclusion=wait_for_inclusion, + wait_for_finalization=wait_for_finalization, use_nonce=True, period=period, nonce_key="hotkey", @@ -170,10 +170,10 @@ async def _do_reveal_weights( }, ) return await subtensor.sign_and_send_extrinsic( - call, - wallet, - wait_for_inclusion, - wait_for_finalization, + call=call, + wallet=wallet, + wait_for_inclusion=wait_for_inclusion, + wait_for_finalization=wait_for_finalization, sign_with="hotkey", period=period, nonce_key="hotkey", @@ -288,10 +288,10 @@ async def _do_set_weights( }, ) success, message = await subtensor.sign_and_send_extrinsic( - call, - wallet, - wait_for_inclusion, - wait_for_finalization, + call=call, + wallet=wallet, + wait_for_inclusion=wait_for_inclusion, + wait_for_finalization=wait_for_finalization, period=period, use_nonce=True, nonce_key="hotkey", diff --git a/bittensor/core/extrinsics/commit_weights.py b/bittensor/core/extrinsics/commit_weights.py index e139907b65..511d1364ef 100644 --- a/bittensor/core/extrinsics/commit_weights.py +++ b/bittensor/core/extrinsics/commit_weights.py @@ -50,10 +50,10 @@ def _do_commit_weights( }, ) return subtensor.sign_and_send_extrinsic( - call, - wallet, - wait_for_inclusion, - wait_for_finalization, + call=call, + wallet=wallet, + wait_for_inclusion=wait_for_inclusion, + wait_for_finalization=wait_for_finalization, use_nonce=True, period=period, sign_with="hotkey", @@ -164,10 +164,10 @@ def _do_reveal_weights( }, ) return subtensor.sign_and_send_extrinsic( - call, - wallet, - wait_for_inclusion, - wait_for_finalization, + call=call, + wallet=wallet, + wait_for_inclusion=wait_for_inclusion, + wait_for_finalization=wait_for_finalization, use_nonce=True, period=period, sign_with="hotkey", diff --git a/bittensor/core/extrinsics/move_stake.py b/bittensor/core/extrinsics/move_stake.py index 58e651b3e9..3e7e49eefd 100644 --- a/bittensor/core/extrinsics/move_stake.py +++ b/bittensor/core/extrinsics/move_stake.py @@ -203,7 +203,7 @@ def swap_stake_extrinsic( # Check sufficient stake stake_in_origin, stake_in_destination = _get_stake_in_origin_and_dest( - subtensor, + subtensor=subtensor, origin_hotkey_ss58=hotkey_ss58, destination_hotkey_ss58=hotkey_ss58, origin_netuid=origin_netuid, @@ -276,7 +276,7 @@ def swap_stake_extrinsic( # Get updated stakes origin_stake, dest_stake = _get_stake_in_origin_and_dest( - subtensor, + subtensor=subtensor, origin_hotkey_ss58=hotkey_ss58, destination_hotkey_ss58=hotkey_ss58, origin_netuid=origin_netuid, @@ -343,7 +343,7 @@ def move_stake_extrinsic( # Check sufficient stake stake_in_origin, stake_in_destination = _get_stake_in_origin_and_dest( - subtensor, + subtensor=subtensor, origin_hotkey_ss58=origin_hotkey, destination_hotkey_ss58=destination_hotkey, origin_netuid=origin_netuid, @@ -390,7 +390,7 @@ def move_stake_extrinsic( # Get updated stakes origin_stake, dest_stake = _get_stake_in_origin_and_dest( - subtensor, + subtensor=subtensor, origin_hotkey_ss58=origin_hotkey, destination_hotkey_ss58=destination_hotkey, origin_netuid=origin_netuid, diff --git a/bittensor/core/extrinsics/root.py b/bittensor/core/extrinsics/root.py index 3545909493..36d3a92a57 100644 --- a/bittensor/core/extrinsics/root.py +++ b/bittensor/core/extrinsics/root.py @@ -83,7 +83,7 @@ def root_register_extrinsic( block=block, ) balance = subtensor.get_balance( - wallet.coldkeypub.ss58_address, + address=wallet.coldkeypub.ss58_address, block=block, ) @@ -119,7 +119,7 @@ def root_register_extrinsic( call_params={"hotkey": wallet.hotkey.ss58_address}, ) success, err_msg = subtensor.sign_and_send_extrinsic( - call, + call=call, wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, diff --git a/bittensor/core/extrinsics/take.py b/bittensor/core/extrinsics/take.py index 20f4de2f8f..fb47bdc770 100644 --- a/bittensor/core/extrinsics/take.py +++ b/bittensor/core/extrinsics/take.py @@ -50,8 +50,8 @@ def increase_take_extrinsic( ) return subtensor.sign_and_send_extrinsic( - call, - wallet, + call=call, + wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, period=period, @@ -101,8 +101,8 @@ def decrease_take_extrinsic( ) return subtensor.sign_and_send_extrinsic( - call, - wallet, + call=call, + wallet=wallet, wait_for_inclusion=wait_for_inclusion, raise_error=raise_error, wait_for_finalization=wait_for_finalization, diff --git a/bittensor/core/extrinsics/utils.py b/bittensor/core/extrinsics/utils.py index a23126d1c8..7566aa9bc2 100644 --- a/bittensor/core/extrinsics/utils.py +++ b/bittensor/core/extrinsics/utils.py @@ -1,17 +1,12 @@ """Module with helper functions for extrinsics.""" -from typing import TYPE_CHECKING, Union - -import numpy as np -from numpy.typing import NDArray +from typing import TYPE_CHECKING from bittensor.utils.balance import Balance -from bittensor.utils.weight_utils import convert_weights_and_uids_for_emit if TYPE_CHECKING: from bittensor_wallet import Wallet from bittensor.core.chain_data import StakeInfo - from bittensor.utils.registration import torch def get_old_stakes( diff --git a/tests/unit_tests/extrinsics/asyncex/test_registration.py b/tests/unit_tests/extrinsics/asyncex/test_registration.py index 322c132045..fa1e66d67b 100644 --- a/tests/unit_tests/extrinsics/asyncex/test_registration.py +++ b/tests/unit_tests/extrinsics/asyncex/test_registration.py @@ -16,19 +16,8 @@ async def test_do_pow_register_success(subtensor, fake_wallet, mocker): seal=b"fake_seal", ) - fake_call = mocker.AsyncMock() - fake_extrinsic = mocker.AsyncMock() - fake_response = mocker.Mock() - fake_response.is_success = mocker.AsyncMock(return_value=True)() - fake_response.process_events = mocker.AsyncMock() - - mocker.patch.object(subtensor.substrate, "compose_call", return_value=fake_call) - mocker.patch.object( - subtensor.substrate, "create_signed_extrinsic", return_value=fake_extrinsic - ) - mocker.patch.object( - subtensor.substrate, "submit_extrinsic", return_value=fake_response - ) + mocker.patch.object(subtensor.substrate, "compose_call") + mocker.patch.object(subtensor, "sign_and_send_extrinsic", new=mocker.AsyncMock(return_value=(True, ""))) # Call result, error_message = await async_registration._do_pow_register( @@ -53,12 +42,12 @@ async def test_do_pow_register_success(subtensor, fake_wallet, mocker): "coldkey": "coldkey_ss58", }, ) - subtensor.substrate.create_signed_extrinsic.assert_awaited_once_with( - call=fake_call, - keypair=fake_wallet.coldkey, - ) - subtensor.substrate.submit_extrinsic.assert_awaited_once_with( - fake_extrinsic, wait_for_inclusion=True, wait_for_finalization=True + subtensor.sign_and_send_extrinsic.assert_awaited_once_with( + call=subtensor.substrate.compose_call.return_value, + wallet=fake_wallet, + wait_for_inclusion=True, + wait_for_finalization=True, + period=None ) assert result is True assert error_message == "" @@ -75,25 +64,9 @@ async def test_do_pow_register_failure(subtensor, fake_wallet, mocker): nonce=67890, seal=b"fake_seal", ) - fake_err_message = mocker.Mock(autospec=str) - fake_call = mocker.AsyncMock() - fake_extrinsic = mocker.AsyncMock() - fake_response = mocker.Mock() - fake_response.is_success = mocker.AsyncMock(return_value=False)() - fake_response.process_events = mocker.AsyncMock() - fake_response.error_message = mocker.AsyncMock(return_value=fake_err_message)() - - mocker.patch.object(subtensor.substrate, "compose_call", return_value=fake_call) - mocker.patch.object( - subtensor.substrate, "create_signed_extrinsic", return_value=fake_extrinsic - ) - mocker.patch.object( - subtensor.substrate, "submit_extrinsic", return_value=fake_response - ) - mocked_format_error_message = mocker.patch.object( - async_subtensor, "format_error_message" - ) + mocker.patch.object(subtensor.substrate, "compose_call") + mocker.patch.object(subtensor, "sign_and_send_extrinsic") # Call result_error_message = await async_registration._do_pow_register( @@ -118,16 +91,15 @@ async def test_do_pow_register_failure(subtensor, fake_wallet, mocker): "coldkey": "coldkey_ss58", }, ) - subtensor.substrate.create_signed_extrinsic.assert_awaited_once_with( - call=fake_call, - keypair=fake_wallet.coldkey, - ) - subtensor.substrate.submit_extrinsic.assert_awaited_once_with( - fake_extrinsic, wait_for_inclusion=True, wait_for_finalization=True + subtensor.sign_and_send_extrinsic.assert_awaited_once_with( + call=subtensor.substrate.compose_call.return_value, + wallet=fake_wallet, + wait_for_inclusion=True, + wait_for_finalization=True, + period=None ) - mocked_format_error_message.assert_called_once_with(fake_err_message) - assert result_error_message == (False, mocked_format_error_message.return_value) + assert result_error_message == subtensor.sign_and_send_extrinsic.return_value @pytest.mark.asyncio @@ -142,20 +114,11 @@ async def test_do_pow_register_no_waiting(subtensor, fake_wallet, mocker): seal=b"fake_seal", ) - fake_call = mocker.AsyncMock() - fake_extrinsic = mocker.AsyncMock() - fake_response = mocker.Mock() - - mocker.patch.object(subtensor.substrate, "compose_call", return_value=fake_call) - mocker.patch.object( - subtensor.substrate, "create_signed_extrinsic", return_value=fake_extrinsic - ) - mocker.patch.object( - subtensor.substrate, "submit_extrinsic", return_value=fake_response - ) + mocker.patch.object(subtensor.substrate, "compose_call") + mocker.patch.object(subtensor, "sign_and_send_extrinsic") # Call - result, error_message = await async_registration._do_pow_register( + result = await async_registration._do_pow_register( subtensor=subtensor, netuid=1, wallet=fake_wallet, @@ -177,15 +140,15 @@ async def test_do_pow_register_no_waiting(subtensor, fake_wallet, mocker): "coldkey": "coldkey_ss58", }, ) - subtensor.substrate.create_signed_extrinsic.assert_awaited_once_with( - call=fake_call, - keypair=fake_wallet.coldkey, - ) - subtensor.substrate.submit_extrinsic.assert_awaited_once_with( - fake_extrinsic, wait_for_inclusion=False, wait_for_finalization=False + subtensor.sign_and_send_extrinsic.assert_awaited_once_with( + call=subtensor.substrate.compose_call.return_value, + wallet=fake_wallet, + wait_for_inclusion=False, + wait_for_finalization=False, + period=None ) - assert result is True - assert error_message == "Not waiting for finalization or inclusion." + + assert result == subtensor.sign_and_send_extrinsic.return_value @pytest.mark.asyncio diff --git a/tests/unit_tests/extrinsics/test_commit_weights.py b/tests/unit_tests/extrinsics/test_commit_weights.py index 71771d2247..e27547528b 100644 --- a/tests/unit_tests/extrinsics/test_commit_weights.py +++ b/tests/unit_tests/extrinsics/test_commit_weights.py @@ -13,7 +13,8 @@ def test_do_commit_weights(subtensor, fake_wallet, mocker): wait_for_inclusion = True wait_for_finalization = True - subtensor.substrate.submit_extrinsic.return_value.is_success = None + mocker.patch.object(subtensor, "sign_and_send_extrinsic", return_value=(False, "")) + mocker.patch.object(subtensor, "get_block_hash", return_value=1) mocked_format_error_message = mocker.Mock() mocker.patch( @@ -41,25 +42,18 @@ def test_do_commit_weights(subtensor, fake_wallet, mocker): }, ) - subtensor.substrate.create_signed_extrinsic.assert_called_once() - _, kwargs = subtensor.substrate.create_signed_extrinsic.call_args - assert kwargs["call"] == subtensor.substrate.compose_call.return_value - assert kwargs["keypair"] == fake_wallet.hotkey - - subtensor.substrate.submit_extrinsic.assert_called_once_with( - subtensor.substrate.create_signed_extrinsic.return_value, + subtensor.sign_and_send_extrinsic.assert_called_once_with( + call=subtensor.substrate.compose_call.return_value, + wallet=fake_wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=None, + nonce_key="hotkey", + sign_with="hotkey", + use_nonce=True, ) - mocked_format_error_message.assert_called_once_with( - subtensor.substrate.submit_extrinsic.return_value.error_message, - ) - - assert result == ( - False, - mocked_format_error_message.return_value, - ) + assert result == (False, "") def test_do_reveal_weights(subtensor, fake_wallet, mocker): @@ -74,13 +68,7 @@ def test_do_reveal_weights(subtensor, fake_wallet, mocker): wait_for_inclusion = True wait_for_finalization = True - subtensor.substrate.submit_extrinsic.return_value.is_success = None - - mocked_format_error_message = mocker.Mock() - mocker.patch( - "bittensor.core.subtensor.format_error_message", - mocked_format_error_message, - ) + mocker.patch.object(subtensor, "sign_and_send_extrinsic") # Call result = _do_reveal_weights( @@ -108,23 +96,15 @@ def test_do_reveal_weights(subtensor, fake_wallet, mocker): }, ) - subtensor.substrate.create_signed_extrinsic.assert_called_once_with( + subtensor.sign_and_send_extrinsic( call=subtensor.substrate.compose_call.return_value, - keypair=fake_wallet.hotkey, - nonce=subtensor.substrate.get_account_next_index.return_value, - ) - - subtensor.substrate.submit_extrinsic.assert_called_once_with( - subtensor.substrate.create_signed_extrinsic.return_value, + wallet=fake_wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=None, + nonce_key="hotkey", + sign_with="hotkey", + use_nonce=True, ) - mocked_format_error_message.assert_called_once_with( - subtensor.substrate.submit_extrinsic.return_value.error_message, - ) - - assert result == ( - False, - mocked_format_error_message.return_value, - ) + assert result == subtensor.sign_and_send_extrinsic.return_value diff --git a/tests/unit_tests/extrinsics/test_root.py b/tests/unit_tests/extrinsics/test_root.py index 9324613fe8..0ebaca5be7 100644 --- a/tests/unit_tests/extrinsics/test_root.py +++ b/tests/unit_tests/extrinsics/test_root.py @@ -99,7 +99,7 @@ def test_root_register_extrinsic( call_params={"hotkey": "fake_hotkey_address"}, ) mocked_sign_and_send_extrinsic.assert_called_once_with( - mock_subtensor.substrate.compose_call.return_value, + call=mock_subtensor.substrate.compose_call.return_value, wallet=mock_wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, @@ -126,7 +126,7 @@ def test_root_register_extrinsic_insufficient_balance( assert success is False mock_subtensor.get_balance.assert_called_once_with( - mock_wallet.coldkeypub.ss58_address, + address=mock_wallet.coldkeypub.ss58_address, block=mock_subtensor.get_current_block.return_value, ) mock_subtensor.substrate.submit_extrinsic.assert_not_called() diff --git a/tests/unit_tests/extrinsics/test_transfer.py b/tests/unit_tests/extrinsics/test_transfer.py index 097156ba49..06567e2737 100644 --- a/tests/unit_tests/extrinsics/test_transfer.py +++ b/tests/unit_tests/extrinsics/test_transfer.py @@ -10,7 +10,8 @@ def test_do_transfer_is_success_true(subtensor, fake_wallet, mocker): fake_wait_for_inclusion = True fake_wait_for_finalization = True - subtensor.substrate.submit_extrinsic.return_value.is_success = True + mocker.patch.object(subtensor, "sign_and_send_extrinsic", return_value=(True, "")) + mocker.patch.object(subtensor, "get_block_hash", return_value=1) # Call result = _do_transfer( @@ -28,20 +29,15 @@ def test_do_transfer_is_success_true(subtensor, fake_wallet, mocker): call_function="transfer_allow_death", call_params={"dest": fake_dest, "value": fake_transfer_balance.rao}, ) - subtensor.substrate.create_signed_extrinsic.assert_called_once_with( - call=subtensor.substrate.compose_call.return_value, keypair=fake_wallet.coldkey - ) - subtensor.substrate.submit_extrinsic.assert_called_once_with( - extrinsic=subtensor.substrate.create_signed_extrinsic.return_value, + subtensor.sign_and_send_extrinsic.assert_called_once_with( + call=subtensor.substrate.compose_call.return_value, + wallet=fake_wallet, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, + period=None ) # subtensor.substrate.submit_extrinsic.return_value.process_events.assert_called_once() - assert result == ( - True, - subtensor.substrate.get_chain_head.return_value, - "Success with response.", - ) + assert result == (True, 1, "Success with response.") def test_do_transfer_is_success_false(subtensor, fake_wallet, mocker): @@ -52,7 +48,8 @@ def test_do_transfer_is_success_false(subtensor, fake_wallet, mocker): fake_wait_for_inclusion = True fake_wait_for_finalization = True - subtensor.substrate.submit_extrinsic.return_value.is_success = False + mocker.patch.object(subtensor, "sign_and_send_extrinsic", return_value=(False, "")) + mocker.patch.object(subtensor, "get_block_hash", return_value=1) # Call result = _do_transfer( @@ -70,20 +67,15 @@ def test_do_transfer_is_success_false(subtensor, fake_wallet, mocker): call_function="transfer_allow_death", call_params={"dest": fake_dest, "value": fake_transfer_balance.rao}, ) - subtensor.substrate.create_signed_extrinsic.assert_called_once_with( - call=subtensor.substrate.compose_call.return_value, keypair=fake_wallet.coldkey - ) - subtensor.substrate.submit_extrinsic.assert_called_once_with( - extrinsic=subtensor.substrate.create_signed_extrinsic.return_value, + subtensor.sign_and_send_extrinsic.assert_called_once_with( + call=subtensor.substrate.compose_call.return_value, + wallet=fake_wallet, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, + period=None ) - assert result == ( - False, - "", - "Subtensor returned `UnknownError(UnknownType)` error. This means: `Unknown Description`.", - ) + assert result == (False, "", "") def test_do_transfer_no_waits(subtensor, fake_wallet, mocker): @@ -94,6 +86,8 @@ def test_do_transfer_no_waits(subtensor, fake_wallet, mocker): fake_wait_for_inclusion = False fake_wait_for_finalization = False + mocker.patch.object(subtensor, "sign_and_send_extrinsic", return_value=(True, "msg")) + # Call result = _do_transfer( subtensor, @@ -110,12 +104,11 @@ def test_do_transfer_no_waits(subtensor, fake_wallet, mocker): call_function="transfer_allow_death", call_params={"dest": fake_dest, "value": fake_transfer_balance.rao}, ) - subtensor.substrate.create_signed_extrinsic.assert_called_once_with( - call=subtensor.substrate.compose_call.return_value, keypair=fake_wallet.coldkey - ) - subtensor.substrate.submit_extrinsic.assert_called_once_with( - extrinsic=subtensor.substrate.create_signed_extrinsic.return_value, + subtensor.sign_and_send_extrinsic.assert_called_once_with( + call=subtensor.substrate.compose_call.return_value, + wallet=fake_wallet, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, + period=None ) - assert result == (True, "", "Not waiting for finalization or inclusion.") + assert result == (True, "", "msg") From e915a3f231b28894ae78adb2dfdadbe11b5959f3 Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 2 May 2025 00:45:11 -0700 Subject: [PATCH 077/100] oops with `set_children` -> fixed --- bittensor/core/async_subtensor.py | 99 +++++++++++++++++-------------- bittensor/core/subtensor.py | 9 ++- 2 files changed, 61 insertions(+), 47 deletions(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index c93007aa50..f9cee8c153 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -3677,6 +3677,7 @@ async def reveal_weights( wait_for_inclusion: bool = False, wait_for_finalization: bool = False, max_retries: int = 5, + period: Optional[int] = None, ) -> tuple[bool, str]: """ Reveals the weights for a specific subnet on the Bittensor blockchain using the provided wallet. @@ -3689,11 +3690,14 @@ async def reveal_weights( weights (np.ndarray): NumPy array of weight values corresponding to each UID. salt (np.ndarray): NumPy array of salt values corresponding to the hash function. version_key (int): Version key for compatibility with the network. Default is ``int representation of - Bittensor version``. + a Bittensor version``. wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``False``. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``. max_retries (int): The number of maximum attempts to reveal weights. Default is ``5``. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: ``True`` if the weight revelation is successful, False otherwise. And `msg`, a string @@ -3718,12 +3722,12 @@ async def reveal_weights( version_key=version_key, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + period=period, ) if success: break except Exception as e: logging.error(f"Error revealing weights: {e}") - finally: retries += 1 return success, message @@ -3812,9 +3816,10 @@ async def set_children( wait_for_inclusion: bool = True, wait_for_finalization: bool = True, raise_error: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str]: """ - Allows a coldkey to set children keys. + Allows a coldkey to set children-keys. Arguments: wallet (bittensor_wallet.Wallet): bittensor wallet instance. @@ -3823,7 +3828,10 @@ async def set_children( children (list[tuple[float, str]]): A list of children with their proportions. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. - raise_error: Raises relevant exception rather than returning `False` if unsuccessful. + raise_error: Raises a relevant exception rather than returning `False` if unsuccessful. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: A tuple where the first element is a boolean indicating success or failure of the @@ -3870,6 +3878,7 @@ async def set_children( wait_for_inclusion, wait_for_finalization, raise_error=raise_error, + period=period, ) async def set_delegate_take( @@ -4257,90 +4266,90 @@ async def swap_stake( period=period ) - async def transfer_stake( + async def transfer( self, wallet: "Wallet", - destination_coldkey_ss58: str, - hotkey_ss58: str, - origin_netuid: int, - destination_netuid: int, + dest: str, amount: Balance, + transfer_all: bool = False, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, + keep_alive: bool = True, period: Optional[int] = None, ) -> bool: """ - Transfers stake from one subnet to another while changing the coldkey owner. + Transfer token of amount to destination. - Args: - wallet (bittensor.wallet): The wallet to transfer stake from. - destination_coldkey_ss58 (str): The destination coldkey SS58 address. - hotkey_ss58 (str): The hotkey SS58 address associated with the stake. - origin_netuid (int): The source subnet UID. - destination_netuid (int): The destination subnet UID. - amount (Balance): Amount to transfer. - wait_for_inclusion (bool): If true, waits for inclusion before returning. - wait_for_finalization (bool): If true, waits for finalization before returning. + Arguments: + wallet (bittensor_wallet.Wallet): Source wallet for the transfer. + dest (str): Destination address for the transfer. + amount (float): Number of tokens to transfer. + transfer_all (bool): Flag to transfer all tokens. Default is ``False``. + wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``True``. + wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is + ``False``. + keep_alive (bool): Flag to keep the connection alive. Default is ``True``. period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. - Returns: - success (bool): True if the transfer was successful. + `True` if the transferring was successful, otherwise `False`. """ amount = check_and_convert_to_balance(amount) - return await transfer_stake_extrinsic( + return await transfer_extrinsic( subtensor=self, wallet=wallet, - destination_coldkey_ss58=destination_coldkey_ss58, - hotkey_ss58=hotkey_ss58, - origin_netuid=origin_netuid, - destination_netuid=destination_netuid, + dest=dest, amount=amount, + transfer_all=transfer_all, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, + keep_alive=keep_alive, period=period, ) - async def transfer( + async def transfer_stake( self, wallet: "Wallet", - dest: str, + destination_coldkey_ss58: str, + hotkey_ss58: str, + origin_netuid: int, + destination_netuid: int, amount: Balance, - transfer_all: bool = False, wait_for_inclusion: bool = True, wait_for_finalization: bool = False, - keep_alive: bool = True, period: Optional[int] = None, ) -> bool: """ - Transfer token of amount to destination. + Transfers stake from one subnet to another while changing the coldkey owner. - Arguments: - wallet (bittensor_wallet.Wallet): Source wallet for the transfer. - dest (str): Destination address for the transfer. - amount (float): Number of tokens to transfer. - transfer_all (bool): Flag to transfer all tokens. Default is ``False``. - wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``True``. - wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is - ``False``. - keep_alive (bool): Flag to keep the connection alive. Default is ``True``. + Args: + wallet (bittensor.wallet): The wallet to transfer stake from. + destination_coldkey_ss58 (str): The destination coldkey SS58 address. + hotkey_ss58 (str): The hotkey SS58 address associated with the stake. + origin_netuid (int): The source subnet UID. + destination_netuid (int): The destination subnet UID. + amount (Balance): Amount to transfer. + wait_for_inclusion (bool): If true, waits for inclusion before returning. + wait_for_finalization (bool): If true, waits for finalization before returning. period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. + Returns: - `True` if the transferring was successful, otherwise `False`. + success (bool): True if the transfer was successful. """ amount = check_and_convert_to_balance(amount) - return await transfer_extrinsic( + return await transfer_stake_extrinsic( subtensor=self, wallet=wallet, - dest=dest, + destination_coldkey_ss58=destination_coldkey_ss58, + hotkey_ss58=hotkey_ss58, + origin_netuid=origin_netuid, + destination_netuid=destination_netuid, amount=amount, - transfer_all=transfer_all, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, - keep_alive=keep_alive, period=period, ) diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index c6cbd34373..442c21841b 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -3101,9 +3101,10 @@ def set_children( wait_for_inclusion: bool = True, wait_for_finalization: bool = True, raise_error: bool = False, + period: Optional[int] = None, ) -> tuple[bool, str]: """ - Allows a coldkey to set children keys. + Allows a coldkey to set children-keys. Arguments: wallet (bittensor_wallet.Wallet): bittensor wallet instance. @@ -3112,7 +3113,10 @@ def set_children( children (list[tuple[float, str]]): A list of children with their proportions. wait_for_inclusion (bool): Waits for the transaction to be included in a block. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. - raise_error: Raises relevant exception rather than returning `False` if unsuccessful. + raise_error: Raises a relevant exception rather than returning `False` if unsuccessful. + period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If + the transaction is not included in a block within that number of blocks, it will expire and be rejected. + You can think of it as an expiration date for the transaction. Returns: tuple[bool, str]: A tuple where the first element is a boolean indicating success or failure of the @@ -3159,6 +3163,7 @@ def set_children( wait_for_inclusion, wait_for_finalization, raise_error=raise_error, + period=period, ) def set_delegate_take( From 7fef30ff338bf55cdb77eb76ca8725dfcbab6952 Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 2 May 2025 00:46:28 -0700 Subject: [PATCH 078/100] ruff + mypy + flake8 --- bittensor/core/async_subtensor.py | 16 ++++++++------- .../core/extrinsics/asyncex/commit_reveal.py | 2 +- .../core/extrinsics/asyncex/registration.py | 2 +- bittensor/core/extrinsics/asyncex/root.py | 2 +- bittensor/core/extrinsics/asyncex/serving.py | 2 +- bittensor/core/extrinsics/asyncex/staking.py | 8 ++++++-- .../core/extrinsics/asyncex/start_call.py | 4 ++-- .../core/extrinsics/asyncex/unstaking.py | 8 ++++++-- bittensor/core/extrinsics/commit_reveal.py | 2 +- bittensor/core/extrinsics/root.py | 2 +- bittensor/core/extrinsics/set_weights.py | 5 ++++- bittensor/core/extrinsics/staking.py | 8 ++++++-- bittensor/core/extrinsics/start_call.py | 4 ++-- bittensor/core/extrinsics/take.py | 4 ++-- bittensor/core/extrinsics/unstaking.py | 8 ++++++-- bittensor/core/subtensor.py | 8 +++++--- tests/e2e_tests/test_staking.py | 2 +- .../extrinsics/asyncex/test_commit_reveal.py | 4 ++-- .../extrinsics/asyncex/test_registration.py | 12 +++++++---- .../extrinsics/asyncex/test_root.py | 8 ++++++-- .../extrinsics/asyncex/test_start_call.py | 2 +- .../extrinsics/asyncex/test_transfer.py | 14 ++++++++++--- .../extrinsics/asyncex/test_weights.py | 8 ++++++-- tests/unit_tests/extrinsics/test_root.py | 2 +- tests/unit_tests/extrinsics/test_serving.py | 4 +++- .../unit_tests/extrinsics/test_set_weights.py | 14 +++++++++---- tests/unit_tests/extrinsics/test_staking.py | 4 ++-- .../unit_tests/extrinsics/test_start_call.py | 2 +- tests/unit_tests/extrinsics/test_transfer.py | 10 ++++++---- tests/unit_tests/test_subtensor.py | 20 +++++++++++-------- 30 files changed, 124 insertions(+), 67 deletions(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index f9cee8c153..4645a1ffda 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -653,7 +653,9 @@ async def bonds( return b_map - async def commit(self, wallet: "Wallet", netuid: int, data: str, period: Optional[int] = None) -> bool: + async def commit( + self, wallet: "Wallet", netuid: int, data: str, period: Optional[int] = None + ) -> bool: """ Commits arbitrary data to the Bittensor network by publishing metadata. @@ -2856,7 +2858,7 @@ async def set_reveal_commitment( data: str, blocks_until_reveal: int = 360, block_time: Union[int, float] = 12, - period: Optional[int] = None + period: Optional[int] = None, ) -> tuple[bool, int]: """ Commits arbitrary data to the Bittensor network by publishing metadata. @@ -2891,7 +2893,7 @@ async def set_reveal_commitment( netuid=netuid, data_type=f"TimelockEncrypted", data=data_, - period=period + period=period, ), reveal_round async def subnet( @@ -3442,7 +3444,7 @@ async def burned_register( netuid=netuid, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, - period=period + period=period, ) async def commit_weights( @@ -3944,7 +3946,7 @@ async def set_delegate_take( wait_for_finalization=wait_for_finalization, wait_for_inclusion=wait_for_inclusion, raise_error=raise_error, - period=period + period=period, ) else: success, error = await decrease_take_extrinsic( @@ -3955,7 +3957,7 @@ async def set_delegate_take( wait_for_finalization=wait_for_finalization, wait_for_inclusion=wait_for_inclusion, raise_error=raise_error, - period=period + period=period, ) if success: @@ -4263,7 +4265,7 @@ async def swap_stake( safe_staking=safe_staking, allow_partial_stake=allow_partial_stake, rate_tolerance=rate_tolerance, - period=period + period=period, ) async def transfer( diff --git a/bittensor/core/extrinsics/asyncex/commit_reveal.py b/bittensor/core/extrinsics/asyncex/commit_reveal.py index 6c4ea6f138..9c65ae8ea1 100644 --- a/bittensor/core/extrinsics/asyncex/commit_reveal.py +++ b/bittensor/core/extrinsics/asyncex/commit_reveal.py @@ -65,7 +65,7 @@ async def _do_commit_reveal_v3( wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, sign_with="hotkey", - period=period + period=period, ) diff --git a/bittensor/core/extrinsics/asyncex/registration.py b/bittensor/core/extrinsics/asyncex/registration.py index e3663f8f64..8758169869 100644 --- a/bittensor/core/extrinsics/asyncex/registration.py +++ b/bittensor/core/extrinsics/asyncex/registration.py @@ -10,7 +10,7 @@ import asyncio from typing import Optional, Union, TYPE_CHECKING -from bittensor.utils import unlock_key, format_error_message +from bittensor.utils import unlock_key from bittensor.utils.btlogging import logging from bittensor.utils.registration import log_no_torch_error, create_pow_async, torch diff --git a/bittensor/core/extrinsics/asyncex/root.py b/bittensor/core/extrinsics/asyncex/root.py index 4641676e36..79c5417e4f 100644 --- a/bittensor/core/extrinsics/asyncex/root.py +++ b/bittensor/core/extrinsics/asyncex/root.py @@ -11,7 +11,7 @@ from bittensor.utils.weight_utils import ( normalize_max_weight, convert_weights_and_uids_for_emit, - convert_uids_and_weights + convert_uids_and_weights, ) if TYPE_CHECKING: diff --git a/bittensor/core/extrinsics/asyncex/serving.py b/bittensor/core/extrinsics/asyncex/serving.py index c86a681b08..c37c612191 100644 --- a/bittensor/core/extrinsics/asyncex/serving.py +++ b/bittensor/core/extrinsics/asyncex/serving.py @@ -221,7 +221,7 @@ async def serve_axon_extrinsic( wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, certificate=certificate, - period=period + period=period, ) return serve_success diff --git a/bittensor/core/extrinsics/asyncex/staking.py b/bittensor/core/extrinsics/asyncex/staking.py index c148fa86f9..41076f0178 100644 --- a/bittensor/core/extrinsics/asyncex/staking.py +++ b/bittensor/core/extrinsics/asyncex/staking.py @@ -205,7 +205,9 @@ async def add_stake_extrinsic( return False except SubstrateRequestException as error: - logging.error(f":cross_mark: [red]Add Stake Error: {format_error_message(error)}[/red]") + logging.error( + f":cross_mark: [red]Add Stake Error: {format_error_message(error)}[/red]" + ) return False @@ -402,7 +404,9 @@ async def add_stake_multiple_extrinsic( continue except SubstrateRequestException as error: - logging.error(f":cross_mark: [red]Add Stake Multiple error: {format_error_message(error)}[/red]") + logging.error( + f":cross_mark: [red]Add Stake Multiple error: {format_error_message(error)}[/red]" + ) continue if successful_stakes != 0: diff --git a/bittensor/core/extrinsics/asyncex/start_call.py b/bittensor/core/extrinsics/asyncex/start_call.py index 3790995524..63f6fbc3c1 100644 --- a/bittensor/core/extrinsics/asyncex/start_call.py +++ b/bittensor/core/extrinsics/asyncex/start_call.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Optional -from bittensor.utils import unlock_key, format_error_message +from bittensor.utils import unlock_key from bittensor.utils.btlogging import logging if TYPE_CHECKING: @@ -51,7 +51,7 @@ async def start_call_extrinsic( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, - period=period + period=period, ) if not wait_for_finalization and not wait_for_inclusion: diff --git a/bittensor/core/extrinsics/asyncex/unstaking.py b/bittensor/core/extrinsics/asyncex/unstaking.py index b114dc7e23..8125b603e9 100644 --- a/bittensor/core/extrinsics/asyncex/unstaking.py +++ b/bittensor/core/extrinsics/asyncex/unstaking.py @@ -189,7 +189,9 @@ async def unstake_extrinsic( return False except SubstrateRequestException as error: - logging.error(f":cross_mark: [red]Unstake filed with error: {format_error_message(error)}[/red]") + logging.error( + f":cross_mark: [red]Unstake filed with error: {format_error_message(error)}[/red]" + ) return False @@ -354,7 +356,9 @@ async def unstake_multiple_extrinsic( continue except SubstrateRequestException as error: - logging.error(f":cross_mark: [red]Multiple unstake filed with error: {format_error_message(error)}[/red]") + logging.error( + f":cross_mark: [red]Multiple unstake filed with error: {format_error_message(error)}[/red]" + ) return False if successful_unstakes != 0: diff --git a/bittensor/core/extrinsics/commit_reveal.py b/bittensor/core/extrinsics/commit_reveal.py index 28f6c112fe..c531986254 100644 --- a/bittensor/core/extrinsics/commit_reveal.py +++ b/bittensor/core/extrinsics/commit_reveal.py @@ -66,7 +66,7 @@ def _do_commit_reveal_v3( wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, sign_with="hotkey", - period=period + period=period, ) diff --git a/bittensor/core/extrinsics/root.py b/bittensor/core/extrinsics/root.py index 36d3a92a57..4a6dfbc0ee 100644 --- a/bittensor/core/extrinsics/root.py +++ b/bittensor/core/extrinsics/root.py @@ -16,7 +16,7 @@ from bittensor.utils.weight_utils import ( normalize_max_weight, convert_weights_and_uids_for_emit, - convert_uids_and_weights + convert_uids_and_weights, ) if TYPE_CHECKING: diff --git a/bittensor/core/extrinsics/set_weights.py b/bittensor/core/extrinsics/set_weights.py index bfa912419c..039dbdf837 100644 --- a/bittensor/core/extrinsics/set_weights.py +++ b/bittensor/core/extrinsics/set_weights.py @@ -7,7 +7,10 @@ from bittensor.core.settings import version_as_int from bittensor.utils.btlogging import logging -from bittensor.utils.weight_utils import convert_and_normalize_weights_and_uids, convert_uids_and_weights +from bittensor.utils.weight_utils import ( + convert_and_normalize_weights_and_uids, + convert_uids_and_weights, +) if TYPE_CHECKING: from bittensor.core.subtensor import Subtensor diff --git a/bittensor/core/extrinsics/staking.py b/bittensor/core/extrinsics/staking.py index 86014c5b07..173fee2db1 100644 --- a/bittensor/core/extrinsics/staking.py +++ b/bittensor/core/extrinsics/staking.py @@ -199,7 +199,9 @@ def add_stake_extrinsic( return False except SubstrateRequestException as error: - logging.error(f":cross_mark: [red]Add Stake Error: {format_error_message((error))}[/red]") + logging.error( + f":cross_mark: [red]Add Stake Error: {format_error_message((error))}[/red]" + ) return False @@ -385,7 +387,9 @@ def add_stake_multiple_extrinsic( continue except SubstrateRequestException as error: - logging.error(f":cross_mark: [red]Add Stake Multiple error: {format_error_message(error)}[/red]") + logging.error( + f":cross_mark: [red]Add Stake Multiple error: {format_error_message(error)}[/red]" + ) continue if successful_stakes != 0: diff --git a/bittensor/core/extrinsics/start_call.py b/bittensor/core/extrinsics/start_call.py index ac6229e802..2788bb88f1 100644 --- a/bittensor/core/extrinsics/start_call.py +++ b/bittensor/core/extrinsics/start_call.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Optional -from bittensor.utils import unlock_key, format_error_message +from bittensor.utils import unlock_key from bittensor.utils.btlogging import logging if TYPE_CHECKING: @@ -50,7 +50,7 @@ def start_call_extrinsic( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, - period=period + period=period, ) if not wait_for_finalization and not wait_for_inclusion: diff --git a/bittensor/core/extrinsics/take.py b/bittensor/core/extrinsics/take.py index fb47bdc770..d07e628aab 100644 --- a/bittensor/core/extrinsics/take.py +++ b/bittensor/core/extrinsics/take.py @@ -54,7 +54,7 @@ def increase_take_extrinsic( wallet=wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, - period=period, + period=period, raise_error=raise_error, ) @@ -70,7 +70,7 @@ def decrease_take_extrinsic( period: Optional[int] = None, ) -> tuple[bool, str]: """Sets the delegate 'take' percentage for a neuron identified by its hotkey. - + Args: subtensor (Subtensor): Blockchain connection. wallet (Wallet): The wallet to sign the extrinsic. diff --git a/bittensor/core/extrinsics/unstaking.py b/bittensor/core/extrinsics/unstaking.py index f4bb46f425..34fe47d7ac 100644 --- a/bittensor/core/extrinsics/unstaking.py +++ b/bittensor/core/extrinsics/unstaking.py @@ -186,7 +186,9 @@ def unstake_extrinsic( return False except SubstrateRequestException as error: - logging.error(f":cross_mark: [red]Unstake filed with error: {format_error_message(error)}[/red]") + logging.error( + f":cross_mark: [red]Unstake filed with error: {format_error_message(error)}[/red]" + ) return False @@ -342,7 +344,9 @@ def unstake_multiple_extrinsic( continue except SubstrateRequestException as error: - logging.error(f":cross_mark: [red]Multiple unstake filed with error: {format_error_message(error)}[/red]") + logging.error( + f":cross_mark: [red]Multiple unstake filed with error: {format_error_message(error)}[/red]" + ) return False if successful_unstakes != 0: diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 442c21841b..7f7a9eaa81 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -452,7 +452,9 @@ def bonds( return b_map - def commit(self, wallet, netuid: int, data: str, period: Optional[int] = None) -> bool: + def commit( + self, wallet, netuid: int, data: str, period: Optional[int] = None + ) -> bool: """ Commits arbitrary data to the Bittensor network by publishing metadata. @@ -3229,7 +3231,7 @@ def set_delegate_take( wait_for_finalization=wait_for_finalization, wait_for_inclusion=wait_for_inclusion, raise_error=raise_error, - period=period + period=period, ) else: success, error = decrease_take_extrinsic( @@ -3240,7 +3242,7 @@ def set_delegate_take( wait_for_finalization=wait_for_finalization, wait_for_inclusion=wait_for_inclusion, raise_error=raise_error, - period=period + period=period, ) if success: diff --git a/tests/e2e_tests/test_staking.py b/tests/e2e_tests/test_staking.py index 3307956095..477c61054e 100644 --- a/tests/e2e_tests/test_staking.py +++ b/tests/e2e_tests/test_staking.py @@ -55,7 +55,7 @@ def test_single_operation(subtensor, alice_wallet, bob_wallet): amount=Balance.from_tao(1), wait_for_inclusion=True, wait_for_finalization=True, - period=16 + period=16, ) assert success is True diff --git a/tests/unit_tests/extrinsics/asyncex/test_commit_reveal.py b/tests/unit_tests/extrinsics/asyncex/test_commit_reveal.py index a81f540f2b..66873eba00 100644 --- a/tests/unit_tests/extrinsics/asyncex/test_commit_reveal.py +++ b/tests/unit_tests/extrinsics/asyncex/test_commit_reveal.py @@ -223,7 +223,7 @@ async def test_commit_reveal_v3_extrinsic_success_with_torch( reveal_round=fake_reveal_round, wait_for_inclusion=True, wait_for_finalization=True, - period=None + period=None, ) @@ -329,7 +329,7 @@ async def test_commit_reveal_v3_extrinsic_response_false( reveal_round=fake_reveal_round, wait_for_inclusion=True, wait_for_finalization=True, - period=None + period=None, ) diff --git a/tests/unit_tests/extrinsics/asyncex/test_registration.py b/tests/unit_tests/extrinsics/asyncex/test_registration.py index fa1e66d67b..a9b3ac511f 100644 --- a/tests/unit_tests/extrinsics/asyncex/test_registration.py +++ b/tests/unit_tests/extrinsics/asyncex/test_registration.py @@ -17,7 +17,11 @@ async def test_do_pow_register_success(subtensor, fake_wallet, mocker): ) mocker.patch.object(subtensor.substrate, "compose_call") - mocker.patch.object(subtensor, "sign_and_send_extrinsic", new=mocker.AsyncMock(return_value=(True, ""))) + mocker.patch.object( + subtensor, + "sign_and_send_extrinsic", + new=mocker.AsyncMock(return_value=(True, "")), + ) # Call result, error_message = await async_registration._do_pow_register( @@ -47,7 +51,7 @@ async def test_do_pow_register_success(subtensor, fake_wallet, mocker): wallet=fake_wallet, wait_for_inclusion=True, wait_for_finalization=True, - period=None + period=None, ) assert result is True assert error_message == "" @@ -96,7 +100,7 @@ async def test_do_pow_register_failure(subtensor, fake_wallet, mocker): wallet=fake_wallet, wait_for_inclusion=True, wait_for_finalization=True, - period=None + period=None, ) assert result_error_message == subtensor.sign_and_send_extrinsic.return_value @@ -145,7 +149,7 @@ async def test_do_pow_register_no_waiting(subtensor, fake_wallet, mocker): wallet=fake_wallet, wait_for_inclusion=False, wait_for_finalization=False, - period=None + period=None, ) assert result == subtensor.sign_and_send_extrinsic.return_value diff --git a/tests/unit_tests/extrinsics/asyncex/test_root.py b/tests/unit_tests/extrinsics/asyncex/test_root.py index ca221b2cd4..baa134ee92 100644 --- a/tests/unit_tests/extrinsics/asyncex/test_root.py +++ b/tests/unit_tests/extrinsics/asyncex/test_root.py @@ -389,7 +389,9 @@ async def test_do_set_root_weights_failure(subtensor, fake_wallet, mocker): fake_call = mocker.AsyncMock() mocker.patch.object(subtensor.substrate, "compose_call", return_value=fake_call) - mocker.patch.object(subtensor, "sign_and_send_extrinsic", return_value=(False, "Transaction failed")) + mocker.patch.object( + subtensor, "sign_and_send_extrinsic", return_value=(False, "Transaction failed") + ) # Call result, message = await async_root._do_set_root_weights( @@ -419,7 +421,9 @@ async def test_do_set_root_weights_no_waiting(subtensor, fake_wallet, mocker): mocker.patch.object(subtensor.substrate, "compose_call", return_value=fake_call) mocker.patch.object( - subtensor, "sign_and_send_extrinsic", return_value=(True, "Not waiting for finalization or inclusion.") + subtensor, + "sign_and_send_extrinsic", + return_value=(True, "Not waiting for finalization or inclusion."), ) # Call diff --git a/tests/unit_tests/extrinsics/asyncex/test_start_call.py b/tests/unit_tests/extrinsics/asyncex/test_start_call.py index ebb5c327a9..d99295195e 100644 --- a/tests/unit_tests/extrinsics/asyncex/test_start_call.py +++ b/tests/unit_tests/extrinsics/asyncex/test_start_call.py @@ -35,7 +35,7 @@ async def test_start_call_extrinsics(subtensor, mocker, fake_wallet): wallet=wallet, wait_for_inclusion=True, wait_for_finalization=False, - period=None + period=None, ) assert success is True diff --git a/tests/unit_tests/extrinsics/asyncex/test_transfer.py b/tests/unit_tests/extrinsics/asyncex/test_transfer.py index 1abd2fe15c..77fcd72f9f 100644 --- a/tests/unit_tests/extrinsics/asyncex/test_transfer.py +++ b/tests/unit_tests/extrinsics/asyncex/test_transfer.py @@ -13,7 +13,9 @@ async def test_do_transfer_success(subtensor, fake_wallet, mocker): mocker.patch.object(subtensor.substrate, "compose_call") mocker.patch.object( - subtensor, "sign_and_send_extrinsic", new=mocker.AsyncMock(return_value=(True, "")) + subtensor, + "sign_and_send_extrinsic", + new=mocker.AsyncMock(return_value=(True, "")), ) mocker.patch.object(subtensor, "get_block_hash", return_value=fake_block_hash) @@ -56,7 +58,9 @@ async def test_do_transfer_failure(subtensor, fake_wallet, mocker): mocker.patch.object(subtensor.substrate, "compose_call") mocker.patch.object( - subtensor, "sign_and_send_extrinsic", new=mocker.AsyncMock(return_value=(False, "Formatted error message")) + subtensor, + "sign_and_send_extrinsic", + new=mocker.AsyncMock(return_value=(False, "Formatted error message")), ) mocker.patch.object(subtensor, "get_block_hash", return_value=fake_block_hash) @@ -99,7 +103,11 @@ async def test_do_transfer_no_waiting(subtensor, fake_wallet, mocker): mocker.patch.object(subtensor.substrate, "compose_call") mocker.patch.object( - subtensor, "sign_and_send_extrinsic", new=mocker.AsyncMock(return_value=(False, "Success, extrinsic submitted without waiting.")) + subtensor, + "sign_and_send_extrinsic", + new=mocker.AsyncMock( + return_value=(False, "Success, extrinsic submitted without waiting.") + ), ) mocker.patch.object(subtensor, "get_block_hash", return_value=fake_block_hash) diff --git a/tests/unit_tests/extrinsics/asyncex/test_weights.py b/tests/unit_tests/extrinsics/asyncex/test_weights.py index ef6900f62f..226292b43c 100644 --- a/tests/unit_tests/extrinsics/asyncex/test_weights.py +++ b/tests/unit_tests/extrinsics/asyncex/test_weights.py @@ -147,7 +147,9 @@ async def test_set_weights_extrinsic_success_with_finalization( mocked_do_set_weights = mocker.patch.object( async_weights, "_do_set_weights", return_value=(True, "") ) - mocker_converter = mocker.patch.object(async_weights, "convert_and_normalize_weights_and_uids") + mocker_converter = mocker.patch.object( + async_weights, "convert_and_normalize_weights_and_uids" + ) mocker_converter.return_value = (mocker.Mock(), mocker.Mock()) # Call @@ -188,7 +190,9 @@ async def test_set_weights_extrinsic_no_waiting(subtensor, fake_wallet, mocker): fake_weights = [0.1, 0.2, 0.7] mocked_do_set_weights = mocker.patch.object( - async_weights, "_do_set_weights", return_value=(True, "Not waiting for finalization or inclusion.") + async_weights, + "_do_set_weights", + return_value=(True, "Not waiting for finalization or inclusion."), ) # Call diff --git a/tests/unit_tests/extrinsics/test_root.py b/tests/unit_tests/extrinsics/test_root.py index 0ebaca5be7..8737b3f32c 100644 --- a/tests/unit_tests/extrinsics/test_root.py +++ b/tests/unit_tests/extrinsics/test_root.py @@ -103,7 +103,7 @@ def test_root_register_extrinsic( wallet=mock_wallet, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, - period=None + period=None, ) diff --git a/tests/unit_tests/extrinsics/test_serving.py b/tests/unit_tests/extrinsics/test_serving.py index 027199ca81..c1688fd3d4 100644 --- a/tests/unit_tests/extrinsics/test_serving.py +++ b/tests/unit_tests/extrinsics/test_serving.py @@ -353,7 +353,9 @@ def test_publish_metadata( # Arrange with ( patch.object(mock_subtensor.substrate, "compose_call"), - patch.object(mock_subtensor, "sign_and_send_extrinsic", return_value=response_success), + patch.object( + mock_subtensor, "sign_and_send_extrinsic", return_value=response_success + ), ): # Act result = serving.publish_metadata( diff --git a/tests/unit_tests/extrinsics/test_set_weights.py b/tests/unit_tests/extrinsics/test_set_weights.py index 645395ab8a..1046385291 100644 --- a/tests/unit_tests/extrinsics/test_set_weights.py +++ b/tests/unit_tests/extrinsics/test_set_weights.py @@ -105,7 +105,9 @@ def test_do_set_weights_is_success(mock_subtensor, fake_wallet, mocker): fake_wait_for_finalization = True mock_subtensor.substrate.submit_extrinsic.return_value.is_success = True - mocker.patch.object(mock_subtensor, "sign_and_send_extrinsic", return_value=(True, "")) + mocker.patch.object( + mock_subtensor, "sign_and_send_extrinsic", return_value=(True, "") + ) # Call result = _do_set_weights( @@ -139,7 +141,7 @@ def test_do_set_weights_is_success(mock_subtensor, fake_wallet, mocker): nonce_key="hotkey", sign_with="hotkey", use_nonce=True, - period=None + period=None, ) assert result == (True, "") @@ -153,7 +155,11 @@ def test_do_set_weights_no_waits(mock_subtensor, fake_wallet, mocker): fake_wait_for_inclusion = False fake_wait_for_finalization = False - mocker.patch.object(mock_subtensor, "sign_and_send_extrinsic", return_value=(True, "Not waiting for finalization or inclusion.")) + mocker.patch.object( + mock_subtensor, + "sign_and_send_extrinsic", + return_value=(True, "Not waiting for finalization or inclusion."), + ) # Call result = _do_set_weights( @@ -184,6 +190,6 @@ def test_do_set_weights_no_waits(mock_subtensor, fake_wallet, mocker): wallet=fake_wallet, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, - period=None + period=None, ) assert result == (True, "Not waiting for finalization or inclusion.") diff --git a/tests/unit_tests/extrinsics/test_staking.py b/tests/unit_tests/extrinsics/test_staking.py index 517280d461..80ecb5c240 100644 --- a/tests/unit_tests/extrinsics/test_staking.py +++ b/tests/unit_tests/extrinsics/test_staking.py @@ -51,7 +51,7 @@ def test_add_stake_extrinsic(mocker): nonce_key="coldkeypub", sign_with="coldkey", use_nonce=True, - period=None + period=None, ) @@ -139,5 +139,5 @@ def test_add_stake_multiple_extrinsic(mocker): nonce_key="coldkeypub", sign_with="coldkey", use_nonce=True, - period=None + period=None, ) diff --git a/tests/unit_tests/extrinsics/test_start_call.py b/tests/unit_tests/extrinsics/test_start_call.py index 658f0883f7..ece0e6cf42 100644 --- a/tests/unit_tests/extrinsics/test_start_call.py +++ b/tests/unit_tests/extrinsics/test_start_call.py @@ -33,7 +33,7 @@ def test_start_call_extrinsics(subtensor, mocker, fake_wallet): wallet=wallet, wait_for_inclusion=True, wait_for_finalization=False, - period=None + period=None, ) assert success is True diff --git a/tests/unit_tests/extrinsics/test_transfer.py b/tests/unit_tests/extrinsics/test_transfer.py index 06567e2737..fcd532e2d0 100644 --- a/tests/unit_tests/extrinsics/test_transfer.py +++ b/tests/unit_tests/extrinsics/test_transfer.py @@ -34,7 +34,7 @@ def test_do_transfer_is_success_true(subtensor, fake_wallet, mocker): wallet=fake_wallet, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, - period=None + period=None, ) # subtensor.substrate.submit_extrinsic.return_value.process_events.assert_called_once() assert result == (True, 1, "Success with response.") @@ -72,7 +72,7 @@ def test_do_transfer_is_success_false(subtensor, fake_wallet, mocker): wallet=fake_wallet, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, - period=None + period=None, ) assert result == (False, "", "") @@ -86,7 +86,9 @@ def test_do_transfer_no_waits(subtensor, fake_wallet, mocker): fake_wait_for_inclusion = False fake_wait_for_finalization = False - mocker.patch.object(subtensor, "sign_and_send_extrinsic", return_value=(True, "msg")) + mocker.patch.object( + subtensor, "sign_and_send_extrinsic", return_value=(True, "msg") + ) # Call result = _do_transfer( @@ -109,6 +111,6 @@ def test_do_transfer_no_waits(subtensor, fake_wallet, mocker): wallet=fake_wallet, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, - period=None + period=None, ) assert result == (True, "", "msg") diff --git a/tests/unit_tests/test_subtensor.py b/tests/unit_tests/test_subtensor.py index 03b45a35fe..17c858c8a5 100644 --- a/tests/unit_tests/test_subtensor.py +++ b/tests/unit_tests/test_subtensor.py @@ -1269,7 +1269,7 @@ def test_commit(subtensor, fake_wallet, mocker): netuid=fake_netuid, data_type=f"Raw{len(fake_data)}", data=fake_data.encode(), - period=None + period=None, ) assert result is mocked_publish_metadata.return_value @@ -1492,7 +1492,7 @@ def test_do_serve_axon_is_success( wallet=fake_wallet, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, - period=None + period=None, ) assert result[0] is True @@ -1505,7 +1505,9 @@ def test_do_serve_axon_is_not_success(subtensor, fake_wallet, mocker, fake_call_ fake_wait_for_inclusion = True fake_wait_for_finalization = True - mocker.patch.object(subtensor, "sign_and_send_extrinsic", return_value=(False, None)) + mocker.patch.object( + subtensor, "sign_and_send_extrinsic", return_value=(False, None) + ) # Call result = do_serve_axon( @@ -1528,7 +1530,7 @@ def test_do_serve_axon_is_not_success(subtensor, fake_wallet, mocker, fake_call_ wallet=fake_wallet, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, - period=None + period=None, ) assert result == (False, None) @@ -1541,7 +1543,9 @@ def test_do_serve_axon_no_waits(subtensor, fake_wallet, mocker, fake_call_params fake_wait_for_finalization = False mocked_sign_and_send_extrinsic = mocker.Mock(return_value=(True, "")) - mocker.patch.object(subtensor, "sign_and_send_extrinsic", new=mocked_sign_and_send_extrinsic) + mocker.patch.object( + subtensor, "sign_and_send_extrinsic", new=mocked_sign_and_send_extrinsic + ) # Call result = do_serve_axon( @@ -1564,7 +1568,7 @@ def test_do_serve_axon_no_waits(subtensor, fake_wallet, mocker, fake_call_params wallet=fake_wallet, wait_for_inclusion=fake_wait_for_inclusion, wait_for_finalization=fake_wait_for_finalization, - period=None + period=None, ) assert result == (True, "") @@ -1956,7 +1960,7 @@ def test_commit_weights(subtensor, fake_wallet, mocker): commit_hash=mocked_generate_weight_hash.return_value, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization, - period=16 + period=16, ) assert result == expected_result @@ -1996,7 +2000,7 @@ def test_reveal_weights(subtensor, fake_wallet, mocker): salt=salt, wait_for_inclusion=False, wait_for_finalization=False, - period=16 + period=16, ) From caf8c7080faa98658d4daa6b60e0c8a060a2baa9 Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 2 May 2025 00:53:23 -0700 Subject: [PATCH 079/100] optimization + period for test --- bittensor/core/async_subtensor.py | 5 ++--- bittensor/core/subtensor.py | 5 ++--- tests/e2e_tests/test_staking.py | 1 + 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index 4645a1ffda..d3c04c42a5 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -98,7 +98,7 @@ check_and_convert_to_balance, ) from bittensor.utils.btlogging import logging -from bittensor.utils.weight_utils import generate_weight_hash +from bittensor.utils.weight_utils import generate_weight_hash, convert_uids_and_weights if TYPE_CHECKING: from async_substrate_interface.types import ScaleObj @@ -3794,8 +3794,7 @@ async def root_set_weights( Returns: `True` if the setting of weights is successful, `False` otherwise. """ - netuids_ = np.array(netuids, dtype=np.int64) - weights_ = np.array(weights, dtype=np.float32) + netuids_, weights_ = convert_uids_and_weights(netuids, weights) logging.info(f"Setting weights in network: [blue]{self.network}[/blue]") # Run the set weights operation. return await set_root_weights_extrinsic( diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 7f7a9eaa81..a01323e050 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -101,7 +101,7 @@ check_and_convert_to_balance, ) from bittensor.utils.btlogging import logging -from bittensor.utils.weight_utils import generate_weight_hash +from bittensor.utils.weight_utils import generate_weight_hash, convert_uids_and_weights if TYPE_CHECKING: from bittensor_wallet import Wallet @@ -3080,8 +3080,7 @@ def root_set_weights( Returns: `True` if the setting of weights is successful, `False` otherwise. """ - netuids_ = np.array(netuids, dtype=np.int64) - weights_ = np.array(weights, dtype=np.float32) + netuids_, weights_ = convert_uids_and_weights(netuids, weights) logging.info(f"Setting weights in network: [blue]{self.network}[/blue]") return set_root_weights_extrinsic( subtensor=self, diff --git a/tests/e2e_tests/test_staking.py b/tests/e2e_tests/test_staking.py index 477c61054e..9ab91351db 100644 --- a/tests/e2e_tests/test_staking.py +++ b/tests/e2e_tests/test_staking.py @@ -169,6 +169,7 @@ def test_single_operation(subtensor, alice_wallet, bob_wallet): amount=stake_bob, wait_for_inclusion=True, wait_for_finalization=True, + period=16, ) assert success is True From a752e50a0b3dee679e3a627ff8b1b35745da72d0 Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:17:47 +0200 Subject: [PATCH 080/100] Update bittensor/core/async_subtensor.py --- bittensor/core/async_subtensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index d3c04c42a5..5149640df5 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -3036,7 +3036,7 @@ async def tx_rate_limit( Optional[int]: The transaction rate limit of the network, None if not available. The transaction rate limit is an essential parameter for ensuring the stability and scalability of the Bittensor - network. It helps in managing a network load and preventing congestion, thereby maintaining efficient and + network. It helps in managing network load and preventing congestion, thereby maintaining efficient and timely transaction processing. """ block_hash = await self.determine_block_hash(block, block_hash, reuse_block) From 6bb89542996670350e4d470f38a1abc00020434a Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:17:55 +0200 Subject: [PATCH 081/100] Update bittensor/core/async_subtensor.py --- bittensor/core/async_subtensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index 5149640df5..9d95c898c1 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -3247,7 +3247,7 @@ async def sign_and_send_extrinsic( the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. nonce_key: the type on nonce to use. Options are "hotkey" or "coldkey". - nonce_key: the type on nonce to use. Options are "hotkey" or "coldkey". + nonce_key: the type on nonce to use. Options are "hotkey", "coldkey", or "coldkeypub". raise_error: raises a relevant exception rather than returning `False` if unsuccessful. Returns: From 1fc275a261472f49559926d981fe6338d293a686 Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:18:05 +0200 Subject: [PATCH 082/100] Update bittensor/core/async_subtensor.py --- bittensor/core/async_subtensor.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index 9d95c898c1..c342cddf4d 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -3421,9 +3421,6 @@ async def burned_register( period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. - period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If - the transaction is not included in a block within that number of blocks, it will expire and be rejected. - You can think of it as an expiration date for the transaction. Returns: bool: ``True`` if the registration is successful, False otherwise. From 12323dcfde88eb8f6d2f426736e4aecbe63fb135 Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:18:14 +0200 Subject: [PATCH 083/100] Update bittensor/core/async_subtensor.py --- bittensor/core/async_subtensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index c342cddf4d..8fc95fdc0e 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -3689,7 +3689,7 @@ async def reveal_weights( weights (np.ndarray): NumPy array of weight values corresponding to each UID. salt (np.ndarray): NumPy array of salt values corresponding to the hash function. version_key (int): Version key for compatibility with the network. Default is ``int representation of - a Bittensor version``. + the Bittensor version``. wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``False``. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``. From 00f0b69d58e9e1f15e9cadbae5d2b9253240d045 Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:18:22 +0200 Subject: [PATCH 084/100] Update bittensor/utils/weight_utils.py --- bittensor/utils/weight_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor/utils/weight_utils.py b/bittensor/utils/weight_utils.py index 3a24f5fcc2..0afa8269ad 100644 --- a/bittensor/utils/weight_utils.py +++ b/bittensor/utils/weight_utils.py @@ -190,7 +190,7 @@ def convert_weights_and_uids_for_emit( f"Passed weights and uids must have the same length, got {len(uids)} and {len(weights)}" ) if sum(weights) == 0: - return [], [] # Nothing to set on a chain. + return [], [] # Nothing to set on chain. else: max_weight = float(max(weights)) weights = [ From 2235197baa0ffb5beb1a876c7059b963c966298d Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:18:35 +0200 Subject: [PATCH 085/100] Update bittensor/utils/weight_utils.py --- bittensor/utils/weight_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor/utils/weight_utils.py b/bittensor/utils/weight_utils.py index 0afa8269ad..2a7b7f3afd 100644 --- a/bittensor/utils/weight_utils.py +++ b/bittensor/utils/weight_utils.py @@ -249,7 +249,7 @@ def process_weights_for_netuid( logging.debug(f"subtensor: {subtensor}") logging.debug(f"metagraph: {metagraph}") - # Get latest metagraph from a chain if metagraph is None. + # Get latest metagraph from chain if metagraph is None. if metagraph is None: metagraph = subtensor.metagraph(netuid) From 4c032d28b992d97f0a5e22bdde8fe628cde4dd1c Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:18:44 +0200 Subject: [PATCH 086/100] Update tests/e2e_tests/test_commit_weights.py --- tests/e2e_tests/test_commit_weights.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e_tests/test_commit_weights.py b/tests/e2e_tests/test_commit_weights.py index 6d77895e76..1008ea7c23 100644 --- a/tests/e2e_tests/test_commit_weights.py +++ b/tests/e2e_tests/test_commit_weights.py @@ -158,7 +158,7 @@ async def test_commit_weights_uses_next_nonce(local_chain, subtensor, alice_wall Steps: 1. Register a subnet through Alice 2. Register Alice's neuron and add stake - 3. Enable a commit-reveal mechanism on subnet + 3. Enable the commit-reveal mechanism on subnet 4. Lower the commit_reveal interval and rate limit 5. Commit weights three times 6. Assert that all commits succeeded From cb7b4d0706a2f610be578e20cf0f88337433d6b7 Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:18:51 +0200 Subject: [PATCH 087/100] Update tests/e2e_tests/test_commit_weights.py --- tests/e2e_tests/test_commit_weights.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e_tests/test_commit_weights.py b/tests/e2e_tests/test_commit_weights.py index 1008ea7c23..d3dabf6152 100644 --- a/tests/e2e_tests/test_commit_weights.py +++ b/tests/e2e_tests/test_commit_weights.py @@ -19,7 +19,7 @@ async def test_commit_and_reveal_weights_legacy(local_chain, subtensor, alice_wa Steps: 1. Register a subnet through Alice - 2. Enable a commit-reveal mechanism on subnet + 2. Enable the commit-reveal mechanism on subnet 3. Lower the commit_reveal interval and rate limit 4. Commit weights and verify 5. Wait interval & reveal weights and verify From eb4d3d65dfe913e7f7fe8c97e4cc7a85b842b4d7 Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:19:04 +0200 Subject: [PATCH 088/100] Update tests/e2e_tests/conftest.py --- tests/e2e_tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e_tests/conftest.py b/tests/e2e_tests/conftest.py index a247b85a5a..cd5229d5ee 100644 --- a/tests/e2e_tests/conftest.py +++ b/tests/e2e_tests/conftest.py @@ -69,7 +69,7 @@ def local_chain(request): if sys.platform.startswith("linux"): docker_command = ( "Install docker with command " - "[blue]sudo apt-gat update && sudo apt-get install docker.io -y[/blue]" + "[blue]sudo apt-get update && sudo apt-get install docker.io -y[/blue]" " or use documentation [blue]https://docs.docker.com/engine/install/[/blue]" ) elif sys.platform == "darwin": From 3f0b2e01ce7d5cf6b12d7498b344bcee01317016 Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:19:21 +0200 Subject: [PATCH 089/100] Update bittensor/core/async_subtensor.py --- bittensor/core/async_subtensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index 8fc95fdc0e..082c0f44e8 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -4030,7 +4030,7 @@ async def set_weights( weights (Union[NDArray[np.float32], torch.FloatTensor, list]): The corresponding weights to be set for each UID. version_key (int): Version key for compatibility with the network. Default is int representation of - a Bittensor version. + the Bittensor version. wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``False``. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``. From a2cc42bfad1398d50526e1cbd2db6834b351b71a Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:19:34 +0200 Subject: [PATCH 090/100] Update bittensor/core/extrinsics/asyncex/weights.py --- bittensor/core/extrinsics/asyncex/weights.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor/core/extrinsics/asyncex/weights.py b/bittensor/core/extrinsics/asyncex/weights.py index 4b3d5cd56d..cf993b37eb 100644 --- a/bittensor/core/extrinsics/asyncex/weights.py +++ b/bittensor/core/extrinsics/asyncex/weights.py @@ -318,7 +318,7 @@ async def set_weights_extrinsic( wait_for_finalization: bool = False, period: Optional[int] = 8, ) -> tuple[bool, str]: - """Sets the given weights and values on a chain for a wallet hotkey account. + """Sets the given weights and values on chain for a given wallet hotkey account. Args: subtensor (bittensor.core.async_subtensor.AsyncSubtensor): Bittensor subtensor object. From a31eca70236545e2893667081897b1c55d571d67 Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:19:46 +0200 Subject: [PATCH 091/100] Update bittensor/core/extrinsics/root.py --- bittensor/core/extrinsics/root.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor/core/extrinsics/root.py b/bittensor/core/extrinsics/root.py index 4a6dfbc0ee..2987df6724 100644 --- a/bittensor/core/extrinsics/root.py +++ b/bittensor/core/extrinsics/root.py @@ -227,7 +227,7 @@ def set_root_weights_extrinsic( wait_for_finalization: bool = False, period: Optional[int] = None, ) -> bool: - """Sets the given weights and values on a chain for a wallet hotkey account. + """Sets the given weights and values on chain for a given wallet hotkey account. Arguments: subtensor (bittensor.core.subtensor.Subtensor): The Subtensor object From 81b7575bf01d93ab1eba8839aa62118e91ebb3f6 Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:20:42 +0200 Subject: [PATCH 092/100] Update bittensor/core/extrinsics/root.py --- bittensor/core/extrinsics/root.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor/core/extrinsics/root.py b/bittensor/core/extrinsics/root.py index 2987df6724..f59a1104d7 100644 --- a/bittensor/core/extrinsics/root.py +++ b/bittensor/core/extrinsics/root.py @@ -233,7 +233,7 @@ def set_root_weights_extrinsic( subtensor (bittensor.core.subtensor.Subtensor): The Subtensor object wallet (bittensor_wallet.Wallet): Bittensor wallet object. netuids (Union[NDArray[np.int64], list[int]]): The `netuid` of the subnet to set weights for. - weights (Union[NDArray[np.float32], list[float]]): Weights to set. These must be `float's and must correspond + weights (Union[NDArray[np.float32], list[float]]): Weights to set. These must be floats and must correspond to the passed `netuid` s. version_key (int): The version key of the validator. wait_for_inclusion (bool): If set, waits for the extrinsic to enter a block before returning `True`, or returns From 65e4f12a935270c2d475d2e678738da483311fe2 Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:20:57 +0200 Subject: [PATCH 093/100] Update bittensor/core/extrinsics/staking.py --- bittensor/core/extrinsics/staking.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor/core/extrinsics/staking.py b/bittensor/core/extrinsics/staking.py index 173fee2db1..58f5ed0b71 100644 --- a/bittensor/core/extrinsics/staking.py +++ b/bittensor/core/extrinsics/staking.py @@ -215,7 +215,7 @@ def add_stake_multiple_extrinsic( wait_for_finalization: bool = False, period: Optional[int] = None, ) -> bool: - """Adds a stake to each ``hotkey_ss58`` in the list, using each amount, from a common coldkey. + """Adds stake to each ``hotkey_ss58`` in the list, using each amount, from a common coldkey. Arguments: subtensor: The initialized SubtensorInterface object. From f02cd52af3a800b424e6f35abf8244516d885ed0 Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:21:19 +0200 Subject: [PATCH 094/100] Update bittensor/core/extrinsics/take.py --- bittensor/core/extrinsics/take.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor/core/extrinsics/take.py b/bittensor/core/extrinsics/take.py index d07e628aab..968338d8a9 100644 --- a/bittensor/core/extrinsics/take.py +++ b/bittensor/core/extrinsics/take.py @@ -69,7 +69,7 @@ def decrease_take_extrinsic( raise_error: bool = False, period: Optional[int] = None, ) -> tuple[bool, str]: - """Sets the delegate 'take' percentage for a neuron identified by its hotkey. + """Sets the delegate `take` percentage for a neuron identified by its hotkey. Args: subtensor (Subtensor): Blockchain connection. From caba14a3e204b14b85a1f83303fafea9c75a53b0 Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:21:32 +0200 Subject: [PATCH 095/100] Update bittensor/core/subtensor.py --- bittensor/core/subtensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index a01323e050..fc923d4576 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -485,7 +485,7 @@ def commit_reveal_enabled( self, netuid: int, block: Optional[int] = None ) -> Optional[bool]: """ - Check if a commit-reveal mechanism is enabled for a given network at a specific block. + Check if the commit-reveal mechanism is enabled for a given network at a specific block. Arguments: netuid: The network identifier for which to check the commit-reveal mechanism. From aefb3851e76f73e6f84b2fa6ed47f7e7019b8141 Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:22:34 +0200 Subject: [PATCH 096/100] Update bittensor/core/subtensor.py --- bittensor/core/subtensor.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index fc923d4576..c1691f19b3 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -2376,9 +2376,6 @@ def wait_for_block(self, block: Optional[int] = None): bool: True if the target block was reached, False if timeout occurred. Example: - >>> import bittensor as bt - >>> subtensor = bt.subtensor(network="finney")) - >>> subtensor.wait_for_block() # Waits for the next block >>> subtensor.wait_for_block(block=1234) # Waits for a specific block """ From 72ac8a4833d7804f5c702fc604c73944acb37653 Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:22:48 +0200 Subject: [PATCH 097/100] Update bittensor/core/subtensor.py --- bittensor/core/subtensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index c1691f19b3..430c042607 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -2528,7 +2528,7 @@ def sign_and_send_extrinsic( the transaction is not included in a block within that number of blocks, it will expire and be rejected. You can think of it as an expiration date for the transaction. nonce_key: the type on nonce to use. Options are "hotkey" or "coldkey". - raise_error: raises a relevant exception rather than returning `False` if unsuccessful. + raise_error: raises the relevant exception rather than returning `False` if unsuccessful. Returns: (success, error message) From ce0d97fff71c77875c0a61f3a227c579d2e0eb8f Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:23:00 +0200 Subject: [PATCH 098/100] Update bittensor/core/subtensor.py --- bittensor/core/subtensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 430c042607..be1a9a3cae 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -2975,7 +2975,7 @@ def reveal_weights( weights (np.ndarray): NumPy array of weight values corresponding to each UID. salt (np.ndarray): NumPy array of salt values corresponding to the hash function. version_key (int): Version key for compatibility with the network. Default is ``int representation of - a Bittensor version``. + the Bittensor version``. wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``False``. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``. From a6a6a1300a5e165d5043d0ea17ff0b35c104b734 Mon Sep 17 00:00:00 2001 From: BD Himes <37844818+thewhaleking@users.noreply.github.com> Date: Fri, 2 May 2025 17:23:11 +0200 Subject: [PATCH 099/100] Update bittensor/core/subtensor.py --- bittensor/core/subtensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index be1a9a3cae..800790ea40 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -3552,7 +3552,7 @@ def transfer( Arguments: wallet (bittensor_wallet.Wallet): Source wallet for the transfer. dest (str): Destination address for the transfer. - amount (float): Number of tokens to transfer. + amount (float): Amount of tao to transfer. transfer_all (bool): Flag to transfer all tokens. Default is ``False``. wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``True``. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is From 05e0fc5ccbe24edc044f7be25842f323acb097bb Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 2 May 2025 08:36:25 -0700 Subject: [PATCH 100/100] add TODO --- bittensor/core/async_subtensor.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index 082c0f44e8..c9b05ceef2 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -3731,9 +3731,11 @@ async def reveal_weights( return success, message + # TODO: remove `block_hash` argument async def root_register( self, wallet: "Wallet", + block_hash: Optional[str] = None, wait_for_inclusion: bool = True, wait_for_finalization: bool = True, period: Optional[int] = None, @@ -3743,6 +3745,7 @@ async def root_register( Arguments: wallet (bittensor_wallet.Wallet): Bittensor wallet instance. + block_hash (Optional[str]): This argument will be removed in Bittensor v10 wait_for_inclusion (bool): Waits for the transaction to be included in a block. Default is ``False``. wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is ``False``.