Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release/8.5.2 #2584

Merged
merged 33 commits into from
Jan 17, 2025
Merged
Changes from 19 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
6c9d6a5
Updates tests for btwallet 3.0.0
ibraheem-opentensor Dec 14, 2024
6818651
fix get_delegates result decoding
roman-opentensor Dec 17, 2024
7cede0c
Feat/use tx pool for set weights (#2534)
camfairchild Dec 17, 2024
6b7eac4
fix tests
roman-opentensor Dec 17, 2024
39bef5c
Merge branch 'staging' into fix-get-delegates-result-decoding
roman-opentensor Dec 17, 2024
935c81e
Merge pull request #2551 from opentensor/fix-get-delegates-result-dec…
roman-opentensor Dec 18, 2024
f33e45a
add connection limit error handler
roman-opentensor Dec 20, 2024
bd368df
add test
roman-opentensor Dec 20, 2024
ae89f09
Merge pull request #2553 from opentensor/feat/roman/hadle-the-maximun…
roman-opentensor Dec 20, 2024
4008488
Backmerge master to staging post 851 (#2557)
ibraheem-opentensor Dec 22, 2024
296f76f
improve handler
roman-opentensor Dec 23, 2024
f4d5ed6
Merge pull request #2558 from opentensor/feat/roman/improve-invalid-s…
roman-opentensor Dec 23, 2024
a8a6a0c
add async commit reveal impl
roman-opentensor Dec 24, 2024
0eec78f
add new logic to async_subtensor
roman-opentensor Dec 24, 2024
db32b21
add unit tests
roman-opentensor Dec 24, 2024
832aff3
ruff
roman-opentensor Dec 24, 2024
3497cd6
add uid check before processing
roman-opentensor Dec 24, 2024
71b0c28
fix test
roman-opentensor Dec 24, 2024
560bf29
Merge pull request #2560 from opentensor/feat/roman/add-async-commit_…
roman-opentensor Dec 24, 2024
7c32248
Merge branch 'staging' into tests/update-tests-btwallet3
roman-opentensor Jan 8, 2025
b3c0ab7
Use apt-get instead of apt for scripts (#2571)
camfairchild Jan 9, 2025
5a22780
fix _do_stake incorrect arguments error in staking.py
Assh-codes Jan 11, 2025
66cd437
Merge branch 'staging' into patch-2
thewhaleking Jan 13, 2025
b0ff5c2
Merge pull request #2574 from Assh-codes/patch-2
thewhaleking Jan 13, 2025
138dde5
Merge branch 'staging' into tests/update-tests-btwallet3
roman-opentensor Jan 14, 2025
508be9e
Updates subtensor branch for e2e
ibraheem-opentensor Jan 16, 2025
cd91cd8
tests fix
roman-opentensor Jan 17, 2025
ab07ec4
Bumps cr3 ffi
ibraheem-opentensor Jan 17, 2025
86f9b4d
Merge pull request #2540 from opentensor/tests/update-tests-btwallet3
ibraheem-opentensor Jan 17, 2025
92008e1
Merge branch 'staging' into bumps/ffi-crv3
ibraheem-opentensor Jan 17, 2025
10da20b
Merge pull request #2583 from opentensor/bumps/ffi-crv3
ibraheem-opentensor Jan 17, 2025
894035b
Bumps version and changelog
ibraheem-opentensor Jan 17, 2025
ac50f0a
Updates changelog
ibraheem-opentensor Jan 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## 8.5.1 /2024-12-16

## What's Changed
* 8.5.0 bugfixes by @thewhaleking in https://github.com/opentensor/bittensor/pull/2541
* Removes substrate call in format_error_message by @thewhaleking in https://github.com/opentensor/bittensor/pull/2542
* Remove torch from the weights calls by @thewhaleking in https://github.com/opentensor/bittensor/pull/2543
* optional arg fix by @thewhaleking in https://github.com/opentensor/bittensor/pull/2544
* async cr3 not implemented by @thewhaleking in https://github.com/opentensor/bittensor/pull/2545
* Backmerge master to staging 851 by @ibraheem-opentensor in https://github.com/opentensor/bittensor/pull/2546
* Adds retry in CRv3 by @ibraheem-opentensor in https://github.com/opentensor/bittensor/pull/2547

**Full Changelog**: https://github.com/opentensor/bittensor/compare/v8.5.0...v8.5.1

## 8.5.0 /2024-12-12

## What's Changed
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8.5.0
8.5.1
43 changes: 35 additions & 8 deletions bittensor/core/async_subtensor.py
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
SubnetHyperparameters,
decode_account_id,
)
from bittensor.core.extrinsics.async_commit_reveal import commit_reveal_v3_extrinsic
from bittensor.core.extrinsics.async_registration import register_extrinsic
from bittensor.core.extrinsics.async_root import (
set_root_weights_extrinsic,
@@ -1596,18 +1597,44 @@ async def set_weights(

This function is crucial in shaping the network's collective intelligence, where each neuron's learning and contribution are influenced by the weights it sets towards others【81†source】.
"""
retries = 0
success = False
if (
uid := await self.get_uid_for_hotkey_on_subnet(
wallet.hotkey.ss58_address, netuid
)
) is None:
return (
False,
f"Hotkey {wallet.hotkey.ss58_address} not registered in subnet {netuid}",
)

if (await self.commit_reveal_enabled(netuid=netuid)) is True:
# go with `commit reveal v3` extrinsic
raise NotImplementedError(
"Not implemented yet for AsyncSubtensor. Coming soon."
)
message = "No attempt made. Perhaps it is too soon to commit weights!"
while (
await self.blocks_since_last_update(netuid, uid)
> await self.weights_rate_limit(netuid)
and retries < max_retries
and success is False
):
logging.info(
f"Committing weights for subnet #{netuid}. Attempt {retries + 1} of {max_retries}."
)
success, message = await commit_reveal_v3_extrinsic(
subtensor=self,
wallet=wallet,
netuid=netuid,
uids=uids,
weights=weights,
version_key=version_key,
wait_for_inclusion=wait_for_inclusion,
wait_for_finalization=wait_for_finalization,
)
retries += 1
return success, message
else:
# go with classic `set weights extrinsic`
uid = await self.get_uid_for_hotkey_on_subnet(
wallet.hotkey.ss58_address, netuid
)
retries = 0
success = False
message = "No attempt made. Perhaps it is too soon to set weights!"
while (
retries < max_retries
152 changes: 152 additions & 0 deletions bittensor/core/extrinsics/async_commit_reveal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
from typing import Optional, Union, TYPE_CHECKING

import numpy as np
from bittensor_commit_reveal import get_encrypted_commit
from numpy.typing import NDArray

from bittensor.core.settings import version_as_int
from bittensor.utils import format_error_message
from bittensor.utils.btlogging import logging
from bittensor.utils.weight_utils import convert_weights_and_uids_for_emit

if TYPE_CHECKING:
from bittensor_wallet import Wallet
from bittensor.core.async_subtensor import AsyncSubtensor
from bittensor.utils.registration import torch


async def _do_commit_reveal_v3(
subtensor: "AsyncSubtensor",
wallet: "Wallet",
netuid: int,
commit: bytes,
reveal_round: int,
wait_for_inclusion: bool = False,
wait_for_finalization: bool = False,
) -> tuple[bool, Optional[str]]:
"""
Executes the commit-reveal phase 3 for a given netuid and commit, and optionally waits for extrinsic inclusion or finalization.

Arguments:
subtensor: An instance of the Subtensor class.
wallet: Wallet An instance of the Wallet class containing the user's keypair.
netuid: int The network unique identifier.
commit bytes The commit data in bytes format.
reveal_round: int The round number for the reveal phase.
wait_for_inclusion: bool, optional Flag indicating whether to wait for the extrinsic to be included in a block.
wait_for_finalization: bool, optional Flag indicating whether to wait for the extrinsic to be finalized.

Returns:
A tuple where the first element is a boolean indicating success or failure, and the second element is an optional string containing error message if any.
"""
logging.info(
f"Committing weights hash [blue]{commit.hex()}[/blue] for subnet #[blue]{netuid}[/blue] with "
f"reveal round [blue]{reveal_round}[/blue]..."
)

call = await subtensor.substrate.compose_call(
call_module="SubtensorModule",
call_function="commit_crv3_weights",
call_params={
"netuid": netuid,
"commit": commit,
"reveal_round": reveal_round,
},
)
extrinsic = await subtensor.substrate.create_signed_extrinsic(
call=call,
keypair=wallet.hotkey,
)

response = await subtensor.substrate.submit_extrinsic(
subtensor=subtensor,
extrinsic=extrinsic,
wait_for_inclusion=wait_for_inclusion,
wait_for_finalization=wait_for_finalization,
)

if not wait_for_finalization and not wait_for_inclusion:
return True, "Not waiting for finalization or inclusion."

if await response.is_success:
return True, None

return False, format_error_message(await response.error_message)


async def commit_reveal_v3_extrinsic(
subtensor: "AsyncSubtensor",
wallet: "Wallet",
netuid: int,
uids: Union[NDArray[np.int64], "torch.LongTensor", list],
weights: Union[NDArray[np.float32], "torch.FloatTensor", list],
version_key: int = version_as_int,
wait_for_inclusion: bool = False,
wait_for_finalization: bool = False,
) -> tuple[bool, str]:
"""
Commits and reveals weights for given subtensor and wallet with provided uids and weights.

Arguments:
subtensor: The Subtensor instance.
wallet: The wallet to use for committing and revealing.
netuid: The id of the network.
uids: The uids to commit.
weights: The weights associated with the uids.
version_key: The version key to use for committing and revealing. Default is version_as_int.
wait_for_inclusion: Whether to wait for the inclusion of the transaction. Default is False.
wait_for_finalization: Whether to wait for the finalization of the transaction. Default is False.

Returns:
tuple[bool, str]: A tuple where the first element is a boolean indicating success or failure, and the second element is a message associated with the result.
"""
try:
# Convert uids and weights
if isinstance(uids, list):
uids = np.array(uids, dtype=np.int64)
if isinstance(weights, list):
weights = np.array(weights, dtype=np.float32)

# Reformat and normalize.
uids, weights = convert_weights_and_uids_for_emit(uids, weights)

current_block = await subtensor.substrate.get_block_number(None)
subnet_hyperparameters = await subtensor.get_subnet_hyperparameters(netuid)
tempo = subnet_hyperparameters.tempo
subnet_reveal_period_epochs = (
subnet_hyperparameters.commit_reveal_weights_interval
)

# Encrypt `commit_hash` with t-lock and `get reveal_round`
commit_for_reveal, reveal_round = get_encrypted_commit(
uids=uids,
weights=weights,
version_key=version_key,
tempo=tempo,
current_block=current_block,
netuid=netuid,
subnet_reveal_period_epochs=subnet_reveal_period_epochs,
)

success, message = await _do_commit_reveal_v3(
subtensor=subtensor,
wallet=wallet,
netuid=netuid,
commit=commit_for_reveal,
reveal_round=reveal_round,
wait_for_inclusion=wait_for_inclusion,
wait_for_finalization=wait_for_finalization,
)

if success is not True:
logging.error(message)
return False, message

logging.success(
f"[green]Finalized![/green] Weights commited with reveal round [blue]{reveal_round}[/blue]."
)
return True, f"reveal_round:{reveal_round}"

except Exception as e:
logging.error(f":cross_mark: [red]Failed. Error:[/red] {e}")
return False, str(e)
12 changes: 12 additions & 0 deletions bittensor/core/extrinsics/async_weights.py
Original file line number Diff line number Diff line change
@@ -58,11 +58,17 @@ async def _do_set_weights(
"version_key": version_key,
},
)

next_nonce = await subtensor.substrate.get_account_next_index(
wallet.hotkey.ss58_address
)

# Period dictates how long the extrinsic will stay as part of waiting pool
extrinsic = await subtensor.substrate.create_signed_extrinsic(
call=call,
keypair=wallet.hotkey,
era={"period": 5},
nonce=next_nonce,
)
response = await subtensor.substrate.submit_extrinsic(
extrinsic,
@@ -180,9 +186,15 @@ async def _do_commit_weights(
"commit_hash": commit_hash,
},
)

next_nonce = await subtensor.substrate.get_account_next_index(
wallet.hotkey.ss58_address
)

extrinsic = await subtensor.substrate.create_signed_extrinsic(
call=call,
keypair=wallet.hotkey,
nonce=next_nonce,
)
response = await subtensor.substrate.submit_extrinsic(
substrate=subtensor.substrate,
2 changes: 2 additions & 0 deletions bittensor/core/extrinsics/commit_weights.py
Original file line number Diff line number Diff line change
@@ -66,9 +66,11 @@ def do_commit_weights(
"commit_hash": commit_hash,
},
)
next_nonce = self.get_account_next_index(wallet.hotkey.ss58_address)
extrinsic = self.substrate.create_signed_extrinsic(
call=call,
keypair=wallet.hotkey,
nonce=next_nonce,
)
response = submit_extrinsic(
subtensor=self,
2 changes: 2 additions & 0 deletions bittensor/core/extrinsics/set_weights.py
Original file line number Diff line number Diff line change
@@ -76,11 +76,13 @@ def do_set_weights(
"version_key": version_key,
},
)
next_nonce = self.get_account_next_index(wallet.hotkey.ss58_address)
# Period dictates how long the extrinsic will stay as part of waiting pool
extrinsic = self.substrate.create_signed_extrinsic(
call=call,
keypair=wallet.hotkey,
era={"period": period},
nonce=next_nonce,
)
response = submit_extrinsic(
self,
2 changes: 1 addition & 1 deletion bittensor/core/settings.py
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.

__version__ = "8.5.0"
__version__ = "8.5.1"

import os
import re
40 changes: 33 additions & 7 deletions bittensor/core/subtensor.py
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
from scalecodec.type_registry import load_type_registry_preset
from scalecodec.types import ScaleType
from substrateinterface.base import QueryMapResult, SubstrateInterface
from websockets.exceptions import InvalidStatus
from websockets.sync import client as ws_client

from bittensor.core import settings
@@ -233,6 +234,7 @@ def _get_substrate(self, force: bool = False):
open_timeout=self._connection_timeout,
max_size=2**32,
)

self.substrate = SubstrateInterface(
ss58_format=settings.SS58_FORMAT,
use_remote_preset=True,
@@ -244,19 +246,27 @@ def _get_substrate(self, force: bool = False):
f"Connected to {self.network} network and {self.chain_endpoint}."
)

except (ConnectionRefusedError, ssl.SSLError) as error:
logging.error(
f"<red>Could not connect to</red> <blue>{self.network}</blue> <red>network with</red> <blue>{self.chain_endpoint}</blue> <red>chain endpoint.</red>",
except ConnectionRefusedError as error:
logging.critical(
f"[red]Could not connect to[/red] [blue]{self.network}[/blue] [red]network with[/red] [blue]{self.chain_endpoint}[/blue] [red]chain endpoint.[/red]",
)
raise ConnectionRefusedError(error.args)
except ssl.SSLError as e:

except ssl.SSLError as error:
logging.critical(
"SSL error occurred. To resolve this issue, run the following command in your terminal:"
)
logging.critical("[blue]sudo python -m bittensor certifi[/blue]")
raise RuntimeError(
"SSL configuration issue, please follow the instructions above."
) from e
) from error

except InvalidStatus as error:
logging.critical(
f"Error [red]'{error.response.reason_phrase}'[/red] with status code [red]{error.response.status_code}[/red]."
)
logging.debug(f"Server response is '{error.response}'.")
raise

@staticmethod
def config() -> "Config":
@@ -661,6 +671,16 @@ def query_module(
),
)

@networking.ensure_connected
def get_account_next_index(self, address: str) -> int:
"""
Returns the next nonce for an account, taking into account the transaction pool.
"""
if not self.substrate.supports_rpc_method("account_nextIndex"):
raise Exception("account_nextIndex not supported")

return self.substrate.rpc_request("account_nextIndex", [address])["result"]

# Common subtensor methods =========================================================================================
def metagraph(
self, netuid: int, lite: bool = True, block: Optional[int] = None
@@ -1764,7 +1784,7 @@ def get_delegates(self, block: Optional[int] = None) -> list[DelegateInfo]:
if not (result := json_body.get("result", None)):
return []

return DelegateInfo.list_from_vec_u8(result)
return DelegateInfo.list_from_vec_u8(bytes(result))

def is_hotkey_delegate(self, hotkey_ss58: str, block: Optional[int] = None) -> bool:
"""
@@ -1816,7 +1836,13 @@ def set_weights(
"""
retries = 0
success = False
uid = self.get_uid_for_hotkey_on_subnet(wallet.hotkey.ss58_address, netuid)
if (
uid := self.get_uid_for_hotkey_on_subnet(wallet.hotkey.ss58_address, netuid)
) is None:
return (
False,
f"Hotkey {wallet.hotkey.ss58_address} not registered in subnet {netuid}",
)

if self.commit_reveal_enabled(netuid=netuid) is True:
# go with `commit reveal v3` extrinsic
Loading
Oops, something went wrong.
Loading
Oops, something went wrong.