diff --git a/bittensor/__init__.py b/bittensor/__init__.py
index d1a06b1e64..18397c7032 100644
--- a/bittensor/__init__.py
+++ b/bittensor/__init__.py
@@ -78,7 +78,7 @@ def turn_console_off():
# Needs to use wss://
__bellagene_entrypoint__ = "wss://parachain.opentensor.ai:443"
-__local_entrypoint__ = "ws://127.0.0.1:9945"
+__local_entrypoint__ = "ws://127.0.0.1:9944"
__tao_symbol__: str = chr(0x03C4)
@@ -87,11 +87,10 @@ def turn_console_off():
# Block Explorers map network to explorer url
## Must all be polkadotjs explorer urls
__network_explorer_map__ = {
- 'local': "https://explorer.nakamoto.opentensor.ai/#/explorer",
+ 'local': "https://explorer.finney.opentensor.ai/#/explorer",
'nakamoto': "https://explorer.nakamoto.opentensor.ai/#/explorer",
- 'endpoint': "https://explorer.nakamoto.opentensor.ai/#/",
- 'nobunaga': "https://staging.opentensor.ai/#/explorer",
- 'finney': "https://explorer.opentensor.ai/"
+ 'endpoint': "https://explorer.finney.opentensor.ai/#/explorer",
+ 'finney': "https://explorer.finney.opentensor.ai/#/explorer"
}
# Avoid collisions with other processes
@@ -101,9 +100,12 @@ def turn_console_off():
__mock_chain_db__ = './tmp/mock_chain_db'
-# Delegate Profiles
-__delegate_profiles_url__: str = 'https://raw.githubusercontent.com/opentensor/delegate_profiles/master/DELEGATES.md'
-
+# --- Type Registry ---
+__type_registry__ = {
+ 'types': {
+ 'Balance': 'u64', # Need to override default u128
+ },
+}
# --- Prometheus ---
__prometheus_version__ = "0.1.0"
@@ -207,4 +209,4 @@ def turn_console_off():
wandb.add_defaults( defaults )
logging.add_defaults( defaults )
-from substrateinterface import Keypair as Keypair
+from substrateinterface import Keypair as Keypair
diff --git a/bittensor/_axon/__init__.py b/bittensor/_axon/__init__.py
index 068e31ca08..df8fab339a 100644
--- a/bittensor/_axon/__init__.py
+++ b/bittensor/_axon/__init__.py
@@ -318,7 +318,7 @@ def check_config(cls, config: 'bittensor.Config' ):
bittensor.wallet.check_config( config )
@classmethod
- def default_synapse_check(cls, synapse, hotkey ):
+ def default_synapse_check(cls, synapse, hotkey, inputs ):
""" default synapse check function
"""
if len(hotkey) == bittensor.__ss58_address_length__:
@@ -412,8 +412,12 @@ def parse_signature(
) -> Tuple[int, str, str, str, int]:
r"""Attempts to parse a signature from the metadata"""
signature = metadata.get("bittensor-signature")
+ version = metadata.get('bittensor-version')
if signature is None:
raise Exception("Request signature missing")
+ if int(version) < 370:
+ raise Exception("Incorrect Version")
+
for parser in [self.parse_signature_v2, self.parse_legacy_signature]:
parts = parser(signature)
if parts is not None:
diff --git a/bittensor/_cli/commands/__init__.py b/bittensor/_cli/commands/__init__.py
index 208c230426..770230692c 100644
--- a/bittensor/_cli/commands/__init__.py
+++ b/bittensor/_cli/commands/__init__.py
@@ -11,4 +11,4 @@
from .list import ListCommand
from .weights import SetWeightsCommand, WeightsCommand
from .query import QueryCommand
-from .misc import HelpCommand, UpdateCommand, ListSubnetsCommand
\ No newline at end of file
+from .misc import HelpCommand, UpdateCommand, ListSubnetsCommand
diff --git a/bittensor/_cli/commands/delegates.py b/bittensor/_cli/commands/delegates.py
index 715919b440..e1e7f377db 100644
--- a/bittensor/_cli/commands/delegates.py
+++ b/bittensor/_cli/commands/delegates.py
@@ -16,6 +16,7 @@
# DEALINGS IN THE SOFTWARE.
import sys
+import os
import json
import argparse
import bittensor
@@ -24,26 +25,55 @@
from rich.prompt import Prompt
from rich.prompt import Confirm
from rich.console import Text
+from tqdm import tqdm
+
+import os
+import bittensor
+from typing import List
+
+def _get_coldkey_wallets_for_path( path: str ) -> List['bittensor.wallet']:
+ try:
+ wallet_names = next(os.walk(os.path.expanduser(path)))[1]
+ return [ bittensor.wallet( path= path, name=name ) for name in wallet_names ]
+ except StopIteration:
+ # No wallet files found.
+ wallets = []
+ return wallets
console = bittensor.__console__
# Uses rich console to pretty print a table of delegates.
-def show_delegates( delegates: List['bittensor.DelegateInfo'], width: Optional[int] = None):
+def show_delegates( delegates: List['bittensor.DelegateInfo'], prev_delegates: List['bittensor.DelegateInfo'], width: Optional[int] = None):
""" Pretty prints a table of delegates sorted by total stake.
"""
delegates.sort(key=lambda delegate: delegate.total_stake, reverse=True)
- registered_delegate_info = json.load( open("delegates.json") )
+ prev_delegates_dict = {}
+ for prev_delegate in prev_delegates:
+ prev_delegates_dict[prev_delegate.hotkey_ss58] = prev_delegate
+ try:
+ package_dir = os.path.dirname(bittensor.__file__)
+ root_dir = os.path.dirname(package_dir)
+ filename = os.path.join(root_dir, 'delegates.json')
+ if os.path.exists(filename):
+ registered_delegate_info = json.load( open(filename, 'r') )
+ else:
+ registered_delegate_info = {}
+ except:
+ registered_delegate_info = {}
+
table = Table(show_footer=True, width=width, pad_edge=False, box=None, expand=True)
table.add_column("[overline white]INDEX", str(len(delegates)), footer_style = "overline white", style='bold white')
- table.add_column("[overline white]OWNER", style='rgb(50,163,219)', no_wrap=True, justify='left')
+ table.add_column("[overline white]DELEGATE", style='rgb(50,163,219)', no_wrap=True, justify='left')
table.add_column("[overline white]SS58", str(len(delegates)), footer_style = "overline white", style='bold yellow')
- table.add_column("[overline white]NOMS", justify='center', style='green', no_wrap=True)
- table.add_column("[overline white]OWNER STAKE(\u03C4)", justify='right', no_wrap=True)
+ table.add_column("[overline white]NOMINATORS", justify='center', style='green', no_wrap=True)
+ table.add_column("[overline white]DELEGATE STAKE(\u03C4)", justify='right', no_wrap=True)
table.add_column("[overline white]TOTAL STAKE(\u03C4)", justify='right', style='green', no_wrap=True)
+ table.add_column("[overline white]CHANGE/(4h)", style='grey0', justify='center')
table.add_column("[overline white]SUBNETS", justify='right', style='white', no_wrap=True)
table.add_column("[overline white]VPERMIT", justify='right', no_wrap=True)
#table.add_column("[overline white]TAKE", style='white', no_wrap=True)
- table.add_column("[overline white]24h/k\u03C4", style='green', justify='center')
+ table.add_column("[overline white]NOMINATOR/(24h)/k\u03C4", style='green', justify='center')
+ table.add_column("[overline white]DELEGATE/(24h)", style='green', justify='center')
table.add_column("[overline white]Desc", style='rgb(50,163,219)')
#table.add_column("[overline white]DESCRIPTION", style='white')
@@ -63,17 +93,34 @@ def show_delegates( delegates: List['bittensor.DelegateInfo'], width: Optional[i
delegate_url = ''
delegate_description = ''
+ if delegate.hotkey_ss58 in prev_delegates_dict:
+ prev_stake = prev_delegates_dict[delegate.hotkey_ss58].total_stake
+ if prev_stake == 0:
+ rate_change_in_stake_str = "[green]100%[/green]"
+ else:
+ rate_change_in_stake = 100 * (float(delegate.total_stake) - float(prev_stake)) / float(prev_stake)
+ if rate_change_in_stake > 0:
+ rate_change_in_stake_str = "[green]{:.2f}%[/green]".format(rate_change_in_stake)
+ elif rate_change_in_stake < 0:
+ rate_change_in_stake_str = "[red]{:.2f}%[/red]".format(rate_change_in_stake)
+ else:
+ rate_change_in_stake_str = "[grey0]0%[/grey0]"
+ else:
+ rate_change_in_stake_str = "[grey0]0%[/grey0]"
+
table.add_row(
str(i),
Text(delegate_name, style=f'link {delegate_url}'),
f'{delegate.hotkey_ss58:8.8}...',
- str(len(delegate.nominators)),
+ str(len([nom for nom in delegate.nominators if nom[1].rao > 0])),
f'{owner_stake!s:13.13}',
f'{delegate.total_stake!s:13.13}',
+ rate_change_in_stake_str,
str(delegate.registrations),
str(['*' if subnet in delegate.validator_permits else '' for subnet in delegate.registrations]),
#f'{delegate.take * 100:.1f}%',
- f'{delegate.return_per_1000!s:6.6}',
+ f'{bittensor.Balance.from_tao( delegate.total_daily_return.tao * (1000/ ( 0.001 + delegate.total_stake.tao ) ))!s:6.6}',
+ f'{bittensor.Balance.from_tao( delegate.total_daily_return.tao * (0.18) ) !s:6.6}',
str(delegate_description)
#f'{delegate_profile.description:140.140}',
)
@@ -143,13 +190,14 @@ def check_config( config: 'bittensor.Config' ):
with bittensor.__console__.status(":satellite: Loading delegates..."):
subtensor = bittensor.subtensor( config = config )
delegates: List[bittensor.DelegateInfo] = subtensor.get_delegates()
+ prev_delegates = subtensor.get_delegates(max(0, subtensor.block - 1200))
if len(delegates) == 0:
console.print(":cross_mark:[red]There are no delegates on {}[/red]".format(subtensor.network))
sys.exit(1)
delegates.sort(key=lambda delegate: delegate.total_stake, reverse=True)
- show_delegates( delegates )
+ show_delegates( delegates, prev_delegates = prev_delegates)
delegate_index = Prompt.ask("Enter delegate index")
config.delegate_ss58key = str(delegates[int(delegate_index)].hotkey_ss58)
console.print("Selected: [yellow]{}[/yellow]".format(config.delegate_ss58key))
@@ -241,13 +289,14 @@ def check_config( config: 'bittensor.Config' ):
with bittensor.__console__.status(":satellite: Loading delegates..."):
subtensor = bittensor.subtensor( config = config )
delegates: List[bittensor.DelegateInfo] = subtensor.get_delegates()
+ prev_delegates = subtensor.get_delegates(max(0, subtensor.block - 1200))
if len(delegates) == 0:
console.print(":cross_mark:[red]There are no delegates on {}[/red]".format(subtensor.network))
sys.exit(1)
delegates.sort(key=lambda delegate: delegate.total_stake, reverse=True)
- show_delegates( delegates )
+ show_delegates( delegates, prev_delegates = prev_delegates)
delegate_index = Prompt.ask("Enter delegate index")
config.delegate_ss58key = str(delegates[int(delegate_index)].hotkey_ss58)
console.print("Selected: [yellow]{}[/yellow]".format(config.delegate_ss58key))
@@ -274,7 +323,8 @@ def run( cli ):
subtensor = bittensor.subtensor( config = cli.config )
with bittensor.__console__.status(":satellite: Loading delegates..."):
delegates: bittensor.DelegateInfo = subtensor.get_delegates()
- show_delegates( delegates, width = cli.config.get('width', None) )
+ prev_delegates = subtensor.get_delegates(max(0, subtensor.block - 1200))
+ show_delegates( delegates, prev_delegates = prev_delegates, width = cli.config.get('width', None) )
@staticmethod
def add_args( parser: argparse.ArgumentParser ):
@@ -351,11 +401,6 @@ def check_config( config: 'bittensor.Config' ):
if config.wallet.get('hotkey') == bittensor.defaults.wallet.hotkey and not config.no_prompt:
hotkey = Prompt.ask("Enter hotkey name", default = bittensor.defaults.wallet.hotkey)
config.wallet.hotkey = str(hotkey)
-
-
-
-
-
class MyDelegatesCommand:
@@ -364,28 +409,18 @@ class MyDelegatesCommand:
def run( cli ):
'''Delegates stake to a chain delegate.'''
config = cli.config.copy()
- wallet = bittensor.wallet( config = config )
+ if config.all == True:
+ wallets = _get_coldkey_wallets_for_path( config.wallet.path )
+ else:
+ wallets = [bittensor.wallet( config = config )]
subtensor: bittensor.Subtensor = bittensor.subtensor( config = config )
- delegates = subtensor.get_delegated( coldkey_ss58=wallet.coldkeypub.ss58_address )
-
- my_delegates = {} # hotkey, amount
- for delegate in delegates:
- for coldkey_addr, staked in delegate[0].nominators:
- if coldkey_addr == wallet.coldkeypub.ss58_address and staked.tao > 0:
- my_delegates[ delegate[0].hotkey_ss58 ] = staked
-
- delegates.sort(key=lambda delegate: delegate[0].total_stake, reverse=True)
-
- try:
- registered_delegate_info = json.load( open("delegates.json") )
- except:
- registered_delegate_info = {}
table = Table(show_footer=True, pad_edge=False, box=None, expand=True)
- table.add_column("[overline white]INDEX", str(len(delegates)), footer_style = "overline white", style='bold white')
+ table.add_column("[overline white]Wallet", footer_style = "overline white", style='bold white')
table.add_column("[overline white]OWNER", style='rgb(50,163,219)', no_wrap=True, justify='left')
- table.add_column("[overline white]SS58", str(len(delegates)), footer_style = "overline white", style='bold yellow')
- table.add_column("[overline green]My Delegation", str(len(delegates)), footer_style = "overline green", style='bold green')
+ table.add_column("[overline white]SS58", footer_style = "overline white", style='bold yellow')
+ table.add_column("[overline green]Delegation", footer_style = "overline green", style='bold green')
+ table.add_column("[overline green]\u03C4/24h", footer_style = "overline green", style='bold green')
table.add_column("[overline white]NOMS", justify='center', style='green', no_wrap=True)
table.add_column("[overline white]OWNER STAKE(\u03C4)", justify='right', no_wrap=True)
table.add_column("[overline white]TOTAL STAKE(\u03C4)", justify='right', style='green', no_wrap=True)
@@ -394,38 +429,63 @@ def run( cli ):
table.add_column("[overline white]24h/k\u03C4", style='green', justify='center')
table.add_column("[overline white]Desc", style='rgb(50,163,219)')
- for i, delegate in enumerate( delegates ):
- owner_stake = next(
- map(lambda x: x[1], # get stake
- filter(lambda x: x[0] == delegate[0].owner_ss58, delegate[0].nominators) # filter for owner
- ),
- bittensor.Balance.from_rao(0) # default to 0 if no owner stake.
- )
- if delegate[0].hotkey_ss58 in registered_delegate_info:
- delegate_name = registered_delegate_info[delegate[0].hotkey_ss58]['name']
- delegate_url = registered_delegate_info[delegate[0].hotkey_ss58]['url']
- delegate_description = registered_delegate_info[delegate[0].hotkey_ss58]['description']
- else:
- delegate_name = ''
- delegate_url = ''
- delegate_description = ''
-
- if delegate[0].hotkey_ss58 in my_delegates:
- table.add_row(
- str(i),
- Text(delegate_name, style=f'link {delegate_url}'),
- f'{delegate[0].hotkey_ss58:8.8}...',
- f'{my_delegates[delegate[0].hotkey_ss58]!s:13.13}',
- str(len(delegate[0].nominators)),
- f'{owner_stake!s:13.13}',
- f'{delegate[0].total_stake!s:13.13}',
- str(delegate[0].registrations),
- str(['*' if subnet in delegate[0].validator_permits else '' for subnet in delegate[0].registrations]),
- #f'{delegate.take * 100:.1f}%',
- f'{delegate[0].return_per_1000!s:6.6}',
- str(delegate_description)
- #f'{delegate_profile.description:140.140}',
+ for wallet in tqdm(wallets):
+ if not wallet.coldkeypub_file.exists_on_device(): continue
+ delegates = subtensor.get_delegated( coldkey_ss58=wallet.coldkeypub.ss58_address )
+
+ my_delegates = {} # hotkey, amount
+ for delegate in delegates:
+ for coldkey_addr, staked in delegate[0].nominators:
+ if coldkey_addr == wallet.coldkeypub.ss58_address and staked.tao > 0:
+ my_delegates[ delegate[0].hotkey_ss58 ] = staked
+
+ delegates.sort(key=lambda delegate: delegate[0].total_stake, reverse=True)
+
+ try:
+ package_dir = os.path.dirname(bittensor.__file__)
+ root_dir = os.path.dirname(package_dir)
+ filename = os.path.join(root_dir, 'delegates.json')
+ if os.path.exists(filename):
+ registered_delegate_info = json.load( open(filename, 'r') )
+ else:
+ registered_delegate_info = {}
+ except:
+ registered_delegate_info = {}
+
+ for i, delegate in enumerate( delegates ):
+ owner_stake = next(
+ map(lambda x: x[1], # get stake
+ filter(lambda x: x[0] == delegate[0].owner_ss58, delegate[0].nominators) # filter for owner
+ ),
+ bittensor.Balance.from_rao(0) # default to 0 if no owner stake.
)
+ if delegate[0].hotkey_ss58 in registered_delegate_info:
+ delegate_name = registered_delegate_info[delegate[0].hotkey_ss58]['name']
+ delegate_url = registered_delegate_info[delegate[0].hotkey_ss58]['url']
+ delegate_description = registered_delegate_info[delegate[0].hotkey_ss58]['description']
+ else:
+ delegate_name = ''
+ delegate_url = ''
+ delegate_description = ''
+
+ if delegate[0].hotkey_ss58 in my_delegates:
+ table.add_row(
+ wallet.name,
+ Text(delegate_name, style=f'link {delegate_url}'),
+ f'{delegate[0].hotkey_ss58:8.8}...',
+ f'{my_delegates[delegate[0].hotkey_ss58]!s:13.13}',
+ f'{delegate[0].total_daily_return.tao * (my_delegates[delegate[0].hotkey_ss58]/delegate[0].total_stake.tao)!s:6.6}',
+ str(len(delegate[0].nominators)),
+ f'{owner_stake!s:13.13}',
+ f'{delegate[0].total_stake!s:13.13}',
+ str(delegate[0].registrations),
+ str(['*' if subnet in delegate[0].validator_permits else '' for subnet in delegate[0].registrations]),
+ #f'{delegate.take * 100:.1f}%',s
+ f'{ delegate[0].total_daily_return.tao * ( 1000 / ( 0.001 + delegate[0].total_stake.tao ) )!s:6.6}',
+ str(delegate_description)
+ #f'{delegate_profile.description:140.140}',
+ )
+
bittensor.__console__.print(table)
@staticmethod
@@ -440,6 +500,12 @@ def add_args( parser: argparse.ArgumentParser ):
help='''Set false to stop cli version checking''',
default = False
)
+ delegate_stake_parser.add_argument(
+ '--all',
+ action='store_true',
+ help='''Check all coldkey wallets.''',
+ default = False
+ )
delegate_stake_parser.add_argument(
'--no_prompt',
dest='no_prompt',
@@ -452,7 +518,7 @@ def add_args( parser: argparse.ArgumentParser ):
@staticmethod
def check_config( config: 'bittensor.Config' ):
- if config.wallet.get('name') == bittensor.defaults.wallet.name and not config.no_prompt:
+ if not config.all and config.wallet.get('name') == bittensor.defaults.wallet.name and not config.no_prompt:
wallet_name = Prompt.ask("Enter wallet name", default = bittensor.defaults.wallet.name)
config.wallet.name = str(wallet_name)
diff --git a/bittensor/_cli/commands/inspect.py b/bittensor/_cli/commands/inspect.py
index cd79a51e8a..84a41d6fdc 100644
--- a/bittensor/_cli/commands/inspect.py
+++ b/bittensor/_cli/commands/inspect.py
@@ -15,137 +15,152 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
-import sys
+import json
import argparse
import bittensor
+from tqdm import tqdm
+from rich.table import Table
from rich.prompt import Prompt
from .utils import check_netuid_set
console = bittensor.__console__
+import os
+import bittensor
+from typing import List, Tuple
+
+def _get_coldkey_wallets_for_path( path: str ) -> List['bittensor.wallet']:
+ try:
+ wallet_names = next(os.walk(os.path.expanduser(path)))[1]
+ return [ bittensor.wallet( path= path, name=name ) for name in wallet_names ]
+ except StopIteration:
+ # No wallet files found.
+ wallets = []
+ return wallets
+
+def _get_hotkey_wallets_for_wallet( wallet ) -> List['bittensor.wallet']:
+ hotkey_wallets = []
+ hotkeys_path = wallet.path + '/' + wallet.name + '/hotkeys'
+ try:
+ hotkey_files = next(os.walk(os.path.expanduser(hotkeys_path)))[2]
+ except StopIteration:
+ hotkey_files = []
+ for hotkey_file_name in hotkey_files:
+ try:
+ hotkey_for_name = bittensor.wallet( path = wallet.path, name = wallet.name, hotkey = hotkey_file_name )
+ if hotkey_for_name.hotkey_file.exists_on_device() and not hotkey_for_name.hotkey_file.is_encrypted():
+ hotkey_wallets.append( hotkey_for_name )
+ except Exception:
+ pass
+ return hotkey_wallets
+
class InspectCommand:
@staticmethod
def run (cli):
r""" Inspect a cold, hot pair.
"""
- wallet = bittensor.wallet(config = cli.config)
+ if cli.config.all == True:
+ wallets = _get_coldkey_wallets_for_path( cli.config.wallet.path )
+ else:
+ wallets = [bittensor.wallet( config = cli.config )]
subtensor = bittensor.subtensor( config = cli.config )
- if cli.config.netuid != None:
- # Verify subnet exists
- if not subtensor.subnet_exists( netuid = cli.config.netuid ):
- bittensor.__console__.print(f"[red]Subnet {cli.config.netuid} does not exist[/red]")
- sys.exit(1)
-
-
- with bittensor.__console__.status(":satellite: Looking up account on: [white]{}[/white] ...".format(cli.config.subtensor.get('network', bittensor.defaults.subtensor.network))):
-
- if cli.config.wallet.get('hotkey', bittensor.defaults.wallet.hotkey) is None:
- # If no hotkey is provided, inspect just the coldkey
- wallet.coldkeypub
- cold_balance = wallet.get_balance( subtensor = subtensor )
- bittensor.__console__.print("\n[bold white]{}[/bold white]:\n {}[bold white]{}[/bold white]\n {} {}\n".format( wallet, "coldkey:".ljust(15), wallet.coldkeypub.ss58_address, " balance:".ljust(15), cold_balance.__rich__()), highlight=True)
+ netuids = subtensor.get_all_subnet_netuids()
+ try:
+ package_dir = os.path.dirname(bittensor.__file__)
+ root_dir = os.path.dirname(package_dir)
+ filename = os.path.join(root_dir, 'delegates.json')
+ if os.path.exists(filename):
+ registered_delegate_info = json.load( open(filename, 'r') )
else:
- wallet.hotkey
- wallet.coldkeypub
+ registered_delegate_info = {}
+ except:
+ registered_delegate_info = {}
- if cli.config.netuid != None:
- # If a netuid is provided, inspect the hotkey and the neuron
- dendrite = bittensor.dendrite( wallet = wallet )
- neuron = subtensor.get_neuron_for_pubkey_and_subnet( hotkey_ss58 = wallet.hotkey.ss58_address, netuid = cli.config.netuid )
- if neuron.is_null:
- registered = '[bold white]No[/bold white]'
- stake = bittensor.Balance.from_tao( 0 )
- emission = bittensor.Balance.from_rao( 0 )
- latency = 'N/A'
- else:
- endpoint = bittensor.endpoint.from_neuron( neuron )
- registered = '[bold white]Yes[/bold white]'
- stake = neuron.total_stake
- emission = bittensor.Balance.from_rao( neuron.emission * 1000000000 )
- synapses = [bittensor.synapse.TextLastHiddenState()]
- _, c, t = dendrite.text( endpoints = endpoint, inputs = 'hello world', synapses=synapses)
- latency = "{}".format((t[0]).tolist()[0]) if (c[0]).tolist()[0] == 1 else 'N/A'
+ neuron_state_dict = {}
+ for netuid in tqdm( netuids ):
+ neuron_state_dict[netuid] = subtensor.neurons_lite( netuid )
- cold_balance = subtensor.get_balance( wallet.coldkeypub.ss58_address )
- bittensor.__console__.print((
- "\n[bold white]{}[/bold white]:\n [bold grey]{}[bold white]{}[/bold white]\n" + \
- " {}[bold white]{}[/bold white]\n {}{}\n {}{}\n {}{}\n {}{}\n {}{}[/bold grey]"
- )
- .format(
- wallet,
- "coldkey:".ljust(15),
- wallet.coldkeypub.ss58_address,
- "hotkey:".ljust(15),
- wallet.hotkey.ss58_address,
- "registered:".ljust(15),
- registered,
- "balance:".ljust(15),
- cold_balance.__rich__(),
- "stake:".ljust(15),
- stake.__rich__(),
- "emission:".ljust(15),
- emission.__rich_rao__(),
- "latency:".ljust(15),
- latency
- ), highlight=True)
+ table = Table(show_footer=True, pad_edge=False, box=None, expand=True)
+ table.add_column("[overline white]Coldkey", footer_style = "overline white", style='bold white')
+ table.add_column("[overline white]Balance", footer_style = "overline white", style='green')
+ table.add_column("[overline white]Delegate", footer_style = "overline white", style='blue')
+ table.add_column("[overline white]Stake", footer_style = "overline white", style='green')
+ table.add_column("[overline white]Emission", footer_style = "overline white", style='green')
+ table.add_column("[overline white]Netuid", footer_style = "overline white", style='bold white')
+ table.add_column("[overline white]Hotkey", footer_style = "overline white", style='yellow')
+ table.add_column("[overline white]Stake", footer_style = "overline white", style='green')
+ table.add_column("[overline white]Emission", footer_style = "overline white", style='green')
+ for wallet in tqdm( wallets ):
+ delegates: List[Tuple(bittensor.DelegateInfo, bittensor.Balance)] = subtensor.get_delegated( coldkey_ss58=wallet.coldkeypub.ss58_address )
+ if not wallet.coldkeypub_file.exists_on_device(): continue
+ cold_balance = wallet.get_balance( subtensor = subtensor )
+ table.add_row(
+ wallet.name,
+ str(cold_balance),
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ )
+ for dele, staked in delegates:
+ if dele.hotkey_ss58 in registered_delegate_info:
+ delegate_name = registered_delegate_info[dele.hotkey_ss58]['name']
else:
- # Otherwise, print all subnets the hotkey is registered on.
- # If a netuid is provided, inspect the hotkey and the neuron
- stake = subtensor.get_stake_for_coldkey_and_hotkey( hotkey_ss58 = wallet.hotkey.ss58_address, coldkey_ss58 = wallet.coldkeypub.ss58_address )
- if stake == None:
- # Not registered on any subnets
- subnets = "[bold white][][/bold white]"
- stake = bittensor.Balance.from_tao( 0 )
- else:
- # Registered on subnets
- subnets_registered = subtensor.get_netuids_for_hotkey( hotkey_ss58 = wallet.hotkey.ss58_address )
- subnets = f'[bold white]{subnets_registered}[/bold white]'
-
- emission = bittensor.Balance.from_rao( 0 )
- for netuid in subnets_registered:
- neuron = subtensor.neuron_for_pubkey( hotkey_ss58 = wallet.hotkey.ss58_address, netuid = netuid )
- emission += bittensor.Balance.from_rao( neuron.emission * 1000000000 )
-
- cold_balance = subtensor.get_balance( wallet.coldkeypub.ss58_address )
- bittensor.__console__.print((
- "\n[bold white]{}[/bold white]:\n [bold grey]{}[bold white]{}[/bold white]\n" + \
- " {}[bold white]{}[/bold white]\n {}{}\n {}{}\n {}{}\n {}{}\n {}{}[/bold grey]"
- )
- .format(
- wallet,
- "coldkey:".ljust(15),
- wallet.coldkeypub.ss58_address,
- "hotkey:".ljust(15),
- wallet.hotkey.ss58_address,
- "subnets:".ljust(15),
- subnets,
- "balance:".ljust(15),
- cold_balance.__rich__(),
- "stake:".ljust(15),
- stake.__rich__(),
- "emission:".ljust(15),
- emission.__rich_rao__(),
- ), highlight=True)
+ delegate_name = dele.hotkey_ss58
+ table.add_row(
+ '',
+ '',
+ str(delegate_name),
+ str(staked),
+ str(dele.total_daily_return.tao * (staked.tao/dele.total_stake.tao)),
+ '',
+ '',
+ '',
+ ''
+ )
+ hotkeys = _get_hotkey_wallets_for_wallet( wallet )
+ for netuid in netuids:
+ for neuron in neuron_state_dict[netuid]:
+ if neuron.coldkey == wallet.coldkeypub.ss58_address:
+ table.add_row(
+ '',
+ '',
+ '',
+ '',
+ '',
+ str( netuid ),
+ str( neuron.hotkey ),
+ str( neuron.stake ),
+ str( bittensor.Balance.from_tao(neuron.emission) )
+ )
+
+ bittensor.__console__.print(table)
+
+
@staticmethod
def check_config( config: 'bittensor.Config' ):
- check_netuid_set( config, subtensor = bittensor.subtensor( config = config ),allow_none = True )
- if config.wallet.get('name') == bittensor.defaults.wallet.name and not config.no_prompt:
+ if not config.all and config.wallet.get('name') == bittensor.defaults.wallet.name and not config.no_prompt:
wallet_name = Prompt.ask("Enter wallet name", default = bittensor.defaults.wallet.name)
config.wallet.name = str(wallet_name)
- if config.wallet.get('hotkey') == bittensor.defaults.wallet.hotkey and not config.no_prompt:
- hotkey = Prompt.ask("Enter hotkey name (optional)", default = None)
- config.wallet.hotkey = hotkey
-
@staticmethod
def add_args( parser: argparse.ArgumentParser ):
inspect_parser = parser.add_parser(
'inspect',
help='''Inspect a wallet (cold, hot) pair'''
)
+ inspect_parser.add_argument(
+ '--all',
+ action='store_true',
+ help='''Check all coldkey wallets.''',
+ default = False
+ )
inspect_parser.add_argument(
'--no_prompt',
dest='no_prompt',
diff --git a/bittensor/_cli/commands/overview.py b/bittensor/_cli/commands/overview.py
index a9f41342ad..38a0a8e38f 100644
--- a/bittensor/_cli/commands/overview.py
+++ b/bittensor/_cli/commands/overview.py
@@ -73,7 +73,7 @@ def run( cli ):
return
# Pull neuron info for all keys.
- neurons: Dict[str, List[bittensor.NeuronInfo, bittensor.Wallet]] = {}
+ neurons: Dict[str, List[bittensor.NeuronInfoLite, bittensor.Wallet]] = {}
block = subtensor.block
netuids = subtensor.get_all_subnet_netuids()
@@ -115,6 +115,7 @@ def run( cli ):
total_neurons = 0
total_stake = 0.0
for netuid in netuids:
+ subnet_tempo = subtensor.tempo(netuid=netuid)
last_subnet = netuid == netuids[-1]
TABLE_DATA = []
total_rank = 0.0
@@ -126,7 +127,7 @@ def run( cli ):
total_emission = 0
for nn, hotwallet in neurons[str(netuid)]:
- nn: bittensor.NeuronInfo
+ nn: bittensor.NeuronInfoLite
uid = nn.uid
active = nn.active
stake = nn.total_stake.tao
@@ -136,7 +137,7 @@ def run( cli ):
validator_trust = nn.validator_trust
incentive = nn.incentive
dividends = nn.dividends
- emission = nn.emission / (subtensor.tempo(netuid=netuid) + 1)
+ emission = int(nn.emission / (subnet_tempo + 1) * 1e9)
last_update = int(block - nn.last_update)
validator_permit = nn.validator_permit
row = [
@@ -150,7 +151,7 @@ def run( cli ):
'{:.5f}'.format(consensus),
'{:.5f}'.format(incentive),
'{:.5f}'.format(dividends),
- '{:.5f}'.format(emission),
+ '{:_}'.format(emission),
'{:.5f}'.format(validator_trust),
'*' if validator_permit else '',
str(last_update),
@@ -196,7 +197,7 @@ def run( cli ):
table.add_column("[overline white]CONSENSUS", '{:.5f}'.format(total_consensus), footer_style = "overline white", justify='right', style='green', no_wrap=True)
table.add_column("[overline white]INCENTIVE", '{:.5f}'.format(total_incentive), footer_style = "overline white", justify='right', style='green', no_wrap=True)
table.add_column("[overline white]DIVIDENDS", '{:.5f}'.format(total_dividends), footer_style = "overline white", justify='right', style='green', no_wrap=True)
- table.add_column("[overline white]EMISSION(\u03C4)", '\u03C4{}'.format(int(total_emission)), footer_style = "overline white", justify='right', style='green', no_wrap=True)
+ table.add_column("[overline white]EMISSION(\u03C1)", '\u03C1{:_}'.format(total_emission), footer_style = "overline white", justify='right', style='green', no_wrap=True)
table.add_column("[overline white]VTRUST", '{:.5f}'.format(total_validator_trust), footer_style="overline white", justify='right', style='green', no_wrap=True)
table.add_column("[overline white]VPERMIT", justify='right', no_wrap=True)
table.add_column("[overline white]UPDATED", justify='right', no_wrap=True)
diff --git a/bittensor/_cli/commands/unstake.py b/bittensor/_cli/commands/unstake.py
index 15b565b420..d08e67d676 100644
--- a/bittensor/_cli/commands/unstake.py
+++ b/bittensor/_cli/commands/unstake.py
@@ -32,12 +32,12 @@ def check_config( cls, config: 'bittensor.Config' ):
wallet_name = Prompt.ask("Enter wallet name", default = bittensor.defaults.wallet.name)
config.wallet.name = str(wallet_name)
- if config.wallet.get('hotkey') == bittensor.defaults.wallet.hotkey and not config.no_prompt and not config.get('all_hotkeys') and not config.get('hotkeys'):
+ if not config.hotkey_ss58address and config.wallet.get('hotkey') == bittensor.defaults.wallet.hotkey and not config.no_prompt and not config.get('all_hotkeys') and not config.get('hotkeys'):
hotkey = Prompt.ask("Enter hotkey name", default = bittensor.defaults.wallet.hotkey)
config.wallet.hotkey = str(hotkey)
# Get amount.
- if not config.get('amount') and not config.get('unstake_all') and not config.get('max_stake'):
+ if not config.hotkey_ss58address and not config.get('amount') and not config.get('unstake_all') and not config.get('max_stake'):
hotkeys: str = ''
if config.get('all_hotkeys'):
hotkeys = "all hotkeys"
@@ -80,6 +80,12 @@ def add_args( command_parser ):
type=float,
required=False
)
+ unstake_parser.add_argument(
+ '--hotkey_ss58address',
+ dest="hotkey_ss58address",
+ type=str,
+ required=False
+ )
unstake_parser.add_argument(
'--max_stake',
dest="max_stake",
@@ -129,7 +135,10 @@ def run( cli ):
# Get the hotkey_names (if any) and the hotkey_ss58s.
hotkeys_to_unstake_from: List[Tuple[Optional[str], str]] = []
- if cli.config.get('all_hotkeys'):
+ if cli.config.get('hotkey_ss58address'):
+ # Stake to specific hotkey.
+ hotkeys_to_unstake_from = [(None, cli.config.get('hotkey_ss58address'))]
+ elif cli.config.get('all_hotkeys'):
# Stake to all hotkeys.
all_hotkeys: List[bittensor.wallet] = get_hotkey_wallets_for_wallet( wallet = wallet )
# Get the hotkeys to exclude. (d)efault to no exclusions.
diff --git a/bittensor/_endpoint/__init__.py b/bittensor/_endpoint/__init__.py
index 8de7747455..2d21d04f4b 100644
--- a/bittensor/_endpoint/__init__.py
+++ b/bittensor/_endpoint/__init__.py
@@ -18,7 +18,7 @@
# DEALINGS IN THE SOFTWARE.
import json
-from types import SimpleNamespace
+from typing import Union
import torch
import bittensor
@@ -63,7 +63,7 @@ def __new__(
@staticmethod
- def from_neuron( neuron: 'bittensor.NeuronInfo' ) -> 'bittensor.Endpoint':
+ def from_neuron( neuron: Union['bittensor.NeuronInfo', 'bittensor.NeuronInfoLite'] ) -> 'bittensor.Endpoint':
"""
endpoint.assert_format(
version = neuron.version,
diff --git a/bittensor/_logging/__init__.py b/bittensor/_logging/__init__.py
index 6958a97d4a..13636849ed 100644
--- a/bittensor/_logging/__init__.py
+++ b/bittensor/_logging/__init__.py
@@ -304,25 +304,12 @@ def rpc_log(
synapse = synapse
)
-
- @classmethod
- def create_receptor_log( cls, endpoint: 'bittensor.Endpoint' ):
- """ Debug logging for the connection between endpoints
- """
- logger.debug( 'endpoint', receptor=True, action = '' + 'Connect'.center(16) + '', uid=str(endpoint.uid).center(4), hotkey=endpoint.hotkey, coldkey=endpoint.coldkey, ip_str=endpoint.ip_str().center(27) )
-
@classmethod
def update_receptor_log( cls, endpoint: 'bittensor.Endpoint' ):
""" Debug logging for updating the connection with endpoint
"""
logger.debug( 'endpoint', receptor=True, action = '' + 'Update'.center(16) + '', uid=str(endpoint.uid).center(4), hotkey=endpoint.hotkey, coldkey=endpoint.coldkey, ip_str=endpoint.ip_str().center(27) )
- @classmethod
- def destroy_receptor_log( cls, endpoint: 'bittensor.Endpoint' ):
- """ Debug logging for destroying connection with endpoint
- """
- logger.debug( 'endpoint', receptor=True, action = '' + 'Destroy'.center(16) + '', uid=str(endpoint.uid).center(4), hotkey=endpoint.hotkey, coldkey=endpoint.coldkey, ip_str=endpoint.ip_str().center(27) )
-
@classmethod
def success( cls, prefix:str, sufix:str ):
""" Success logging
diff --git a/bittensor/_metagraph/__init__.py b/bittensor/_metagraph/__init__.py
index 3b0d9fd244..435affc954 100644
--- a/bittensor/_metagraph/__init__.py
+++ b/bittensor/_metagraph/__init__.py
@@ -24,7 +24,7 @@
import bittensor
from . import metagraph_impl
from . import metagraph_mock
-from typing import Optional, List
+from typing import Optional, List, Union
import bittensor.utils.weight_utils as weight_utils
from .naka_metagraph_impl import Metagraph as naka_metagraph
@@ -77,11 +77,11 @@ def __new__(
if network == None:
network = config.subtensor.get('network', bittensor.defaults.subtensor.network)
- if network =='finney':
- return metagraph_impl.Metagraph( network = network, netuid = netuid )
- elif network =='nakamoto':
+ if network =='nakamoto':
config.subtensor.network = 'nakamoto'
return naka_metagraph(config = config, subtensor = subtensor)
+ else:
+ return metagraph_impl.Metagraph( network = network, netuid = netuid )
@classmethod
def config(cls) -> 'bittensor.Config':
@@ -123,7 +123,7 @@ def check_config( cls, config: 'bittensor.Config' ):
pass
@staticmethod
- def from_neurons( network: str, netuid: int, info: 'bittensor.SubnetInfo', neurons: List['bittensor.NeuronInfo'], block: int ) -> 'bittensor.Metagraph':
+ def from_neurons( network: str, netuid: int, info: 'bittensor.SubnetInfo', neurons: Union[List['bittensor.NeuronInfo'], List['bittensor.NeuronInfoLite']], block: int ) -> 'bittensor.Metagraph':
r""" Creates a metagraph from a list of neurons.
Args:
network: (:obj:`str`, required):
@@ -132,7 +132,7 @@ def from_neurons( network: str, netuid: int, info: 'bittensor.SubnetInfo', neuro
netuid of the subnet for the metagraph.
info: (:obj:`SubnetInfo`, required):
SubnetInfo object for the metagraph, including the subnet's hyperparameters.
- neurons: (:obj:`List[NeuronInfo]`, required):
+ neurons: (:obj:`Union[List[NeuronInfo], List[NeuronInfoLite]]`, required):
List of neurons to create metagraph from.
block: (:obj:`int`, required):
Block number at time of the metagraph.
@@ -179,6 +179,9 @@ def from_neurons( network: str, netuid: int, info: 'bittensor.SubnetInfo', neuro
endpoint = bittensor.endpoint.from_neuron(n)
metagraph._endpoint_objs[n.uid] = endpoint
endpoints[n.uid] = endpoint.to_tensor().tolist()
+ if isinstance(n, bittensor.NeuronInfoLite):
+ continue
+ # Weights and bonds only for full neurons.
if len(n.weights) > 0:
w_uids, w_weights = zip(*n.weights)
weights[n.uid] = weight_utils.convert_weight_uids_and_vals_to_tensor( n_total, w_uids, w_weights ).tolist()
diff --git a/bittensor/_metagraph/metagraph_impl.py b/bittensor/_metagraph/metagraph_impl.py
index 5b5e2ab4f6..5496a0d5b0 100644
--- a/bittensor/_metagraph/metagraph_impl.py
+++ b/bittensor/_metagraph/metagraph_impl.py
@@ -342,7 +342,7 @@ def load_from_state_dict(self, state_dict: dict ) -> 'Metagraph':
self.info = bittensor.SubnetInfo.from_parameter_dict( state_dict['info'] ) if 'info' in state_dict else None
return self
- def sync ( self, netuid: Optional[int] = None, subtensor: 'bittensor.Subtensor' = None, block: Optional[int] = None ) -> 'Metagraph':
+ def sync ( self, netuid: Optional[int] = None, subtensor: 'bittensor.Subtensor' = None, block: Optional[int] = None, lite: bool = True ) -> 'Metagraph':
r""" Synchronizes this metagraph with the chain state.
Args:
subtensor: (:obj:`bittensor.Subtensor`, optional, defaults to None):
@@ -353,6 +353,9 @@ def sync ( self, netuid: Optional[int] = None, subtensor: 'bittensor.Subtensor'
Defaults to the netuid of the metagraph object.
block: (:obj:`int`, optional, defaults to None):
block to sync with. If None, syncs with the current block.
+ lite: (:obj:`bool`, defaults to True):
+ If true, syncs using the lite version of the metagraph.
+ Note: lite version does not include weights, bonds
Returns:
self: (:obj:`Metagraph`, required):
Returns self.
@@ -365,7 +368,7 @@ def sync ( self, netuid: Optional[int] = None, subtensor: 'bittensor.Subtensor'
if netuid == None:
raise ValueError('Metagraph.sync() requires a netuid to sync with.')
# Pull metagraph from chain using subtensor.
- metagraph = subtensor.metagraph( netuid = netuid, block = block )
+ metagraph = subtensor.metagraph( netuid = netuid, block = block, lite = lite )
# Update self with new values.
self.__dict__.update(metagraph.__dict__)
return self
diff --git a/bittensor/_neuron/text/core_server/__init__.py b/bittensor/_neuron/text/core_server/__init__.py
index 2440d9edc9..1e4d56d4e2 100644
--- a/bittensor/_neuron/text/core_server/__init__.py
+++ b/bittensor/_neuron/text/core_server/__init__.py
@@ -214,7 +214,7 @@ def run(
# Load/Create our bittensor wallet.
self.wallet.reregister(subtensor=self.subtensor, netuid = self.config.netuid)
- self.metagraph.load().sync(netuid = self.config.netuid, subtensor=self.subtensor).save()
+ self.metagraph.sync(netuid = self.config.netuid, subtensor=self.subtensor).save()
# Create our optimizer.
optimizer = torch.optim.SGD(
diff --git a/bittensor/_neuron/text/core_validator/__init__.py b/bittensor/_neuron/text/core_validator/__init__.py
index 1e5136669e..b20638da79 100644
--- a/bittensor/_neuron/text/core_validator/__init__.py
+++ b/bittensor/_neuron/text/core_validator/__init__.py
@@ -76,8 +76,6 @@ class neuron:
bittensor dendrite object
dataset (:obj:bittensor.dendrite, `optional`):
bittensor dendrite object
- axon (:obj:bittensor.axon, `optional`):
- bittensor axon object
Examples::
>>> subtensor = bittensor.subtensor(network='nakamoto')
>>> validator = bittensor.neuron.text.core_validator.neuron(subtensor=subtensor)
@@ -91,7 +89,6 @@ def __init__(
metagraph: 'bittensor.Metagraph' = None,
dendrite: 'bittensor.Dendrite' = None,
dataset: 'bittensor.dataset' = None,
- axon: 'bittensor.axon' = None,
netuid: int = None
):
@@ -123,7 +120,6 @@ def __init__(
self.config.dendrite._mock = True
self.config.metagraph._mock = True
self.config.subtensor._mock = True
- self.config.axon._mock = True
print ( self.config )
# === Logging + prometheus ===
@@ -139,8 +135,7 @@ def __init__(
self.wallet = bittensor.wallet ( config = self.config ) if wallet == None else wallet
self.subtensor = subtensor
self.metagraph = bittensor.metagraph ( config = self.config ) if metagraph == None else metagraph
- self.dendrite = bittensor.dendrite ( config = self.config, wallet = self.wallet, max_active_receptors = 0 ) if dendrite == None else dendrite # Dendrite should not store receptor in validator.
- self.axon = bittensor.axon ( netuid=self.config.netuid, config = self.config, wallet = self.wallet ) if axon == None else axon
+ self.dendrite = bittensor.dendrite ( config = self.config, wallet = self.wallet, max_active_receptors = 0 ) if dendrite == None else dendrite # Dendrite should not store receptor in validator.
self.device = torch.device ( device = self.config.neuron.device )
self.nucleus = nucleus ( config = self.config, device = self.device, subtensor = self.subtensor, vlogger = self.vlogger ).to( self.device )
if self.config.subtensor.network == 'nakamoto':
@@ -192,7 +187,6 @@ def check_config( cls, config: 'bittensor.Config' ):
bittensor.dataset.check_config( config )
bittensor.dendrite.check_config( config )
bittensor.wandb.check_config( config )
- bittensor.axon.check_config( config )
bittensor.prometheus.check_config( config )
full_path = os.path.expanduser('{}/{}/{}/netuid{}/{}'.format( config.logging.logging_dir, config.wallet.name, config.wallet.hotkey, config.netuid, config.neuron.name ))
config.neuron.full_path = os.path.expanduser(full_path)
@@ -236,7 +230,6 @@ def config ( cls ):
bittensor.logging.add_args( parser )
bittensor.dataset.add_args( parser )
bittensor.wandb.add_args(parser)
- bittensor.axon.add_args( parser )
bittensor.prometheus.add_args( parser )
return bittensor.config( parser )
@@ -286,15 +279,13 @@ def __enter__(self):
)
# === Set prometheus run info ===
- # Serve the prometheus with axon so we can determine where the prometheus server port is (the axon is only served for this reason.)
- # TODO (Cameron) this should be it's own storage map on-chain.
+ # Serve the prometheus
bittensor.prometheus(
config = self.config,
wallet = self.wallet,
netuid = self.config.netuid,
- port = self.config.prometheus.port if self.config.prometheus.port == bittensor.defaults.axon.port else self.config.axon.port - 1000
+ port = self.config.prometheus.port
)
- self.axon.serve( subtensor = self.subtensor )
self.vlogger.prometheus.log_run_info(
parameters = self.nucleus.parameters(),
@@ -844,7 +835,7 @@ def add_args( cls, parser ):
parser.add_argument('--nucleus.dropout', type=float, help='the dropout value', default=0.2)
parser.add_argument('--nucleus.importance', type=float, help='hyperparameter for the importance loss', default=3)
parser.add_argument('--nucleus.noise_multiplier', type=float, help='Standard deviation multipler on weights', default=2 )
- parser.add_argument('--nucleus.no_dendrite_backward', action='store_true', help='Pass backward request to the server side or not', default=False )
+ parser.add_argument('--nucleus.dendrite_backward', action='store_true', help='Pass backward request to the server side or not', default=False )
parser.add_argument('--nucleus.scaling_law_power', type=float, help='Power for modified scaling law, powered down to improve dynamic range, e.g. 3 → 6 nats for 0.5. (default value: -1, pulling from subtensor directly)', default=-1)
parser.add_argument('--nucleus.synergy_scaling_law_power', type=float, help='Power for synergy modified scaling law, powered down to improve dynamic range, e.g. 3 → 6 nats for 0.5. (default value: -1, pulling from subtensor directly)', default=-1)
parser.add_argument('--nucleus.logits_divergence', type=float, help=' the divergence value for logit anomaly detection (default value: -1, pulling from subtensor directly)', default=-1)
@@ -985,10 +976,11 @@ def forward(
timeout=bittensor.__blocktime__
)
- if self.config.nucleus.no_dendrite_backward:
- query_responses = [[syn.detach().to(self.device) for syn in res] for res in query_responses]
- return_ops = [ops.detach().to(self.device) for ops in return_ops]
- times = [t.detach().to(self.device) for t in times]
+ if not self.config.nucleus.dendrite_backward:
+ query_responses = [[syn.detach() for syn in res] for res in query_responses]
+ return_ops = [ops.detach() for ops in return_ops]
+ times = [t.detach() for t in times]
+
# Send responses to device. This is required to ensure we move the responses
# Onto the correct device.
diff --git a/bittensor/_receptor/receptor_pool_impl.py b/bittensor/_receptor/receptor_pool_impl.py
index db76bb3c5a..04ae83c368 100644
--- a/bittensor/_receptor/receptor_pool_impl.py
+++ b/bittensor/_receptor/receptor_pool_impl.py
@@ -338,7 +338,6 @@ def _destroy_receptors_over_max_allowed( self ):
if receptor_to_remove != None:
try:
- bittensor.logging.destroy_receptor_log(receptor_to_remove.endpoint)
self.receptors[ receptor_to_remove.endpoint.hotkey ].close()
del self.receptors[ receptor_to_remove.endpoint.hotkey ]
except KeyError:
@@ -370,7 +369,6 @@ def _get_or_create_receptor_for_endpoint( self, endpoint: 'bittensor.Endpoint' )
# ---- Or: Create a new receptor ----
else:
- bittensor.logging.create_receptor_log( endpoint )
receptor = bittensor.receptor (
endpoint = endpoint,
wallet = self.wallet,
diff --git a/bittensor/_subtensor/__init__.py b/bittensor/_subtensor/__init__.py
index e20f86c266..a17f61e3cc 100644
--- a/bittensor/_subtensor/__init__.py
+++ b/bittensor/_subtensor/__init__.py
@@ -112,15 +112,16 @@ def __new__(
# make sure formatting is good
endpoint_url = bittensor.utils.networking.get_formatted_ws_endpoint_url(endpoint_url)
- substrate = SubstrateInterface(
- ss58_format = bittensor.__ss58_format__,
- use_remote_preset=True,
- url = endpoint_url,
- )
+
subtensor.check_config( config )
network = config.subtensor.get('network', bittensor.defaults.subtensor.network)
if network == 'nakamoto':
+ substrate = SubstrateInterface(
+ ss58_format = bittensor.__ss58_format__,
+ use_remote_preset=True,
+ url = endpoint_url,
+ )
# Use nakamoto-specific subtensor.
return Nakamoto_subtensor(
substrate = substrate,
@@ -128,6 +129,12 @@ def __new__(
chain_endpoint = config.subtensor.chain_endpoint,
)
else:
+ substrate = SubstrateInterface(
+ ss58_format = bittensor.__ss58_format__,
+ use_remote_preset=True,
+ url = endpoint_url,
+ type_registry=bittensor.__type_registry__
+ )
return subtensor_impl.Subtensor(
substrate = substrate,
network = config.subtensor.get('network', bittensor.defaults.subtensor.network),
diff --git a/bittensor/_subtensor/extrinsics/set_weights.py b/bittensor/_subtensor/extrinsics/set_weights.py
index a6286e94e3..06164337fa 100644
--- a/bittensor/_subtensor/extrinsics/set_weights.py
+++ b/bittensor/_subtensor/extrinsics/set_weights.py
@@ -90,7 +90,8 @@ def set_weights_extrinsic(
'version_key': version_key,
}
)
- extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.hotkey )
+ # Period dictates how long the extrinsic will stay as part of waiting pool
+ extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.hotkey, era={'period':100})
response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization )
# We only wait here if we expect finalization.
if not wait_for_finalization and not wait_for_inclusion:
diff --git a/bittensor/_subtensor/extrinsics/staking.py b/bittensor/_subtensor/extrinsics/staking.py
index 37caab6afa..214101a30a 100644
--- a/bittensor/_subtensor/extrinsics/staking.py
+++ b/bittensor/_subtensor/extrinsics/staking.py
@@ -289,7 +289,7 @@ def add_stake_multiple_extrinsic (
block = subtensor.get_current_block()
new_stake = subtensor.get_stake_for_coldkey_and_hotkey( coldkey_ss58 = wallet.coldkeypub.ss58_address, hotkey_ss58 = hotkey_ss58, block = block )
new_balance = subtensor.get_balance( wallet.coldkeypub.ss58_address, block = block )
- bittensor.__console__.print("Stake ({}): [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( wallet.hotkey.ss58_address, old_stake, new_stake ))
+ bittensor.__console__.print("Stake ({}): [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( hotkey_ss58, old_stake, new_stake ))
old_balance = new_balance
successful_stakes += 1
if staking_all:
@@ -301,7 +301,7 @@ def add_stake_multiple_extrinsic (
continue
except NotRegisteredError as e:
- bittensor.__console__.print(":cross_mark: [red]Hotkey: {} is not registered.[/red]".format(wallet.hotkey_str))
+ bittensor.__console__.print(":cross_mark: [red]Hotkey: {} is not registered.[/red]".format(hotkey_ss58))
continue
except StakeError as e:
bittensor.__console__.print(":cross_mark: [red]Stake Error: {}[/red]".format(e))
diff --git a/bittensor/_subtensor/extrinsics/transfer.py b/bittensor/_subtensor/extrinsics/transfer.py
index 10266e537a..8b5ed9c7a7 100644
--- a/bittensor/_subtensor/extrinsics/transfer.py
+++ b/bittensor/_subtensor/extrinsics/transfer.py
@@ -31,6 +31,7 @@ def transfer_extrinsic(
amount: Union[Balance, float],
wait_for_inclusion: bool = True,
wait_for_finalization: bool = False,
+ keep_alive: bool = True,
prompt: bool = False,
) -> bool:
r""" Transfers funds from this wallet to the destination public key address
@@ -47,6 +48,8 @@ def transfer_extrinsic(
wait_for_finalization (bool):
If set, waits for the extrinsic to be finalized on the chain before returning true,
or returns false if the extrinsic fails to be finalized within the timeout.
+ keep_alive (bool):
+ If set, keeps the account alive by keeping the balance above the existential deposit.
prompt (bool):
If true, the call waits for confirmation from the user before proceeding.
Returns:
@@ -75,14 +78,42 @@ def transfer_extrinsic(
# Check balance.
with bittensor.__console__.status(":satellite: Checking Balance..."):
account_balance = subtensor.get_balance( wallet.coldkey.ss58_address )
+ # check existential deposit.
+ existential_deposit = subtensor.get_existential_deposit()
+
+ with bittensor.__console__.status(":satellite: Transferring..."):
+ with subtensor.substrate as substrate:
+ call = substrate.compose_call(
+ call_module='Balances',
+ call_function='transfer',
+ call_params={
+ 'dest': dest,
+ 'value': transfer_balance.rao
+ }
+ )
+
+ try:
+ payment_info = substrate.get_payment_info( call = call, keypair = wallet.coldkey )
+ except Exception as e:
+ bittensor.__console__.print(":cross_mark: [red]Failed to get payment info[/red]:[bold white]\n {}[/bold white]".format(e))
+ payment_info = {
+ 'partialFee': 2e7, # assume 0.02 Tao
+ }
+
+ fee = bittensor.Balance.from_rao( payment_info['partialFee'] )
- if account_balance < transfer_balance:
- bittensor.__console__.print(":cross_mark: [red]Not enough balance[/red]:[bold white]\n balance: {}\n amount: {}[/bold white]".format( account_balance, transfer_balance ))
+ if not keep_alive:
+ # Check if the transfer should keep_alive the account
+ existential_deposit = bittensor.Balance(0)
+
+ # Check if we have enough balance.
+ if account_balance < (transfer_balance + fee + existential_deposit):
+ bittensor.__console__.print(":cross_mark: [red]Not enough balance[/red]:[bold white]\n balance: {}\n amount: {}\n for fee: {}[/bold white]".format( account_balance, transfer_balance, fee ))
return False
# Ask before moving on.
if prompt:
- if not Confirm.ask("Do you want to transfer:[bold white]\n amount: {}\n from: {}:{}\n to: {}[/bold white]".format( transfer_balance, wallet.name, wallet.coldkey.ss58_address, dest )):
+ if not Confirm.ask("Do you want to transfer:[bold white]\n amount: {}\n from: {}:{}\n to: {}\n for fee: {}[/bold white]".format( transfer_balance, wallet.name, wallet.coldkey.ss58_address, dest, fee )):
return False
with bittensor.__console__.status(":satellite: Transferring..."):
@@ -95,6 +126,7 @@ def transfer_extrinsic(
'value': transfer_balance.rao
}
)
+
extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.coldkey )
response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization )
# We only wait here if we expect finalization.
diff --git a/bittensor/_subtensor/extrinsics/unstaking.py b/bittensor/_subtensor/extrinsics/unstaking.py
index 447c85baf4..82e01151b0 100644
--- a/bittensor/_subtensor/extrinsics/unstaking.py
+++ b/bittensor/_subtensor/extrinsics/unstaking.py
@@ -288,14 +288,14 @@ def unstake_multiple_extrinsic (
with bittensor.__console__.status(":satellite: Checking Balance on: [white]{}[/white] ...".format(subtensor.network)):
block = subtensor.get_current_block()
new_stake = subtensor.get_stake_for_coldkey_and_hotkey( coldkey_ss58 = wallet.coldkeypub.ss58_address, hotkey_ss58 = hotkey_ss58, block = block )
- bittensor.__console__.print("Stake ({}): [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( wallet.hotkey.ss58_address, stake_on_uid, new_stake ))
+ bittensor.__console__.print("Stake ({}): [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( hotkey_ss58, stake_on_uid, new_stake ))
successful_unstakes += 1
else:
bittensor.__console__.print(":cross_mark: [red]Failed[/red]: Error unknown.")
continue
except NotRegisteredError as e:
- bittensor.__console__.print(":cross_mark: [red]Hotkey: {} is not registered.[/red]".format(wallet.hotkey_str))
+ bittensor.__console__.print(":cross_mark: [red]{} is not registered.[/red]".format(hotkey_ss58))
continue
except StakeError as e:
bittensor.__console__.print(":cross_mark: [red]Stake Error: {}[/red]".format(e))
diff --git a/bittensor/_subtensor/subtensor_impl.py b/bittensor/_subtensor/subtensor_impl.py
index 62618e1418..88e12a2b7a 100644
--- a/bittensor/_subtensor/subtensor_impl.py
+++ b/bittensor/_subtensor/subtensor_impl.py
@@ -241,6 +241,22 @@ def transfer(
wait_for_finalization = wait_for_finalization,
prompt = prompt
)
+
+ def get_existential_deposit(
+ self,
+ block: Optional[int] = None,
+ ) -> Optional[Balance]:
+ """ Returns the existential deposit for the chain. """
+ result = self.query_constant(
+ module_name='Balances',
+ constant_name='ExistentialDeposit',
+ block = block,
+ )
+
+ if result is None:
+ return None
+
+ return Balance.from_rao(result.value)
#################
#### Serving ####
@@ -373,6 +389,18 @@ def make_substrate_call_with_retry():
block_hash = None if block == None else substrate.get_block_hash(block)
)
return make_substrate_call_with_retry()
+
+ """ Gets a constant from subtensor with module_name, constant_name, and block. """
+ def query_constant( self, module_name: str, constant_name: str, block: Optional[int] = None ) -> Optional[object]:
+ @retry(delay=2, tries=3, backoff=2, max_delay=4)
+ def make_substrate_call_with_retry():
+ with self.substrate as substrate:
+ return substrate.get_constant(
+ module_name=module_name,
+ constant_name=constant_name,
+ block_hash = None if block == None else substrate.get_block_hash(block)
+ )
+ return make_substrate_call_with_retry()
#####################################
#### Hyper parameter calls. ####
@@ -484,7 +512,7 @@ def tempo (self, netuid: int, block: Optional[int] = None) -> int:
return self.query_subtensor('Tempo', block, [netuid] ).value
##########################
- #### Account fucntions ###
+ #### Account functions ###
##########################
""" Returns the total stake held on a hotkey including delegative """
@@ -621,7 +649,7 @@ def make_substrate_call_with_retry():
block_hash = None if block == None else substrate.get_block_hash( block )
params = []
if block_hash:
- params = [block_hash] + params
+ params = params + [block_hash]
return substrate.rpc_request(
method="subnetInfo_getSubnetsInfo", # custom rpc method
params=params
@@ -642,7 +670,7 @@ def make_substrate_call_with_retry():
block_hash = None if block == None else substrate.get_block_hash( block )
params = [netuid]
if block_hash:
- params = [block_hash] + params
+ params = params + [block_hash]
return substrate.rpc_request(
method="subnetInfo_getSubnetInfo", # custom rpc method
params=params
@@ -679,7 +707,7 @@ def make_substrate_call_with_retry(encoded_hotkey: List[int]):
block_hash = None if block == None else substrate.get_block_hash( block )
params = [encoded_hotkey]
if block_hash:
- params = [block_hash] + params
+ params = params + [block_hash]
return substrate.rpc_request(
method="delegateInfo_getDelegate", # custom rpc method
params=params
@@ -702,7 +730,7 @@ def make_substrate_call_with_retry():
block_hash = None if block == None else substrate.get_block_hash( block )
params = []
if block_hash:
- params = [block_hash] + params
+ params = params + [block_hash]
return substrate.rpc_request(
method="delegateInfo_getDelegates", # custom rpc method
params=params
@@ -724,7 +752,7 @@ def make_substrate_call_with_retry(encoded_coldkey: List[int]):
block_hash = None if block == None else substrate.get_block_hash( block )
params = [encoded_coldkey]
if block_hash:
- params = [block_hash] + params
+ params = params + [block_hash]
return substrate.rpc_request(
method="delegateInfo_getDelegated", # custom rpc method
params=params
@@ -802,7 +830,7 @@ def make_substrate_call_with_retry():
block_hash = None if block == None else substrate.get_block_hash( block )
params = [netuid, uid]
if block_hash:
- params = [block_hash] + params
+ params = params + [block_hash]
return substrate.rpc_request(
method="neuronInfo_getNeuron", # custom rpc method
params=params
@@ -832,7 +860,7 @@ def make_substrate_call_with_retry():
block_hash = None if block == None else substrate.get_block_hash( block )
params = [netuid]
if block_hash:
- params = [block_hash] + params
+ params = params + [block_hash]
return substrate.rpc_request(
method="neuronInfo_getNeurons", # custom rpc method
params=params
@@ -866,7 +894,7 @@ def make_substrate_call_with_retry():
block_hash = None if block == None else substrate.get_block_hash( block )
params = [netuid, uid]
if block_hash:
- params = [block_hash] + params
+ params = params + [block_hash]
return substrate.rpc_request(
method="neuronInfo_getNeuronLite", # custom rpc method
params=params
@@ -896,7 +924,7 @@ def make_substrate_call_with_retry():
block_hash = None if block == None else substrate.get_block_hash( block )
params = [netuid]
if block_hash:
- params = [block_hash] + params
+ params = params + [block_hash]
return substrate.rpc_request(
method="neuronInfo_getNeuronsLite", # custom rpc method
params=params
@@ -910,7 +938,7 @@ def make_substrate_call_with_retry():
return NeuronInfoLite.list_from_vec_u8( result )
- def metagraph( self, netuid: int, block: Optional[int] = None ) -> 'bittensor.Metagraph':
+ def metagraph( self, netuid: int, block: Optional[int] = None, lite: bool = True ) -> 'bittensor.Metagraph':
r""" Returns the metagraph for the subnet.
Args:
netuid ( int ):
@@ -918,6 +946,8 @@ def metagraph( self, netuid: int, block: Optional[int] = None ) -> 'bittensor.Me
block (Optional[int]):
The block to create the metagraph for.
Defaults to latest.
+ lite (bool, default=True):
+ If true, returns a metagraph using the lite sync (no weights, no bonds)
Returns:
metagraph ( `bittensor.Metagraph` ):
The metagraph for the subnet at the block.
@@ -928,7 +958,11 @@ def metagraph( self, netuid: int, block: Optional[int] = None ) -> 'bittensor.Me
status.start()
# Get neurons.
- neurons = self.neurons( netuid = netuid, block = block )
+ if lite:
+ neurons = self.neurons_lite( netuid = netuid, block = block )
+ else:
+ neurons = self.neurons( netuid = netuid, block = block )
+
# Get subnet info.
subnet_info: Optional[bittensor.SubnetInfo] = self.get_subnet_info( netuid = netuid, block = block )
if subnet_info == None:
@@ -939,11 +973,17 @@ def metagraph( self, netuid: int, block: Optional[int] = None ) -> 'bittensor.Me
# Create metagraph.
block_number = self.block
-
+
metagraph = bittensor.metagraph.from_neurons( network = self.network, netuid = netuid, info = subnet_info, neurons = neurons, block = block_number )
print("Metagraph subtensor: ", self.network)
return metagraph
+ ################
+ #### Transfer ##
+ ################
+
+
+
################
#### Legacy ####
diff --git a/bittensor/utils/weight_utils.py b/bittensor/utils/weight_utils.py
index 3a66baa2dc..c89d6a9c34 100644
--- a/bittensor/utils/weight_utils.py
+++ b/bittensor/utils/weight_utils.py
@@ -138,4 +138,4 @@ def convert_weights_and_uids_for_emit( uids: torch.LongTensor, weights: torch.Fl
weight_vals.append( uint16_val )
weight_uids.append( uid_i )
- return weight_uids, weight_vals
+ return weight_uids, weight_vals
\ No newline at end of file
diff --git a/delegates.json b/delegates.json
index 492db831f5..ccbc5f33da 100644
--- a/delegates.json
+++ b/delegates.json
@@ -1,21 +1,21 @@
{
"5F4tQyWrhfGVcNhoqeiNsR6KjD4wMZ2kfhLj4oHYuyHbZAc3": {
- "name": "Opentensor Foundation",
+ "name": "Openτensor Foundaτion",
"url": "https://opentensor.ai/",
"description": "Founded, maintain and advance Bittensor"
},
"5HNQURvmjjYhTSksi8Wfsw676b4owGwfLR2BFAQzG7H3HhYf": {
- "name": "Neural Internet",
+ "name": "Neural Interneτ",
"url": "https://neuralinternet.ai/",
"description": "An AI research and development decentralized autonomous organization (DAO)."
},
"5FLKnbMjHY8LarHZvk2q2RY9drWFbpxjAcR5x8tjr3GqtU6F": {
- "name": "Tao Bridge",
+ "name": "τao Bridge",
"url": "https://taobridge.xyz",
"description": "A community bridge between Bittensor and Ethereum"
},
"5HeKSHGdsRCwVgyrHchijnZJnq4wiv6GqoDLNah8R5WMfnLB": {
- "name": "TaoStation",
+ "name": "τaoStation",
"url": "https://taostation.com",
"description": "The go to validator for maximal TAO returns to stakers."
},
@@ -25,7 +25,7 @@
"description": "Vune is a dev at Opentensor and a BSc CS student at UofT."
},
"5H6BgKkAr2Anmm9Xw5BVDE4VaQmFEVMkJUHeT7Gki4J7yF4x": {
- "name": "TaoPolishNode",
+ "name": "τaoPolishNode",
"url": "https://taonode.io",
"description": "This node is a collective effort of the polish community. We are engaged in evangelizing the project, educating and sharing the knowledge."
},
@@ -35,12 +35,12 @@
"description": "GPU Cloud built for AI. We plan to introduce perks for those who stake."
},
"5CPzGD8sxyv8fKKXNvKem4qJRhCXABRmpUgC1wb1V4YAXLc3": {
- "name": "Tao Staking",
+ "name": "τao Staking",
"url": "https://www.taostaking.com",
"description": "Empowering innovation on the Bittensor network by helping upcoming projects grow and thrive on Bittensor."
},
"5FFApaS75bv5pJHfAp2FVLBj9ZaXuFDjEypsaBNc1wCfe52v": {
- "name": "RoundTable21",
+ "name": "Roundτable21",
"url": "https://roundtable21.com",
"description": "RoundTable21 is an International, multi-disciplinary team of consultants and advisors partnering alongside leading blockchain startups to offer guidance, expertise, investment and hands-on assistance in every aspect of development."
},
@@ -50,7 +50,7 @@
"description": "Foundry works to empower a decentralized infrastructure. We are protocol-agnostic and seek to support like-minded blockchain entrepreneurs who share our mission to advance the industry."
},
"5DCc5oHA6c1Lpt9R6T1xU8jJGTMvvwBqD1yGX67sL8dHUcga": {
- "name": "WaveTensor",
+ "name": "Waveτensor",
"url": "https://twitter.com/wavetensor",
"description": "A new Wave is coming, join the AI revolution on top of Bittensor by staking with us."
},
@@ -59,14 +59,79 @@
"url": "https://taostats.io",
"description": "Supporting the bittensor eco-system through data provision, statistics and analytics."
},
+ "5CXRfP2ekFhe62r7q3vppRajJmGhTi7vwvb2yr79jveZ282w": {
+ "name": "Rizzo",
+ "url": "",
+ "description": "Validator built for performance and uptime. Data center housed, redundancies include dual physical failover servers (HA), power, internet, tested DR Plan."
+ },
+ "5DRZr3d3twF8SzqB9jBof3a1vPnAkgkxeo2E8yUKJAnE2rSZ": {
+ "name": "Humble AI-Loving Anon",
+ "url": "",
+ "description": "Doing our best to support the Bittensor ecosystem."
+ },
"5GcBK8PDrVifV1xAf4Qkkk6KsbsmhDdX9atvk8vyKU8xdU63": {
- "name": "Tensor.Exchange",
+ "name": "τensor.exchange",
"url": "www.tensor.exchange",
"description": "Bittensor's first community OTC exchange"
},
+ "5EhvL1FVkQPpMjZX4MAADcW42i3xPSF1KiCpuaxTYVr28sux": {
+ "name": "TAO-Validator.com",
+ "url": "www.tao-validator.com",
+ "description": "Maximize your return when staking with TAO-Validator.com. TAO-Validator.com is a highly secure validator that aims to become one of the top contributing entities to Bittensor."
+ },
+ "5FvhvCWLbu2VgotT5obC9E6S9nskerJUrVsWqkWXCbuD8veW": {
+ "name": "The Lost Cove",
+ "url": "https://lostcove.tech/",
+ "description": "Australia and New Zealand community. We're in it for the gains."
+ },
+ "5Dyi5e2QqnWn2RN9X6r8A8Q1QBjYD536H75mxNye193oeCJ4": {
+ "name": "Makoto AI",
+ "url": "https://www.linkedin.com/in/henry-thrasher-17b320239/",
+ "description": "An interdisciplinary research institute committed to discovering and accelerating innovative solutions for climate change, social inequality, and mental and physical illness."
+ },
+ "5Ehv5XMriPZwNBtYHdQV7VrdbN8MBTDTmQhWprZJXxSiMapR": {
+ "name": "Dale Cooper",
+ "url": "",
+ "description": "I have no idea where this will lead us, but I have a definite feeling it will be a place both wonderful and strange."
+ },
+ "5FP9miYmgjAP8Wt3747M2Y6Kk7PrXf6zG7a3EjokQiFFcmUu": {
+ "name": "Elm Place",
+ "url": "",
+ "description": "Run by individuals passionate about creating decentralised digital infrastructure. Background in fiduciary funds management managing institutional investors' capital in real assets, energy and infrastructure"
+ },
+ "5E6oB7h5wtWPbqtPxtSoZeo11fpvDjPuY13SobAMxqEUjqkQ": {
+ "name": "StakeTensor.com-3",
+ "url": "www.staketensor.com",
+ "description": "We run multiple, parallel validators to support Bittensor decentralization & achieve maximum returns"
+ },
+ "5DnWFhKfeu6gXMydzrv8bkwxFegAC6bMWsC4Z2XtaotAeB6S": {
+ "name": "Bittensor Greece",
+ "url": "",
+ "description": "The Greek / Cypriot validator supporting the development of decentralised AI"
+ },
+ "5GBxDYkDp8eJZHGT89wcZJKcMc4ytSqnqqVSpeuGeqtGfqxK": {
+ "name": "τao Stake",
+ "url": "www.taostake.io",
+ "description": "We have been mining since the start of bittensor and want to maintain a long term solid validator to help people get some value from thier investment and keep TAO within the ecosystem."
+ },
+ "5FcXnzNo3mrqReTEY4ftkg5iXRBi61iyvM4W1bywZLRqfxAY": {
+ "name": "Lucrosus Capiτal",
+ "url": "https://lucrosuspool.io/",
+ "description": "Decentralized VC focused on the most thriving blockchain ideas. Join our pool to receive early entrance into promising projects!"
+ },
+ "5CAW5xpgPbxGUzkE3dgmM2XasaygpbvtSoTh3UeR8RMfHQZU": {
+ "name": "Vogue τensor",
+ "url": "https://voguetensor.webflow.io/",
+ "description": "Designing branded clothing for the Bittensor community."
+ },
"5CsvRJXuR955WojnGMdok1hbhffZyB4N5ocrv82f3p5A2zVp": {
"name": "Owl Ventures",
"url": "https://owlventures.co.uk",
"description": "Owl Ventures Bittensor Validator"
+ },
+ "5D9wuLzoWSbucNx6NQRo7wdNfvW2poMy3NumSiggsEStPc9X": {
+ "name": "T A O A L M A N A C H",
+ "url": "",
+ "description": "TAO ALMANACH is the validator of bittensor mod blardo and polkadot mod mister_cole"
}
}
diff --git a/requirements/prod.txt b/requirements/prod.txt
index 88bedfb26a..6bdfb67e1a 100644
--- a/requirements/prod.txt
+++ b/requirements/prod.txt
@@ -31,7 +31,7 @@ pyyaml==6.0
rich==12.5.1
retry==0.9.2
requests==2.25.0
-scalecodec>=1.2,<1.3
+scalecodec==1.2.0
sentencepiece==0.1.97
termcolor==2.1.1
torch==1.13.1
@@ -43,4 +43,5 @@ qqdm==0.0.7
wandb>=0.11.1,<0.13.4
ansible_vault>=2.1
substrate-interface==1.5.0
+jsonschema[format-nongpl]>=4.14.0,<=4.17.0
markupsafe==2.0.1