Skip to content

Commit f54004f

Browse files
authored
Merge pull request #2882 from opentensor/release/9.6.0
Release/9.6.0
2 parents d0cfd9e + 3e33869 commit f54004f

File tree

12 files changed

+152
-39
lines changed

12 files changed

+152
-39
lines changed

.github/workflows/monitor_requirements_size_master.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ name: Monitor SDK Requirements Size
66

77
on:
88
pull_request:
9-
types: [opened]
10-
branches: [master]
9+
types: [opened, labeled]
10+
branches: [master, staging]
1111

1212
permissions:
1313
pull-requests: write
1414
contents: read
1515

1616
jobs:
1717
measure-venv:
18+
if: github.event_name == 'pull_request' && github.base_ref == 'master' || contains( github.event.pull_request.labels.*.name, 'show-venv-size')
1819
runs-on: ubuntu-latest
1920
strategy:
2021
matrix:
@@ -54,7 +55,6 @@ jobs:
5455
esac
5556
5657
comment-on-pr:
57-
if: github.event_name == 'pull_request' && github.base_ref == 'master'
5858
needs: measure-venv
5959
runs-on: ubuntu-latest
6060
steps:

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Changelog
22

3+
## 9.5.0 /2025-05-15
4+
5+
* Add manual way to show the size of virtual environments in the PR by @basfroman in https://github.com/opentensor/bittensor/pull/2875
6+
* Improve `Monitor SDK Requirements Size` workflow by @basfroman in https://github.com/opentensor/bittensor/pull/2878
7+
* Add subtensor.is_subnet_active method by @basfroman in https://github.com/opentensor/bittensor/pull/2877
8+
* Using `hotkey` instead of `coldkey` to sign extrinsic in `serve_axon` by @basfroman in https://github.com/opentensor/bittensor/pull/2879
9+
* Rename argument `fallback_chains` to `fallback_endpoints` by @basfroman in https://github.com/opentensor/bittensor/pull/2880
10+
11+
**Full Changelog**: https://github.com/opentensor/bittensor/compare/v9.5.0...v9.6.0
12+
313
## 9.5.0 /2025-05-12
414

515
## What's Changed

bittensor/core/async_subtensor.py

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -115,19 +115,19 @@ def __init__(
115115
network: Optional[str] = None,
116116
config: Optional["Config"] = None,
117117
log_verbose: bool = False,
118-
fallback_chains: Optional[list[str]] = None,
118+
fallback_endpoints: Optional[list[str]] = None,
119119
retry_forever: bool = False,
120120
_mock: bool = False,
121121
):
122122
"""
123123
Initializes an instance of the AsyncSubtensor class.
124124
125125
Arguments:
126-
network (str): The network name or type to connect to.
127-
config (Optional[Config]): Configuration object for the AsyncSubtensor instance.
128-
log_verbose (bool): Enables or disables verbose logging.
129-
fallback_chains (list): List of fallback chains endpoints to use if no network is specified. Defaults to `None`.
130-
retry_forever (bool): Whether to retry forever on connection errors. Defaults to `False`.
126+
network: The network name or type to connect to.
127+
config: Configuration object for the AsyncSubtensor instance.
128+
log_verbose: Enables or disables verbose logging.
129+
fallback_endpoints: List of fallback endpoints to use if default or provided network is not available. Defaults to `None`.
130+
retry_forever: Whether to retry forever on connection errors. Defaults to `False`.
131131
_mock: Whether this is a mock instance. Mainly just for use in testing.
132132
133133
Raises:
@@ -148,7 +148,9 @@ def __init__(
148148
f"chain_endpoint: [blue]{self.chain_endpoint}[/blue]..."
149149
)
150150
self.substrate = self._get_substrate(
151-
fallback_chains=fallback_chains, retry_forever=retry_forever, _mock=_mock
151+
fallback_endpoints=fallback_endpoints,
152+
retry_forever=retry_forever,
153+
_mock=_mock,
152154
)
153155
if self.log_verbose:
154156
logging.info(
@@ -284,24 +286,24 @@ async def get_hyperparameter(
284286

285287
def _get_substrate(
286288
self,
287-
fallback_chains: Optional[list[str]] = None,
289+
fallback_endpoints: Optional[list[str]] = None,
288290
retry_forever: bool = False,
289291
_mock: bool = False,
290292
) -> Union[AsyncSubstrateInterface, RetryAsyncSubstrate]:
291293
"""Creates the Substrate instance based on provided arguments.
292294
293295
Arguments:
294-
fallback_chains (list): List of fallback chains endpoints to use if no network is specified. Defaults to `None`.
295-
retry_forever (bool): Whether to retry forever on connection errors. Defaults to `False`.
296+
fallback_endpoints: List of fallback endpoints to use if default or provided network is not available. Defaults to `None`.
297+
retry_forever: Whether to retry forever on connection errors. Defaults to `False`.
296298
_mock: Whether this is a mock instance. Mainly just for use in testing.
297299
298300
Returns:
299301
the instance of the SubstrateInterface or RetrySyncSubstrate class.
300302
"""
301-
if fallback_chains or retry_forever:
303+
if fallback_endpoints or retry_forever:
302304
return RetryAsyncSubstrate(
303305
url=self.chain_endpoint,
304-
fallback_chains=fallback_chains,
306+
fallback_chains=fallback_endpoints,
305307
ss58_format=SS58_FORMAT,
306308
type_registry=TYPE_REGISTRY,
307309
retry_forever=retry_forever,
@@ -2582,6 +2584,35 @@ async def is_hotkey_registered_on_subnet(
25822584
is not None
25832585
)
25842586

2587+
async def is_subnet_active(
2588+
self,
2589+
netuid: int,
2590+
block: Optional[int] = None,
2591+
block_hash: Optional[str] = None,
2592+
reuse_block: bool = False,
2593+
) -> bool:
2594+
"""Verify if subnet with provided netuid is active.
2595+
2596+
Args:
2597+
netuid (int): The unique identifier of the subnet.
2598+
block (Optional[int]): The blockchain block number for the query.
2599+
block_hash (Optional[str]): The blockchain block_hash representation of block id.
2600+
reuse_block (bool): Whether to reuse the last-used block hash.
2601+
2602+
Returns:
2603+
True if subnet is active, False otherwise.
2604+
2605+
This means whether the `start_call` was initiated or not.
2606+
"""
2607+
query = await self.query_subtensor(
2608+
name="FirstEmissionBlockNumber",
2609+
block=block,
2610+
block_hash=block_hash,
2611+
reuse_block=reuse_block,
2612+
params=[netuid],
2613+
)
2614+
return True if query and query.value > 0 else False
2615+
25852616
async def last_drand_round(self) -> Optional[int]:
25862617
"""
25872618
Retrieves the last drand round emitted in bittensor. This corresponds when committed weights will be revealed.

bittensor/core/extrinsics/asyncex/serving.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ async def do_serve_axon(
6161
wallet=wallet,
6262
wait_for_inclusion=wait_for_inclusion,
6363
wait_for_finalization=wait_for_finalization,
64+
sign_with="hotkey",
6465
period=period,
6566
)
6667
return success, message
@@ -140,7 +141,7 @@ async def serve_extrinsic(
140141
f"Serving axon with: [blue]AxonInfo({wallet.hotkey.ss58_address}, {ip}:{port})[/blue] -> "
141142
f"[green]{subtensor.network}:{netuid}[/green]"
142143
)
143-
success, message = do_serve_axon(
144+
success, message = await do_serve_axon(
144145
subtensor=subtensor,
145146
wallet=wallet,
146147
call_params=params,

bittensor/core/extrinsics/serving.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def do_serve_axon(
6060
wallet=wallet,
6161
wait_for_inclusion=wait_for_inclusion,
6262
wait_for_finalization=wait_for_finalization,
63+
sign_with="hotkey",
6364
period=period,
6465
)
6566
return success, message

bittensor/core/subtensor.py

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -117,19 +117,19 @@ def __init__(
117117
network: Optional[str] = None,
118118
config: Optional["Config"] = None,
119119
log_verbose: bool = False,
120-
fallback_chains: Optional[list[str]] = None,
120+
fallback_endpoints: Optional[list[str]] = None,
121121
retry_forever: bool = False,
122122
_mock: bool = False,
123123
):
124124
"""
125125
Initializes an instance of the Subtensor class.
126126
127127
Arguments:
128-
network (str): The network name or type to connect to.
129-
config (Optional[Config]): Configuration object for the AsyncSubtensor instance.
130-
log_verbose (bool): Enables or disables verbose logging.
131-
fallback_chains (list): List of fallback chains endpoints to use if no network is specified. Defaults to `None`.
132-
retry_forever (bool): Whether to retry forever on connection errors. Defaults to `False`.
128+
network: The network name or type to connect to.
129+
config: Configuration object for the AsyncSubtensor instance.
130+
log_verbose: Enables or disables verbose logging.
131+
fallback_endpoints: List of fallback endpoints to use if default or provided network is not available. Defaults to `None`.
132+
retry_forever: Whether to retry forever on connection errors. Defaults to `False`.
133133
_mock: Whether this is a mock instance. Mainly just for use in testing.
134134
135135
Raises:
@@ -148,7 +148,9 @@ def __init__(
148148
f"chain_endpoint: [blue]{self.chain_endpoint}[/blue]> ..."
149149
)
150150
self.substrate = self._get_substrate(
151-
fallback_chains=fallback_chains, retry_forever=retry_forever, _mock=_mock
151+
fallback_endpoints=fallback_endpoints,
152+
retry_forever=retry_forever,
153+
_mock=_mock,
152154
)
153155
if self.log_verbose:
154156
logging.info(
@@ -167,28 +169,28 @@ def close(self):
167169

168170
def _get_substrate(
169171
self,
170-
fallback_chains: Optional[list[str]] = None,
172+
fallback_endpoints: Optional[list[str]] = None,
171173
retry_forever: bool = False,
172174
_mock: bool = False,
173175
) -> Union[SubstrateInterface, RetrySyncSubstrate]:
174176
"""Creates the Substrate instance based on provided arguments.
175177
176178
Arguments:
177-
fallback_chains (list): List of fallback chains endpoints to use if no network is specified. Defaults to `None`.
178-
retry_forever (bool): Whether to retry forever on connection errors. Defaults to `False`.
179+
fallback_endpoints: List of fallback chains endpoints to use if main network isn't available. Defaults to `None`.
180+
retry_forever: Whether to retry forever on connection errors. Defaults to `False`.
179181
_mock: Whether this is a mock instance. Mainly just for use in testing.
180182
181183
Returns:
182184
the instance of the SubstrateInterface or RetrySyncSubstrate class.
183185
"""
184-
if fallback_chains or retry_forever:
186+
if fallback_endpoints or retry_forever:
185187
return RetrySyncSubstrate(
186188
url=self.chain_endpoint,
187189
ss58_format=SS58_FORMAT,
188190
type_registry=TYPE_REGISTRY,
189191
use_remote_preset=True,
190192
chain_name="Bittensor",
191-
fallback_chains=fallback_chains,
193+
fallback_chains=fallback_endpoints,
192194
retry_forever=retry_forever,
193195
_mock=_mock,
194196
)
@@ -2023,6 +2025,25 @@ def is_hotkey_registered_on_subnet(
20232025
is not None
20242026
)
20252027

2028+
def is_subnet_active(self, netuid: int, block: Optional[int] = None) -> bool:
2029+
"""Verify if subnet with provided netuid is active.
2030+
2031+
Args:
2032+
netuid (int): The unique identifier of the subnet.
2033+
block (Optional[int]): The blockchain block number for the query.
2034+
2035+
Returns:
2036+
True if subnet is active, False otherwise.
2037+
2038+
This means whether the `start_call` was initiated or not.
2039+
"""
2040+
query = self.query_subtensor(
2041+
name="FirstEmissionBlockNumber",
2042+
block=block,
2043+
params=[netuid],
2044+
)
2045+
return True if query and query.value > 0 else False
2046+
20262047
def last_drand_round(self) -> Optional[int]:
20272048
"""
20282049
Retrieves the last drand round emitted in bittensor. This corresponds when committed weights will be revealed.

bittensor/core/subtensor_api/__init__.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ class SubtensorApi:
2525
network: The network to connect to. Defaults to `None` -> "finney".
2626
config: Bittensor configuration object. Defaults to `None`.
2727
legacy_methods: If `True`, all methods from the Subtensor class will be added to the root level of this class.
28-
fallback_chains (list): List of fallback chains to use if no network is specified. Defaults to `None`.
29-
retry_forever (bool): Whether to retry forever on connection errors. Defaults to `False`.
30-
log_verbose (bool): Enables or disables verbose logging.
28+
fallback_endpoints: List of fallback endpoints to use if default or provided network is not available. Defaults to `None`.
29+
retry_forever: Whether to retry forever on connection errors. Defaults to `False`.
30+
log_verbose: Enables or disables verbose logging.
3131
mock: Whether this is a mock instance. Mainly just for use in testing.
3232
3333
Example:
@@ -54,10 +54,15 @@ class SubtensorApi:
5454
subtensor = bt.SubtensorApi(legacy_methods=True)
5555
print(subtensor.bonds(0))
5656
57-
# using `fallback_chains` or `retry_forever`
57+
# using `fallback_endpoints` or `retry_forever`
5858
import bittensor as bt
5959
60-
60+
subtensor = bt.SubtensorApi(
61+
network="finney",
62+
fallback_endpoints=["wss://localhost:9945", "wss://some-other-endpoint:9945"],
63+
retry_forever=True,
64+
)
65+
print(subtensor.block)
6166
"""
6267

6368
def __init__(
@@ -66,13 +71,13 @@ def __init__(
6671
config: Optional["Config"] = None,
6772
async_subtensor: bool = False,
6873
legacy_methods: bool = False,
69-
fallback_chains: Optional[list[str]] = None,
74+
fallback_endpoints: Optional[list[str]] = None,
7075
retry_forever: bool = False,
7176
log_verbose: bool = False,
7277
mock: bool = False,
7378
):
7479
self.network = network
75-
self._fallback_chains = fallback_chains
80+
self._fallback_endpoints = fallback_endpoints
7681
self._retry_forever = retry_forever
7782
self._mock = mock
7883
self.log_verbose = log_verbose
@@ -111,7 +116,7 @@ def _get_subtensor(self) -> Union["_Subtensor", "_AsyncSubtensor"]:
111116
network=self.network,
112117
config=self._config,
113118
log_verbose=self.log_verbose,
114-
fallback_chains=self._fallback_chains,
119+
fallback_endpoints=self._fallback_endpoints,
115120
retry_forever=self._retry_forever,
116121
_mock=self._mock,
117122
)
@@ -122,7 +127,7 @@ def _get_subtensor(self) -> Union["_Subtensor", "_AsyncSubtensor"]:
122127
network=self.network,
123128
config=self._config,
124129
log_verbose=self.log_verbose,
125-
fallback_chains=self._fallback_chains,
130+
fallback_endpoints=self._fallback_endpoints,
126131
retry_forever=self._retry_forever,
127132
_mock=self._mock,
128133
)

bittensor/core/subtensor_api/subnets.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ def __init__(self, subtensor: Union["_Subtensor", "_AsyncSubtensor"]):
3232
self.get_uid_for_hotkey_on_subnet = subtensor.get_uid_for_hotkey_on_subnet
3333
self.immunity_period = subtensor.immunity_period
3434
self.is_hotkey_registered_on_subnet = subtensor.is_hotkey_registered_on_subnet
35+
self.is_subnet_active = subtensor.is_subnet_active
3536
self.max_weight_limit = subtensor.max_weight_limit
3637
self.min_allowed_weights = subtensor.min_allowed_weights
3738
self.recycle = subtensor.recycle

bittensor/core/subtensor_api/utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ def add_legacy_methods(subtensor: "SubtensorApi"):
108108
subtensor.is_hotkey_registered_on_subnet = (
109109
subtensor._subtensor.is_hotkey_registered_on_subnet
110110
)
111+
subtensor.is_subnet_active = subtensor._subtensor.is_subnet_active
111112
subtensor.last_drand_round = subtensor._subtensor.last_drand_round
112113
subtensor.log_verbose = subtensor._subtensor.log_verbose
113114
subtensor.max_weight_limit = subtensor._subtensor.max_weight_limit

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "bittensor"
7-
version = "9.5.0"
7+
version = "9.6.0"
88
description = "Bittensor"
99
readme = "README.md"
1010
authors = [

0 commit comments

Comments
 (0)