Skip to content

Commit cb95522

Browse files
authored
Merge branch 'staging' into fix/roman/balance-unit
2 parents 4b08634 + f48125c commit cb95522

File tree

5 files changed

+188
-49
lines changed

5 files changed

+188
-49
lines changed

bittensor/core/async_subtensor.py

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import asyncio
22
import copy
3-
from datetime import datetime, timezone
43
import ssl
4+
from datetime import datetime, timezone
55
from functools import partial
66
from typing import Optional, Any, Union, Iterable, TYPE_CHECKING
77

88
import asyncstdlib as a
99
import numpy as np
1010
import scalecodec
1111
from async_substrate_interface import AsyncSubstrateInterface
12+
from bittensor_commit_reveal import get_encrypted_commitment
1213
from bittensor_wallet.utils import SS58_FORMAT
1314
from numpy.typing import NDArray
1415
from scalecodec import GenericCall
@@ -27,7 +28,6 @@
2728
decode_account_id,
2829
DynamicInfo,
2930
)
30-
from bittensor_commit_reveal import get_encrypted_commitment
3131
from bittensor.core.chain_data.chain_identity import ChainIdentity
3232
from bittensor.core.chain_data.delegate_info import DelegatedInfo
3333
from bittensor.core.chain_data.utils import (
@@ -38,17 +38,17 @@
3838
from bittensor.core.config import Config
3939
from bittensor.core.errors import ChainError, SubstrateRequestException
4040
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+
)
4146
from bittensor.core.extrinsics.asyncex.registration import (
4247
burned_register_extrinsic,
4348
register_extrinsic,
4449
register_subnet_extrinsic,
4550
set_subnet_identity_extrinsic,
4651
)
47-
from bittensor.core.extrinsics.asyncex.move_stake import (
48-
transfer_stake_extrinsic,
49-
swap_stake_extrinsic,
50-
move_stake_extrinsic,
51-
)
5252
from bittensor.core.extrinsics.asyncex.root import (
5353
set_root_weights_extrinsic,
5454
root_register_extrinsic,
@@ -84,6 +84,7 @@
8484
decode_hex_identity_dict,
8585
float_to_u64,
8686
format_error_message,
87+
is_valid_ss58_address,
8788
torch,
8889
u16_normalized_float,
8990
u64_normalized_float,
@@ -1064,14 +1065,14 @@ async def get_all_commitments(
10641065
result[decode_account_id(id_[0])] = decode_metadata(value)
10651066
return result
10661067

1067-
async def get_revealed_commitment(
1068+
async def get_revealed_commitment_by_hotkey(
10681069
self,
10691070
netuid: int,
10701071
hotkey_ss58_address: Optional[str] = None,
10711072
block: Optional[int] = None,
10721073
block_hash: Optional[str] = None,
10731074
reuse_block: bool = False,
1074-
) -> Optional[tuple[int, str]]:
1075+
) -> Optional[tuple[tuple[int, str], ...]]:
10751076
"""Returns hotkey related revealed commitment for a given netuid.
10761077
10771078
Arguments:
@@ -1084,6 +1085,9 @@ async def get_revealed_commitment(
10841085
Returns:
10851086
result (tuple[int, str): A tuple of reveal block and commitment message.
10861087
"""
1088+
if not is_valid_ss58_address(address=hotkey_ss58_address):
1089+
raise ValueError(f"Invalid ss58 address {hotkey_ss58_address} provided.")
1090+
10871091
query = await self.query_module(
10881092
module="Commitments",
10891093
name="RevealedCommitments",
@@ -1092,15 +1096,50 @@ async def get_revealed_commitment(
10921096
block_hash=block_hash,
10931097
reuse_block=reuse_block,
10941098
)
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+
)
10961135

10971136
async def get_all_revealed_commitments(
10981137
self,
10991138
netuid: int,
11001139
block: Optional[int] = None,
11011140
block_hash: Optional[str] = None,
11021141
reuse_block: bool = False,
1103-
) -> dict[str, tuple[int, str]]:
1142+
) -> dict[str, tuple[tuple[int, str], ...]]:
11041143
"""Returns all revealed commitments for a given netuid.
11051144
11061145
Arguments:
@@ -1111,6 +1150,12 @@ async def get_all_revealed_commitments(
11111150
11121151
Returns:
11131152
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+
}
11141159
"""
11151160
query = await self.query_map(
11161161
module="Commitments",
@@ -1122,8 +1167,11 @@ async def get_all_revealed_commitments(
11221167
)
11231168

11241169
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
11271175
return result
11281176

11291177
async def get_current_weight_commit_info(

bittensor/core/chain_data/utils.py

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from bittensor.utils.balance import Balance
1212

1313
if TYPE_CHECKING:
14-
from async_substrate_interface.types import ScaleObj
14+
from async_substrate_interface.sync_substrate import QueryMapResult
1515

1616

1717
class ChainDataType(Enum):
@@ -140,12 +140,16 @@ def decode_metadata(metadata: dict) -> str:
140140
return bytes(bytes_tuple).decode()
141141

142142

143-
def decode_revealed_commitment(
144-
value: Optional["ScaleObj"],
145-
) -> Optional[tuple[int, str]]:
146-
"""Decode the revealed commitment data from the given input if it is not None."""
147-
if value is None:
148-
return None
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+
"""
149153

150154
def scale_decode_offset(data: bytes) -> int:
151155
"""Decodes the scale offset from a given byte data sequence."""
@@ -158,16 +162,25 @@ def scale_decode_offset(data: bytes) -> int:
158162
else:
159163
return 4
160164

161-
v = next(iter(value))
162-
revealed_block = v[1]
163-
cut = scale_decode_offset(v[0])
165+
com_bytes, revealed_block = encoded_data
166+
offset = scale_decode_offset(com_bytes)
164167

165-
revealed_commitment = bytes(v[0][cut:]).decode("utf-8", errors="ignore")
168+
revealed_commitment = bytes(com_bytes[offset:]).decode("utf-8", errors="ignore")
166169
return revealed_block, revealed_commitment
167170

168171

169-
def decode_revealed_commitment_with_hotkey(data: list) -> dict[str, tuple[int, str]]:
170-
"""Decode revealed commitment using a hotkey."""
171-
key, value = data
172-
ss58_address = decode_account_id(key[0])
173-
return {ss58_address: decode_revealed_commitment(value)}
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

bittensor/core/subtensor.py

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
decode_hex_identity_dict,
8787
float_to_u64,
8888
format_error_message,
89+
is_valid_ss58_address,
8990
torch,
9091
u16_normalized_float,
9192
u64_normalized_float,
@@ -807,33 +808,71 @@ def get_all_commitments(
807808
result[decode_account_id(id_[0])] = decode_metadata(value)
808809
return result
809810

810-
def get_revealed_commitment(
811+
def get_revealed_commitment_by_hotkey(
811812
self,
812813
netuid: int,
813-
hotkey_ss58_address: Optional[str] = None,
814+
hotkey_ss58_address: str,
814815
block: Optional[int] = None,
815-
) -> Optional[tuple[int, str]]:
816+
) -> Optional[tuple[tuple[int, str], ...]]:
816817
"""Returns hotkey related revealed commitment for a given netuid.
817818
818819
Arguments:
819820
netuid (int): The unique identifier of the subnetwork.
820-
block (Optional[int]): The block number to retrieve the commitment from. Default is ``None``.
821821
hotkey_ss58_address (str): The ss58 address of the committee member.
822+
block (Optional[int]): The block number to retrieve the commitment from. Default is ``None``.
822823
823824
Returns:
824825
result (tuple[int, str): A tuple of reveal block and commitment message.
825826
"""
827+
if not is_valid_ss58_address(address=hotkey_ss58_address):
828+
raise ValueError(f"Invalid ss58 address {hotkey_ss58_address} provided.")
829+
826830
query = self.query_module(
827831
module="Commitments",
828832
name="RevealedCommitments",
829833
params=[netuid, hotkey_ss58_address],
830834
block=block,
831835
)
832-
return decode_revealed_commitment(query)
836+
if query is None:
837+
return None
838+
return tuple(decode_revealed_commitment(pair) for pair in query)
839+
840+
def get_revealed_commitment(
841+
self,
842+
netuid: int,
843+
uid: int,
844+
block: Optional[int] = None,
845+
) -> Optional[tuple[tuple[int, str], ...]]:
846+
"""Returns uid related revealed commitment for a given netuid.
847+
848+
Arguments:
849+
netuid (int): The unique identifier of the subnetwork.
850+
uid (int): The neuron uid to retrieve the commitment from.
851+
block (Optional[int]): The block number to retrieve the commitment from. Default is ``None``.
852+
853+
Returns:
854+
result (Optional[tuple[int, str]]: A tuple of reveal block and commitment message.
855+
856+
Example of result:
857+
( (12, "Alice message 1"), (152, "Alice message 2") )
858+
( (12, "Bob message 1"), (147, "Bob message 2") )
859+
"""
860+
try:
861+
meta_info = self.get_metagraph_info(netuid, block=block)
862+
if meta_info:
863+
hotkey_ss58_address = meta_info.hotkeys[uid]
864+
else:
865+
raise ValueError(f"Subnet with netuid {netuid} does not exist.")
866+
except IndexError:
867+
raise ValueError(f"Subnet {netuid} does not have a neuron with uid {uid}.")
868+
869+
return self.get_revealed_commitment_by_hotkey(
870+
netuid=netuid, hotkey_ss58_address=hotkey_ss58_address, block=block
871+
)
833872

834873
def get_all_revealed_commitments(
835874
self, netuid: int, block: Optional[int] = None
836-
) -> dict[str, tuple[int, str]]:
875+
) -> dict[str, tuple[tuple[int, str], ...]]:
837876
"""Returns all revealed commitments for a given netuid.
838877
839878
Arguments:
@@ -842,6 +881,12 @@ def get_all_revealed_commitments(
842881
843882
Returns:
844883
result (dict): A dictionary of all revealed commitments in view {ss58_address: (reveal block, commitment message)}.
884+
885+
Example of result:
886+
{
887+
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY": ( (12, "Alice message 1"), (152, "Alice message 2") ),
888+
"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty": ( (12, "Bob message 1"), (147, "Bob message 2") ),
889+
}
845890
"""
846891
query = self.query_map(
847892
module="Commitments",
@@ -851,8 +896,11 @@ def get_all_revealed_commitments(
851896
)
852897

853898
result = {}
854-
for item in query:
855-
result.update(decode_revealed_commitment_with_hotkey(item))
899+
for pair in query:
900+
hotkey_ss58_address, commitment_message = (
901+
decode_revealed_commitment_with_hotkey(pair)
902+
)
903+
result[hotkey_ss58_address] = commitment_message
856904
return result
857905

858906
def get_current_weight_commit_info(

tests/e2e_tests/conftest.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
)
2121

2222
LOCALNET_IMAGE_NAME = "ghcr.io/opentensor/subtensor-localnet:devnet-ready"
23+
CONTAINER_NAME_PREFIX = "test_local_chain_"
2324

2425

2526
def wait_for_node_start(process, timestamp=None):
@@ -163,7 +164,32 @@ def try_start_docker():
163164
print("Docker wasn't run. Manual start may be required.")
164165
return False
165166

166-
container_name = f"test_local_chain_{str(time.time()).replace('.', '_')}"
167+
def stop_existing_test_containers():
168+
"""Stop running Docker containers with names starting with 'test_local_chain_'."""
169+
try:
170+
existing_container_result = subprocess.run(
171+
[
172+
"docker",
173+
"ps",
174+
"--filter",
175+
f"name={CONTAINER_NAME_PREFIX}",
176+
"--format",
177+
"{{.ID}}",
178+
],
179+
stdout=subprocess.PIPE,
180+
stderr=subprocess.PIPE,
181+
text=True,
182+
check=True,
183+
)
184+
container_ids = existing_container_result.stdout.strip().splitlines()
185+
for cid in container_ids:
186+
if cid:
187+
print(f"Stopping existing container: {cid}")
188+
subprocess.run(["docker", "stop", cid], check=True)
189+
except subprocess.CalledProcessError as e:
190+
print(f"Failed to stop existing containers: {e}")
191+
192+
container_name = f"{CONTAINER_NAME_PREFIX}{str(time.time()).replace('.', '_')}"
167193

168194
# Command to start container
169195
cmds = [
@@ -182,6 +208,8 @@ def try_start_docker():
182208

183209
try_start_docker()
184210

211+
stop_existing_test_containers()
212+
185213
# Start container
186214
with subprocess.Popen(
187215
cmds,

0 commit comments

Comments
 (0)