From 6b66bcf8b695dc3a2738404068efec46d242a93f Mon Sep 17 00:00:00 2001 From: philanthrope Date: Tue, 17 Oct 2023 15:49:45 -0400 Subject: [PATCH] Release/6.1.0 (#1550) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ifrit98 * Fix typo (#1543) Co-authored-by: philanthrope * remove duplicated debug message in dendrite (#1544) * Cli fix (#1541) don't break on mismatched coldkey from local wallet <> chain * update faucet helpstr (#1542) * Added mechanism to sum all delegated tao (#1547) Co-authored-by: Ala Shaabana * Dict hash fix (#1548) * use dict() when hasing body objects to not convert arbitrary objects to str * recreate synapse in axon dependency to avoid duplicating code * black * update version * update changelog --------- Co-authored-by: Cameron Fairchild Co-authored-by: Eugene Co-authored-by: isabella618033 <49876827+isabella618033@users.noreply.github.com> Co-authored-by: Cameron Fairchild Co-authored-by: opentaco <93473497+opentaco@users.noreply.github.com> Co-authored-by: Eduardo García Co-authored-by: Ayden Brewer Co-authored-by: Steffen Cruz Co-authored-by: Ala Shaabana --- CHANGELOG.md | 29 ++++++++++++ VERSION | 2 +- bittensor/__init__.py | 2 +- bittensor/axon.py | 15 ++---- bittensor/cli.py | 1 + bittensor/commands/__init__.py | 7 ++- bittensor/commands/delegates.py | 3 ++ bittensor/commands/overview.py | 82 +++++++++++++++++---------------- bittensor/commands/register.py | 2 +- bittensor/commands/root.py | 59 ++++++++++++++++++++++++ bittensor/dendrite.py | 3 -- bittensor/extrinsics/network.py | 2 +- bittensor/synapse.py | 2 +- 13 files changed, 151 insertions(+), 58 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6091f356e6..83254fbd3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ # Changelog +## 6.1.0 / 2023-10-17 + +## What's Changed +* (un)Staking multiple avoid tx limit by @camfairchild in https://github.com/opentensor/bittensor/pull/1244 +* additional logging for prometheus by @Eugene-hu in https://github.com/opentensor/bittensor/pull/1246 +* Dataset fix by @isabella618033 in https://github.com/opentensor/bittensor/pull/1249 +* Grab delegates details from GitHub by @camfairchild in https://github.com/opentensor/bittensor/pull/1245 +* Add raw spec for local test and new bins by @camfairchild in https://github.com/opentensor/bittensor/pull/1243 +* Fix list_delegates on non-archive nodes by @camfairchild in https://github.com/opentensor/bittensor/pull/1232 +* Blacklist fixes + depreciation of old signatures by @Eugene-hu in https://github.com/opentensor/bittensor/pull/1240 +* [BIT-636] Change u16 weight normalization to max-upscaling by @opentaco in https://github.com/opentensor/bittensor/pull/1241 +* remove duplicate command #1228 by @camfairchild in https://github.com/opentensor/bittensor/pull/1231 +* test_forward_priority_2nd_request_timeout fix by @isabella618033 in https://github.com/opentensor/bittensor/pull/1276 +* Remove btcli query and btcli set_weights by @camfairchild in https://github.com/opentensor/bittensor/pull/1144 +* Merge releases 4.0.0 and 4.0.1 back to staging by @camfairchild in https://github.com/opentensor/bittensor/pull/1306 +* Improve development workflow documentation by @quac88 in https://github.com/opentensor/bittensor/pull/1262 +* staging updates and fixes by @ifrit98 in https://github.com/opentensor/bittensor/pull/1540 +* Add root get_weights command to btcli by @Rubberbandits in https://github.com/opentensor/bittensor/pull/1536 +* Fix typo by @steffencruz in https://github.com/opentensor/bittensor/pull/1543 +* remove duplicated debug message in dendrite by @ifrit98 in https://github.com/opentensor/bittensor/pull/1544 +* Cli fix by @ifrit98 in https://github.com/opentensor/bittensor/pull/1541 +* update faucet helpstr by @ifrit98 in https://github.com/opentensor/bittensor/pull/1542 +* Added mechanism to sum all delegated tao by @shibshib in https://github.com/opentensor/bittensor/pull/1547 +* Dict hash fix by @ifrit98 in https://github.com/opentensor/bittensor/pull/1548 + + +**Full Changelog**: https://github.com/opentensor/bittensor/compare/v6.0.1...v6.1.0 + + ## 6.0.1 / 2023-10-02 ## What's Changed diff --git a/VERSION b/VERSION index 5fe6072304..358e78e607 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.0.1 +6.1.0 \ No newline at end of file diff --git a/bittensor/__init__.py b/bittensor/__init__.py index c0342a6637..600e5e8797 100644 --- a/bittensor/__init__.py +++ b/bittensor/__init__.py @@ -27,7 +27,7 @@ nest_asyncio.apply() # Bittensor code and protocol version. -__version__ = "6.0.1" +__version__ = "6.1.0" version_split = __version__.split(".") __version_as_int__ = ( (100 * int(version_split[0])) diff --git a/bittensor/axon.py b/bittensor/axon.py index c9fc220a2f..8dbba96e93 100644 --- a/bittensor/axon.py +++ b/bittensor/axon.py @@ -526,16 +526,11 @@ async def some_endpoint(body_dict: dict = Depends(verify_body_integrity)): # Load the body dict and check if all required field hashes match body_dict = json.loads(request_body) - field_hashes = [] - for required_field in required_hash_fields: - # Hash the field in the body to compare against the header hashes - body_value = body_dict.get(required_field, None) - if body_value == None: - raise ValueError(f"Missing required field {required_field}") - field_hash = bittensor.utils.hash(str(body_value)) - field_hashes.append(field_hash) - - parsed_body_hash = bittensor.utils.hash("".join(field_hashes)) + + # Reconstruct the synapse object from the body dict and recompute the hash + syn = self.forward_class_types[request_name](**body_dict) + parsed_body_hash = syn.body_hash # Rehash the body from request + body_hash = request.headers.get("computed_body_hash", "") if parsed_body_hash != body_hash: raise ValueError( diff --git a/bittensor/cli.py b/bittensor/cli.py index 1d1ef56561..673fa31419 100644 --- a/bittensor/cli.py +++ b/bittensor/cli.py @@ -65,6 +65,7 @@ "commands": { "list": RootList, "weights": RootSetWeightsCommand, + "get_weights": RootGetWeightsCommand, "senate_vote": VoteCommand, "register": RootRegisterCommand, "proposals": ProposalsCommand, diff --git a/bittensor/commands/__init__.py b/bittensor/commands/__init__.py index f48d0bb3bf..b9e7721547 100644 --- a/bittensor/commands/__init__.py +++ b/bittensor/commands/__init__.py @@ -103,4 +103,9 @@ SubnetHyperparamsCommand, SubnetGetHyperparamsCommand, ) -from .root import RootRegisterCommand, RootList, RootSetWeightsCommand +from .root import ( + RootRegisterCommand, + RootList, + RootSetWeightsCommand, + RootGetWeightsCommand, +) diff --git a/bittensor/commands/delegates.py b/bittensor/commands/delegates.py index b622abf6fb..474d4d6fd6 100644 --- a/bittensor/commands/delegates.py +++ b/bittensor/commands/delegates.py @@ -526,6 +526,7 @@ def run(cli): table.add_column("[overline white]VPERMIT", justify="right", no_wrap=True) table.add_column("[overline white]24h/k\u03C4", style="green", justify="center") table.add_column("[overline white]Desc", style="rgb(50,163,219)") + total_delegated = 0 for wallet in tqdm(wallets): if not wallet.coldkeypub_file.exists_on_device(): @@ -544,6 +545,7 @@ def run(cli): my_delegates[delegate[0].hotkey_ss58] = staked delegates.sort(key=lambda delegate: delegate[0].total_stake, reverse=True) + total_delegated += sum(my_delegates.values()) registered_delegate_info: Optional[ DelegatesDetails @@ -602,6 +604,7 @@ def run(cli): ) bittensor.__console__.print(table) + bittensor.__console__.print("Total delegated Tao: {}".format(total_delegated)) @staticmethod def add_args(parser: argparse.ArgumentParser): diff --git a/bittensor/commands/overview.py b/bittensor/commands/overview.py index 877b4226fb..43e23552d2 100644 --- a/bittensor/commands/overview.py +++ b/bittensor/commands/overview.py @@ -160,11 +160,15 @@ def run(cli: "bittensor.cli"): total_coldkey_stake_from_metagraph = defaultdict( lambda: bittensor.Balance(0.0) ) + checked_hotkeys = set() for neuron_list in neurons.values(): for neuron in neuron_list: + if neuron.hotkey in checked_hotkeys: + continue total_coldkey_stake_from_metagraph[ neuron.coldkey ] += neuron.stake_dict[neuron.coldkey] + checked_hotkeys.add(neuron.hotkey) alerts_table = Table(show_header=True, header_style="bold magenta") alerts_table.add_column("🥩 alert!") @@ -209,40 +213,38 @@ def run(cli: "bittensor.cli"): ) executor.shutdown(wait=True) # wait for all complete - for result in results: - coldkey_wallet, de_registered_stake, err_msg = result - if err_msg is not None: - console.print(err_msg) + for result in results: + coldkey_wallet, de_registered_stake, err_msg = result + if err_msg is not None: + console.print(err_msg) + + if len(de_registered_stake) == 0: + continue # We have no de-registered stake with this coldkey. + + de_registered_neurons = [] + for hotkey_addr, our_stake in de_registered_stake: + # Make a neuron info lite for this hotkey and coldkey. + de_registered_neuron = bittensor.NeuronInfoLite._null_neuron() + de_registered_neuron.hotkey = hotkey_addr + de_registered_neuron.coldkey = ( + coldkey_wallet.coldkeypub.ss58_address + ) + de_registered_neuron.total_stake = bittensor.Balance(our_stake) - if len(de_registered_stake) == 0: - continue # We have no de-registered stake with this coldkey. - - de_registered_neurons = [] - for hotkey_addr, our_stake in de_registered_stake: - # Make a neuron info lite for this hotkey and coldkey. - de_registered_neuron = bittensor.NeuronInfoLite._null_neuron() - de_registered_neuron.hotkey = hotkey_addr - de_registered_neuron.coldkey = ( - coldkey_wallet.coldkeypub.ss58_address - ) - de_registered_neuron.total_stake = bittensor.Balance(our_stake) - - de_registered_neurons.append(de_registered_neuron) - - # Add this hotkey to the wallets dict - wallet_ = bittensor.Wallet( - name=wallet, - ) - wallet_.hotkey = hotkey_addr - wallet.hotkey_str = hotkey_addr[ - :5 - ] # Max length of 5 characters - hotkey_coldkey_to_hotkey_wallet[hotkey_addr][ - coldkey_wallet.coldkeypub.ss58_address - ] = wallet_ - - # Add neurons to overview. - neurons["-1"].extend(de_registered_neurons) + de_registered_neurons.append(de_registered_neuron) + + # Add this hotkey to the wallets dict + wallet_ = bittensor.Wallet( + name=wallet, + ) + wallet_.hotkey = hotkey_addr + wallet.hotkey_str = hotkey_addr[:5] # Max length of 5 characters + hotkey_coldkey_to_hotkey_wallet[hotkey_addr][ + coldkey_wallet.coldkeypub.ss58_address + ] = wallet_ + + # Add neurons to overview. + neurons["-1"].extend(de_registered_neurons) # Setup outer table. grid = Table.grid(pad_edge=False) @@ -279,7 +281,11 @@ def run(cli: "bittensor.cli"): total_emission = 0 for nn in neurons[str(netuid)]: - hotwallet = hotkey_coldkey_to_hotkey_wallet[nn.hotkey][nn.coldkey] + hotwallet = hotkey_coldkey_to_hotkey_wallet.get(nn.hotkey, {}).get( + nn.coldkey, None + ) + if not hotwallet: + continue nn: bittensor.NeuronInfoLite uid = nn.uid active = nn.active @@ -551,13 +557,11 @@ def _get_de_registered_stake_for_coldkey_wallet( ## Filter out hotkeys that are in our wallets ## Filter out hotkeys that are delegates. def _filter_stake_info(stake_info: "bittensor.StakeInfo") -> bool: - hotkey_addr, our_stake = stake_info - - if our_stake == 0: + if stake_info.stake == 0: return False # Skip hotkeys that we have no stake with. - if hotkey_addr in all_hotkey_addresses: + if stake_info.hotkey_ss58 in all_hotkey_addresses: return False # Skip hotkeys that are in our wallets. - if subtensor.is_hotkey_delegate(hotkey_ss58=hotkey_addr): + if subtensor.is_hotkey_delegate(hotkey_ss58=stake_info.hotkey_ss58): return False # Skip hotkeys that are delegates, they show up in btcli my_delegates table. return True diff --git a/bittensor/commands/register.py b/bittensor/commands/register.py index 834ab4e872..2fc615fd26 100644 --- a/bittensor/commands/register.py +++ b/bittensor/commands/register.py @@ -264,7 +264,7 @@ def run(cli): @staticmethod def add_args(parser: argparse.ArgumentParser): run_faucet_parser = parser.add_parser( - "faucet", help="""Register a wallet to a network.""" + "faucet", help="""Perform PoW to receieve test TAO in your wallet.""" ) run_faucet_parser.add_argument( "--register.num_processes", diff --git a/bittensor/commands/root.py b/bittensor/commands/root.py index 427e91e2b7..0886a032de 100644 --- a/bittensor/commands/root.py +++ b/bittensor/commands/root.py @@ -210,3 +210,62 @@ def check_config(config: "bittensor.config"): if not config.is_set("wallet.hotkey") and not config.no_prompt: hotkey = Prompt.ask("Enter hotkey name", default=defaults.wallet.hotkey) config.wallet.hotkey = str(hotkey) + + +class RootGetWeightsCommand: + @staticmethod + def run(cli): + r"""Get weights for root network.""" + subtensor = bittensor.subtensor(config=cli.config) + weights = subtensor.weights(0) + + table = Table(show_footer=False) + table.title = "[white]Root Network Weights" + table.add_column( + "[overline white]UID", + footer_style="overline white", + style="rgb(50,163,219)", + no_wrap=True, + ) + table.add_column( + "[overline white]NETUID", + footer_style="overline white", + justify="right", + style="green", + no_wrap=True, + ) + table.add_column( + "[overline white]WEIGHT", + footer_style="overline white", + justify="right", + style="green", + no_wrap=True, + ) + table.show_footer = True + + for matrix in weights: + uid = matrix[0] + for weight_data in matrix[1]: + table.add_row( + str(uid), + str(weight_data[0]), + "{:0.2f}%".format((weight_data[1] / 65535) * 100), + ) + + table.box = None + table.pad_edge = False + table.width = None + bittensor.__console__.print(table) + + @staticmethod + def add_args(parser: argparse.ArgumentParser): + parser = parser.add_parser( + "get_weights", help="""Get weights for root network.""" + ) + + bittensor.wallet.add_args(parser) + bittensor.subtensor.add_args(parser) + + @staticmethod + def check_config(config: "bittensor.config"): + pass diff --git a/bittensor/dendrite.py b/bittensor/dendrite.py index e831fa0d02..9e1cd0a5d9 100644 --- a/bittensor/dendrite.py +++ b/bittensor/dendrite.py @@ -271,9 +271,6 @@ async def call( # Set process time and log the response synapse.dendrite.process_time = str(time.time() - start_time) - bittensor.logging.debug( - f"dendrite | <-- | {synapse.get_total_size()} B | {synapse.name} | {synapse.axon.hotkey} | {synapse.axon.ip}:{str(synapse.axon.port)} | {synapse.axon.status_code} | {synapse.axon.status_message}" - ) except aiohttp.ClientConnectorError as e: synapse.dendrite.status_code = "503" diff --git a/bittensor/extrinsics/network.py b/bittensor/extrinsics/network.py index d2e8ac3455..04447e9f14 100644 --- a/bittensor/extrinsics/network.py +++ b/bittensor/extrinsics/network.py @@ -51,7 +51,7 @@ def register_subnetwork_extrinsic( burn_cost = bittensor.utils.balance.Balance(subtensor.get_subnet_burn_cost()) if burn_cost > your_balance: bittensor.__console__.print( - f"Your balance of: [green]{your_balance}[/green] is not enough to pay the subnet burn cost of: [green]{burn_cost}[/green]" + f"Your balance of: [green]{your_balance}[/green] is not enough to pay the subnet lock cost of: [green]{burn_cost}[/green]" ) return False diff --git a/bittensor/synapse.py b/bittensor/synapse.py index b9e3479e72..0cb3a118b9 100644 --- a/bittensor/synapse.py +++ b/bittensor/synapse.py @@ -513,7 +513,7 @@ def body_hash(self) -> str: hashes = [] # Getting the fields of the instance - instance_fields = self.__dict__ + instance_fields = self.dict() for field, value in instance_fields.items(): # If the field is required in the subclass schema, hash and add it.