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
5 changes: 5 additions & 0 deletions bittensor/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,8 @@ class KeyFileError(Exception):
"""Error thrown when the keyfile is corrupt, non-writable, non-readable or the password used to decrypt is invalid."""

pass


class MetadataError(ChainTransactionError):
r"""Error raised when metadata commitment transaction fails."""
pass
87 changes: 87 additions & 0 deletions bittensor/extrinsics/serving.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from dataclasses import asdict
import bittensor.utils.networking as net
from rich.prompt import Confirm
from ..errors import MetadataError


def serve_extrinsic(
Expand Down Expand Up @@ -203,3 +204,89 @@ def serve_axon_extrinsic(
prompt=prompt,
)
return serve_success


def publish_metadata(
subtensor: "bittensor.subtensor",
wallet: "bittensor.wallet",
netuid: int,
type: str,
data: str,
wait_for_inclusion: bool = False,
wait_for_finalization: bool = True,
) -> bool:
"""
Publishes metadata on the bittensor network using the specified wallet and network identifier.

Args:
subtensor (bittensor.subtensor):
The subtensor instance representing the bittensor blockchain connection.
wallet (bittensor.wallet):
The wallet object used for authentication in the transaction.
netuid (int):
Network UID on which the metadata is to be published.
type (str):
The data type of the information being submitted. It should be one of the following:
'Sha256', 'Blake256', 'Keccak256', or 'Raw0-128'. This specifies the format or
hashing algorithm used for the data.
data (str):
The actual metadata content to be published. This should be formatted or hashed
according to the 'type' specified. (Note: max str length of 128 bytes)
wait_for_inclusion (bool, optional):
If True, the function will wait for the extrinsic to be included in a block before returning.
Defaults to False.
wait_for_finalization (bool, optional):
If True, the function will wait for the extrinsic to be finalized on the chain before returning.
Defaults to True.

Returns:
bool:
True if the metadata was successfully published (and finalized if specified). False otherwise.

Raises:
MetadataError:
If there is an error in submitting the extrinsic or if the response from the blockchain indicates failure.
"""

wallet.hotkey

with subtensor.substrate as substrate:
call = substrate.compose_call(
call_module="Commitments",
call_function="set_commitment",
call_params={"netuid": netuid, "info": {"fields": [[{f"{type}": data}]]}},
)

extrinsic = substrate.create_signed_extrinsic(call=call, keypair=wallet.hotkey)
response = substrate.submit_extrinsic(
extrinsic,
wait_for_inclusion=wait_for_inclusion,
wait_for_finalization=wait_for_finalization,
)
# We only wait here if we expect finalization.
if not wait_for_finalization and not wait_for_inclusion:
return True
response.process_events()
if response.is_success:
return True
else:
raise MetadataError(response.error_message)


from retry import retry
from typing import Optional


def get_metadata(self, netuid: int, hotkey: str, block: Optional[int] = None) -> str:
@retry(delay=2, tries=3, backoff=2, max_delay=4)
def make_substrate_call_with_retry():
with self.substrate as substrate:
return substrate.query(
module="Commitments",
storage_function="CommitmentOf",
params=[netuid, hotkey],
block_hash=None if block == None else substrate.get_block_hash(block),
)

commit_data = make_substrate_call_with_retry()
return commit_data.value
18 changes: 17 additions & 1 deletion bittensor/subtensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,12 @@
)
from .extrinsics.staking import add_stake_extrinsic, add_stake_multiple_extrinsic
from .extrinsics.unstaking import unstake_extrinsic, unstake_multiple_extrinsic
from .extrinsics.serving import serve_extrinsic, serve_axon_extrinsic
from .extrinsics.serving import (
serve_extrinsic,
serve_axon_extrinsic,
publish_metadata,
get_metadata,
)
from .extrinsics.registration import (
register_extrinsic,
burned_register_extrinsic,
Expand Down Expand Up @@ -2143,6 +2148,17 @@ def make_substrate_call_with_retry():

return make_substrate_call_with_retry()

""" Make some commitment on-chain about arbitary data """

def commit(self, wallet, netuid: int, data: str):
publish_metadata(self, wallet, netuid, f"Raw{len(data)}", data.encode())

def get_commitment(self, netuid: int, uid: int, block: Optional[int] = None) -> str:
metagraph = self.metagraph(netuid)
hotkey = metagraph.hotkeys[uid]

return get_metadata(self, netuid, hotkey, block)

########################
#### Standard Calls ####
########################
Expand Down