Skip to content

Commit

Permalink
Merge pull request #2662 from opentensor/feat/roman/add-subnet-identi…
Browse files Browse the repository at this point in the history
…ty-with-subnet-creation

feat/roman/add-subnet-identity-with-subnet-creation
  • Loading branch information
ibraheem-opentensor authored Feb 12, 2025
2 parents 820b1e2 + 1fab7b0 commit d244791
Show file tree
Hide file tree
Showing 10 changed files with 681 additions and 9 deletions.
44 changes: 42 additions & 2 deletions bittensor/core/async_subtensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
NeuronInfo,
ProposalVoteData,
SubnetHyperparameters,
SubnetIdentity,
SubnetInfo,
WeightCommitInfo,
decode_account_id,
Expand All @@ -34,6 +35,7 @@
burned_register_extrinsic,
register_extrinsic,
register_subnet_extrinsic,
set_subnet_identity_extrinsic,
)
from bittensor.core.extrinsics.asyncex.move_stake import (
transfer_stake_extrinsic,
Expand Down Expand Up @@ -2581,8 +2583,8 @@ async def wait_for_block(self, block: Optional[int] = None):
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() # Waits for next block
await subtensor.wait_for_block(block=1234) # Waits for specific block
"""

async def handler(block_data: dict):
Expand Down Expand Up @@ -3188,6 +3190,44 @@ async def root_set_weights(
wait_for_inclusion=wait_for_inclusion,
)

async def set_subnet_identity(
self,
wallet: "Wallet",
netuid: int,
subnet_identity: SubnetIdentity,
wait_for_inclusion: bool = False,
wait_for_finalization: bool = True,
) -> tuple[bool, str]:
"""
Sets the identity of a subnet for a specific wallet and network.
Arguments:
wallet (Wallet): The wallet instance that will authorize the transaction.
netuid (int): The unique ID of the network on which the operation takes place.
subnet_identity (SubnetIdentity): The identity data of the subnet including attributes like name, GitHub
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.
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.
"""
return await set_subnet_identity_extrinsic(
subtensor=self,
wallet=wallet,
netuid=netuid,
subnet_name=subnet_identity.subnet_name,
github_repo=subnet_identity.github_repo,
subnet_contact=subnet_identity.subnet_contact,
subnet_url=subnet_identity.subnet_url,
discord=subnet_identity.discord,
description=subnet_identity.description,
additional=subnet_identity.additional,
wait_for_inclusion=wait_for_inclusion,
wait_for_finalization=wait_for_finalization,
)

async def set_weights(
self,
wallet: "Wallet",
Expand Down
82 changes: 80 additions & 2 deletions bittensor/core/extrinsics/asyncex/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,14 +430,92 @@ async def register_subnet_extrinsic(
if not wait_for_finalization and not wait_for_inclusion:
return True

await response.process_events()
if not await response.is_success:
logging.error(
f"Failed to register subnet: {format_error_message(await response.error_message, subtensor.substrate)}"
f"Failed to register subnet: {format_error_message(await response.error_message)}"
)
return False

logging.success(
":white_heavy_check_mark: [green]Successfully registered subnet[/green]"
)
return True


async def set_subnet_identity_extrinsic(
subtensor: "AsyncSubtensor",
wallet: "Wallet",
netuid: int,
subnet_name: str,
github_repo: str,
subnet_contact: str,
subnet_url: str,
discord: str,
description: str,
additional: str,
wait_for_inclusion: bool = False,
wait_for_finalization: bool = True,
) -> tuple[bool, str]:
"""
Set the identity information for a given subnet.
Arguments:
subtensor (AsyncSubtensor): An instance of the Subtensor class to interact with the blockchain.
wallet (Wallet): A wallet instance used to sign and submit the extrinsic.
netuid (int): The unique ID for the subnet.
subnet_name (str): The name of the subnet to assign the identity information.
github_repo (str): URL of the GitHub repository related to the subnet.
subnet_contact (str): Subnet's contact information, e.g., email or contact link.
subnet_url (str): The URL of the subnet's primary web portal.
discord (str): Discord server or contact for the subnet.
description (str): A textual description of the subnet.
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).
Returns:
tuple[bool, str]: A tuple where the first element indicates success or failure (True/False), and the second
element contains a descriptive message.
"""

if not (unlock := unlock_key(wallet)).success:
logging.error(unlock.message)
return False, unlock.message

call = await subtensor.substrate.compose_call(
call_module="SubtensorModule",
call_function="set_subnet_identity",
call_params={
"hotkey": wallet.hotkey.ss58_address,
"netuid": netuid,
"subnet_name": subnet_name,
"github_repo": github_repo,
"subnet_contact": subnet_contact,
"subnet_url": subnet_url,
"discord": discord,
"description": description,
"additional": additional,
},
)

response = await subtensor.substrate.submit_extrinsic(
call=call,
wallet=wallet,
wait_for_inclusion=wait_for_inclusion,
wait_for_finalization=wait_for_finalization,
)

if not wait_for_finalization and not wait_for_inclusion:
return True, f"Identities for subnet {netuid} are sent to the chain."

if await response.is_success:
logging.success(
f":white_heavy_check_mark: [green]Identities for subnet[/green] [blue]{netuid}[/blue] [green]are set.[/green]"
)
return True, f"Identities for subnet {netuid} are set."
else:
error_message = await response.error_message
logging.error(
f":cross_mark: Failed to set identity for subnet [blue]{netuid}[/blue]: {error_message}"
)
return False, f"Failed to set identity for subnet {netuid}: {error_message}"
78 changes: 78 additions & 0 deletions bittensor/core/extrinsics/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,3 +424,81 @@ def register_extrinsic(
# Failed to register after max attempts.
logging.error("[red]No more attempts.[/red]")
return False


def set_subnet_identity_extrinsic(
subtensor: "Subtensor",
wallet: "Wallet",
netuid: int,
subnet_name: str,
github_repo: str,
subnet_contact: str,
subnet_url: str,
discord: str,
description: str,
additional: str,
wait_for_inclusion: bool = False,
wait_for_finalization: bool = True,
) -> tuple[bool, str]:
"""
Set the identity information for a given subnet.
Arguments:
subtensor (Subtensor): An instance of the Subtensor class to interact with the blockchain.
wallet (Wallet): A wallet instance used to sign and submit the extrinsic.
netuid (int): The unique ID for the subnet.
subnet_name (str): The name of the subnet to assign the identity information.
github_repo (str): URL of the GitHub repository related to the subnet.
subnet_contact (str): Subnet's contact information, e.g., email or contact link.
subnet_url (str): The URL of the subnet's primary web portal.
discord (str): Discord server or contact for the subnet.
description (str): A textual description of the subnet.
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).
Returns:
tuple[bool, str]: A tuple where the first element indicates success or failure (True/False), and the second
element contains a descriptive message.
"""

if not (unlock := unlock_key(wallet)).success:
logging.error(unlock.message)
return False, unlock.message

call = subtensor.substrate.compose_call(
call_module="SubtensorModule",
call_function="set_subnet_identity",
call_params={
"hotkey": wallet.hotkey.ss58_address,
"netuid": netuid,
"subnet_name": subnet_name,
"github_repo": github_repo,
"subnet_contact": subnet_contact,
"subnet_url": subnet_url,
"discord": discord,
"description": description,
"additional": additional,
},
)

success, message = subtensor.sign_and_send_extrinsic(
call=call,
wallet=wallet,
wait_for_inclusion=wait_for_inclusion,
wait_for_finalization=wait_for_finalization,
)

if not wait_for_finalization and not wait_for_inclusion:
return True, f"Identities for subnet {netuid} are sent to the chain."

if success:
logging.success(
f":white_heavy_check_mark: [green]Identities for subnet[/green] [blue]{netuid}[/blue] [green]are set.[/green]"
)
return True, f"Identities for subnet {netuid} are set."
else:
logging.error(
f":cross_mark: Failed to set identity for subnet [blue]{netuid}[/blue]: {message}"
)
return False, f"Failed to set identity for subnet {netuid}: {message}"
40 changes: 40 additions & 0 deletions bittensor/core/subtensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
StakeInfo,
SubnetHyperparameters,
WeightCommitInfo,
SubnetIdentity,
SubnetInfo,
decode_account_id,
)
Expand All @@ -40,6 +41,7 @@
burned_register_extrinsic,
register_extrinsic,
register_subnet_extrinsic,
set_subnet_identity_extrinsic,
)
from bittensor.core.extrinsics.root import (
root_register_extrinsic,
Expand Down Expand Up @@ -2526,6 +2528,44 @@ def root_set_weights(
wait_for_inclusion=wait_for_inclusion,
)

def set_subnet_identity(
self,
wallet: "Wallet",
netuid: int,
subnet_identity: SubnetIdentity,
wait_for_inclusion: bool = False,
wait_for_finalization: bool = True,
) -> tuple[bool, str]:
"""
Sets the identity of a subnet for a specific wallet and network.
Arguments:
wallet (Wallet): The wallet instance that will authorize the transaction.
netuid (int): The unique ID of the network on which the operation takes place.
subnet_identity (SubnetIdentity): The identity data of the subnet including attributes like name, GitHub
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.
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.
"""
return set_subnet_identity_extrinsic(
subtensor=self,
wallet=wallet,
netuid=netuid,
subnet_name=subnet_identity.subnet_name,
github_repo=subnet_identity.github_repo,
subnet_contact=subnet_identity.subnet_contact,
subnet_url=subnet_identity.subnet_url,
discord=subnet_identity.discord,
description=subnet_identity.description,
additional=subnet_identity.additional,
wait_for_inclusion=wait_for_inclusion,
wait_for_finalization=wait_for_finalization,
)

def set_weights(
self,
wallet: "Wallet",
Expand Down
21 changes: 16 additions & 5 deletions bittensor/utils/easy_imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,27 @@
from bittensor.core.axon import Axon
from bittensor.core.chain_data import ( # noqa: F401
AxonInfo,
ChainIdentity,
DelegateInfo,
DelegateInfoLite,
DynamicInfo,
IPInfo,
MetagraphInfo,
MetagraphInfoEmissions,
MetagraphInfoParams,
MetagraphInfoPool,
NeuronInfo,
NeuronInfoLite,
PrometheusInfo,
DelegateInfo,
StakeInfo,
SubnetInfo,
SubnetHyperparameters,
IPInfo,
ProposalCallData,
ProposalVoteData,
ScheduledColdkeySwapInfo,
StakeInfo,
SubnetHyperparameters,
SubnetIdentity,
SubnetInfo,
SubnetState,
WeightCommitInfo,
)
from bittensor.core.config import ( # noqa: F401
InvalidConfigFile,
Expand Down
Loading

0 comments on commit d244791

Please sign in to comment.