Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
74 changes: 61 additions & 13 deletions bittensor/core/async_subtensor.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import asyncio
import copy
from datetime import datetime, timezone
import ssl
from datetime import datetime, timezone
from functools import partial
from typing import Optional, Any, Union, Iterable, TYPE_CHECKING

import asyncstdlib as a
import numpy as np
import scalecodec
from async_substrate_interface import AsyncSubstrateInterface
from bittensor_commit_reveal import get_encrypted_commitment
from bittensor_wallet.utils import SS58_FORMAT
from numpy.typing import NDArray
from scalecodec import GenericCall
Expand All @@ -27,7 +28,6 @@
decode_account_id,
DynamicInfo,
)
from bittensor_commit_reveal import get_encrypted_commitment
from bittensor.core.chain_data.chain_identity import ChainIdentity
from bittensor.core.chain_data.delegate_info import DelegatedInfo
from bittensor.core.chain_data.utils import (
Expand All @@ -38,17 +38,17 @@
from bittensor.core.config import Config
from bittensor.core.errors import ChainError, SubstrateRequestException
from bittensor.core.extrinsics.asyncex.commit_reveal import commit_reveal_v3_extrinsic
from bittensor.core.extrinsics.asyncex.move_stake import (
transfer_stake_extrinsic,
swap_stake_extrinsic,
move_stake_extrinsic,
)
from bittensor.core.extrinsics.asyncex.registration import (
burned_register_extrinsic,
register_extrinsic,
register_subnet_extrinsic,
set_subnet_identity_extrinsic,
)
from bittensor.core.extrinsics.asyncex.move_stake import (
transfer_stake_extrinsic,
swap_stake_extrinsic,
move_stake_extrinsic,
)
from bittensor.core.extrinsics.asyncex.root import (
set_root_weights_extrinsic,
root_register_extrinsic,
Expand Down Expand Up @@ -84,6 +84,7 @@
decode_hex_identity_dict,
float_to_u64,
format_error_message,
is_valid_ss58_address,
torch,
u16_normalized_float,
u64_normalized_float,
Expand Down Expand Up @@ -1064,14 +1065,14 @@ async def get_all_commitments(
result[decode_account_id(id_[0])] = decode_metadata(value)
return result

async def get_revealed_commitment(
async def get_revealed_commitment_by_hotkey(
self,
netuid: int,
hotkey_ss58_address: Optional[str] = None,
block: Optional[int] = None,
block_hash: Optional[str] = None,
reuse_block: bool = False,
) -> Optional[tuple[int, str]]:
) -> Optional[tuple[tuple[int, str], ...]]:
"""Returns hotkey related revealed commitment for a given netuid.

Arguments:
Expand All @@ -1084,6 +1085,9 @@ async def get_revealed_commitment(
Returns:
result (tuple[int, str): A tuple of reveal block and commitment message.
"""
if not is_valid_ss58_address(address=hotkey_ss58_address):
raise ValueError(f"Invalid ss58 address {hotkey_ss58_address} provided.")

query = await self.query_module(
module="Commitments",
name="RevealedCommitments",
Expand All @@ -1092,15 +1096,50 @@ async def get_revealed_commitment(
block_hash=block_hash,
reuse_block=reuse_block,
)
return decode_revealed_commitment(query)
if query is None:
return None
return tuple(decode_revealed_commitment(pair) for pair in query)

async def get_revealed_commitment(
self,
netuid: int,
uid: int,
block: Optional[int] = None,
) -> Optional[tuple[tuple[int, str], ...]]:
"""Returns uid related revealed commitment for a given netuid.

Arguments:
netuid (int): The unique identifier of the subnetwork.
uid (int): The neuron uid to retrieve the commitment from.
block (Optional[int]): The block number to retrieve the commitment from. Default is ``None``.

Returns:
result (Optional[tuple[int, str]]: A tuple of reveal block and commitment message.

Example of result:
( (12, "Alice message 1"), (152, "Alice message 2") )
( (12, "Bob message 1"), (147, "Bob message 2") )
"""
try:
meta_info = await self.get_metagraph_info(netuid, block=block)
if meta_info:
hotkey_ss58_address = meta_info.hotkeys[uid]
else:
raise ValueError(f"Subnet with netuid {netuid} does not exist.")
except IndexError:
raise ValueError(f"Subnet {netuid} does not have a neuron with uid {uid}.")

return await self.get_revealed_commitment_by_hotkey(
netuid=netuid, hotkey_ss58_address=hotkey_ss58_address, block=block
)

async def get_all_revealed_commitments(
self,
netuid: int,
block: Optional[int] = None,
block_hash: Optional[str] = None,
reuse_block: bool = False,
) -> dict[str, tuple[int, str]]:
) -> dict[str, tuple[tuple[int, str], ...]]:
"""Returns all revealed commitments for a given netuid.

Arguments:
Expand All @@ -1111,6 +1150,12 @@ async def get_all_revealed_commitments(

Returns:
result (dict): A dictionary of all revealed commitments in view {ss58_address: (reveal block, commitment message)}.

Example of result:
{
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY": ( (12, "Alice message 1"), (152, "Alice message 2") ),
"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty": ( (12, "Bob message 1"), (147, "Bob message 2") ),
}
"""
query = await self.query_map(
module="Commitments",
Expand All @@ -1122,8 +1167,11 @@ async def get_all_revealed_commitments(
)

result = {}
async for item in query:
result.update(decode_revealed_commitment_with_hotkey(item))
async for pair in query:
hotkey_ss58_address, commitment_message = (
decode_revealed_commitment_with_hotkey(pair)
)
result[hotkey_ss58_address] = commitment_message
return result

async def get_current_weight_commit_info(
Expand Down
45 changes: 29 additions & 16 deletions bittensor/core/chain_data/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from bittensor.utils.balance import Balance

if TYPE_CHECKING:
from async_substrate_interface.types import ScaleObj
from async_substrate_interface.sync_substrate import QueryMapResult


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


def decode_revealed_commitment(
value: Optional["ScaleObj"],
) -> Optional[tuple[int, str]]:
"""Decode the revealed commitment data from the given input if it is not None."""
if value is None:
return None
def decode_revealed_commitment(encoded_data) -> tuple[int, str]:
"""
Decode the revealed commitment data from the given input if it is not None.

Arguments:
encoded_data (tuple[bytes, int]): A tuple containing the revealed message and the block number.

Returns:
tuple[int, str]: A tuple containing the revealed block number and decoded commitment message.
"""

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

v = next(iter(value))
revealed_block = v[1]
cut = scale_decode_offset(v[0])
com_bytes, revealed_block = encoded_data
offset = scale_decode_offset(com_bytes)

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


def decode_revealed_commitment_with_hotkey(data: list) -> dict[str, tuple[int, str]]:
"""Decode revealed commitment using a hotkey."""
key, value = data
ss58_address = decode_account_id(key[0])
return {ss58_address: decode_revealed_commitment(value)}
def decode_revealed_commitment_with_hotkey(
encoded_data: "QueryMapResult",
) -> tuple[str, tuple[tuple[int, str], ...]]:
"""
Decode revealed commitment using a hotkey.

Returns:
tuple[str, tuple[tuple[int, str], ...]]: A tuple containing the hotkey (ss58 address) and a tuple of block
numbers and their corresponding revealed commitments.
"""
key, data = encoded_data

ss58_address = decode_account_id(next(iter(key)))
block_data = tuple(decode_revealed_commitment(p) for p in data.value)
return ss58_address, block_data
64 changes: 56 additions & 8 deletions bittensor/core/subtensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
decode_hex_identity_dict,
float_to_u64,
format_error_message,
is_valid_ss58_address,
torch,
u16_normalized_float,
u64_normalized_float,
Expand Down Expand Up @@ -807,33 +808,71 @@ def get_all_commitments(
result[decode_account_id(id_[0])] = decode_metadata(value)
return result

def get_revealed_commitment(
def get_revealed_commitment_by_hotkey(
self,
netuid: int,
hotkey_ss58_address: Optional[str] = None,
hotkey_ss58_address: str,
block: Optional[int] = None,
) -> Optional[tuple[int, str]]:
) -> Optional[tuple[tuple[int, str], ...]]:
"""Returns hotkey related revealed commitment for a given netuid.

Arguments:
netuid (int): The unique identifier of the subnetwork.
block (Optional[int]): The block number to retrieve the commitment from. Default is ``None``.
hotkey_ss58_address (str): The ss58 address of the committee member.
block (Optional[int]): The block number to retrieve the commitment from. Default is ``None``.

Returns:
result (tuple[int, str): A tuple of reveal block and commitment message.
"""
if not is_valid_ss58_address(address=hotkey_ss58_address):
raise ValueError(f"Invalid ss58 address {hotkey_ss58_address} provided.")

query = self.query_module(
module="Commitments",
name="RevealedCommitments",
params=[netuid, hotkey_ss58_address],
block=block,
)
return decode_revealed_commitment(query)
if query is None:
return None
return tuple(decode_revealed_commitment(pair) for pair in query)

def get_revealed_commitment(
self,
netuid: int,
uid: int,
block: Optional[int] = None,
) -> Optional[tuple[tuple[int, str], ...]]:
"""Returns uid related revealed commitment for a given netuid.

Arguments:
netuid (int): The unique identifier of the subnetwork.
uid (int): The neuron uid to retrieve the commitment from.
block (Optional[int]): The block number to retrieve the commitment from. Default is ``None``.

Returns:
result (Optional[tuple[int, str]]: A tuple of reveal block and commitment message.

Example of result:
( (12, "Alice message 1"), (152, "Alice message 2") )
( (12, "Bob message 1"), (147, "Bob message 2") )
"""
try:
meta_info = self.get_metagraph_info(netuid, block=block)
if meta_info:
hotkey_ss58_address = meta_info.hotkeys[uid]
else:
raise ValueError(f"Subnet with netuid {netuid} does not exist.")
except IndexError:
raise ValueError(f"Subnet {netuid} does not have a neuron with uid {uid}.")

return self.get_revealed_commitment_by_hotkey(
netuid=netuid, hotkey_ss58_address=hotkey_ss58_address, block=block
)

def get_all_revealed_commitments(
self, netuid: int, block: Optional[int] = None
) -> dict[str, tuple[int, str]]:
) -> dict[str, tuple[tuple[int, str], ...]]:
"""Returns all revealed commitments for a given netuid.

Arguments:
Expand All @@ -842,6 +881,12 @@ def get_all_revealed_commitments(

Returns:
result (dict): A dictionary of all revealed commitments in view {ss58_address: (reveal block, commitment message)}.

Example of result:
{
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY": ( (12, "Alice message 1"), (152, "Alice message 2") ),
"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty": ( (12, "Bob message 1"), (147, "Bob message 2") ),
}
"""
query = self.query_map(
module="Commitments",
Expand All @@ -851,8 +896,11 @@ def get_all_revealed_commitments(
)

result = {}
for item in query:
result.update(decode_revealed_commitment_with_hotkey(item))
for pair in query:
hotkey_ss58_address, commitment_message = (
decode_revealed_commitment_with_hotkey(pair)
)
result[hotkey_ss58_address] = commitment_message
return result

def get_current_weight_commit_info(
Expand Down
Loading
Loading