Skip to content

Commit b40a3c3

Browse files
Merge pull request #2696 from opentensor/release/9.0.2
Release/9.0.2
2 parents fad97f6 + 6071aed commit b40a3c3

File tree

12 files changed

+125
-74
lines changed

12 files changed

+125
-74
lines changed

.github/workflows/e2e-subtensor-tests.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ jobs:
5252
max-parallel: 8 # Set the maximum number of parallel jobs
5353
matrix:
5454
rust-branch:
55-
- nightly-2024-03-05
55+
- stable
5656
rust-target:
5757
- x86_64-unknown-linux-gnu
5858
os:

CHANGELOG.md

+17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
# Changelog
22

3+
## 9.0.2 /2025-02-24
4+
5+
## What's Changed
6+
* CI: Upgrade rust compiler for E2E tests by @zyzniewski-reef in https://github.com/opentensor/bittensor/pull/2690
7+
* Break away cli reqs by @thewhaleking in https://github.com/opentensor/bittensor/pull/2692
8+
* Updates DelegateInfo chain data by @ibraheem-opentensor in https://github.com/opentensor/bittensor/pull/2683
9+
* Backmerge main to staging 901 by @ibraheem-opentensor in https://github.com/opentensor/bittensor/pull/2689
10+
* fix: typos in documentation files by @zeevick10 in https://github.com/opentensor/bittensor/pull/2687
11+
* Removes tx limit in stake_multiple by @ibraheem-opentensor in https://github.com/opentensor/bittensor/pull/2694
12+
13+
## New Contributors
14+
* @zeevick10 made their first contribution in https://github.com/opentensor/bittensor/pull/2687
15+
16+
**Full Changelog**: https://github.com/opentensor/bittensor/compare/v9.0.1...v9.0.2
17+
18+
## 9.0.1 /2025-02-20
19+
320
## What's Changed
421
* Release/9.0.0 by @ibraheem-opentensor in https://github.com/opentensor/bittensor/pull/2671
522
* fix e2e test by @roman-opentensor in https://github.com/opentensor/bittensor/pull/2673

VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
9.0.1
1+
9.0.2

bittensor/core/chain_data/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from .axon_info import AxonInfo
99
from .chain_identity import ChainIdentity
10-
from .delegate_info import DelegateInfo
10+
from .delegate_info import DelegateInfo, DelegatedInfo
1111
from .delegate_info_lite import DelegateInfoLite
1212
from .dynamic_info import DynamicInfo
1313
from .ip_info import IPInfo
@@ -36,6 +36,7 @@
3636
AxonInfo,
3737
ChainIdentity,
3838
DelegateInfo,
39+
DelegatedInfo,
3940
DelegateInfoLite,
4041
DynamicInfo,
4142
IPInfo,
+87-42
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from dataclasses import dataclass
2-
from typing import Any, Optional
2+
from typing import Optional
33

44
from bittensor.core.chain_data.info_base import InfoBase
55
from bittensor.core.chain_data.utils import decode_account_id
@@ -8,27 +8,20 @@
88

99

1010
@dataclass
11-
class DelegateInfo(InfoBase):
12-
"""
13-
Dataclass for delegate information. For a lighter version of this class, see ``DelegateInfoLite``.
11+
class DelegateInfoBase(InfoBase):
12+
"""Base class containing common delegate information fields.
1413
15-
Args:
16-
hotkey_ss58 (str): Hotkey of the delegate for which the information is being fetched.
17-
total_stake (int): Total stake of the delegate.
18-
nominators (list[tuple[str, int]]): List of nominators of the delegate and their stake.
14+
Attributes:
15+
hotkey_ss58 (str): Hotkey of delegate.
16+
owner_ss58 (str): Coldkey of owner.
1917
take (float): Take of the delegate as a percentage.
20-
owner_ss58 (str): Coldkey of the owner.
21-
registrations (list[int]): List of subnets that the delegate is registered on.
2218
validator_permits (list[int]): List of subnets that the delegate is allowed to validate on.
23-
return_per_1000 (int): Return per 1000 TAO, for the delegate over a day.
24-
total_daily_return (int): Total daily return of the delegate.
19+
registrations (list[int]): List of subnets that the delegate is registered on.
20+
return_per_1000 (Balance): Return per 1000 tao of the delegate over a day.
21+
total_daily_return (Balance): Total daily return of the delegate.
2522
"""
2623

2724
hotkey_ss58: str # Hotkey of delegate
28-
total_stake: Balance # Total stake of the delegate
29-
nominators: list[
30-
tuple[str, Balance]
31-
] # List of nominators of the delegate and their stake
3225
owner_ss58: str # Coldkey of owner
3326
take: float # Take of the delegate as a percentage
3427
validator_permits: list[
@@ -38,35 +31,87 @@ class DelegateInfo(InfoBase):
3831
return_per_1000: Balance # Return per 1000 tao of the delegate over a day
3932
total_daily_return: Balance # Total daily return of the delegate
4033

34+
35+
@dataclass
36+
class DelegateInfo(DelegateInfoBase):
37+
"""
38+
Dataclass for delegate information.
39+
40+
Additional Attributes:
41+
total_stake (dict[int, Balance]): Total stake of the delegate mapped by netuid.
42+
nominators (dict[str, dict[int, Balance]]): Mapping of nominator SS58 addresses to their stakes per subnet.
43+
"""
44+
45+
total_stake: dict[int, Balance] # Total stake of the delegate by netuid and stake
46+
nominators: dict[
47+
str, dict[int, Balance]
48+
] # Mapping of nominator addresses to their stakes per subnet
49+
4150
@classmethod
4251
def _from_dict(cls, decoded: dict) -> Optional["DelegateInfo"]:
43-
"""Returns a DelegateInfo object from decoded chain data."""
44-
nominators = [
45-
(decode_account_id(x), Balance.from_rao(y))
46-
for x, y in decoded["nominators"]
47-
]
48-
total_stake = sum((x[1] for x in nominators)) if nominators else Balance(0)
49-
50-
return DelegateInfo(
51-
hotkey_ss58=decode_account_id(decoded["delegate_ss58"]),
52+
hotkey = decode_account_id(decoded.get("delegate_ss58"))
53+
owner = decode_account_id(decoded.get("owner_ss58"))
54+
55+
nominators = {}
56+
total_stake_by_netuid = {}
57+
58+
for raw_nominator, raw_stakes in decoded.get("nominators", []):
59+
nominator_ss58 = decode_account_id(raw_nominator)
60+
stakes = {
61+
int(netuid): Balance.from_rao(stake_amt).set_unit(int(netuid))
62+
for (netuid, stake_amt) in raw_stakes
63+
}
64+
nominators[nominator_ss58] = stakes
65+
66+
for netuid, stake in stakes.items():
67+
if netuid not in total_stake_by_netuid:
68+
total_stake_by_netuid[netuid] = Balance(0).set_unit(netuid)
69+
total_stake_by_netuid[netuid] += stake
70+
71+
return cls(
72+
hotkey_ss58=hotkey,
73+
total_stake=total_stake_by_netuid,
5274
nominators=nominators,
53-
owner_ss58=decode_account_id(decoded["owner_ss58"]),
54-
registrations=decoded["registrations"],
55-
return_per_1000=Balance.from_rao(decoded["return_per_1000"]),
56-
take=u16_normalized_float(decoded["take"]),
57-
total_daily_return=Balance.from_rao(decoded["total_daily_return"]),
58-
total_stake=total_stake,
59-
validator_permits=decoded["validator_permits"],
75+
owner_ss58=owner,
76+
take=u16_normalized_float(decoded.get("take")),
77+
validator_permits=list(decoded.get("validator_permits", [])),
78+
registrations=list(decoded.get("registrations", [])),
79+
return_per_1000=Balance.from_rao(decoded.get("return_per_1000")),
80+
total_daily_return=Balance.from_rao(decoded.get("total_daily_return")),
6081
)
6182

83+
84+
@dataclass
85+
class DelegatedInfo(DelegateInfoBase):
86+
"""
87+
Dataclass for delegated information. This class represents a delegate's information
88+
specific to a particular subnet.
89+
90+
Additional Attributes:
91+
netuid (int): Network ID of the subnet.
92+
stake (Balance): Stake amount for this specific delegation.
93+
"""
94+
95+
netuid: int
96+
stake: Balance
97+
6298
@classmethod
63-
def delegated_list_from_dicts(
64-
cls, delegates: list[Any]
65-
) -> list[tuple["DelegateInfo", Balance]]:
66-
return [
67-
(
68-
DelegateInfo.from_dict(delegate),
69-
Balance.from_rao(balance),
70-
)
71-
for delegate, balance in delegates
72-
]
99+
def _from_dict(
100+
cls, decoded: tuple[dict, tuple[int, int]]
101+
) -> Optional["DelegatedInfo"]:
102+
delegate_info, (netuid, stake) = decoded
103+
hotkey = decode_account_id(delegate_info.get("delegate_ss58"))
104+
owner = decode_account_id(delegate_info.get("owner_ss58"))
105+
return cls(
106+
hotkey_ss58=hotkey,
107+
owner_ss58=owner,
108+
take=u16_normalized_float(delegate_info.get("take")),
109+
validator_permits=list(delegate_info.get("validator_permits", [])),
110+
registrations=list(delegate_info.get("registrations", [])),
111+
return_per_1000=Balance.from_rao(delegate_info.get("return_per_1000")),
112+
total_daily_return=Balance.from_rao(
113+
delegate_info.get("total_daily_return")
114+
),
115+
netuid=int(netuid),
116+
stake=Balance.from_rao(int(stake)).set_unit(int(netuid)),
117+
)

bittensor/core/extrinsics/staking.py

+2-17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import time
21
from typing import Optional, TYPE_CHECKING, Sequence
32

43
from bittensor.core.errors import StakeError, NotRegisteredError
@@ -233,7 +232,7 @@ def add_stake_multiple_extrinsic(
233232
total_staking_rao = sum(
234233
[amount.rao if amount is not None else 0 for amount in new_amounts]
235234
)
236-
old_balance = inital_balance = subtensor.get_balance(
235+
old_balance = initial_balance = subtensor.get_balance(
237236
wallet.coldkeypub.ss58_address, block=block
238237
)
239238
if total_staking_rao == 0:
@@ -298,20 +297,6 @@ def add_stake_multiple_extrinsic(
298297
if staking_response is True: # If we successfully staked.
299298
# We only wait here if we expect finalization.
300299

301-
if idx < len(hotkey_ss58s) - 1:
302-
# Wait for tx rate limit.
303-
tx_query = subtensor.substrate.query(
304-
module="SubtensorModule", storage_function="TxRateLimit"
305-
)
306-
tx_rate_limit_blocks: int = getattr(tx_query, "value", 0)
307-
if tx_rate_limit_blocks > 0:
308-
logging.error(
309-
f":hourglass: [yellow]Waiting for tx rate limit: [white]{tx_rate_limit_blocks}[/white] "
310-
f"blocks[/yellow]"
311-
)
312-
# 12 seconds per block
313-
time.sleep(tx_rate_limit_blocks * 12)
314-
315300
if not wait_for_finalization and not wait_for_inclusion:
316301
old_balance -= staking_balance
317302
successful_stakes += 1
@@ -365,7 +350,7 @@ def add_stake_multiple_extrinsic(
365350
)
366351
new_balance = subtensor.get_balance(wallet.coldkeypub.ss58_address)
367352
logging.info(
368-
f"Balance: [blue]{inital_balance}[/blue] :arrow_right: [green]{new_balance}[/green]"
353+
f"Balance: [blue]{initial_balance}[/blue] :arrow_right: [green]{new_balance}[/green]"
369354
)
370355
return True
371356

bittensor/core/settings.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "9.0.1"
1+
__version__ = "9.0.2"
22

33
import os
44
import re

bittensor/core/subtensor.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
WeightCommitInfo,
2525
SubnetIdentity,
2626
SubnetInfo,
27+
DelegatedInfo,
2728
decode_account_id,
2829
)
2930
from bittensor.core.chain_data.utils import decode_metadata
@@ -925,7 +926,7 @@ def get_delegated(
925926
if not result:
926927
return []
927928

928-
return DelegateInfo.delegated_list_from_dicts(result)
929+
return DelegatedInfo.list_from_dicts(result)
929930

930931
def get_delegates(self, block: Optional[int] = None) -> list["DelegateInfo"]:
931932
"""

requirements/cli.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
bittensor-cli>=9.0.2

requirements/prod.txt

+2-3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,5 @@ scalecodec==1.2.11
2222
uvicorn
2323
websockets>=14.1
2424
bittensor-commit-reveal>=0.2.0
25-
bittensor-wallet>=3.0.3
26-
async-substrate-interface>=1.0.0
27-
bittensor-cli>=9.0.0
25+
bittensor-wallet>=3.0.4
26+
async-substrate-interface>=1.0.3

setup.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,25 @@
88
from setuptools import setup, find_packages
99

1010

11-
def read_requirements(path):
12-
requirements = []
11+
def read_requirements(path_):
12+
requirements_ = []
1313

14-
with pathlib.Path(path).open() as requirements_txt:
14+
with pathlib.Path(path_).open() as requirements_txt:
1515
for line in requirements_txt:
1616
if line.startswith("git+"):
1717
pkg_name = re.search(r"egg=([a-zA-Z0-9_-]+)", line.strip()).group(1)
18-
requirements.append(pkg_name + " @ " + line.strip())
18+
requirements_.append(pkg_name + " @ " + line.strip())
1919
else:
20-
requirements.append(line.strip())
20+
requirements_.append(line.strip())
2121

22-
return requirements
22+
return requirements_
2323

2424

2525
requirements = read_requirements("requirements/prod.txt")
2626
extra_requirements_dev = read_requirements("requirements/dev.txt")
2727
extra_requirements_cubit = read_requirements("requirements/cubit.txt")
2828
extra_requirements_torch = read_requirements("requirements/torch.txt")
29+
extra_requirements_cli = read_requirements("requirements/cli.txt")
2930

3031
here = path.abspath(path.dirname(__file__))
3132

@@ -62,6 +63,7 @@ def read_requirements(path):
6263
extras_require={
6364
"dev": extra_requirements_dev + extra_requirements_torch,
6465
"torch": extra_requirements_torch,
66+
"cli": extra_requirements_cli,
6567
},
6668
classifiers=[
6769
"Development Status :: 3 - Alpha",

tests/e2e_tests/test_commit_weights.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ async def test_commit_and_reveal_weights_legacy(local_chain, subtensor, alice_wa
7070
), "Failed to set weights_rate_limit"
7171
assert subtensor.weights_rate_limit(netuid=netuid) == 0
7272

73-
# Increase subnet tempo so we have enought time to commit and reveal weights
73+
# Increase subnet tempo so we have enough time to commit and reveal weights
7474
sudo_set_admin_utils(
7575
local_chain,
7676
alice_wallet,

0 commit comments

Comments
 (0)