Skip to content

Commit

Permalink
Merge pull request #2649 from opentensor/fix/roman/dataclasses
Browse files Browse the repository at this point in the history
Fix InfoBase + dataclasses
  • Loading branch information
roman-opentensor authored Feb 8, 2025
2 parents 0cc2b8e + da522a3 commit 25b8a3a
Show file tree
Hide file tree
Showing 17 changed files with 128 additions and 100 deletions.
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

0 comments on commit 25b8a3a

Please sign in to comment.