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
8
8
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
27
28
decode_account_id ,
28
29
DynamicInfo ,
29
30
)
30
- from bittensor_commit_reveal import get_encrypted_commitment
31
31
from bittensor .core .chain_data .chain_identity import ChainIdentity
32
32
from bittensor .core .chain_data .delegate_info import DelegatedInfo
33
33
from bittensor .core .chain_data .utils import (
38
38
from bittensor .core .config import Config
39
39
from bittensor .core .errors import ChainError , SubstrateRequestException
40
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
+ )
41
46
from bittensor .core .extrinsics .asyncex .registration import (
42
47
burned_register_extrinsic ,
43
48
register_extrinsic ,
44
49
register_subnet_extrinsic ,
45
50
set_subnet_identity_extrinsic ,
46
51
)
47
- from bittensor .core .extrinsics .asyncex .move_stake import (
48
- transfer_stake_extrinsic ,
49
- swap_stake_extrinsic ,
50
- move_stake_extrinsic ,
51
- )
52
52
from bittensor .core .extrinsics .asyncex .root import (
53
53
set_root_weights_extrinsic ,
54
54
root_register_extrinsic ,
84
84
decode_hex_identity_dict ,
85
85
float_to_u64 ,
86
86
format_error_message ,
87
+ is_valid_ss58_address ,
87
88
torch ,
88
89
u16_normalized_float ,
89
90
u64_normalized_float ,
@@ -1064,14 +1065,14 @@ async def get_all_commitments(
1064
1065
result [decode_account_id (id_ [0 ])] = decode_metadata (value )
1065
1066
return result
1066
1067
1067
- async def get_revealed_commitment (
1068
+ async def get_revealed_commitment_by_hotkey (
1068
1069
self ,
1069
1070
netuid : int ,
1070
1071
hotkey_ss58_address : Optional [str ] = None ,
1071
1072
block : Optional [int ] = None ,
1072
1073
block_hash : Optional [str ] = None ,
1073
1074
reuse_block : bool = False ,
1074
- ) -> Optional [tuple [int , str ]]:
1075
+ ) -> Optional [tuple [tuple [ int , str ], ... ]]:
1075
1076
"""Returns hotkey related revealed commitment for a given netuid.
1076
1077
1077
1078
Arguments:
@@ -1084,6 +1085,9 @@ async def get_revealed_commitment(
1084
1085
Returns:
1085
1086
result (tuple[int, str): A tuple of reveal block and commitment message.
1086
1087
"""
1088
+ if not is_valid_ss58_address (address = hotkey_ss58_address ):
1089
+ raise ValueError (f"Invalid ss58 address { hotkey_ss58_address } provided." )
1090
+
1087
1091
query = await self .query_module (
1088
1092
module = "Commitments" ,
1089
1093
name = "RevealedCommitments" ,
@@ -1092,15 +1096,50 @@ async def get_revealed_commitment(
1092
1096
block_hash = block_hash ,
1093
1097
reuse_block = reuse_block ,
1094
1098
)
1095
- return decode_revealed_commitment (query )
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
+ )
1096
1135
1097
1136
async def get_all_revealed_commitments (
1098
1137
self ,
1099
1138
netuid : int ,
1100
1139
block : Optional [int ] = None ,
1101
1140
block_hash : Optional [str ] = None ,
1102
1141
reuse_block : bool = False ,
1103
- ) -> dict [str , tuple [int , str ]]:
1142
+ ) -> dict [str , tuple [tuple [ int , str ], ... ]]:
1104
1143
"""Returns all revealed commitments for a given netuid.
1105
1144
1106
1145
Arguments:
@@ -1111,6 +1150,12 @@ async def get_all_revealed_commitments(
1111
1150
1112
1151
Returns:
1113
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
+ }
1114
1159
"""
1115
1160
query = await self .query_map (
1116
1161
module = "Commitments" ,
@@ -1122,8 +1167,11 @@ async def get_all_revealed_commitments(
1122
1167
)
1123
1168
1124
1169
result = {}
1125
- async for item in query :
1126
- result .update (decode_revealed_commitment_with_hotkey (item ))
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
1127
1175
return result
1128
1176
1129
1177
async def get_current_weight_commit_info (
@@ -1639,6 +1687,38 @@ async def get_neuron_for_pubkey_and_subnet(
1639
1687
reuse_block = reuse_block ,
1640
1688
)
1641
1689
1690
+ async def get_next_epoch_start_block (
1691
+ self ,
1692
+ netuid : int ,
1693
+ block : Optional [int ] = None ,
1694
+ block_hash : Optional [str ] = None ,
1695
+ reuse_block : bool = False ,
1696
+ ) -> Optional [int ]:
1697
+ """
1698
+ Calculates the first block number of the next epoch for the given subnet.
1699
+
1700
+ If `block` is not provided, the current chain block will be used. Epochs are
1701
+ determined based on the subnet's tempo (i.e., blocks per epoch). The result
1702
+ is the block number at which the next epoch will begin.
1703
+
1704
+ Args:
1705
+ netuid (int): The unique identifier of the subnet.
1706
+ block (Optional[int], optional): The reference block to calculate from.
1707
+ If None, uses the current chain block height.
1708
+ block_hash (Optional[int]): The blockchain block number at which to perform the query.
1709
+ reuse_block (bool): Whether to reuse the last-used blockchain block hash.
1710
+
1711
+
1712
+ Returns:
1713
+ int: The block number at which the next epoch will start.
1714
+ """
1715
+ block_hash = await self .determine_block_hash (block , block_hash , reuse_block )
1716
+ if not block_hash and reuse_block :
1717
+ block_hash = self .substrate .last_block_hash
1718
+ block = await self .substrate .get_block_number (block_hash = block_hash )
1719
+ tempo = await self .tempo (netuid = netuid , block_hash = block_hash )
1720
+ return (((block // tempo ) + 1 ) * tempo ) + 1 if tempo else None
1721
+
1642
1722
async def get_owned_hotkeys (
1643
1723
self ,
1644
1724
coldkey_ss58 : str ,
@@ -3764,6 +3844,8 @@ async def set_weights(
3764
3844
wait_for_inclusion : bool = False ,
3765
3845
wait_for_finalization : bool = False ,
3766
3846
max_retries : int = 5 ,
3847
+ block_time : float = 12.0 ,
3848
+ period : int = 5 ,
3767
3849
):
3768
3850
"""
3769
3851
Sets the inter-neuronal weights for the specified neuron. This process involves specifying the influence or
@@ -3783,6 +3865,8 @@ async def set_weights(
3783
3865
wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain. Default is
3784
3866
``False``.
3785
3867
max_retries (int): The number of maximum attempts to set weights. Default is ``5``.
3868
+ block_time (float): The amount of seconds for block duration. Default is 12.0 seconds.
3869
+ period (int, optional): The period in seconds to wait for extrinsic inclusion or finalization. Defaults to 5.
3786
3870
3787
3871
Returns:
3788
3872
tuple[bool, str]: ``True`` if the setting of weights is successful, False otherwise. And `msg`, a string
@@ -3831,6 +3915,7 @@ async def _blocks_weight_limit() -> bool:
3831
3915
version_key = version_key ,
3832
3916
wait_for_inclusion = wait_for_inclusion ,
3833
3917
wait_for_finalization = wait_for_finalization ,
3918
+ block_time = block_time ,
3834
3919
)
3835
3920
retries += 1
3836
3921
return success , message
@@ -3856,6 +3941,7 @@ async def _blocks_weight_limit() -> bool:
3856
3941
version_key = version_key ,
3857
3942
wait_for_inclusion = wait_for_inclusion ,
3858
3943
wait_for_finalization = wait_for_finalization ,
3944
+ period = period ,
3859
3945
)
3860
3946
except Exception as e :
3861
3947
logging .error (f"Error setting weights: { e } " )
0 commit comments