edge-maxxing-dashboard / src /chain_data.py
AlexNijjar's picture
Sync metagraph first
ea6faf1
raw
history blame
6.66 kB
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
@dataclass
class Commitment:
provider: str
repository: str
revision: str
contest: ContestId
block: int
@classmethod
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)