bittensor 9.2.0__tar.gz → 9.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. {bittensor-9.2.0 → bittensor-9.3.0}/PKG-INFO +12 -12
  2. {bittensor-9.2.0 → bittensor-9.3.0}/README.md +1 -0
  3. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/__main__.py +3 -1
  4. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/async_subtensor.py +320 -9
  5. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/axon.py +3 -1
  6. bittensor-9.3.0/bittensor/core/chain_data/proposal_vote_data.py +27 -0
  7. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/utils.py +50 -1
  8. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/errors.py +94 -24
  9. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/asyncex/commit_reveal.py +3 -0
  10. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/asyncex/serving.py +4 -4
  11. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/asyncex/weights.py +1 -1
  12. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/commit_reveal.py +3 -0
  13. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/serving.py +4 -4
  14. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/set_weights.py +1 -1
  15. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/settings.py +1 -1
  16. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/subtensor.py +289 -6
  17. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/__init__.py +12 -0
  18. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/balance.py +84 -32
  19. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/easy_imports.py +8 -0
  20. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/registration/pow.py +26 -4
  21. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/version.py +26 -1
  22. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/weight_utils.py +48 -9
  23. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor.egg-info/PKG-INFO +12 -12
  24. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor.egg-info/requires.txt +11 -11
  25. {bittensor-9.2.0 → bittensor-9.3.0}/pyproject.toml +12 -12
  26. bittensor-9.2.0/bittensor/core/chain_data/proposal_vote_data.py +0 -22
  27. {bittensor-9.2.0 → bittensor-9.3.0}/LICENSE +0 -0
  28. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/__init__.py +0 -0
  29. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/__init__.py +0 -0
  30. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/__init__.py +0 -0
  31. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/axon_info.py +0 -0
  32. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/chain_identity.py +0 -0
  33. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/delegate_info.py +0 -0
  34. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/delegate_info_lite.py +0 -0
  35. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/dynamic_info.py +0 -0
  36. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/info_base.py +0 -0
  37. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/ip_info.py +0 -0
  38. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/metagraph_info.py +0 -0
  39. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/neuron_info.py +0 -0
  40. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/neuron_info_lite.py +0 -0
  41. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/prometheus_info.py +0 -0
  42. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/scheduled_coldkey_swap_info.py +0 -0
  43. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/stake_info.py +0 -0
  44. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/subnet_hyperparameters.py +0 -0
  45. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/subnet_identity.py +0 -0
  46. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/subnet_info.py +0 -0
  47. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/subnet_state.py +0 -0
  48. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/chain_data/weight_commit_info.py +0 -0
  49. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/config.py +0 -0
  50. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/dendrite.py +0 -0
  51. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/__init__.py +0 -0
  52. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/asyncex/__init__.py +0 -0
  53. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/asyncex/move_stake.py +0 -0
  54. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/asyncex/registration.py +0 -0
  55. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/asyncex/root.py +0 -0
  56. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/asyncex/staking.py +0 -0
  57. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/asyncex/take.py +0 -0
  58. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/asyncex/transfer.py +0 -0
  59. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/asyncex/unstaking.py +0 -0
  60. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/commit_weights.py +0 -0
  61. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/move_stake.py +0 -0
  62. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/registration.py +0 -0
  63. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/root.py +0 -0
  64. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/staking.py +0 -0
  65. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/take.py +0 -0
  66. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/transfer.py +0 -0
  67. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/unstaking.py +0 -0
  68. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/extrinsics/utils.py +0 -0
  69. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/metagraph.py +0 -0
  70. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/stream.py +0 -0
  71. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/synapse.py +0 -0
  72. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/tensor.py +0 -0
  73. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/threadpool.py +0 -0
  74. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/core/types.py +0 -0
  75. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/axon_utils.py +0 -0
  76. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/btlogging/__init__.py +0 -0
  77. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/btlogging/console.py +0 -0
  78. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/btlogging/defines.py +0 -0
  79. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/btlogging/format.py +0 -0
  80. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/btlogging/helpers.py +0 -0
  81. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/btlogging/loggingmachine.py +0 -0
  82. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/certifi.sh +0 -0
  83. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/formatting.py +0 -0
  84. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/mock/__init__.py +0 -0
  85. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/mock/subtensor_mock.py +0 -0
  86. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/networking.py +0 -0
  87. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/registration/__init__.py +0 -0
  88. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/registration/async_pow.py +0 -0
  89. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/registration/register_cuda.py +0 -0
  90. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/subnets.py +0 -0
  91. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/substrate_utils/__init__.py +0 -0
  92. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/substrate_utils/hasher.py +0 -0
  93. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor/utils/substrate_utils/storage.py +0 -0
  94. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor.egg-info/SOURCES.txt +0 -0
  95. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor.egg-info/dependency_links.txt +0 -0
  96. {bittensor-9.2.0 → bittensor-9.3.0}/bittensor.egg-info/top_level.txt +0 -0
  97. {bittensor-9.2.0 → bittensor-9.3.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bittensor
3
- Version: 9.2.0
3
+ Version: 9.3.0
4
4
  Summary: Bittensor
5
5
  Author: bittensor.com
6
6
  License: The MIT License (MIT)
@@ -33,23 +33,20 @@ Requires-Dist: fastapi~=0.110.1
33
33
  Requires-Dist: munch~=2.5.0
34
34
  Requires-Dist: numpy~=2.0.1
35
35
  Requires-Dist: msgpack-numpy-opentensor~=0.5.0
36
- Requires-Dist: nest_asyncio
37
- Requires-Dist: netaddr
36
+ Requires-Dist: nest_asyncio==1.6.0
37
+ Requires-Dist: netaddr==1.3.0
38
38
  Requires-Dist: packaging
39
39
  Requires-Dist: python-statemachine~=2.1
40
40
  Requires-Dist: pycryptodome<4.0.0,>=3.18.0
41
- Requires-Dist: pyyaml
42
- Requires-Dist: retry
43
- Requires-Dist: requests
44
- Requires-Dist: rich
41
+ Requires-Dist: pyyaml>=6.0
42
+ Requires-Dist: retry==0.9.2
43
+ Requires-Dist: requests<3.0,>=2.0.0
45
44
  Requires-Dist: pydantic<3,>=2.3
46
- Requires-Dist: python-Levenshtein
47
45
  Requires-Dist: scalecodec==1.2.11
48
46
  Requires-Dist: uvicorn
49
- Requires-Dist: websockets>=14.1
50
- Requires-Dist: bittensor-commit-reveal>=0.2.0
51
- Requires-Dist: bittensor-wallet>=3.0.4
52
- Requires-Dist: async-substrate-interface>=1.0.8
47
+ Requires-Dist: bittensor-commit-reveal>=0.3.1
48
+ Requires-Dist: bittensor-wallet>=3.0.8
49
+ Requires-Dist: async-substrate-interface>=1.1.0
53
50
  Provides-Extra: dev
54
51
  Requires-Dist: pytest==7.2.0; extra == "dev"
55
52
  Requires-Dist: pytest-asyncio==0.23.7; extra == "dev"
@@ -73,11 +70,14 @@ Requires-Dist: types-requests; extra == "dev"
73
70
  Requires-Dist: torch<2.6.0,>=1.13.1; extra == "dev"
74
71
  Provides-Extra: torch
75
72
  Requires-Dist: torch<2.6.0,>=1.13.1; extra == "torch"
73
+ Provides-Extra: cli
74
+ Requires-Dist: bittensor-cli>=9.0.2; extra == "cli"
76
75
 
77
76
  <div align="center">
78
77
 
79
78
  # **Bittensor SDK** <!-- omit in toc -->
80
79
  [![Discord Chat](https://img.shields.io/discord/308323056592486420.svg)](https://discord.gg/bittensor)
80
+ [![CodeQL](https://github.com/opentensor/bittensor/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/opentensor/bittensor/actions)
81
81
  [![PyPI version](https://badge.fury.io/py/bittensor.svg)](https://badge.fury.io/py/bittensor)
82
82
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
83
83
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  # **Bittensor SDK** <!-- omit in toc -->
4
4
  [![Discord Chat](https://img.shields.io/discord/308323056592486420.svg)](https://discord.gg/bittensor)
5
+ [![CodeQL](https://github.com/opentensor/bittensor/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/opentensor/bittensor/actions)
5
6
  [![PyPI version](https://badge.fury.io/py/bittensor.svg)](https://badge.fury.io/py/bittensor)
6
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
8
 
@@ -3,6 +3,7 @@ import subprocess
3
3
  import sys
4
4
 
5
5
  from bittensor import __version__
6
+ from bittensor.utils.version import check_latest_version_in_pypi
6
7
 
7
8
  if __name__ == "__main__":
8
9
  if len(sys.argv) > 1 and sys.argv[1] == "certifi":
@@ -18,4 +19,5 @@ if __name__ == "__main__":
18
19
  # Run the script
19
20
  subprocess.run([certifi_script], check=True)
20
21
  else:
21
- print(f"Bittensor SDK version: {__version__}")
22
+ print(f"Installed Bittensor SDK version: {__version__}")
23
+ check_latest_version_in_pypi()
@@ -1,7 +1,7 @@
1
1
  import asyncio
2
2
  import copy
3
- from datetime import datetime, timezone
4
3
  import ssl
4
+ from datetime import datetime, timezone
5
5
  from functools import partial
6
6
  from typing import Optional, Any, Union, Iterable, TYPE_CHECKING
7
7
 
@@ -9,6 +9,7 @@ import asyncstdlib as a
9
9
  import numpy as np
10
10
  import scalecodec
11
11
  from async_substrate_interface import AsyncSubstrateInterface
12
+ from bittensor_commit_reveal import get_encrypted_commitment
12
13
  from bittensor_wallet.utils import SS58_FORMAT
13
14
  from numpy.typing import NDArray
14
15
  from scalecodec import GenericCall
@@ -29,21 +30,25 @@ from bittensor.core.chain_data import (
29
30
  )
30
31
  from bittensor.core.chain_data.chain_identity import ChainIdentity
31
32
  from bittensor.core.chain_data.delegate_info import DelegatedInfo
32
- from bittensor.core.chain_data.utils import decode_metadata
33
+ from bittensor.core.chain_data.utils import (
34
+ decode_metadata,
35
+ decode_revealed_commitment,
36
+ decode_revealed_commitment_with_hotkey,
37
+ )
33
38
  from bittensor.core.config import Config
34
39
  from bittensor.core.errors import ChainError, SubstrateRequestException
35
40
  from bittensor.core.extrinsics.asyncex.commit_reveal import commit_reveal_v3_extrinsic
41
+ from bittensor.core.extrinsics.asyncex.move_stake import (
42
+ transfer_stake_extrinsic,
43
+ swap_stake_extrinsic,
44
+ move_stake_extrinsic,
45
+ )
36
46
  from bittensor.core.extrinsics.asyncex.registration import (
37
47
  burned_register_extrinsic,
38
48
  register_extrinsic,
39
49
  register_subnet_extrinsic,
40
50
  set_subnet_identity_extrinsic,
41
51
  )
42
- from bittensor.core.extrinsics.asyncex.move_stake import (
43
- transfer_stake_extrinsic,
44
- swap_stake_extrinsic,
45
- move_stake_extrinsic,
46
- )
47
52
  from bittensor.core.extrinsics.asyncex.root import (
48
53
  set_root_weights_extrinsic,
49
54
  root_register_extrinsic,
@@ -77,10 +82,13 @@ from bittensor.core.types import ParamWithTypes, SubtensorMixin
77
82
  from bittensor.utils import (
78
83
  Certificate,
79
84
  decode_hex_identity_dict,
85
+ float_to_u64,
80
86
  format_error_message,
87
+ is_valid_ss58_address,
81
88
  torch,
82
89
  u16_normalized_float,
83
90
  u64_normalized_float,
91
+ unlock_key,
84
92
  )
85
93
  from bittensor.utils.balance import (
86
94
  Balance,
@@ -934,6 +942,57 @@ class AsyncSubtensor(SubtensorMixin):
934
942
  except SubstrateRequestException as e:
935
943
  return False, [], format_error_message(e)
936
944
 
945
+ async def get_children_pending(
946
+ self,
947
+ hotkey: str,
948
+ netuid: int,
949
+ block: Optional[int] = None,
950
+ block_hash: Optional[str] = None,
951
+ reuse_block: bool = False,
952
+ ) -> tuple[
953
+ list[tuple[float, str]],
954
+ int,
955
+ ]:
956
+ """
957
+ This method retrieves the pending children of a given hotkey and netuid.
958
+ It queries the SubtensorModule's PendingChildKeys storage function.
959
+
960
+ Arguments:
961
+ hotkey (str): The hotkey value.
962
+ netuid (int): The netuid value.
963
+ block (Optional[int]): The block number for which the children are to be retrieved.
964
+ block_hash (Optional[str]): The hash of the block to retrieve the subnet unique identifiers from.
965
+ reuse_block (bool): Whether to reuse the last-used block hash.
966
+
967
+ Returns:
968
+ list[tuple[float, str]]: A list of children with their proportions.
969
+ int: The cool-down block number.
970
+ """
971
+
972
+ response = await self.substrate.query(
973
+ module="SubtensorModule",
974
+ storage_function="PendingChildKeys",
975
+ params=[netuid, hotkey],
976
+ block_hash=await self.determine_block_hash(
977
+ block,
978
+ block_hash,
979
+ reuse_block,
980
+ ),
981
+ reuse_block_hash=reuse_block,
982
+ )
983
+ children, cooldown = response.value
984
+
985
+ return (
986
+ [
987
+ (
988
+ u64_normalized_float(proportion),
989
+ decode_account_id(child[0]),
990
+ )
991
+ for proportion, child in children
992
+ ],
993
+ cooldown,
994
+ )
995
+
937
996
  async def get_commitment(
938
997
  self,
939
998
  netuid: int,
@@ -1006,6 +1065,115 @@ class AsyncSubtensor(SubtensorMixin):
1006
1065
  result[decode_account_id(id_[0])] = decode_metadata(value)
1007
1066
  return result
1008
1067
 
1068
+ async def get_revealed_commitment_by_hotkey(
1069
+ self,
1070
+ netuid: int,
1071
+ hotkey_ss58_address: Optional[str] = None,
1072
+ block: Optional[int] = None,
1073
+ block_hash: Optional[str] = None,
1074
+ reuse_block: bool = False,
1075
+ ) -> Optional[tuple[tuple[int, str], ...]]:
1076
+ """Returns hotkey related revealed commitment for a given netuid.
1077
+
1078
+ Arguments:
1079
+ netuid (int): The unique identifier of the subnetwork.
1080
+ block (Optional[int]): The block number to retrieve the commitment from. Default is ``None``.
1081
+ hotkey_ss58_address (str): The ss58 address of the committee member.
1082
+ block_hash (Optional[str]): The hash of the block to retrieve the subnet unique identifiers from.
1083
+ reuse_block (bool): Whether to reuse the last-used block hash.
1084
+
1085
+ Returns:
1086
+ result (tuple[int, str): A tuple of reveal block and commitment message.
1087
+ """
1088
+ if not is_valid_ss58_address(address=hotkey_ss58_address):
1089
+ raise ValueError(f"Invalid ss58 address {hotkey_ss58_address} provided.")
1090
+
1091
+ query = await self.query_module(
1092
+ module="Commitments",
1093
+ name="RevealedCommitments",
1094
+ params=[netuid, hotkey_ss58_address],
1095
+ block=block,
1096
+ block_hash=block_hash,
1097
+ reuse_block=reuse_block,
1098
+ )
1099
+ if query is None:
1100
+ return None
1101
+ return tuple(decode_revealed_commitment(pair) for pair in query)
1102
+
1103
+ async def get_revealed_commitment(
1104
+ self,
1105
+ netuid: int,
1106
+ uid: int,
1107
+ block: Optional[int] = None,
1108
+ ) -> Optional[tuple[tuple[int, str], ...]]:
1109
+ """Returns uid related revealed commitment for a given netuid.
1110
+
1111
+ Arguments:
1112
+ netuid (int): The unique identifier of the subnetwork.
1113
+ uid (int): The neuron uid to retrieve the commitment from.
1114
+ block (Optional[int]): The block number to retrieve the commitment from. Default is ``None``.
1115
+
1116
+ Returns:
1117
+ result (Optional[tuple[int, str]]: A tuple of reveal block and commitment message.
1118
+
1119
+ Example of result:
1120
+ ( (12, "Alice message 1"), (152, "Alice message 2") )
1121
+ ( (12, "Bob message 1"), (147, "Bob message 2") )
1122
+ """
1123
+ try:
1124
+ meta_info = await self.get_metagraph_info(netuid, block=block)
1125
+ if meta_info:
1126
+ hotkey_ss58_address = meta_info.hotkeys[uid]
1127
+ else:
1128
+ raise ValueError(f"Subnet with netuid {netuid} does not exist.")
1129
+ except IndexError:
1130
+ raise ValueError(f"Subnet {netuid} does not have a neuron with uid {uid}.")
1131
+
1132
+ return await self.get_revealed_commitment_by_hotkey(
1133
+ netuid=netuid, hotkey_ss58_address=hotkey_ss58_address, block=block
1134
+ )
1135
+
1136
+ async def get_all_revealed_commitments(
1137
+ self,
1138
+ netuid: int,
1139
+ block: Optional[int] = None,
1140
+ block_hash: Optional[str] = None,
1141
+ reuse_block: bool = False,
1142
+ ) -> dict[str, tuple[tuple[int, str], ...]]:
1143
+ """Returns all revealed commitments for a given netuid.
1144
+
1145
+ Arguments:
1146
+ netuid (int): The unique identifier of the subnetwork.
1147
+ block (Optional[int]): The block number to retrieve the commitment from. Default is ``None``.
1148
+ block_hash (Optional[str]): The hash of the block to retrieve the subnet unique identifiers from.
1149
+ reuse_block (bool): Whether to reuse the last-used block hash.
1150
+
1151
+ Returns:
1152
+ result (dict): A dictionary of all revealed commitments in view {ss58_address: (reveal block, commitment message)}.
1153
+
1154
+ Example of result:
1155
+ {
1156
+ "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY": ( (12, "Alice message 1"), (152, "Alice message 2") ),
1157
+ "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty": ( (12, "Bob message 1"), (147, "Bob message 2") ),
1158
+ }
1159
+ """
1160
+ query = await self.query_map(
1161
+ module="Commitments",
1162
+ name="RevealedCommitments",
1163
+ params=[netuid],
1164
+ block=block,
1165
+ block_hash=block_hash,
1166
+ reuse_block=reuse_block,
1167
+ )
1168
+
1169
+ result = {}
1170
+ async for pair in query:
1171
+ hotkey_ss58_address, commitment_message = (
1172
+ decode_revealed_commitment_with_hotkey(pair)
1173
+ )
1174
+ result[hotkey_ss58_address] = commitment_message
1175
+ return result
1176
+
1009
1177
  async def get_current_weight_commit_info(
1010
1178
  self,
1011
1179
  netuid: int,
@@ -1519,6 +1687,36 @@ class AsyncSubtensor(SubtensorMixin):
1519
1687
  reuse_block=reuse_block,
1520
1688
  )
1521
1689
 
1690
+ async def get_owned_hotkeys(
1691
+ self,
1692
+ coldkey_ss58: str,
1693
+ block: Optional[int] = None,
1694
+ block_hash: Optional[str] = None,
1695
+ reuse_block: bool = False,
1696
+ ) -> list[str]:
1697
+ """
1698
+ Retrieves all hotkeys owned by a specific coldkey address.
1699
+
1700
+ Args:
1701
+ coldkey_ss58 (str): The SS58 address of the coldkey to query.
1702
+ block (int): The blockchain block number for the query.
1703
+ block_hash (str): The hash of the blockchain block number for the query.
1704
+ reuse_block (bool): Whether to reuse the last-used blockchain block hash.
1705
+
1706
+ Returns:
1707
+ list[str]: A list of hotkey SS58 addresses owned by the coldkey.
1708
+ """
1709
+ block_hash = await self.determine_block_hash(block, block_hash, reuse_block)
1710
+ owned_hotkeys = await self.substrate.query(
1711
+ module="SubtensorModule",
1712
+ storage_function="OwnedHotkeys",
1713
+ params=[coldkey_ss58],
1714
+ block_hash=block_hash,
1715
+ reuse_block_hash=reuse_block,
1716
+ )
1717
+
1718
+ return [decode_account_id(hotkey[0]) for hotkey in owned_hotkeys or []]
1719
+
1522
1720
  async def get_stake(
1523
1721
  self,
1524
1722
  coldkey_ss58: str,
@@ -2020,10 +2218,11 @@ class AsyncSubtensor(SubtensorMixin):
2020
2218
  block_hash=block_hash,
2021
2219
  reuse_block_hash=reuse_block,
2022
2220
  )
2221
+
2023
2222
  if vote_data is None:
2024
2223
  return None
2025
- else:
2026
- return ProposalVoteData(vote_data)
2224
+
2225
+ return ProposalVoteData.from_dict(vote_data)
2027
2226
 
2028
2227
  async def get_uid_for_hotkey_on_subnet(
2029
2228
  self,
@@ -2566,6 +2765,46 @@ class AsyncSubtensor(SubtensorMixin):
2566
2765
  )
2567
2766
  return None if call is None else Balance.from_rao(int(call))
2568
2767
 
2768
+ async def set_reveal_commitment(
2769
+ self,
2770
+ wallet,
2771
+ netuid: int,
2772
+ data: str,
2773
+ blocks_until_reveal: int = 360,
2774
+ block_time: Union[int, float] = 12,
2775
+ ) -> tuple[bool, int]:
2776
+ """
2777
+ Commits arbitrary data to the Bittensor network by publishing metadata.
2778
+
2779
+ Arguments:
2780
+ wallet (bittensor_wallet.Wallet): The wallet associated with the neuron committing the data.
2781
+ netuid (int): The unique identifier of the subnetwork.
2782
+ data (str): The data to be committed to the network.
2783
+ blocks_until_reveal (int): The number of blocks from now after which the data will be revealed. Defaults to `360`.
2784
+ Then amount of blocks in one epoch.
2785
+ block_time (Union[int, float]): The number of seconds between each block. Defaults to `12`.
2786
+
2787
+ Returns:
2788
+ bool: `True` if the commitment was successful, `False` otherwise.
2789
+
2790
+ Note: A commitment can be set once per subnet epoch and is reset at the next epoch in the chain automatically.
2791
+ """
2792
+
2793
+ encrypted, reveal_round = get_encrypted_commitment(
2794
+ data, blocks_until_reveal, block_time
2795
+ )
2796
+
2797
+ # increase reveal_round in return + 1 because we want to fetch data from the chain after that round was revealed
2798
+ # and stored.
2799
+ data_ = {"encrypted": encrypted, "reveal_round": reveal_round}
2800
+ return await publish_metadata(
2801
+ subtensor=self,
2802
+ wallet=wallet,
2803
+ netuid=netuid,
2804
+ data_type=f"TimelockEncrypted",
2805
+ data=data_,
2806
+ ), reveal_round
2807
+
2569
2808
  async def subnet(
2570
2809
  self,
2571
2810
  netuid: int,
@@ -3380,6 +3619,75 @@ class AsyncSubtensor(SubtensorMixin):
3380
3619
  wait_for_inclusion=wait_for_inclusion,
3381
3620
  )
3382
3621
 
3622
+ async def set_children(
3623
+ self,
3624
+ wallet: "Wallet",
3625
+ hotkey: str,
3626
+ netuid: int,
3627
+ children: list[tuple[float, str]],
3628
+ wait_for_inclusion: bool = True,
3629
+ wait_for_finalization: bool = True,
3630
+ raise_error: bool = False,
3631
+ ) -> tuple[bool, str]:
3632
+ """
3633
+ Allows a coldkey to set children keys.
3634
+
3635
+ Arguments:
3636
+ wallet (bittensor_wallet.Wallet): bittensor wallet instance.
3637
+ hotkey (str): The ``SS58`` address of the neuron's hotkey.
3638
+ netuid (int): The netuid value.
3639
+ children (list[tuple[float, str]]): A list of children with their proportions.
3640
+ wait_for_inclusion (bool): Waits for the transaction to be included in a block.
3641
+ wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain.
3642
+ raise_error: Raises relevant exception rather than returning `False` if unsuccessful.
3643
+
3644
+ Returns:
3645
+ tuple[bool, str]: A tuple where the first element is a boolean indicating success or failure of the
3646
+ operation, and the second element is a message providing additional information.
3647
+
3648
+ Raises:
3649
+ DuplicateChild: There are duplicates in the list of children.
3650
+ InvalidChild: Child is the hotkey.
3651
+ NonAssociatedColdKey: The coldkey does not own the hotkey or the child is the same as the hotkey.
3652
+ NotEnoughStakeToSetChildkeys: Parent key doesn't have minimum own stake.
3653
+ ProportionOverflow: The sum of the proportions does exceed uint64.
3654
+ RegistrationNotPermittedOnRootSubnet: Attempting to register a child on the root network.
3655
+ SubNetworkDoesNotExist: Attempting to register to a non-existent network.
3656
+ TooManyChildren: Too many children in request.
3657
+ TxRateLimitExceeded: Hotkey hit the rate limit.
3658
+ bittensor_wallet.errors.KeyFileError: Failed to decode keyfile data.
3659
+ bittensor_wallet.errors.PasswordError: Decryption failed or wrong password for decryption provided.
3660
+ """
3661
+
3662
+ unlock = unlock_key(wallet, raise_error=raise_error)
3663
+
3664
+ if not unlock.success:
3665
+ return False, unlock.message
3666
+
3667
+ call = await self.substrate.compose_call(
3668
+ call_module="SubtensorModule",
3669
+ call_function="set_children",
3670
+ call_params={
3671
+ "children": [
3672
+ (
3673
+ float_to_u64(proportion),
3674
+ child_hotkey,
3675
+ )
3676
+ for proportion, child_hotkey in children
3677
+ ],
3678
+ "hotkey": hotkey,
3679
+ "netuid": netuid,
3680
+ },
3681
+ )
3682
+
3683
+ return await self.sign_and_send_extrinsic(
3684
+ call,
3685
+ wallet,
3686
+ wait_for_inclusion,
3687
+ wait_for_finalization,
3688
+ raise_error=raise_error,
3689
+ )
3690
+
3383
3691
  async def set_delegate_take(
3384
3692
  self,
3385
3693
  wallet: "Wallet",
@@ -3504,6 +3812,7 @@ class AsyncSubtensor(SubtensorMixin):
3504
3812
  wait_for_inclusion: bool = False,
3505
3813
  wait_for_finalization: bool = False,
3506
3814
  max_retries: int = 5,
3815
+ block_time: float = 12.0,
3507
3816
  ):
3508
3817
  """
3509
3818
  Sets the inter-neuronal weights for the specified neuron. This process involves specifying the influence or
@@ -3523,6 +3832,7 @@ class AsyncSubtensor(SubtensorMixin):
3523
3832
  wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is
3524
3833
  ``False``.
3525
3834
  max_retries (int): The number of maximum attempts to set weights. Default is ``5``.
3835
+ block_time (float): The amount of seconds for block duration. Default is 12.0 seconds.
3526
3836
 
3527
3837
  Returns:
3528
3838
  tuple[bool, str]: ``True`` if the setting of weights is successful, False otherwise. And `msg`, a string
@@ -3571,6 +3881,7 @@ class AsyncSubtensor(SubtensorMixin):
3571
3881
  version_key=version_key,
3572
3882
  wait_for_inclusion=wait_for_inclusion,
3573
3883
  wait_for_finalization=wait_for_finalization,
3884
+ block_time=block_time,
3574
3885
  )
3575
3886
  retries += 1
3576
3887
  return success, message
@@ -976,7 +976,9 @@ class Axon:
976
976
  ):
977
977
  raise Exception("Nonce is too old, a newer one was last processed")
978
978
 
979
- if not keypair.verify(message, synapse.dendrite.signature):
979
+ if synapse.dendrite.signature and not keypair.verify(
980
+ message, synapse.dendrite.signature
981
+ ):
980
982
  raise Exception(
981
983
  f"Signature mismatch with {message} and {synapse.dendrite.signature}"
982
984
  )
@@ -0,0 +1,27 @@
1
+ from dataclasses import dataclass
2
+
3
+ from bittensor.core.chain_data.info_base import InfoBase
4
+ from bittensor.core.chain_data.utils import decode_account_id
5
+
6
+
7
+ @dataclass
8
+ class ProposalVoteData(InfoBase):
9
+ """
10
+ Senate / Proposal data
11
+ """
12
+
13
+ index: int
14
+ threshold: int
15
+ ayes: list[str]
16
+ nays: list[str]
17
+ end: int
18
+
19
+ @classmethod
20
+ def from_dict(cls, proposal_dict: dict) -> "ProposalVoteData":
21
+ return cls(
22
+ ayes=[decode_account_id(key) for key in proposal_dict["ayes"]],
23
+ end=proposal_dict["end"],
24
+ index=proposal_dict["index"],
25
+ nays=[decode_account_id(key) for key in proposal_dict["nays"]],
26
+ threshold=proposal_dict["threshold"],
27
+ )
@@ -1,7 +1,7 @@
1
1
  """Chain data helper functions and data."""
2
2
 
3
3
  from enum import Enum
4
- from typing import Optional, Union
4
+ from typing import Optional, Union, TYPE_CHECKING
5
5
 
6
6
  from scalecodec.base import RuntimeConfiguration, ScaleBytes
7
7
  from scalecodec.type_registry import load_type_registry_preset
@@ -10,6 +10,9 @@ from scalecodec.utils.ss58 import ss58_encode
10
10
  from bittensor.core.settings import SS58_FORMAT
11
11
  from bittensor.utils.balance import Balance
12
12
 
13
+ if TYPE_CHECKING:
14
+ from async_substrate_interface.sync_substrate import QueryMapResult
15
+
13
16
 
14
17
  class ChainDataType(Enum):
15
18
  NeuronInfo = 1
@@ -135,3 +138,49 @@ def decode_metadata(metadata: dict) -> str:
135
138
  commitment = metadata["info"]["fields"][0][0]
136
139
  bytes_tuple = commitment[next(iter(commitment.keys()))][0]
137
140
  return bytes(bytes_tuple).decode()
141
+
142
+
143
+ def decode_revealed_commitment(encoded_data) -> tuple[int, str]:
144
+ """
145
+ Decode the revealed commitment data from the given input if it is not None.
146
+
147
+ Arguments:
148
+ encoded_data (tuple[bytes, int]): A tuple containing the revealed message and the block number.
149
+
150
+ Returns:
151
+ tuple[int, str]: A tuple containing the revealed block number and decoded commitment message.
152
+ """
153
+
154
+ def scale_decode_offset(data: bytes) -> int:
155
+ """Decodes the scale offset from a given byte data sequence."""
156
+ first_byte = data[0]
157
+ mode = first_byte & 0b11
158
+ if mode == 0:
159
+ return 1
160
+ elif mode == 1:
161
+ return 2
162
+ else:
163
+ return 4
164
+
165
+ com_bytes, revealed_block = encoded_data
166
+ offset = scale_decode_offset(com_bytes)
167
+
168
+ revealed_commitment = bytes(com_bytes[offset:]).decode("utf-8", errors="ignore")
169
+ return revealed_block, revealed_commitment
170
+
171
+
172
+ def decode_revealed_commitment_with_hotkey(
173
+ encoded_data: "QueryMapResult",
174
+ ) -> tuple[str, tuple[tuple[int, str], ...]]:
175
+ """
176
+ Decode revealed commitment using a hotkey.
177
+
178
+ Returns:
179
+ tuple[str, tuple[tuple[int, str], ...]]: A tuple containing the hotkey (ss58 address) and a tuple of block
180
+ numbers and their corresponding revealed commitments.
181
+ """
182
+ key, data = encoded_data
183
+
184
+ ss58_address = decode_account_id(next(iter(key)))
185
+ block_data = tuple(decode_revealed_commitment(p) for p in data.value)
186
+ return ss58_address, block_data