From ab3bad1f92acd423db6f480cef9fd3b631937cba Mon Sep 17 00:00:00 2001 From: ifrit98 Date: Wed, 23 Aug 2023 17:23:59 +0000 Subject: [PATCH 01/20] remove miniupnpc --- bittensor/extrinsics/serving.py | 29 +--------- bittensor/subtensor.py | 3 +- bittensor/utils/networking.py | 68 ----------------------- requirements/prod.txt | 1 - tests/unit_tests/test_subtensor.py | 2 - tests/unit_tests/utils/test_networking.py | 1 - 6 files changed, 2 insertions(+), 102 deletions(-) diff --git a/bittensor/extrinsics/serving.py b/bittensor/extrinsics/serving.py index 90806f7ff3..4bdfde7f76 100644 --- a/bittensor/extrinsics/serving.py +++ b/bittensor/extrinsics/serving.py @@ -143,7 +143,6 @@ def serve_axon_extrinsic( subtensor: "bittensor.subtensor", netuid: int, axon: "bittensor.Axon", - use_upnpc: bool = False, wait_for_inclusion: bool = False, wait_for_finalization: bool = True, prompt: bool = False, @@ -154,9 +153,6 @@ def serve_axon_extrinsic( The netuid being served on. axon (bittensor.Axon): Axon to serve. - use_upnpc (:type:bool, `optional`): - If true, the axon attempts port forward through your router before - subscribing. wait_for_inclusion (bool): If set, waits for the extrinsic to enter a block before returning true, or returns false if the extrinsic fails to enter the block within the timeout. @@ -172,30 +168,7 @@ def serve_axon_extrinsic( """ axon.wallet.hotkey axon.wallet.coldkeypub - - # ---- Setup UPNPC ---- - if use_upnpc: - if prompt: - if not Confirm.ask("Attempt port forwarding with upnpc?"): - return False - try: - external_port = net.upnpc_create_port_map(port=axon.port) - bittensor.__console__.print( - ":white_heavy_check_mark: [green]Forwarded port: {}[/green]".format( - axon.port - ) - ) - bittensor.logging.success( - prefix="Forwarded port", sufix="{}".format(axon.port) - ) - except net.UPNPCException as upnpc_exception: - raise RuntimeError( - "Failed to hole-punch with upnpc with exception {}".format( - upnpc_exception - ) - ) from upnpc_exception - else: - external_port = axon.external_port + external_port = axon.external_port # ---- Get external ip ---- if axon.external_ip == None: diff --git a/bittensor/subtensor.py b/bittensor/subtensor.py index 642d62dfbb..769e4b2b6f 100644 --- a/bittensor/subtensor.py +++ b/bittensor/subtensor.py @@ -707,13 +707,12 @@ def serve_axon( self, netuid: int, axon: "bittensor.Axon", - use_upnpc: bool = False, wait_for_inclusion: bool = False, wait_for_finalization: bool = True, prompt: bool = False, ) -> bool: return serve_axon_extrinsic( - self, netuid, axon, use_upnpc, wait_for_inclusion, wait_for_finalization + self, netuid, axon, wait_for_inclusion, wait_for_finalization ) def _do_serve_axon( diff --git a/bittensor/utils/networking.py b/bittensor/utils/networking.py index ab2e698f85..d8e1b79e9f 100644 --- a/bittensor/utils/networking.py +++ b/bittensor/utils/networking.py @@ -24,7 +24,6 @@ import json import netaddr import requests -import miniupnpc from loguru import logger @@ -156,73 +155,6 @@ def get_external_ip() -> str: raise ExternalIPNotFound -class UPNPCException(Exception): - """Raised when trying to perform a port mapping on your router.""" - - -def upnpc_create_port_map(port: int): - r"""Creates a upnpc port map on your router from passed external_port to local port. - - Args: - port (int, `required`): - The local machine port to map from your external port. - - Return: - external_port (int, `required`): - The external port mapped to the local port on your machine. - - Raises: - UPNPCException (Exception): - Raised if UPNPC port mapping fails, for instance, if upnpc is not enabled on your router. - """ - try: - upnp = miniupnpc.UPnP() - upnp.discoverdelay = 200 - logger.debug("UPNPC: Using UPnP to open a port on your router ...") - logger.debug("UPNPC: Discovering... delay={}ms", upnp.discoverdelay) - ndevices = upnp.discover() - upnp.selectigd() - logger.debug("UPNPC: " + str(ndevices) + " device(s) detected") - - ip = upnp.lanaddr - external_ip = upnp.externalipaddress() - - logger.debug("UPNPC: your local ip address: " + str(ip)) - logger.debug("UPNPC: your external ip address: " + str(external_ip)) - logger.debug( - "UPNPC: status = " - + str(upnp.statusinfo()) - + " connection type = " - + str(upnp.connectiontype()) - ) - - # find a free port for the redirection - external_port = port - rc = upnp.getspecificportmapping(external_port, "TCP") - while rc != None and external_port < 65536: - external_port += 1 - rc = upnp.getspecificportmapping(external_port, "TCP") - if rc != None: - raise UPNPCException("UPNPC: No available external ports for port mapping.") - - logger.info( - "UPNPC: trying to redirect remote: {}:{} => local: {}:{} over TCP", - external_ip, - external_port, - ip, - port, - ) - upnp.addportmapping( - external_port, "TCP", ip, port, "Bittensor: %u" % external_port, "" - ) - logger.info("UPNPC: Create Success") - - return external_port - - except Exception as e: - raise UPNPCException(e) from e - - def get_formatted_ws_endpoint_url(endpoint_url: str) -> str: """ Returns a formatted websocket endpoint url. diff --git a/requirements/prod.txt b/requirements/prod.txt index e0797f34a6..47970a6b35 100644 --- a/requirements/prod.txt +++ b/requirements/prod.txt @@ -7,7 +7,6 @@ fuzzywuzzy>=0.18.0 fastapi==0.99.1 httpx==0.24.1 loguru==0.7.0 -miniupnpc==2.0.2 munch==2.5.0 netaddr numpy diff --git a/tests/unit_tests/test_subtensor.py b/tests/unit_tests/test_subtensor.py index f9632d930b..cddedc9752 100644 --- a/tests/unit_tests/test_subtensor.py +++ b/tests/unit_tests/test_subtensor.py @@ -60,7 +60,6 @@ def test_serve_axon_with_external_ip_set(self): mock_subtensor.serve_axon( netuid=-1, axon=mock_axon_with_external_ip_set, - use_upnpc=False, ) mock_serve_axon.assert_called_once() @@ -115,7 +114,6 @@ def test_serve_axon_with_external_port_set(self): mock_subtensor.serve_axon( netuid=-1, axon=mock_axon_with_external_port_set, - use_upnpc=False, ) mock_serve_axon.assert_called_once() diff --git a/tests/unit_tests/utils/test_networking.py b/tests/unit_tests/utils/test_networking.py index a686a88b06..8e729a8594 100644 --- a/tests/unit_tests/utils/test_networking.py +++ b/tests/unit_tests/utils/test_networking.py @@ -5,7 +5,6 @@ import unittest.mock as mock from bittensor import utils from unittest.mock import MagicMock, PropertyMock -from bittensor.utils.networking import UPNPCException, upnpc_create_port_map # Test conversion functions for IPv4 From 2834cc314dc19e9175fe744552021d31a43fa1cb Mon Sep 17 00:00:00 2001 From: ifrit98 Date: Wed, 26 Jul 2023 17:19:58 +0000 Subject: [PATCH 02/20] add try/except and timeout to version checking with exception handles --- bittensor/utils/__init__.py | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/bittensor/utils/__init__.py b/bittensor/utils/__init__.py index 2f19761dab..0b659295c9 100644 --- a/bittensor/utils/__init__.py +++ b/bittensor/utils/__init__.py @@ -54,22 +54,20 @@ def unbiased_topk(values, k, dim=0, sorted=True, largest=True): return topk, permutation[indices] -def version_checking(): - response = requests.get(bittensor.__pipaddress__) - latest_version = response.json()["info"]["version"] - version_split = latest_version.split(".") - latest_version_as_int = ( - (100 * int(version_split[0])) - + (10 * int(version_split[1])) - + (1 * int(version_split[2])) - ) - - if latest_version_as_int > bittensor.__version_as_int__: - print( - "\u001b[33mBittensor Version: Current {}/Latest {}\nPlease update to the latest version at your earliest convenience\u001b[0m".format( - bittensor.__version__, latest_version - ) - ) +def version_checking( timeout : int = 15 ): + try: + response = requests.get(bittensor.__pipaddress__, timeout=timeout) + latest_version = response.json()['info']['version'] + version_split = latest_version.split(".") + latest_version_as_int = (100 * int(version_split[0])) + (10 * int(version_split[1])) + (1 * int(version_split[2])) + + if latest_version_as_int > bittensor.__version_as_int__: + print('\u001b[33mBittensor Version: Current {}/Latest {}\nPlease update to the latest version at your earliest convenience\u001b[0m'.format(bittensor.__version__,latest_version)) + + except requests.exceptions.Timeout: + bittensor.logging.error('Version check failed due to timeout') + except requests.exceptions.RequestException as e: + bittensor.logging.error(f'Version check failed due to request failure: {e}') def strtobool_with_default( From 57dfd32078f1c2e622baca8782786aa509e9bafc Mon Sep 17 00:00:00 2001 From: gitphantomman <140101294+gitphantomman@users.noreply.github.com> Date: Mon, 7 Aug 2023 08:11:09 -0700 Subject: [PATCH 03/20] update CONTRIBUTING.md and DEVELOPMENT_WORKFLOW.md (#1475) * update CONTRIBUTING.md and DEVELOPMENT_WORKFLOW.md * Update contrib/DEVELOPMENT_WORKFLOW.md Co-authored-by: philanthrope * move styles to style guide * update workflow doc based on comment * update contributing.md delete Architecture section * fix CODE_REVIEW_DOC dev_note link * Update contrib/CONTRIBUTING.md Great Co-authored-by: philanthrope * Update contrib/CONTRIBUTING.md Ditto: Co-authored-by: philanthrope --------- Co-authored-by: gitphantomman Co-authored-by: philanthrope --- contrib/CODE_REVIEW_DOCS.md | 71 +++++++++++++++++++++++++++++++++++++ contrib/CONTRIBUTING.md | 48 ++++++++++++++++++++++++- contrib/STYLE.md | 57 ++++++++++++++++++++++++++--- 3 files changed, 171 insertions(+), 5 deletions(-) create mode 100644 contrib/CODE_REVIEW_DOCS.md diff --git a/contrib/CODE_REVIEW_DOCS.md b/contrib/CODE_REVIEW_DOCS.md new file mode 100644 index 0000000000..d1f41c5fcd --- /dev/null +++ b/contrib/CODE_REVIEW_DOCS.md @@ -0,0 +1,71 @@ +# Code Review +### Conceptual Review + +A review can be a conceptual review, where the reviewer leaves a comment + * `Concept (N)ACK`, meaning "I do (not) agree with the general goal of this pull + request", + * `Approach (N)ACK`, meaning `Concept ACK`, but "I do (not) agree with the + approach of this change". + +A `NACK` needs to include a rationale why the change is not worthwhile. +NACKs without accompanying reasoning may be disregarded. +After conceptual agreement on the change, code review can be provided. A review +begins with `ACK BRANCH_COMMIT`, where `BRANCH_COMMIT` is the top of the PR +branch, followed by a description of how the reviewer did the review. The +following language is used within pull request comments: + + - "I have tested the code", involving change-specific manual testing in + addition to running the unit, functional, or fuzz tests, and in case it is + not obvious how the manual testing was done, it should be described; + - "I have not tested the code, but I have reviewed it and it looks + OK, I agree it can be merged"; + - A "nit" refers to a trivial, often non-blocking issue. +### Code Review +Project maintainers reserve the right to weigh the opinions of peer reviewers +using common sense judgement and may also weigh based on merit. Reviewers that +have demonstrated a deeper commitment and understanding of the project over time +or who have clear domain expertise may naturally have more weight, as one would +expect in all walks of life. + +Where a patch set affects consensus-critical code, the bar will be much +higher in terms of discussion and peer review requirements, keeping in mind that +mistakes could be very costly to the wider community. This includes refactoring +of consensus-critical code. + +Where a patch set proposes to change the Bittensor consensus, it must have been +discussed extensively on the mailing list and IRC, be accompanied by a widely +discussed BIP and have a generally widely perceived technical consensus of being +a worthwhile change based on the judgement of the maintainers. + +### Finding Reviewers + +As most reviewers are themselves developers with their own projects, the review +process can be quite lengthy, and some amount of patience is required. If you find +that you've been waiting for a pull request to be given attention for several +months, there may be a number of reasons for this, some of which you can do something +about: + + - It may be because of a feature freeze due to an upcoming release. During this time, + only bug fixes are taken into consideration. If your pull request is a new feature, + it will not be prioritized until after the release. Wait for the release. + - It may be because the changes you are suggesting do not appeal to people. Rather than + nits and critique, which require effort and means they care enough to spend time on your + contribution, thundering silence is a good sign of widespread (mild) dislike of a given change + (because people don't assume *others* won't actually like the proposal). Don't take + that personally, though! Instead, take another critical look at what you are suggesting + and see if it: changes too much, is too broad, doesn't adhere to the + [developer notes](DEVELOPMENT_WORKFLOW.md), is dangerous or insecure, is messily written, etc. + Identify and address any of the issues you find. Then ask e.g. on IRC if someone could give + their opinion on the concept itself. + - It may be because your code is too complex for all but a few people, and those people + may not have realized your pull request even exists. A great way to find people who + are qualified and care about the code you are touching is the + [Git Blame feature](https://docs.github.com/en/github/managing-files-in-a-repository/managing-files-on-github/tracking-changes-in-a-file). Simply + look up who last modified the code you are changing and see if you can find + them and give them a nudge. Don't be incessant about the nudging, though. + - Finally, if all else fails, ask on IRC or elsewhere for someone to give your pull request + a look. If you think you've been waiting for an unreasonably long time (say, + more than a month) for no particular reason (a few lines changed, etc.), + this is totally fine. Try to return the favor when someone else is asking + for feedback on their code, and the universe balances out. + - Remember that the best thing you can do while waiting is give review to others! \ No newline at end of file diff --git a/contrib/CONTRIBUTING.md b/contrib/CONTRIBUTING.md index cb04527a52..0a47469250 100644 --- a/contrib/CONTRIBUTING.md +++ b/contrib/CONTRIBUTING.md @@ -3,9 +3,11 @@ The following is a set of guidelines for contributing to Bittensor, which are hosted in the [Opentensor Organization](https://github.com/opentensor) on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. ## Table Of Contents - 1. [I don't want to read this whole thing, I just have a question!!!](#i-dont-want-to-read-this-whole-thing-i-just-have-a-question) 1. [What should I know before I get started?](#what-should-i-know-before-i-get-started) +1. [Getting Started](#getting-started) + 1. [Good First Issue Label](#good-first-issue-label) + 1. [Beginner and Help-wanted Issues Label](#beginner-and-help-wanted-issues-label) 1. [How Can I Contribute?](#how-can-i-contribute) 1. [Code Contribution General Guideline](#code-contribution-general-guidelines) 1. [Pull Request Philosophy](#pull-request-philosophy) @@ -14,6 +16,7 @@ The following is a set of guidelines for contributing to Bittensor, which are ho 1. [Addressing Feedback](#addressing-feedback) 1. [Squashing Commits](#squashing-commits) 1. [Refactoring](#refactoring) + 1. [Peer Review](#peer-review) 1. [Reporting Bugs](#reporting-bugs) 1. [Suggesting Features](#suggesting-enhancements) @@ -34,6 +37,34 @@ Additionally, note that the core implementation of Bittensor consists of two sep Supplemental, yet necessary repositories are [openvalidators](https://github.com/opentensor/validators) and [openminers](https://github.com/opentensor/miners) which contain Bittensor Validators and Miners (respectively) designed by the OpenTensor Foundation team and open-sourced for the community to use. +## Getting Started +New contributors are very welcome and needed. +Reviewing and testing is highly valued and the most effective way you can contribute as a new contributor. It also will teach you much more about the code and process than opening pull requests. + +Before you start contributing, familiarize yourself with the Bittensor Core build system and tests. Refer to the documentation in the repository on how to build Bittensor core and how to run the unit tests, functional tests. + +There are many open issues of varying difficulty waiting to be fixed. If you're looking for somewhere to start contributing, check out the [good first issue](https://github.com/opentensor/bittensor/labels/good%20first%20issue) list or changes that are up for grabs. Some of them might no longer be applicable. So if you are interested, but unsure, you might want to leave a comment on the issue first. +### Good First Issue Label +The purpose of the good first issue label is to highlight which issues are suitable for a new contributor without a deep understanding of the codebase. + +However, good first issues can be solved by anyone. If they remain unsolved for a longer time, a frequent contributor might address them. + +You do not need to request permission to start working on an issue. However, you are encouraged to leave a comment if you are planning to work on it. This will help other contributors monitor which issues are actively being addressed and is also an effective way to request assistance if and when you need it. +### Beginner and Help-wanted Issues Label +You can start by looking through these `beginner` and `help-wanted` issues: + +* [Beginner issues](https://github.com/opentensor/bittensor/labels/beginner) - issues which should only require a few lines of code, and a test or two. +* [Help wanted issues](https://github.com/opentensor/bittensor/labels/help%20wanted) - issues which should be a bit more involved than `beginner` issues. + + +## Communication Channels +Most communication about Bittensor development happens on Discord channel. +Here's the link of Discord community. +[Bittensor Discord](https://discord.com/channels/799672011265015819/799672011814862902) + +And also here. +[Bittensor Community Discord](https://discord.com/channels/1120750674595024897/1120799375703162950) + ## How Can I Contribute? @@ -183,6 +214,21 @@ Project maintainers aim for a quick turnaround on refactoring pull requests, so Pull requests that refactor the code should not be made by new contributors. It requires a certain level of experience to know where the code belongs to and to understand the full ramification (including rebase effort of open pull requests). Trivial pull requests or pull requests that refactor the code with no clear benefits may be immediately closed by the maintainers to reduce unnecessary workload on reviewing. +#### Peer Review + +Anyone may participate in peer review which is expressed by comments in the pull request. Typically reviewers will review the code for obvious errors, as well as test out the patch set and opine on the technical merits of the patch. Project maintainers take into account the peer review when determining if there is consensus to merge a pull request (remember that discussions may have taken place elsewhere, not just on GitHub). The following language is used within pull-request comments: + +- ACK means "I have tested the code and I agree it should be merged"; +- NACK means "I disagree this should be merged", and must be accompanied by sound technical justification. NACKs without accompanying reasoning may be disregarded; +- utACK means "I have not tested the code, but I have reviewed it and it looks OK, I agree it can be merged"; +- Concept ACK means "I agree in the general principle of this pull request"; +- Nit refers to trivial, often non-blocking issues. + +Reviewers should include the commit(s) they have reviewed in their comments. This can be done by copying the commit SHA1 hash. + +A pull request that changes consensus-critical code is considerably more involved than a pull request that adds a feature to the wallet, for example. Such patches must be reviewed and thoroughly tested by several reviewers who are knowledgeable about the changed subsystems. Where new features are proposed, it is helpful for reviewers to try out the patch set on a test network and indicate that they have done so in their review. Project maintainers will take this into consideration when merging changes. + +For a more detailed description of the review process, see the [Code Review Guidelines](CODE_REVIEW_DOCS.md). ### Reporting Bugs diff --git a/contrib/STYLE.md b/contrib/STYLE.md index daf2a68d32..b7ac755fc0 100644 --- a/contrib/STYLE.md +++ b/contrib/STYLE.md @@ -6,21 +6,58 @@ Most programming languages have well-established conventions as to what constitu # Table of Contents 1. [Code Style](#code-style) -2. [Git Commit Style](#git-commit-style) -3. [The Six Rules of a Great Commit](#the-six-rules-of-a-great-commit) +2. [Naming Conventions](#naming-conventions) +3. [Git Commit Style](#git-commit-style) +4. [The Six Rules of a Great Commit](#the-six-rules-of-a-great-commit) - [1. Atomic Commits](#1-atomic-commits) - [2. Separate Subject from Body with a Blank Line](#2-separate-subject-from-body-with-a-blank-line) - [3. Limit the Subject Line to 50 Characters](#3-limit-the-subject-line-to-50-characters) - [4. Use the Imperative Mood in the Subject Line](#4-use-the-imperative-mood-in-the-subject-line) - [5. Wrap the Body at 72 Characters](#5-wrap-the-body-at-72-characters) - [6. Use the Body to Explain What and Why vs. How](#6-use-the-body-to-explain-what-and-why-vs-how) -4. [Tools Worth Mentioning](#tools-worth-mentioning) +5. [Tools Worth Mentioning](#tools-worth-mentioning) - [Using `--fixup`](#using---fixup) - [Interactive Rebase](#interactive-rebase) -5. [Pull Request and Squashing Commits Caveats](#pull-request-and-squashing-commits-caveats) +6. [Pull Request and Squashing Commits Caveats](#pull-request-and-squashing-commits-caveats) ### Code style + +#### General Style +Python's official style guide is PEP 8, which provides conventions for writing code for the main Python distribution. Here are some key points: + +- `Indentation:` Use 4 spaces per indentation level. + +- `Line Length:` Limit all lines to a maximum of 79 characters. + +- `Blank Lines:` Surround top-level function and class definitions with two blank lines. Method definitions inside a class are surrounded by a single blank line. + +- `Imports:` Imports should usually be on separate lines and should be grouped in the following order: + + - Standard library imports. + - Related third party imports. + - Local application/library specific imports. +- `Whitespace:` Avoid extraneous whitespace in the following situations: + + - Immediately inside parentheses, brackets or braces. + - Immediately before a comma, semicolon, or colon. + - Immediately before the open parenthesis that starts the argument list of a function call. +- `Comments:` Comments should be complete sentences and should be used to clarify code and are not a substitute for poorly written code. + +#### For Python + +- `List Comprehensions:` Use list comprehensions for concise and readable creation of lists. + +- `Generators:` Use generators when dealing with large amounts of data to save memory. + +- `Context Managers:` Use context managers (with statement) for resource management. + +- `String Formatting:` Use f-strings for formatting strings in Python 3.6 and above. + +- `Error Handling:` Use exceptions for error handling whenever possible. + +#### More details + Use `black` to format your python code before commiting for consistency across such a large pool of contributors. Black's code [style](https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#code-style) ensures consistent and opinionated code formatting. It automatically formats your Python code according to the Black style guide, enhancing code readability and maintainability. Key Features of Black: @@ -31,6 +68,18 @@ Key Features of Black: Automation: Black automates the code formatting process, saving time and effort. It eliminates the need for manual formatting and reduces the likelihood of inconsistencies. +### Naming Conventions + +- `Classes:` Class names should normally use the CapWords Convention. +- `Functions and Variables:` Function names should be lowercase, with words separated by underscores as necessary to improve readability. Variable names follow the same convention as function names. + +- `Constants:` Constants are usually defined on a module level and written in all capital letters with underscores separating words. + +- `Non-public Methods and Instance Variables:` Use a single leading underscore (_). This is a weak "internal use" indicator. + +- `Strongly "private" methods and variables:` Use a double leading underscore (__). This triggers name mangling in Python. + + ### Git commit style Here’s a model Git commit message when contributing: From f3bde5e6aff88ea35b5772615fe109958a0b3327 Mon Sep 17 00:00:00 2001 From: philanthrope Date: Wed, 16 Aug 2023 16:19:21 -0400 Subject: [PATCH 04/20] add checks (#1484) * add checks * fix docker img * fix docker img2 --- .circleci/config.yml | 32 +++++++++++++++ scripts/check_compatibility.sh | 71 ++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100755 scripts/check_compatibility.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index 1448958556..e5a4066ae6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -41,6 +41,23 @@ jobs: . env/bin/activate python -m black --exclude '(env|venv|.eggs)' --check . + check_compatibility: + parameters: + python_version: + type: string + docker: + - image: cimg/python:3.10 + steps: + - checkout + - run: + name: Install dependencies + command: | + sudo apt-get update + sudo apt-get install -y jq curl + - run: + name: Check compatibility + command: ./scripts/check_compatibility.sh << parameters.python_version >> + build-and-test: resource_class: medium parallelism: 2 @@ -202,6 +219,21 @@ jobs: workflows: + compatibility_checks: + jobs: + - check_compatibility: + python_version: "3.8" + name: check-compatibility-3.8 + - check_compatibility: + python_version: "3.9" + name: check-compatibility-3.9 + - check_compatibility: + python_version: "3.10" + name: check-compatibility-3.10 + - check_compatibility: + python_version: "3.11" + name: check-compatibility-3.11 + pr-requirements: jobs: - black: diff --git a/scripts/check_compatibility.sh b/scripts/check_compatibility.sh new file mode 100755 index 0000000000..3a6cf47e4c --- /dev/null +++ b/scripts/check_compatibility.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +if [ -z "$1" ]; then + echo "Please provide a Python version as an argument." + exit 1 +fi + +python_version="$1" +all_passed=true + +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +check_compatibility() { + all_supported=0 + + while read -r requirement; do + package_name=$(echo "$requirement" | awk -F'[!=<>]' '{print $1}' | awk -F'[' '{print $1}') # Strip off brackets + echo -n "Checking $package_name... " + + url="https://pypi.org/pypi/$package_name/json" + response=$(curl -s $url) + status_code=$(curl -s -o /dev/null -w "%{http_code}" $url) + + if [ "$status_code" != "200" ]; then + echo -e "${RED}Information not available for $package_name. Failure.${NC}" + all_supported=1 + continue + fi + + classifiers=$(echo "$response" | jq -r '.info.classifiers[]') + requires_python=$(echo "$response" | jq -r '.info.requires_python') + + base_version="Programming Language :: Python :: ${python_version%%.*}" + specific_version="Programming Language :: Python :: $python_version" + + if echo "$classifiers" | grep -q "$specific_version" || echo "$classifiers" | grep -q "$base_version"; then + echo -e "${GREEN}Supported${NC}" + elif [ "$requires_python" != "null" ]; then + if echo "$requires_python" | grep -Eq "==$python_version|>=$python_version|<=$python_version"; then + echo -e "${GREEN}Supported${NC}" + else + echo -e "${RED}Not compatible with Python $python_version due to constraint $requires_python.${NC}" + all_supported=1 + fi + else + echo -e "${YELLOW}Warning: Specific version not listed, assuming compatibility${NC}" + fi + done < requirements/prod.txt + + return $all_supported +} + +echo "Checking compatibility for Python $python_version..." +check_compatibility +if [ $? -eq 0 ]; then + echo -e "${GREEN}All requirements are compatible with Python $python_version.${NC}" +else + echo -e "${RED}All requirements are NOT compatible with Python $python_version.${NC}" + all_passed=false +fi + +echo "" +if $all_passed; then + echo -e "${GREEN}All tests passed.${NC}" +else + echo -e "${RED}All tests did not pass.${NC}" + exit 1 +fi From d4cb89377d1612f0831bd3c254b418c4be3cd4c8 Mon Sep 17 00:00:00 2001 From: ifrit98 Date: Fri, 18 Aug 2023 13:53:22 +0000 Subject: [PATCH 05/20] only run check_requirements job when an actual requirement changes --- .circleci/config.yml | 3 +++ scripts/check_requirements_changes.sh | 10 ++++++++++ 2 files changed, 13 insertions(+) create mode 100644 scripts/check_requirements_changes.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index e5a4066ae6..e9576a307d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -49,6 +49,9 @@ jobs: - image: cimg/python:3.10 steps: - checkout + - run: + name: Check if requirements files have changed + command: ./scripts/check_requirements_changes.sh - run: name: Install dependencies command: | diff --git a/scripts/check_requirements_changes.sh b/scripts/check_requirements_changes.sh new file mode 100644 index 0000000000..11ec1359ae --- /dev/null +++ b/scripts/check_requirements_changes.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# Check if requirements files have changed in the last commit +if git diff --name-only HEAD~1 | grep -E 'requirements/prod.txt|requirements/dev.txt'; then + echo "Requirements files have changed. Running compatibility checks..." + exit 0 +else + echo "Requirements files have not changed. Skipping compatibility checks..." + exit 1 +fi From d3ef1827ece50208a197b58511962a0f8df878af Mon Sep 17 00:00:00 2001 From: ifrit98 Date: Fri, 18 Aug 2023 14:25:44 +0000 Subject: [PATCH 06/20] log bittensor pipaddress for version_checking --- bittensor/utils/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bittensor/utils/__init__.py b/bittensor/utils/__init__.py index 0b659295c9..95b4e6dc13 100644 --- a/bittensor/utils/__init__.py +++ b/bittensor/utils/__init__.py @@ -56,6 +56,7 @@ def unbiased_topk(values, k, dim=0, sorted=True, largest=True): def version_checking( timeout : int = 15 ): try: + bittensor.logging.info(f"Checking latest Bittensor version at: {bittensor.__pipaddress__}") response = requests.get(bittensor.__pipaddress__, timeout=timeout) latest_version = response.json()['info']['version'] version_split = latest_version.split(".") From a29a455e6fd0239634f42c94c28b3e85738ec499 Mon Sep 17 00:00:00 2001 From: ifrit98 Date: Fri, 18 Aug 2023 14:31:03 +0000 Subject: [PATCH 07/20] add newline --- contrib/CODE_REVIEW_DOCS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/CODE_REVIEW_DOCS.md b/contrib/CODE_REVIEW_DOCS.md index d1f41c5fcd..275319f160 100644 --- a/contrib/CODE_REVIEW_DOCS.md +++ b/contrib/CODE_REVIEW_DOCS.md @@ -20,6 +20,7 @@ following language is used within pull request comments: - "I have not tested the code, but I have reviewed it and it looks OK, I agree it can be merged"; - A "nit" refers to a trivial, often non-blocking issue. + ### Code Review Project maintainers reserve the right to weigh the opinions of peer reviewers using common sense judgement and may also weigh based on merit. Reviewers that From 5a9ede767c4f3b94c337c5e0aaf78dbae7ea4a80 Mon Sep 17 00:00:00 2001 From: ifrit98 Date: Fri, 18 Aug 2023 14:31:46 +0000 Subject: [PATCH 08/20] add newline to contrib --- contrib/CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/CONTRIBUTING.md b/contrib/CONTRIBUTING.md index 0a47469250..5ebbb7df22 100644 --- a/contrib/CONTRIBUTING.md +++ b/contrib/CONTRIBUTING.md @@ -50,6 +50,7 @@ The purpose of the good first issue label is to highlight which issues are suita However, good first issues can be solved by anyone. If they remain unsolved for a longer time, a frequent contributor might address them. You do not need to request permission to start working on an issue. However, you are encouraged to leave a comment if you are planning to work on it. This will help other contributors monitor which issues are actively being addressed and is also an effective way to request assistance if and when you need it. + ### Beginner and Help-wanted Issues Label You can start by looking through these `beginner` and `help-wanted` issues: From d612d2ba4c2ea8252c7cf2c70e193cb3d9810a7b Mon Sep 17 00:00:00 2001 From: ifrit98 Date: Fri, 18 Aug 2023 14:33:45 +0000 Subject: [PATCH 09/20] fix formatting to 1 newline --- contrib/CONTRIBUTING.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/contrib/CONTRIBUTING.md b/contrib/CONTRIBUTING.md index 5ebbb7df22..628c52614a 100644 --- a/contrib/CONTRIBUTING.md +++ b/contrib/CONTRIBUTING.md @@ -57,7 +57,6 @@ You can start by looking through these `beginner` and `help-wanted` issues: * [Beginner issues](https://github.com/opentensor/bittensor/labels/beginner) - issues which should only require a few lines of code, and a test or two. * [Help wanted issues](https://github.com/opentensor/bittensor/labels/help%20wanted) - issues which should be a bit more involved than `beginner` issues. - ## Communication Channels Most communication about Bittensor development happens on Discord channel. Here's the link of Discord community. @@ -66,7 +65,6 @@ Here's the link of Discord community. And also here. [Bittensor Community Discord](https://discord.com/channels/1120750674595024897/1120799375703162950) - ## How Can I Contribute? You can contribute to Bittensor in one of three main ways (as well as many others): @@ -97,7 +95,6 @@ Here is a high-level summary: If you're looking to contribute to Bittensor but unsure where to start, please join our community [discord](https://discord.gg/bittensor), a developer-friendly Bittensor town square. Start with [#development](https://discord.com/channels/799672011265015819/799678806159392768) and [#bounties](https://discord.com/channels/799672011265015819/1095684873810890883) to see what issues are currently posted. For a greater understanding of Bittensor's usage and development, check the [Bittensor Documentation](https://bittensor.com/docs). - #### Pull Request Philosophy Patchsets and enhancements should always be focused. A pull request could add a feature, fix a bug, or refactor code, but it should not contain a mixture of these. Please also avoid 'super' pull requests which attempt to do too much, are overly large, or overly complex as this makes review difficult. @@ -112,7 +109,6 @@ Specifically, pull requests must adhere to the following criteria: - If your changes are extensive, consider breaking your PR into smaller, related PRs. This makes your contributions easier to understand and review. - Be active in the discussion about your PR. Respond promptly to comments and questions to help reviewers understand your changes and speed up the acceptance process. - Generally, all pull requests must: - Have a clear use case, fix a demonstrable bug or serve the greater good of the project (e.g. refactoring for modularisation). @@ -126,7 +122,6 @@ Generally, all pull requests must: Please follow these steps to have your contribution considered by the maintainers: - *Before* creating the PR: 1. Read the [development workflow](./DEVELOPMENT_WORKFLOW.md) defined for this repository to understand our workflow. 2. Ensure your PR meets the criteria stated in the 'Pull Request Philosophy' section. @@ -178,7 +173,6 @@ Here is a quick summary: Remember, testing is crucial for maintaining code health, catching issues early, and facilitating the addition of new features or refactoring of existing code. - #### Addressing Feedback After submitting your pull request, expect comments and reviews from other contributors. You can add more commits to your pull request by committing them locally and pushing to your fork. From e96cc81d6d08da34b4f8ecae998471b7dbb8632c Mon Sep 17 00:00:00 2001 From: ifrit98 Date: Fri, 18 Aug 2023 14:45:03 +0000 Subject: [PATCH 10/20] add perms to checK-compat script --- scripts/check_requirements_changes.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/check_requirements_changes.sh diff --git a/scripts/check_requirements_changes.sh b/scripts/check_requirements_changes.sh old mode 100644 new mode 100755 From 68d0a09d2f98152ac1bdce03875c8d2d8cd8bcc2 Mon Sep 17 00:00:00 2001 From: ifrit98 Date: Fri, 18 Aug 2023 15:09:16 +0000 Subject: [PATCH 11/20] fix check_reqs ci --- .circleci/config.yml | 14 ++++++++------ scripts/check_requirements_changes.sh | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e9576a307d..e263d392ae 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -53,13 +53,15 @@ jobs: name: Check if requirements files have changed command: ./scripts/check_requirements_changes.sh - run: - name: Install dependencies + name: Install dependencies and Check compatibility command: | - sudo apt-get update - sudo apt-get install -y jq curl - - run: - name: Check compatibility - command: ./scripts/check_compatibility.sh << parameters.python_version >> + if [ "$REQUIREMENTS_CHANGED" == "true" ]; then + sudo apt-get update + sudo apt-get install -y jq curl + ./scripts/check_compatibility.sh << parameters.python_version >> + else + echo "Skipping compatibility checks..." + fi build-and-test: resource_class: medium diff --git a/scripts/check_requirements_changes.sh b/scripts/check_requirements_changes.sh index 11ec1359ae..5fcd27ea3f 100755 --- a/scripts/check_requirements_changes.sh +++ b/scripts/check_requirements_changes.sh @@ -3,8 +3,8 @@ # Check if requirements files have changed in the last commit if git diff --name-only HEAD~1 | grep -E 'requirements/prod.txt|requirements/dev.txt'; then echo "Requirements files have changed. Running compatibility checks..." - exit 0 + echo 'export REQUIREMENTS_CHANGED="true"' >> $BASH_ENV else echo "Requirements files have not changed. Skipping compatibility checks..." - exit 1 + echo 'export REQUIREMENTS_CHANGED="false"' >> $BASH_ENV fi From e51a545d6e240b6da8e7fe52d714552bb0ecfaa3 Mon Sep 17 00:00:00 2001 From: philanthrope Date: Fri, 18 Aug 2023 17:34:51 -0400 Subject: [PATCH 12/20] Update contrib/CODE_REVIEW_DOCS.md Co-authored-by: Cameron Fairchild --- contrib/CODE_REVIEW_DOCS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/CODE_REVIEW_DOCS.md b/contrib/CODE_REVIEW_DOCS.md index 275319f160..9909606a89 100644 --- a/contrib/CODE_REVIEW_DOCS.md +++ b/contrib/CODE_REVIEW_DOCS.md @@ -34,7 +34,7 @@ mistakes could be very costly to the wider community. This includes refactoring of consensus-critical code. Where a patch set proposes to change the Bittensor consensus, it must have been -discussed extensively on the mailing list and IRC, be accompanied by a widely +discussed extensively on the discord server and other channels, be accompanied by a widely discussed BIP and have a generally widely perceived technical consensus of being a worthwhile change based on the judgement of the maintainers. From 3b568736400a86d0ab6ab0c9815c8c5427cc8068 Mon Sep 17 00:00:00 2001 From: ifrit98 Date: Wed, 23 Aug 2023 18:37:21 +0000 Subject: [PATCH 13/20] manually add 69df50cf885616c7169e304d24ed18a931b98dd3 --- bittensor/commands/delegates.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/bittensor/commands/delegates.py b/bittensor/commands/delegates.py index 2d3ac648eb..49e2cf8deb 100644 --- a/bittensor/commands/delegates.py +++ b/bittensor/commands/delegates.py @@ -25,7 +25,6 @@ from rich.prompt import Confirm from rich.console import Text from tqdm import tqdm -from substrateinterface.exceptions import SubstrateRequestException from .utils import get_delegates_details, DelegatesDetails from . import defaults @@ -56,9 +55,8 @@ def show_delegates( """Pretty prints a table of delegates sorted by total stake.""" delegates.sort(key=lambda delegate: delegate.total_stake, reverse=True) prev_delegates_dict = {} - if prev_delegates is not None: - for prev_delegate in prev_delegates: - prev_delegates_dict[prev_delegate.hotkey_ss58] = prev_delegate + for prev_delegate in prev_delegates: + prev_delegates_dict[prev_delegate.hotkey_ss58] = prev_delegate registered_delegate_info: Optional[ Dict[str, DelegatesDetails] From 5d2889d949db1eb332591c97f8f7f3df8a2e34e4 Mon Sep 17 00:00:00 2001 From: ifrit98 Date: Wed, 23 Aug 2023 18:40:14 +0000 Subject: [PATCH 14/20] Revert "manually add 69df50cf885616c7169e304d24ed18a931b98dd3" This reverts commit 3b568736400a86d0ab6ab0c9815c8c5427cc8068. Was erroneous. --- bittensor/commands/delegates.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bittensor/commands/delegates.py b/bittensor/commands/delegates.py index 49e2cf8deb..2d3ac648eb 100644 --- a/bittensor/commands/delegates.py +++ b/bittensor/commands/delegates.py @@ -25,6 +25,7 @@ from rich.prompt import Confirm from rich.console import Text from tqdm import tqdm +from substrateinterface.exceptions import SubstrateRequestException from .utils import get_delegates_details, DelegatesDetails from . import defaults @@ -55,8 +56,9 @@ def show_delegates( """Pretty prints a table of delegates sorted by total stake.""" delegates.sort(key=lambda delegate: delegate.total_stake, reverse=True) prev_delegates_dict = {} - for prev_delegate in prev_delegates: - prev_delegates_dict[prev_delegate.hotkey_ss58] = prev_delegate + if prev_delegates is not None: + for prev_delegate in prev_delegates: + prev_delegates_dict[prev_delegate.hotkey_ss58] = prev_delegate registered_delegate_info: Optional[ Dict[str, DelegatesDetails] From 685f3c578815cce7353beec43c803b71dfdf9559 Mon Sep 17 00:00:00 2001 From: ifrit98 Date: Wed, 23 Aug 2023 23:40:43 +0000 Subject: [PATCH 15/20] remove compat check for dropped py3.8 --- .circleci/config.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index dff37c482f..4902222058 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -226,9 +226,6 @@ jobs: workflows: compatibility_checks: jobs: - - check_compatibility: - python_version: "3.8" - name: check-compatibility-3.8 - check_compatibility: python_version: "3.9" name: check-compatibility-3.9 From e7aa9860ccadabe3aae30fa6a6d379d6adac1b3b Mon Sep 17 00:00:00 2001 From: ifrit98 Date: Wed, 23 Aug 2023 23:41:20 +0000 Subject: [PATCH 16/20] run black --- bittensor/utils/__init__.py | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/bittensor/utils/__init__.py b/bittensor/utils/__init__.py index 95b4e6dc13..c0c99b7c6c 100644 --- a/bittensor/utils/__init__.py +++ b/bittensor/utils/__init__.py @@ -54,21 +54,31 @@ def unbiased_topk(values, k, dim=0, sorted=True, largest=True): return topk, permutation[indices] -def version_checking( timeout : int = 15 ): +def version_checking(timeout: int = 15): try: - bittensor.logging.info(f"Checking latest Bittensor version at: {bittensor.__pipaddress__}") + bittensor.logging.info( + f"Checking latest Bittensor version at: {bittensor.__pipaddress__}" + ) response = requests.get(bittensor.__pipaddress__, timeout=timeout) - latest_version = response.json()['info']['version'] + latest_version = response.json()["info"]["version"] version_split = latest_version.split(".") - latest_version_as_int = (100 * int(version_split[0])) + (10 * int(version_split[1])) + (1 * int(version_split[2])) + latest_version_as_int = ( + (100 * int(version_split[0])) + + (10 * int(version_split[1])) + + (1 * int(version_split[2])) + ) if latest_version_as_int > bittensor.__version_as_int__: - print('\u001b[33mBittensor Version: Current {}/Latest {}\nPlease update to the latest version at your earliest convenience\u001b[0m'.format(bittensor.__version__,latest_version)) - + print( + "\u001b[33mBittensor Version: Current {}/Latest {}\nPlease update to the latest version at your earliest convenience\u001b[0m".format( + bittensor.__version__, latest_version + ) + ) + except requests.exceptions.Timeout: - bittensor.logging.error('Version check failed due to timeout') + bittensor.logging.error("Version check failed due to timeout") except requests.exceptions.RequestException as e: - bittensor.logging.error(f'Version check failed due to request failure: {e}') + bittensor.logging.error(f"Version check failed due to request failure: {e}") def strtobool_with_default( From 49b43aef532dea25a61fe88d8f54c107158a693f Mon Sep 17 00:00:00 2001 From: ifrit98 Date: Wed, 23 Aug 2023 23:45:25 +0000 Subject: [PATCH 17/20] manual add of f267fb7f17ec9e9dcdbfc2bfac75952171a75236 --- bittensor/mock/subtensor_mock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor/mock/subtensor_mock.py b/bittensor/mock/subtensor_mock.py index 60235d5237..0e1b122f25 100644 --- a/bittensor/mock/subtensor_mock.py +++ b/bittensor/mock/subtensor_mock.py @@ -671,7 +671,7 @@ def query_constant( if state_at_block is not None: return SimpleNamespace(value=state_at_block) - return state_at_block # Can be None + return state_at_block["data"]["free"] # Can be None else: return None From c7de0b6c9261e71a15aa5bb23ca708c7d257e8be Mon Sep 17 00:00:00 2001 From: ifrit98 Date: Thu, 24 Aug 2023 00:17:47 +0000 Subject: [PATCH 18/20] faster overview manual add: be31c4921fc4a70e369008f53041ca20a33a96a1 --- bittensor/commands/overview.py | 73 ++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/bittensor/commands/overview.py b/bittensor/commands/overview.py index 27278349c6..70679ab8f8 100644 --- a/bittensor/commands/overview.py +++ b/bittensor/commands/overview.py @@ -18,11 +18,12 @@ import argparse import bittensor from tqdm import tqdm +from concurrent.futures import ProcessPoolExecutor from fuzzywuzzy import fuzz from rich.align import Align from rich.table import Table from rich.prompt import Prompt -from typing import List, Optional, Dict +from typing import List, Optional, Dict, Tuple from .utils import ( get_hotkey_wallets_for_wallet, get_coldkey_wallets_for_path, @@ -95,7 +96,7 @@ def run(cli): return # Pull neuron info for all keys. - neurons: Dict[str, List[bittensor.NeuronInfoLite, bittensor.wallet]] = {} + neurons: Dict[str, List[bittensor.NeuronInfoLite, str]] = {} block = subtensor.block netuids = subtensor.get_all_subnet_netuids() @@ -110,21 +111,32 @@ def run(cli): cli.config.subtensor.get("network", defaults.subtensor.network) ) ): - for netuid in tqdm(netuids_copy, desc="Checking each subnet"): - all_neurons: List[bittensor.NeuronInfoLite] = subtensor.neurons_lite( - netuid=netuid + hotkey_addr_to_wallet = { + hotkey.hotkey.ss58_address: hotkey for hotkey in all_hotkeys + } + all_hotkey_addresses = list(hotkey_addr_to_wallet.keys()) + + # Pull neuron info for all keys. + ## Max len(netuids) or 5 threads. + with ProcessPoolExecutor(max_workers=max(len(netuids), 5)) as executor: + results = executor.map( + OverviewCommand._get_neurons_for_netuid, + [(cli.config, netuid, all_hotkey_addresses) for netuid in netuids], ) - # Map the hotkeys to uids - hotkey_to_neurons = {n.hotkey: n.uid for n in all_neurons} - for hot_wallet in all_hotkeys: - uid = hotkey_to_neurons.get(hot_wallet.hotkey.ss58_address) - if uid is not None: - nn = all_neurons[uid] - neurons[str(netuid)].append((nn, hot_wallet)) - - if len(neurons[str(netuid)]) == 0: - # Remove netuid from overview if no neurons are found. - netuids.remove(netuid) + executor.shutdown(wait=True) # wait for all complete + + for result in results: + netuid, neurons_result, err_msg = result + if err_msg is not None: + console.print(err_msg) + + if len(neurons_result) == 0: + # Remove netuid from overview if no neurons are found. + netuids.remove(netuid) + del neurons[str(netuid)] + else: + # Add neurons to overview. + neurons[str(netuid)] = neurons_result # Setup outer table. grid = Table.grid(pad_edge=False) @@ -156,7 +168,8 @@ def run(cli): total_dividends = 0.0 total_emission = 0 - for nn, hotwallet in neurons[str(netuid)]: + for nn, hotwallet_addr in neurons[str(netuid)]: + hotwallet = hotkey_addr_to_wallet[hotwallet_addr] nn: bittensor.NeuronInfoLite uid = nn.uid active = nn.active @@ -373,6 +386,32 @@ def overview_sort_function(row): # Print the entire table/grid console.print(grid, width=cli.config.get("width", None)) + @staticmethod + def _get_neurons_for_netuid( + args_tuple: Tuple["bittensor.Config", int, List[str]] + ) -> Tuple[int, List[Tuple["bittensor.NeuronInfoLite", str]], Optional[str]]: + subtensor_config, netuid, hot_wallets = args_tuple + + result: List[Tuple["bittensor.NeuronInfoLite", str]] = [] + + try: + subtensor = bittensor.subtensor(config=subtensor_config) + + all_neurons: List["bittensor.NeuronInfoLite"] = subtensor.neurons_lite( + netuid=netuid + ) + # Map the hotkeys to uids + hotkey_to_neurons = {n.hotkey: n.uid for n in all_neurons} + for hot_wallet_addr in hot_wallets: + uid = hotkey_to_neurons.get(hot_wallet_addr) + if uid is not None: + nn = all_neurons[uid] + result.append((nn, hot_wallet_addr)) + except Exception as e: + return netuid, [], "Error: {}".format(e) + + return netuid, result, None + @staticmethod def add_args(parser: argparse.ArgumentParser): overview_parser = parser.add_parser( From 3234ba8b6702c46c221431bb08d70ccdd2220fae Mon Sep 17 00:00:00 2001 From: ifrit98 Date: Thu, 24 Aug 2023 00:18:24 +0000 Subject: [PATCH 19/20] remove duplicate weights --- bittensor/subtensor.py | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/bittensor/subtensor.py b/bittensor/subtensor.py index ffb04e46a1..980ec34bc6 100644 --- a/bittensor/subtensor.py +++ b/bittensor/subtensor.py @@ -2172,32 +2172,6 @@ def _do_nominate( else: raise NominationError(response.error_message) - def weights( - self, netuid: int, block: Optional[int] = None - ) -> List[Tuple[int, List[Tuple[int, int]]]]: - w_map = [] - w_map_encoded = self.query_map_subtensor( - name="Weights", block=block, params=[netuid] - ) - if w_map_encoded.records: - for uid, w in w_map_encoded: - w_map.append((uid.serialize(), w.serialize())) - - return w_map - - def bonds( - self, netuid: int, block: Optional[int] = None - ) -> List[Tuple[int, List[Tuple[int, int]]]]: - b_map = [] - b_map_encoded = self.query_map_subtensor( - name="Bonds", block=block, params=[netuid] - ) - if b_map_encoded.records: - for uid, b in b_map_encoded: - b_map.append((uid.serialize(), b.serialize())) - - return b_map - ################ #### Legacy #### ################ From e802a2ccaa25e1856e5a38c69d44ed333e7d4436 Mon Sep 17 00:00:00 2001 From: ifrit98 Date: Thu, 24 Aug 2023 19:59:27 +0000 Subject: [PATCH 20/20] run black --- bittensor/commands/overview.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bittensor/commands/overview.py b/bittensor/commands/overview.py index 70679ab8f8..db3a9000b0 100644 --- a/bittensor/commands/overview.py +++ b/bittensor/commands/overview.py @@ -112,8 +112,8 @@ def run(cli): ) ): hotkey_addr_to_wallet = { - hotkey.hotkey.ss58_address: hotkey for hotkey in all_hotkeys - } + hotkey.hotkey.ss58_address: hotkey for hotkey in all_hotkeys + } all_hotkey_addresses = list(hotkey_addr_to_wallet.keys()) # Pull neuron info for all keys.