Skip to content
Merged
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
79 changes: 75 additions & 4 deletions bittensor/_subtensor/chain_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
# DEALINGS IN THE SOFTWARE.

from dataclasses import dataclass
from typing import List, Tuple, Dict
from typing import List, Tuple, Dict, Optional
import bittensor
from bittensor import Balance
import scalecodec
import json
import torch


Expand All @@ -28,6 +28,17 @@
U16_MAX = 65535
U64_MAX = 18446744073709551615

def json_from_vec_u8( vec_u8: List[int] ) -> Optional[Dict]:
r""" Returns a json dictionary from a bytes object.
"""
if len(vec_u8) == 0:
return None

as_bytes = bytes(vec_u8)
as_json_str = as_bytes.decode('utf-8')
as_json = json.loads(as_json_str)
return as_json

# Dataclasses for chain data.
@dataclass
class NeuronInfo:
Expand Down Expand Up @@ -57,6 +68,26 @@ class NeuronInfo:
axon_info: 'AxonInfo'
is_null: bool = False

@classmethod
def from_vec_u8(cls, vec_u8: List[int]) -> 'NeuronInfo':
r""" Returns a NeuronInfo object from a vec_u8.
"""
json = json_from_vec_u8(vec_u8)
if json is None:
return NeuronInfo._null_neuron() # return null neuron instead of None

return NeuronInfo.from_json(json)

@classmethod
def list_from_vec_u8(cls, vec_u8: List[int]) -> List['NeuronInfo']:
r""" Returns a list of NeuronInfo objects from a vec_u8.
"""
json = json_from_vec_u8(vec_u8)
if json is None:
return []

return [NeuronInfo.from_json(neuron) for neuron in json]

@classmethod
def from_json(cls, json: Dict) -> 'NeuronInfo':
r""" Returns a NeuronInfo object from a json dictionary.
Expand All @@ -78,8 +109,8 @@ def from_json(cls, json: Dict) -> 'NeuronInfo':
dividends = json['dividends'] / U16_MAX,
last_update = json['last_update'],
validator_permit = json['validator_permit'],
weights = json['weights'],
bonds = json['bonds'],
weights = [ (uid, w) for uid, w in enumerate(json['weights']) ],
bonds = [ (uid, b) for uid, b in enumerate(json['bonds']) ],
prometheus_info = PrometheusInfo.from_json(json['prometheus_info']),
axon_info = AxonInfo.from_json(json['axon_info']),
)
Expand Down Expand Up @@ -194,6 +225,26 @@ class DelegateInfo:
owner_ss58: str # Coldkey of owner
take: float # Take of the delegate as a percentage

@classmethod
def from_vec_u8(cls, vec_u8: List[int]) -> Optional['DelegateInfo']:
r""" Returns a DelegateInfo object from a vec_u8.
"""
json = json_from_vec_u8(vec_u8)
if json is None:
return None

return DelegateInfo.from_json(json)

@classmethod
def list_from_vec_u8(cls, vec_u8: List[int]) -> List['DelegateInfo']:
r""" Returns a list of DelegateInfo objects from a vec_u8.
"""
json = json_from_vec_u8(vec_u8)
if json is None:
return []

return [DelegateInfo.from_json(delegate) for delegate in json]

@classmethod
def from_json(cls, json: Dict) -> 'DelegateInfo':
r""" Returns a DelegateInfo object from a json dictionary.
Expand Down Expand Up @@ -243,6 +294,26 @@ class SubnetInfo:
connection_requirements: Dict[str, int] # netuid -> connection requirements
emission_value: float

@classmethod
def from_vec_u8(cls, vec_u8: List[int]) -> Optional['SubnetInfo']:
r""" Returns a SubnetInfo object from a vec_u8.
"""
json = json_from_vec_u8(vec_u8)
if json is None:
return None

return SubnetInfo.from_json(json)

@classmethod
def list_from_vec_u8(cls, vec_u8: List[int]) -> List['SubnetInfo']:
r""" Returns a list of SubnetInfo objects from a vec_u8.
"""
json = json_from_vec_u8(vec_u8)
if json is None:
return []

return [SubnetInfo.from_json(subnet) for subnet in json]

@classmethod
def from_json(cls, json: Dict) -> 'SubnetInfo':
r""" Returns a SubnetInfo object from a json dictionary.
Expand Down
32 changes: 21 additions & 11 deletions bittensor/_subtensor/subtensor_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -630,10 +630,10 @@ def make_substrate_call_with_retry():
json_body = make_substrate_call_with_retry()
result = json_body['result']

if result == None:
if result in (None, []):
return []

return [ SubnetInfo.from_json(subnet_info) for subnet_info in result ]
return SubnetInfo.list_from_vec_u8( result )

def get_subnet_info( self, netuid: int, block: Optional[int] = None ) -> Optional[SubnetInfo]:
@retry(delay=2, tries=3, backoff=2, max_delay=4)
Expand All @@ -651,10 +651,10 @@ def make_substrate_call_with_retry():
json_body = make_substrate_call_with_retry()
result = json_body['result']

if result == None:
if result in (None, []):
return None

return SubnetInfo.from_json(result)
return SubnetInfo.from_vec_u8( result )

####################
#### Nomination ####
Expand Down Expand Up @@ -688,10 +688,12 @@ def make_substrate_call_with_retry(encoded_hotkey: List[int]):
hotkey_bytes: bytes = bittensor.utils.ss58_address_to_bytes( hotkey_ss58 )
encoded_hotkey: List[int] = [ int( byte ) for byte in hotkey_bytes ]
json_body = make_substrate_call_with_retry(encoded_hotkey)
if json_body['result'] == None:
result = json_body['result']

if result in (None, []):
return None

return DelegateInfo.from_json( json_body['result'] )
return DelegateInfo.from_vec_u8( result )

def get_delegates( self, block: Optional[int] = None ) -> List[DelegateInfo]:
@retry(delay=2, tries=3, backoff=2, max_delay=4)
Expand All @@ -706,10 +708,12 @@ def make_substrate_call_with_retry():
params=params
)
json_body = make_substrate_call_with_retry()
if json_body['result'] == None:
result = json_body['result']

if result in (None, []):
return []

return [DelegateInfo.from_json( delegate ) for delegate in json_body['result']]
return DelegateInfo.list_from_vec_u8( result )


########################################
Expand Down Expand Up @@ -779,9 +783,12 @@ def make_substrate_call_with_retry():
params=params
)
json_body = make_substrate_call_with_retry()
if json_body['result'] == None:
result = json_body['result']

if result in (None, []):
return NeuronInfo._null_neuron()
return NeuronInfo.from_json( json_body['result'] )

return NeuronInfo.from_vec_u8( result )

def neurons(self, netuid: int, block: Optional[int] = None ) -> List[NeuronInfo]:
r""" Returns a list of neuron from the chain.
Expand All @@ -808,8 +815,11 @@ def make_substrate_call_with_retry():

json_body = make_substrate_call_with_retry()
result = json_body['result']

if result in (None, []):
return []

return [ NeuronInfo.from_json( neuron ) for neuron in result ]
return NeuronInfo.list_from_vec_u8( result )

def metagraph( self, netuid: int, block: Optional[int] = None ) -> 'bittensor.Metagraph':
r""" Returns the metagraph for the subnet.
Expand Down