Spaces:
Running
Running
import os | |
import traceback | |
from dataclasses import dataclass | |
from datetime import datetime, timedelta | |
from enum import Enum | |
from math import ceil | |
from typing import TypeAlias | |
from fiber import constants | |
from fiber.chain.commitments import _deserialize_commitment_field | |
from fiber.chain.interface import get_substrate | |
from fiber.chain.metagraph import Metagraph | |
from fiber.chain.models import Node | |
from substrateinterface import SubstrateInterface | |
from substrateinterface.storage import StorageKey | |
from network_commitments import Decoder | |
from src import Key, Uid, TIMEZONE | |
DISABLE_COMMITMENTS_FETCH = int(os.getenv("DISABLE_COMMITMENTS_FETCH") or 0) > 0 | |
Weight: TypeAlias = float | |
Incentive: TypeAlias = float | |
class ContestId(Enum): | |
FLUX_NVIDIA_4090 = 0 | |
SDXL_NEWDREAM_NVIDIA_4090 = 1 | |
class Commitment: | |
provider: str | |
repository: str | |
revision: str | |
contest: ContestId | |
block: int | |
def decode(cls, decoder: Decoder, block: int): | |
provider = decoder.read_str() | |
repository = decoder.read_str() | |
revision = decoder.read_sized_str(7) | |
contest_id = ContestId(decoder.read_uint16()) | |
return cls( | |
provider=provider, | |
repository=repository, | |
revision=revision, | |
contest=contest_id, | |
block=block | |
) | |
def get_repo_link(self): | |
return f"https://{self.provider}/{self.repository}" | |
SPEC_VERSION = 8 | |
NET_UID = 39 | |
WEIGHTS_BY_MINER: dict[Key, list[tuple[Key, Weight]]] = {} | |
VALIDATOR_IDENTITIES: dict[Key, str] = {} | |
COMMITMENTS: dict[Key, Commitment] = {} | |
UPDATED: dict[Key, int] = {} | |
UIDS_BY_HOTKEY: dict[Key, Uid] = {} | |
HOTKEYS_BY_UID: dict[Uid, Key] = {} | |
substrate = get_substrate(subtensor_address=constants.FINNEY_SUBTENSOR_ADDRESS) | |
metagraph = Metagraph(substrate, netuid=str(NET_UID), load_old_nodes=False) | |
def query_subtensor(storage_keys: list[StorageKey], block: int) -> list: | |
global substrate | |
try: | |
return substrate.query_multi( | |
storage_keys=storage_keys, | |
block_hash=substrate.get_block_hash(block), | |
) | |
except Exception: | |
substrate = get_substrate(subtensor_address=substrate.url) | |
raise | |
def is_validator(node: Node) -> bool: | |
return node.vtrust > 0 or node.stake > 10_000 | |
def get_nodes() -> dict[Key, Node]: | |
return metagraph.nodes | |
def fetch_weights(block: int): | |
WEIGHTS_BY_MINER.clear() | |
storage_keys: list[StorageKey] = [] | |
for hotkey, node in metagraph.nodes.items(): | |
if not is_validator(node): continue | |
storage_keys.append(substrate.create_storage_key( | |
"SubtensorModule", | |
"Weights", | |
[metagraph.netuid, UIDS_BY_HOTKEY[node.hotkey]] | |
)) | |
weights = query_subtensor(storage_keys, block) | |
for hotkey, node in metagraph.nodes.items(): | |
for storage, validator_weights in weights: | |
validator_hotkey = HOTKEYS_BY_UID[storage.params[1]] | |
if hotkey not in WEIGHTS_BY_MINER: | |
WEIGHTS_BY_MINER[hotkey] = [] | |
weight = 0.0 | |
for miner_weight in validator_weights: | |
if miner_weight[0].value == UIDS_BY_HOTKEY[hotkey]: | |
weight = miner_weight[1].value / 2 ** 16 | |
break | |
WEIGHTS_BY_MINER[hotkey].append((validator_hotkey, weight)) | |
def fetch_updated(block: int): | |
UPDATED.clear() | |
for hotkey, node in metagraph.nodes.items(): | |
UPDATED[hotkey] = ceil(block - node.last_updated) | |
def fetch_identities(block: int): | |
VALIDATOR_IDENTITIES.clear() | |
storage_keys: list[StorageKey] = [] | |
for hotkey, node in metagraph.nodes.items(): | |
if not is_validator(node): continue | |
storage_keys.append(substrate.create_storage_key( | |
"SubtensorModule", | |
"Identities", | |
[node.coldkey] | |
)) | |
identities = query_subtensor(storage_keys, block) | |
for hotkey, node in metagraph.nodes.items(): | |
for storage, info in identities: | |
if node.coldkey != storage.params[0]: continue | |
if info != None: # noqa | |
VALIDATOR_IDENTITIES[hotkey] = info.value["name"] | |
break | |
def fetch_commitments(block: int): | |
if DISABLE_COMMITMENTS_FETCH: | |
return | |
COMMITMENTS.clear() | |
storage_keys: list[StorageKey] = [] | |
for hotkey, node in metagraph.nodes.items(): | |
if is_validator(node): continue | |
storage_keys.append(substrate.create_storage_key( | |
"Commitments", | |
"CommitmentOf", | |
[metagraph.netuid, hotkey] | |
)) | |
commitments = query_subtensor(storage_keys, block) | |
for storage, commitment in commitments: | |
try: | |
if not commitment or not commitment.value: | |
continue | |
fields = commitment.value["info"]["fields"] | |
if not fields: | |
continue | |
field = _deserialize_commitment_field(fields[0]) | |
if field is None: | |
continue | |
decoder = Decoder(field[1]) | |
spec_version = decoder.read_uint16() | |
if spec_version != SPEC_VERSION: | |
continue | |
COMMITMENTS[storage.params[1]] = Commitment.decode(decoder, int(commitment.value["block"])) | |
except: | |
continue | |
last_sync: datetime = datetime.fromtimestamp(0, TIMEZONE) | |
last_identity_sync: datetime = datetime.fromtimestamp(0, TIMEZONE) | |
last_commitment_sync: datetime = datetime.fromtimestamp(0, TIMEZONE) | |
def sync_metagraph(): | |
global substrate | |
global last_sync | |
now = datetime.now(TIMEZONE) | |
if now - last_sync < timedelta(minutes=5): | |
return | |
last_sync = now | |
try: | |
print("Syncing metagraph...") | |
metagraph.sync_nodes() | |
block = substrate.get_block_number(None) # type: ignore | |
for uid, node in enumerate(metagraph.nodes.values()): | |
UIDS_BY_HOTKEY[node.hotkey] = uid | |
HOTKEYS_BY_UID[uid] = node.hotkey | |
fetch_weights(block) | |
fetch_updated(block) | |
global last_identity_sync | |
if now - last_identity_sync > timedelta(days=1): | |
print("Syncing identities...") | |
last_identity_sync = now | |
fetch_identities(block) | |
global last_commitment_sync | |
if now - last_commitment_sync > timedelta(hours=12): | |
print("Syncing commitments...") | |
last_commitment_sync = now | |
fetch_commitments(block) | |
except Exception: | |
print(f"Error occurred while syncing metagraph") | |
traceback.print_exc() | |
substrate = SubstrateInterface(substrate.url) | |