Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimisations and tests for Async Sync Subtensor #2569

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 28 additions & 16 deletions bittensor/core/async_subtensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import copy
from itertools import chain
import ssl
from typing import Optional, Any, Union, TypedDict, Iterable, TYPE_CHECKING
from typing import Optional, Any, Union, Iterable, TYPE_CHECKING

import aiohttp
import asyncstdlib as a
Expand Down Expand Up @@ -60,6 +60,7 @@
reveal_weights_extrinsic,
)
from bittensor.core.metagraph import AsyncMetagraph
from bittensor.core.types import ParamWithTypes
from bittensor.core.settings import version_as_int, TYPE_REGISTRY, DELEGATES_DETAILS_URL
from bittensor.utils import (
decode_hex_identity_dict,
Expand All @@ -68,6 +69,7 @@
ss58_to_vec_u8,
torch,
u16_normalized_float,
execute_coroutine,
)
from bittensor.utils import networking
from bittensor.utils.substrate_interface import AsyncSubstrateInterface
Expand All @@ -85,11 +87,6 @@
from bittensor.utils.substrate_interface import QueryMapResult


class ParamWithTypes(TypedDict):
name: str # Name of the parameter.
type: str # ScaleType string of the parameter.


def _decode_hex_identity_dict(info_dictionary: dict[str, Any]) -> dict[str, Any]:
"""Decodes a dictionary of hexadecimal identities."""
for k, v in info_dictionary.items():
Expand Down Expand Up @@ -123,6 +120,7 @@ def __init__(
self,
network: Optional[str] = None,
config: Optional["Config"] = None,
_mock: bool = False,
log_verbose: bool = False,
event_loop: asyncio.AbstractEventLoop = None,
):
Expand All @@ -132,6 +130,7 @@ def __init__(
Arguments:
network (str): The network name or type to connect to.
config (Optional[Config]): Configuration object for the AsyncSubtensor instance.
_mock: Whether this is a mock instance. Mainly just for use in testing.
log_verbose (bool): Enables or disables verbose logging.
event_loop (Optional[asyncio.AbstractEventLoop]): Custom asyncio event loop.

Expand All @@ -144,6 +143,7 @@ def __init__(
self.chain_endpoint, self.network = AsyncSubtensor.setup_config(
network, self._config
)
self._mock = _mock

self.log_verbose = log_verbose
self._check_and_log_network_settings()
Expand All @@ -158,6 +158,7 @@ def __init__(
use_remote_preset=True,
chain_name="Bittensor",
event_loop=event_loop,
_mock=_mock,
)
if self.log_verbose:
logging.info(
Expand All @@ -170,6 +171,9 @@ def __str__(self):
def __repr__(self):
return self.__str__()

def __del__(self):
execute_coroutine(self.close())

def _check_and_log_network_settings(self):
if self.network == settings.NETWORKS[3]: # local
logging.warning(
Expand Down Expand Up @@ -439,7 +443,9 @@ async def get_hyperparameter(
The value of the specified hyperparameter if the subnet exists, or None
"""
block_hash = await self.determine_block_hash(block, block_hash, reuse_block)
if not await self.subnet_exists(netuid, block_hash, reuse_block=reuse_block):
if not await self.subnet_exists(
netuid, block_hash=block_hash, reuse_block=reuse_block
):
logging.error(f"subnet {netuid} does not exist")
return None

Expand Down Expand Up @@ -797,7 +803,7 @@ async def bonds(

return b_map

async def commit(self, wallet: "Wallet", netuid: int, data: str):
async def commit(self, wallet: "Wallet", netuid: int, data: str) -> bool:
"""
Commits arbitrary data to the Bittensor network by publishing metadata.

Expand All @@ -806,7 +812,7 @@ async def commit(self, wallet: "Wallet", netuid: int, data: str):
netuid (int): The unique identifier of the subnetwork.
data (str): The data to be committed to the network.
"""
await publish_metadata(
return await publish_metadata(
subtensor=self,
wallet=wallet,
netuid=netuid,
Expand Down Expand Up @@ -1042,7 +1048,7 @@ async def get_block_hash(self, block: Optional[int] = None):
trustworthiness of the blockchain.
"""
if block:
return await self.substrate.get_block_hash(block)
return await self._get_block_hash(block)
else:
return await self.substrate.get_chain_head()

Expand Down Expand Up @@ -2977,7 +2983,7 @@ async def root_register(
try:
recycle_call, balance = await asyncio.gather(
self.get_hyperparameter(
param_name="Burn", netuid=netuid, reuse_block=True
param_name="Burn", netuid=netuid, block_hash=block_hash
),
self.get_balance(wallet.coldkeypub.ss58_address, block_hash=block_hash),
)
Expand Down Expand Up @@ -3071,6 +3077,14 @@ async def set_weights(

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】.
"""

async def _blocks_weight_limit() -> bool:
bslu, wrl = await asyncio.gather(
self.blocks_since_last_update(netuid, uid),
self.weights_rate_limit(netuid),
)
return bslu > wrl

retries = 0
success = False
if (
Expand All @@ -3087,10 +3101,9 @@ async def set_weights(
# go with `commit reveal v3` extrinsic
message = "No attempt made. Perhaps it is too soon to commit weights!"
while (
await self.blocks_since_last_update(netuid, uid)
> await self.weights_rate_limit(netuid)
and retries < max_retries
retries < max_retries
and success is False
and await _blocks_weight_limit()
):
logging.info(
f"Committing weights for subnet #{netuid}. Attempt {retries + 1} of {max_retries}."
Expand All @@ -3112,9 +3125,8 @@ async def set_weights(
message = "No attempt made. Perhaps it is too soon to set weights!"
while (
retries < max_retries
and await self.blocks_since_last_update(netuid, uid)
> await self.weights_rate_limit(netuid)
and success is False
and await _blocks_weight_limit()
):
try:
logging.info(
Expand Down
8 changes: 2 additions & 6 deletions bittensor/core/classic_subtensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import argparse
import copy
import ssl
from typing import Union, Optional, TypedDict, Any
from typing import Union, Optional, Any

import numpy as np
import scalecodec
Expand Down Expand Up @@ -64,6 +64,7 @@
unstake_multiple_extrinsic,
)
from bittensor.core.metagraph import Metagraph
from bittensor.core.types import ParamWithTypes
from bittensor.utils import (
networking,
torch,
Expand All @@ -80,11 +81,6 @@
KEY_NONCE: dict[str, int] = {}


class ParamWithTypes(TypedDict):
name: str # Name of the parameter.
type: str # ScaleType string of the parameter.


class Subtensor:
"""
The Subtensor class in Bittensor serves as a crucial interface for interacting with the Bittensor blockchain,
Expand Down
10 changes: 1 addition & 9 deletions bittensor/core/dendrite.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from bittensor.core.settings import version_as_int
from bittensor.core.stream import StreamingSynapse
from bittensor.core.synapse import Synapse, TerminalInfo
from bittensor.utils import networking
from bittensor.utils import networking, event_loop_is_running
from bittensor.utils.btlogging import logging
from bittensor.utils.registration import torch, use_torch

Expand All @@ -48,14 +48,6 @@
DENDRITE_DEFAULT_ERROR = ("422", "Failed to parse response")


def event_loop_is_running():
try:
asyncio.get_running_loop()
return True
except RuntimeError:
return False


class DendriteMixin:
"""
The Dendrite class represents the abstracted implementation of a network client module.
Expand Down
6 changes: 3 additions & 3 deletions bittensor/core/extrinsics/asyncex/commit_reveal.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ async def commit_reveal_v3_extrinsic(
# Reformat and normalize.
uids, weights = convert_weights_and_uids_for_emit(uids, weights)

current_block = await subtensor.get_current_block()
current_block = await subtensor.substrate.get_block(None)
subnet_hyperparameters = await subtensor.get_subnet_hyperparameters(
netuid, block=current_block
netuid, block_hash=current_block["header"]["hash"]
)
tempo = subnet_hyperparameters.tempo
subnet_reveal_period_epochs = (
Expand All @@ -128,7 +128,7 @@ async def commit_reveal_v3_extrinsic(
weights=weights,
version_key=version_key,
tempo=tempo,
current_block=current_block,
current_block=current_block["header"]["number"],
netuid=netuid,
subnet_reveal_period_epochs=subnet_reveal_period_epochs,
)
Expand Down
Loading