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

Release/9.0.0rc5 #2650

Draft
wants to merge 4 commits into
base: release/9.0.0rc4
Choose a base branch
from
Draft
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 9.0.0rc5 /2025-02-07
* Fix InfoBase + dataclasses @roman-opentensor in https://github.com/opentensor/bittensor/pull/2649

**Full Changelog**: https://github.com/opentensor/bittensor/compare/v9.0.0rc4...v9.0.0rc5

## 9.0.0rc4 /2025-02-07
* Fix for extra fields from chain data by @roman-opentensor in https://github.com/opentensor/bittensor/pull/2647
* Adds get_all_commitments and fixes commitment tests and query_map @thewhaleking in https://github.com/opentensor/bittensor/pull/2644
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9.0.0rc4
9.0.0rc5
1 change: 1 addition & 0 deletions bittensor/core/chain_data/axon_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ def to_string(self) -> str:

@classmethod
def _from_dict(cls, data):
"""Returns a AxonInfo object from decoded chain data."""
return AxonInfo(
version=data["version"],
ip=str(netaddr.IPAddress(data["ip"])),
Expand Down
1 change: 1 addition & 0 deletions bittensor/core/chain_data/chain_identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class ChainIdentity(InfoBase):

@classmethod
def _from_dict(cls, decoded: dict) -> "ChainIdentity":
"""Returns a ChainIdentity object from decoded chain data."""
return cls(
name=decoded["name"],
url=decoded["url"],
Expand Down
1 change: 1 addition & 0 deletions bittensor/core/chain_data/delegate_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class DelegateInfo(InfoBase):

@classmethod
def _from_dict(cls, decoded: dict) -> Optional["DelegateInfo"]:
"""Returns a DelegateInfo object from decoded chain data."""
nominators = [
(decode_account_id(x), Balance.from_rao(y))
for x, y in decoded["nominators"]
Expand Down
20 changes: 18 additions & 2 deletions bittensor/core/chain_data/delegate_info_lite.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from dataclasses import dataclass

from bittensor.core.chain_data.info_base import InfoBase
from bittensor.core.chain_data.utils import decode_account_id
from bittensor.utils import u16_normalized_float
from bittensor.utils.balance import Balance


@dataclass
Expand All @@ -27,5 +30,18 @@ class DelegateInfoLite(InfoBase):
validator_permits: list[
int
] # List of subnets that the delegate is allowed to validate on
return_per_1000: int # Return per 1000 tao for the delegate over a day
total_daily_return: int # Total daily return of the delegate
return_per_1000: Balance # Return per 1000 tao for the delegate over a day
total_daily_return: Balance # Total daily return of the delegate

@classmethod
def _from_dict(cls, decoded: dict) -> "DelegateInfoLite":
return DelegateInfoLite(
delegate_ss58=decode_account_id(decoded["delegate_ss58"]),
take=u16_normalized_float(decoded["take"]),
nominators=decoded["nominators"],
owner_ss58=decode_account_id(decoded["owner_ss58"]),
registrations=decoded["registrations"],
validator_permits=decoded["validator_permits"],
return_per_1000=Balance.from_rao(decoded["return_per_1000"]),
total_daily_return=Balance.from_rao(decoded["total_daily_return"]),
)
2 changes: 1 addition & 1 deletion bittensor/core/chain_data/dynamic_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class DynamicInfo(InfoBase):

@classmethod
def _from_dict(cls, decoded: dict) -> "DynamicInfo":
"""Returns a DynamicInfo object from a decoded DynamicInfo dictionary."""
"""Returns a DynamicInfo object from decoded chain data."""

netuid = int(decoded["netuid"])
symbol = bytes([int(b) for b in decoded["token_symbol"]]).decode()
Expand Down
10 changes: 2 additions & 8 deletions bittensor/core/chain_data/info_base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from dataclasses import dataclass, fields
from dataclasses import dataclass
from typing import Any, TypeVar

from bittensor.core.errors import SubstrateRequestException
Expand All @@ -13,13 +13,7 @@ class InfoBase:
@classmethod
def from_dict(cls, decoded: dict) -> T:
try:
class_fields = {f.name for f in fields(cls)}
extra_keys = decoded.keys() - class_fields
instance = cls._from_dict(
{k: v for k, v in decoded.items() if k in class_fields}
)
[setattr(instance, k, decoded[k]) for k in extra_keys]
return instance
return cls._from_dict(decoded)
except KeyError as e:
raise SubstrateRequestException(
f"The {cls} structure is missing {e} from the chain.",
Expand Down
2 changes: 1 addition & 1 deletion bittensor/core/chain_data/ip_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def encode(self) -> dict[str, Any]:

@classmethod
def _from_dict(cls, decoded: dict) -> "IPInfo":
"""Returns a SubnetInfo object from a decoded IPInfo dictionary."""
"""Returns a IPInfo object from decoded chain data."""
return IPInfo(
ip_type=decoded["ip_type_and_protocol"] >> 4,
ip=net.int_to_ip(decoded["ip"]),
Expand Down
167 changes: 94 additions & 73 deletions bittensor/core/chain_data/metagraph_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class MetagraphInfo(InfoBase):

@classmethod
def _from_dict(cls, decoded: dict) -> "MetagraphInfo":
"""Returns a Metagraph object from a decoded MetagraphInfo dictionary."""
"""Returns a MetagraphInfo object from decoded chain data."""
# Subnet index
_netuid = decoded["netuid"]

Expand All @@ -152,80 +152,101 @@ def _from_dict(cls, decoded: dict) -> "MetagraphInfo":
processed = process_nested(raw_data, _chr_str)
decoded.update({key: processed})

# Keys for owner.
decoded["owner_hotkey"] = decode_account_id(decoded["owner_hotkey"])
decoded["owner_coldkey"] = decode_account_id(decoded["owner_coldkey"])

# Subnet emission terms
decoded["subnet_emission"] = _tbwu(decoded["subnet_emission"])
decoded["alpha_in"] = _tbwu(decoded["alpha_in"], _netuid)
decoded["alpha_out"] = _tbwu(decoded["alpha_out"], _netuid)
decoded["tao_in"] = _tbwu(decoded["tao_in"])
decoded["alpha_out_emission"] = _tbwu(decoded["alpha_out_emission"], _netuid)
decoded["alpha_in_emission"] = _tbwu(decoded["alpha_in_emission"], _netuid)
decoded["tao_in_emission"] = _tbwu(decoded["tao_in_emission"])
decoded["pending_alpha_emission"] = _tbwu(
decoded["pending_alpha_emission"], _netuid
)
decoded["pending_root_emission"] = _tbwu(decoded["pending_root_emission"])
decoded["subnet_volume"] = _tbwu(decoded["subnet_volume"], _netuid)
decoded["moving_price"] = Balance.from_tao(
fixed_to_float(decoded.get("moving_price"), 32)
return cls(
# Subnet index
netuid=_netuid,
# Name and symbol
name=decoded["name"],
symbol=decoded["symbol"],
identity=decoded["identity"],
network_registered_at=decoded["network_registered_at"],
# Keys for owner.
owner_hotkey=decoded["owner_hotkey"],
owner_coldkey=decoded["owner_coldkey"],
# Tempo terms.
block=decoded["block"],
tempo=decoded["tempo"],
last_step=decoded["last_step"],
blocks_since_last_step=decoded["blocks_since_last_step"],
# Subnet emission terms
subnet_emission=_tbwu(decoded["subnet_emission"]),
alpha_in=_tbwu(decoded["alpha_in"], _netuid),
alpha_out=_tbwu(decoded["alpha_out"], _netuid),
tao_in=_tbwu(decoded["tao_in"]),
alpha_out_emission=_tbwu(decoded["alpha_out_emission"], _netuid),
alpha_in_emission=_tbwu(decoded["alpha_in_emission"], _netuid),
tao_in_emission=_tbwu(decoded["tao_in_emission"]),
pending_alpha_emission=_tbwu(decoded["pending_alpha_emission"], _netuid),
pending_root_emission=_tbwu(decoded["pending_root_emission"]),
subnet_volume=_tbwu(decoded["subnet_volume"], _netuid),
moving_price=Balance.from_tao(
fixed_to_float(decoded.get("moving_price"), 32)
),
# Hparams for epoch
rho=decoded["rho"],
kappa=decoded["kappa"],
# Validator params
min_allowed_weights=u16tf(decoded["min_allowed_weights"]),
max_weights_limit=u16tf(decoded["max_weights_limit"]),
weights_version=decoded["weights_version"],
weights_rate_limit=decoded["weights_rate_limit"],
activity_cutoff=decoded["activity_cutoff"],
max_validators=decoded["max_validators"],
# Registration
num_uids=decoded["num_uids"],
max_uids=decoded["max_uids"],
burn=_tbwu(decoded["burn"]),
difficulty=u64tf(decoded["difficulty"]),
registration_allowed=decoded["registration_allowed"],
pow_registration_allowed=decoded["pow_registration_allowed"],
immunity_period=decoded["immunity_period"],
min_difficulty=u64tf(decoded["min_difficulty"]),
max_difficulty=u64tf(decoded["max_difficulty"]),
min_burn=_tbwu(decoded["min_burn"]),
max_burn=_tbwu(decoded["max_burn"]),
adjustment_alpha=u64tf(decoded["adjustment_alpha"]),
adjustment_interval=decoded["adjustment_interval"],
target_regs_per_interval=decoded["target_regs_per_interval"],
max_regs_per_block=decoded["max_regs_per_block"],
serving_rate_limit=decoded["serving_rate_limit"],
# CR
commit_reveal_weights_enabled=decoded["commit_reveal_weights_enabled"],
commit_reveal_period=decoded["commit_reveal_period"],
# Bonds
liquid_alpha_enabled=decoded["liquid_alpha_enabled"],
alpha_high=u16tf(decoded["alpha_high"]),
alpha_low=u16tf(decoded["alpha_low"]),
bonds_moving_avg=u64tf(decoded["bonds_moving_avg"]),
# Metagraph info.
hotkeys=[decode_account_id(ck) for ck in decoded.get("hotkeys", [])],
coldkeys=[decode_account_id(hk) for hk in decoded.get("coldkeys", [])],
identities=decoded["identities"],
axons=decoded.get("axons", []),
active=decoded["active"],
validator_permit=decoded["validator_permit"],
pruning_score=[u16tf(ps) for ps in decoded.get("pruning_score", [])],
last_update=decoded["last_update"],
emission=[_tbwu(em, _netuid) for em in decoded.get("emission", [])],
dividends=[u16tf(dv) for dv in decoded.get("dividends", [])],
incentives=[u16tf(ic) for ic in decoded.get("incentives", [])],
consensus=[u16tf(cs) for cs in decoded.get("consensus", [])],
trust=[u16tf(tr) for tr in decoded.get("trust", [])],
rank=[u16tf(rk) for rk in decoded.get("rank", [])],
block_at_registration=decoded["block_at_registration"],
alpha_stake=[_tbwu(ast, _netuid) for ast in decoded["alpha_stake"]],
tao_stake=[_tbwu(ts) for ts in decoded["tao_stake"]],
total_stake=[_tbwu(ts, _netuid) for ts in decoded["total_stake"]],
# Dividend break down
tao_dividends_per_hotkey=[
(decode_account_id(alpha[0]), _tbwu(alpha[1]))
for alpha in decoded["tao_dividends_per_hotkey"]
],
alpha_dividends_per_hotkey=[
(decode_account_id(adphk[0]), _tbwu(adphk[1], _netuid))
for adphk in decoded["alpha_dividends_per_hotkey"]
],
)

# Hparams for epoch
decoded["kappa"] = u16tf(decoded["kappa"])

# Validator params
decoded["min_allowed_weights"] = u16tf(decoded["min_allowed_weights"])
decoded["max_weights_limit"] = u16tf(decoded["max_weights_limit"])

# Registration
decoded["burn"] = _tbwu(decoded["burn"])
decoded["difficulty"] = u64tf(decoded["difficulty"])
decoded["min_difficulty"] = u64tf(decoded["min_difficulty"])
decoded["max_difficulty"] = u64tf(decoded["max_difficulty"])
decoded["min_burn"] = _tbwu(decoded["min_burn"])
decoded["max_burn"] = _tbwu(decoded["max_burn"])
decoded["adjustment_alpha"] = u64tf(decoded["adjustment_alpha"])

# Bonds
decoded["alpha_high"] = u16tf(decoded["alpha_high"])
decoded["alpha_low"] = u16tf(decoded["alpha_low"])
decoded["bonds_moving_avg"] = u64tf(decoded["bonds_moving_avg"])

# Metagraph info.
decoded["hotkeys"] = [
decode_account_id(ck) for ck in decoded.get("hotkeys", [])
]
decoded["coldkeys"] = [
decode_account_id(hk) for hk in decoded.get("coldkeys", [])
]
decoded["axons"] = decoded.get("axons", [])
decoded["pruning_score"] = [
u16tf(ps) for ps in decoded.get("pruning_score", [])
]
decoded["emission"] = [_tbwu(em, _netuid) for em in decoded.get("emission", [])]
decoded["dividends"] = [u16tf(dv) for dv in decoded.get("dividends", [])]
decoded["incentives"] = [u16tf(ic) for ic in decoded.get("incentives", [])]
decoded["consensus"] = [u16tf(cs) for cs in decoded.get("consensus", [])]
decoded["trust"] = [u16tf(tr) for tr in decoded.get("trust", [])]
decoded["rank"] = [u16tf(rk) for rk in decoded.get("trust", [])]
decoded["alpha_stake"] = [_tbwu(ast, _netuid) for ast in decoded["alpha_stake"]]
decoded["tao_stake"] = [_tbwu(ts) for ts in decoded["tao_stake"]]
decoded["total_stake"] = [_tbwu(ts, _netuid) for ts in decoded["total_stake"]]

# Dividend break down
decoded["tao_dividends_per_hotkey"] = [
(decode_account_id(alpha[0]), _tbwu(alpha[1]))
for alpha in decoded["tao_dividends_per_hotkey"]
]
decoded["alpha_dividends_per_hotkey"] = [
(decode_account_id(adphk[0]), _tbwu(adphk[1], _netuid))
for adphk in decoded["alpha_dividends_per_hotkey"]
]
return MetagraphInfo(**decoded)


@dataclass
class MetagraphInfoEmissions:
Expand Down
2 changes: 1 addition & 1 deletion bittensor/core/chain_data/neuron_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def get_null_neuron() -> "NeuronInfo":

@classmethod
def _from_dict(cls, decoded: Any) -> "NeuronInfo":
"""Instantiates NeuronInfo from a byte vector."""
"""Returns a NeuronInfo object from decoded chain data."""
stake_dict = process_stake_data(decoded["stake"])
total_stake = sum(stake_dict.values()) if stake_dict else Balance(0)
coldkey = decode_account_id(decoded["coldkey"])
Expand Down
1 change: 1 addition & 0 deletions bittensor/core/chain_data/neuron_info_lite.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ def get_null_neuron() -> "NeuronInfoLite":

@classmethod
def _from_dict(cls, decoded: Any) -> "NeuronInfoLite":
"""Returns a NeuronInfoLite object from decoded chain data."""
coldkey = decode_account_id(decoded["coldkey"])
hotkey = decode_account_id(decoded["hotkey"])
stake_dict = process_stake_data(decoded["stake"])
Expand Down
1 change: 1 addition & 0 deletions bittensor/core/chain_data/prometheus_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class PrometheusInfo(InfoBase):

@classmethod
def _from_dict(cls, data):
"""Returns a PrometheusInfo object from decoded chain data."""
return cls(
block=data["block"],
ip_type=data["ip_type"],
Expand Down
1 change: 1 addition & 0 deletions bittensor/core/chain_data/scheduled_coldkey_swap_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class ScheduledColdkeySwapInfo(InfoBase):

@classmethod
def _from_dict(cls, decoded: dict) -> "ScheduledColdkeySwapInfo":
"""Returns a ScheduledColdkeySwapInfo object from decoded chain data."""
return cls(
arbitration_block=decoded["arbitration_block"],
new_coldkey=ss58_encode(decoded["new_coldkey"], SS58_FORMAT),
Expand Down
2 changes: 1 addition & 1 deletion bittensor/core/chain_data/stake_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class StakeInfo(InfoBase):

@classmethod
def from_dict(cls, decoded: dict) -> "StakeInfo":
"""Returns a StakeInfo object."""
"""Returns a StakeInfo object from decoded chain data."""
netuid = decoded["netuid"]
return cls(
hotkey_ss58=decode_account_id(decoded["hotkey"]),
Expand Down
14 changes: 1 addition & 13 deletions bittensor/core/chain_data/subnet_hyperparameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,7 @@ class SubnetHyperparameters(InfoBase):

@classmethod
def _from_dict(cls, decoded: dict) -> "SubnetHyperparameters":
"""
Create a `SubnetHyperparameters` instance from a vector of bytes.

This method decodes the given vector of bytes using the `bt_decode` module and creates a new instance of
`SubnetHyperparameters` with the decoded values.

Args:
vec_u8 (bytes): A vector of bytes to decode into `SubnetHyperparameters`.

Returns:
Optional[SubnetHyperparameters]: An instance of `SubnetHyperparameters` if decoding is successful, None
otherwise.
"""
"""Returns a SubnetHyperparameters object from decoded chain data."""
return SubnetHyperparameters(
activity_cutoff=decoded["activity_cutoff"],
adjustment_alpha=decoded["adjustment_alpha"],
Expand Down
1 change: 1 addition & 0 deletions bittensor/core/chain_data/subnet_identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class SubnetIdentity:

@classmethod
def _from_dict(cls, decoded: dict) -> "SubnetIdentity":
"""Returns a SubnetIdentity object from decoded chain data."""
return cls(
subnet_name=decoded["subnet_name"],
github_repo=decoded["github_repo"],
Expand Down
1 change: 1 addition & 0 deletions bittensor/core/chain_data/subnet_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class SubnetInfo(InfoBase):

@classmethod
def _from_dict(cls, decoded: Any) -> "SubnetInfo":
"""Returns a SubnetInfo object from decoded chain data."""
return SubnetInfo(
blocks_since_epoch=decoded["blocks_since_last_step"],
burn=Balance.from_rao(decoded["burn"]),
Expand Down
1 change: 1 addition & 0 deletions bittensor/core/chain_data/subnet_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class SubnetState(InfoBase):

@classmethod
def _from_dict(cls, decoded: dict) -> "SubnetState":
"""Returns a SubnetState object from decoded chain data."""
netuid = decoded["netuid"]
return SubnetState(
netuid=netuid,
Expand Down
2 changes: 1 addition & 1 deletion bittensor/core/settings.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "9.0.0rc4"
__version__ = "9.0.0rc5"

import os
import re
Expand Down
Loading