bittensor.core.extrinsics.async_registration

Contents

bittensor.core.extrinsics.async_registration#

Attributes#

Exceptions#

CUDAException

An exception raised when an error occurs in the CUDA environment.

MaxAttemptsException

Raised when the POW Solver has reached the max number of attempts.

MaxSuccessException

Raised when the POW Solver has reached the max number of successful solutions.

Classes#

LazyLoadedTorch

POWSolution

A solution to the registration PoW problem.

RegistrationStatistics

Statistics for a registration.

RegistrationStatistics

Statistics for a registration.

RegistrationStatisticsLogger

Logs statistics for a registration.

_CUDASolver

Performs POW Solution using CUDA.

_Solver

Performs POW Solution.

_SolverBase

A process that solves the registration PoW problem.

_UsingSpawnStartMethod

Functions#

_block_solver(subtensor, wallet, num_processes, ...)

Shared code used by the Solvers to solve the POW solution.

_check_for_newest_block_and_update(subtensor, netuid, ...)

Checks for a new block and updates the current block information if a new block is found.

_create_seal_hash(block_and_hotkey_hash_bytes, nonce)

Create a cryptographic seal hash from the given block and hotkey hash bytes and nonce.

_get_block_with_retry(subtensor, netuid)

Gets the current block number, difficulty, and block hash from the substrate node.

_get_real_torch()

_hash_block_with_hotkey(block_bytes, hotkey_bytes)

Hashes the block with the hotkey using Keccak-256 to get 32 bytes

_hex_bytes_to_u8_list(hex_bytes)

_registration_diff_pack(diff, packed_diff)

Packs the difficulty into two 32-bit integers. Little endian.

_registration_diff_unpack(packed_diff)

Unpacks the packed two 32-bit integers into one 64-bit integer. Little endian.

_seal_meets_difficulty(seal, difficulty, limit)

Determines if a seal meets the specified difficulty

_solve_for_difficulty_fast(subtensor, wallet, netuid)

Solves the POW for registration using multiprocessing.

_solve_for_difficulty_fast_cuda(subtensor, wallet, netuid)

Solves the registration fast using CUDA

_solve_for_nonce_block(nonce_start, nonce_end, ...)

Tries to solve the POW for a block of nonces (nonce_start, nonce_end)

_solve_for_nonce_block_cuda(nonce_start, ...)

Tries to solve the POW on a CUDA device for a block of nonces (nonce_start, nonce_start + update_interval * tpb

_terminate_workers_and_wait_for_exit(workers)

_update_curr_block(curr_diff, curr_block, ...)

Update the current block data with the provided block information and difficulty.

create_pow(subtensor, wallet, netuid[, ...])

Creates a proof of work for the given subtensor and wallet.

get_cpu_count()

is_hotkey_registered(subtensor, netuid, hotkey_ss58)

Checks to see if the hotkey is registered on a given netuid

legacy_torch_api_compat(func)

Convert function operating on numpy Input&Output to legacy torch Input&Output API if use_torch() is True.

log_cuda_errors()

Logs any CUDA errors.

log_no_torch_error()

register_extrinsic(subtensor, wallet, netuid[, ...])

Registers the wallet to the chain.

reset_cuda()

Resets the CUDA environment.

run_faucet_extrinsic(subtensor, wallet[, ...])

Runs a continual POW to get a faucet of TAO on the test net.

solve_cuda(nonce_start, update_interval, tpb, ...[, ...])

Solves the PoW problem using CUDA.

use_torch()

Force the use of torch over numpy for certain operations.

Module Contents#

exception bittensor.core.extrinsics.async_registration.CUDAException#

Bases: Exception

An exception raised when an error occurs in the CUDA environment.

Initialize self. See help(type(self)) for accurate signature.

class bittensor.core.extrinsics.async_registration.LazyLoadedTorch#
__bool__()#
__getattr__(name)#
exception bittensor.core.extrinsics.async_registration.MaxAttemptsException#

Bases: Exception

Raised when the POW Solver has reached the max number of attempts.

Initialize self. See help(type(self)) for accurate signature.

exception bittensor.core.extrinsics.async_registration.MaxSuccessException#

Bases: Exception

Raised when the POW Solver has reached the max number of successful solutions.

Initialize self. See help(type(self)) for accurate signature.

class bittensor.core.extrinsics.async_registration.POWSolution#

A solution to the registration PoW problem.

block_number: int#
difficulty: int#
async is_stale(subtensor)#

Returns True if the POW is stale.

This means the block the POW is solved for is within 3 blocks of the current block.

Parameters:

subtensor (bittensor.core.async_subtensor.AsyncSubtensor)

Return type:

bool

nonce: int#
seal: bytes#
class bittensor.core.extrinsics.async_registration.RegistrationStatistics#

Statistics for a registration.

block_hash: str#
block_number: int#
difficulty: int#
hash_rate: float#
hash_rate_perpetual: float#
rounds_total: int#
time_average: float#
time_spent: float#
time_spent_total: float#
class bittensor.core.extrinsics.async_registration.RegistrationStatistics#

Statistics for a registration.

block_hash: bytes#
block_number: int#
difficulty: int#
hash_rate: float#
hash_rate_perpetual: float#
rounds_total: int#
time_average: float#
time_spent: float#
time_spent_total: float#
class bittensor.core.extrinsics.async_registration.RegistrationStatisticsLogger(console_=None, output_in_place=True)#

Logs statistics for a registration.

Parameters:
  • console_ (Optional[rich.console.Console])

  • output_in_place (bool)

console: rich.console.Console#
classmethod get_status_message(stats, verbose=False)#

Provides a message of the current status of the block solving as a str for a logger or stdout.

Parameters:
Return type:

str

start()#
Return type:

None

status: rich.status.Status | None#
stop()#
Return type:

None

update(stats, verbose=False)#

Passes the current status to the logger.

Parameters:
Return type:

None

class bittensor.core.extrinsics.async_registration._CUDASolver(proc_num, num_proc, update_interval, finished_queue, solution_queue, stop_event, curr_block, curr_block_num, curr_diff, check_block, limit, dev_id, tpb)#

Bases: _SolverBase

Performs POW Solution using CUDA.

Parameters:
dev_id: int#
run()#

Method to be run in sub-process; can be overridden in sub-class

tpb: int#
class bittensor.core.extrinsics.async_registration._Solver(proc_num, num_proc, update_interval, finished_queue, solution_queue, stop_event, curr_block, curr_block_num, curr_diff, check_block, limit)#

Bases: _SolverBase

Performs POW Solution.

run()#

Method to be run in sub-process; can be overridden in sub-class

class bittensor.core.extrinsics.async_registration._SolverBase(proc_num, num_proc, update_interval, finished_queue, solution_queue, stop_event, curr_block, curr_block_num, curr_diff, check_block, limit)#

Bases: multiprocessing.Process

A process that solves the registration PoW problem.

Parameters:
  • proc_num – The number of the process being created.

  • num_proc – The total number of processes running.

  • update_interval – The number of nonces to try to solve before checking for a new block.

  • finished_queue – The queue to put the process number when a process finishes each update_interval. Used for calculating the average time per update_interval across all processes.

  • solution_queue – The queue to put the solution the process has found during the pow solve.

  • stop_event – The event to set by the main process when all the solver processes should stop. The solver process will check for the event after each update_interval. The solver process will stop when the event is set. Used to stop the solver processes when a solution is found.

  • curr_block – The array containing this process’s current block hash. The main process will set the array to the new block hash when a new block is finalized in the network. The solver process will get the new block hash from this array when newBlockEvent is set

  • curr_block_num – The value containing this process’s current block number. The main process will set the value to the new block number when a new block is finalized in the network. The solver process will get the new block number from this value when new_block_event is set.

  • curr_diff – The array containing this process’s current difficulty. The main process will set the array to the new difficulty when a new block is finalized in the network. The solver process will get the new difficulty from this array when newBlockEvent is set.

  • check_block – The lock to prevent this process from getting the new block data while the main process is updating the data.

  • limit – The limit of the pow solve for a valid solution.

Returns:

The event to set by the main process when a new block is finalized in the network. The solver process will check for the event after each update_interval. The solver process will get the new block hash and difficulty and start solving for a new nonce.

Return type:

new_block_event

check_block: multiprocessing.Lock#
static create_shared_memory()#

Creates shared memory for the solver processes to use.

Return type:

tuple[multiprocessing.Array, multiprocessing.Value, multiprocessing.Array]

curr_block: multiprocessing.Array#
curr_block_num: multiprocessing.Value#
curr_diff: multiprocessing.Array#
finished_queue: multiprocessing.queues.Queue#
hotkey_bytes: bytes#
limit: int#
new_block_event: multiprocessing.Event#
num_proc: int#
proc_num: int#
abstract run()#

Method to be run in sub-process; can be overridden in sub-class

solution_queue: multiprocessing.queues.Queue#
stop_event: multiprocessing.Event#
update_interval: int#
class bittensor.core.extrinsics.async_registration._UsingSpawnStartMethod(force=False)#
Parameters:

force (bool)

__enter__()#
__exit__(*args)#
_force#
_old_start_method = None#
async bittensor.core.extrinsics.async_registration._block_solver(subtensor, wallet, num_processes, netuid, dev_id, tpb, update_interval, curr_block, curr_block_num, curr_diff, n_samples, alpha_, output_in_place, log_verbose, cuda)#

Shared code used by the Solvers to solve the POW solution.

Parameters:
async bittensor.core.extrinsics.async_registration._check_for_newest_block_and_update(subtensor, netuid, old_block_number, hotkey_bytes, curr_diff, curr_block, curr_block_num, update_curr_block, check_block, solvers, curr_stats)#

Checks for a new block and updates the current block information if a new block is found.

Parameters:
  • subtensor (bittensor.core.async_subtensor.AsyncSubtensor) – The subtensor object to use for getting the current block.

  • netuid (int) – The netuid to use for retrieving the difficulty.

  • old_block_number (int) – The old block number to check against.

  • hotkey_bytes (bytes) – The bytes of the hotkey’s pubkey.

  • curr_diff (multiprocessing.Array) – The current difficulty as a multiprocessing array.

  • curr_block (multiprocessing.Array) – Where the current block is stored as a multiprocessing array.

  • curr_block_num (multiprocessing.Value) – Where the current block number is stored as a multiprocessing value.

  • update_curr_block (Callable) – A function that updates the current block.

  • check_block (multiprocessing.Lock) – A mp lock that is used to check for a new block.

  • solvers (list[_Solver]) – A list of solvers to update the current block for.

  • curr_stats (RegistrationStatistics) – The current registration statistics to update.

Returns:

The current block number.

Return type:

int

bittensor.core.extrinsics.async_registration._create_seal_hash(block_and_hotkey_hash_bytes, nonce)#

Create a cryptographic seal hash from the given block and hotkey hash bytes and nonce.

This function generates a seal hash by combining the given block and hotkey hash bytes with a nonce. It first converts the nonce to a byte representation, then concatenates it with the first 64 hex characters of the block and hotkey hash bytes. The result is then hashed using SHA-256 followed by the Keccak-256 algorithm to produce the final seal hash.

Parameters:
  • block_and_hotkey_hash_bytes (bytes) – The combined hash bytes of the block and hotkey.

  • nonce (int) – The nonce value used for hashing.

Returns:

The resulting seal hash.

Return type:

bytes

async bittensor.core.extrinsics.async_registration._get_block_with_retry(subtensor, netuid)#

Gets the current block number, difficulty, and block hash from the substrate node.

Parameters:
  • subtensor (bittensor.core.async_subtensor.AsyncSubtensor) – The subtensor object to use to get the block number, difficulty, and block hash.

  • netuid (int) – The netuid of the network to get the block number, difficulty, and block hash from.

Returns:

The current block number, difficulty of the subnet, block hash

Raises:
Return type:

tuple[int, int, bytes]

bittensor.core.extrinsics.async_registration._get_real_torch()#
bittensor.core.extrinsics.async_registration._hash_block_with_hotkey(block_bytes, hotkey_bytes)#

Hashes the block with the hotkey using Keccak-256 to get 32 bytes

Parameters:
Return type:

bytes

bittensor.core.extrinsics.async_registration._hex_bytes_to_u8_list(hex_bytes)#
Parameters:

hex_bytes (bytes)

bittensor.core.extrinsics.async_registration._registration_diff_pack(diff, packed_diff)#

Packs the difficulty into two 32-bit integers. Little endian.

Parameters:
  • diff (int)

  • packed_diff (multiprocessing.Array)

bittensor.core.extrinsics.async_registration._registration_diff_unpack(packed_diff)#

Unpacks the packed two 32-bit integers into one 64-bit integer. Little endian.

Parameters:

packed_diff (multiprocessing.Array)

Return type:

int

bittensor.core.extrinsics.async_registration._seal_meets_difficulty(seal, difficulty, limit)#

Determines if a seal meets the specified difficulty

Parameters:
Return type:

bool

async bittensor.core.extrinsics.async_registration._solve_for_difficulty_fast(subtensor, wallet, netuid, output_in_place=True, num_processes=None, update_interval=None, n_samples=10, alpha_=0.8, log_verbose=False)#

Solves the POW for registration using multiprocessing.

Parameters:
  • subtensor – Subtensor to connect to for block information and to submit.

  • wallet (bittensor_wallet.Wallet) – wallet to use for registration.

  • netuid (int) – The netuid of the subnet to register to.

  • output_in_place (bool) – If true, prints the status in place. Otherwise, prints the status on a new line.

  • num_processes (Optional[int]) – Number of processes to use.

  • update_interval (Optional[int]) – Number of nonces to solve before updating block information.

  • n_samples (int) – The number of samples of the hash_rate to keep for the EWMA

  • alpha – The alpha for the EWMA for the hash_rate calculation

  • log_verbose (bool) – If true, prints more verbose logging of the registration metrics.

  • alpha_ (float)

Return type:

Optional[POWSolution]

Notes

The hash rate is calculated as an exponentially weighted moving average in order to make the measure more robust. We can also modify the update interval to do smaller blocks of work, while still updating the block information after a different number of nonces, to increase the transparency of the process while still keeping the speed.

async bittensor.core.extrinsics.async_registration._solve_for_difficulty_fast_cuda(subtensor, wallet, netuid, output_in_place=True, update_interval=50000, tpb=512, dev_id=0, n_samples=10, alpha_=0.8, log_verbose=False)#

Solves the registration fast using CUDA

Parameters:
  • subtensor (bittensor.core.async_subtensor.AsyncSubtensor) – The subtensor node to grab blocks

  • wallet (bittensor_wallet.Wallet) – The wallet to register

  • netuid (int) – The netuid of the subnet to register to.

  • output_in_place (bool) – If true, prints the output in place, otherwise prints to new lines

  • update_interval (int) – The number of nonces to try before checking for more blocks

  • tpb (int) – The number of threads per block. CUDA param that should match the GPU capability

  • dev_id (Union[list[int], int]) – The CUDA device IDs to execute the registration on, either a single device or a list of devices

  • n_samples (int) – The number of samples of the hash_rate to keep for the EWMA

  • alpha – The alpha for the EWMA for the hash_rate calculation

  • log_verbose (bool) – If true, prints more verbose logging of the registration metrics.

  • alpha_ (float)

Return type:

Optional[POWSolution]

Note

The hash rate is calculated as an exponentially weighted moving average in order to make the measure more robust.

bittensor.core.extrinsics.async_registration._solve_for_nonce_block(nonce_start, nonce_end, block_and_hotkey_hash_bytes, difficulty, limit, block_number)#

Tries to solve the POW for a block of nonces (nonce_start, nonce_end)

Parameters:
  • nonce_start (int)

  • nonce_end (int)

  • block_and_hotkey_hash_bytes (bytes)

  • difficulty (int)

  • limit (int)

  • block_number (int)

Return type:

Optional[POWSolution]

bittensor.core.extrinsics.async_registration._solve_for_nonce_block_cuda(nonce_start, update_interval, block_and_hotkey_hash_bytes, difficulty, limit, block_number, dev_id, tpb)#

Tries to solve the POW on a CUDA device for a block of nonces (nonce_start, nonce_start + update_interval * tpb

Parameters:
  • nonce_start (int)

  • update_interval (int)

  • block_and_hotkey_hash_bytes (bytes)

  • difficulty (int)

  • limit (int)

  • block_number (int)

  • dev_id (int)

  • tpb (int)

Return type:

Optional[POWSolution]

bittensor.core.extrinsics.async_registration._terminate_workers_and_wait_for_exit(workers)#
Parameters:

workers (list[Union[multiprocessing.Process, multiprocessing.queues.Queue]])

Return type:

None

bittensor.core.extrinsics.async_registration._update_curr_block(curr_diff, curr_block, curr_block_num, block_number, block_bytes, diff, hotkey_bytes, lock)#

Update the current block data with the provided block information and difficulty.

This function updates the current block and its difficulty in a thread-safe manner. It sets the current block number, hashes the block with the hotkey, updates the current block bytes, and packs the difficulty.

curr_diff: Shared array to store the current difficulty. curr_block: Shared array to store the current block data. curr_block_num: Shared value to store the current block number. block_number: The block number to set as the current block number. block_bytes: The block data bytes to be hashed with the hotkey. diff: The difficulty value to be packed into the current difficulty array. hotkey_bytes: The hotkey bytes used for hashing the block. lock: A lock to ensure thread-safe updates.

Parameters:
  • curr_diff (multiprocessing.Array)

  • curr_block (multiprocessing.Array)

  • curr_block_num (multiprocessing.Value)

  • block_number (int)

  • block_bytes (bytes)

  • diff (int)

  • hotkey_bytes (bytes)

  • lock (multiprocessing.Lock)

async bittensor.core.extrinsics.async_registration.create_pow(subtensor, wallet, netuid, output_in_place=True, cuda=False, dev_id=0, tpb=256, num_processes=None, update_interval=None, log_verbose=False)#

Creates a proof of work for the given subtensor and wallet.

Parameters:
  • subtensor (bittensor.core.async_subtensor.AsyncSubtensor) – The subtensor to create a proof of work for.

  • wallet (bittensor_wallet.Wallet) – The wallet to create a proof of work for.

  • netuid (int) – The netuid for the subnet to create a proof of work for.

  • output_in_place (bool) – If true, prints the progress of the proof of work to the console in-place. Meaning the progress is printed on the same lines.

  • cuda (bool) – If true, uses CUDA to solve the proof of work.

  • dev_id (Union[list[int], int]) – The CUDA device id(s) to use. If cuda is true and dev_id is a list, then multiple CUDA devices will be used to solve the proof of work.

  • tpb (int) – The number of threads per block to use when solving the proof of work. Should be a multiple of 32.

  • num_processes (int) – The number of processes to use when solving the proof of work. If None, then the number of processes is equal to the number of CPU cores.

  • update_interval (int) – The number of nonces to run before checking for a new block.

  • log_verbose (bool) – If true, prints the progress of the proof of work more verbosely.

Returns:

The proof of work solution or None if the wallet is already registered or there is a different error.

Raises:

ValueError – If the subnet does not exist.

Return type:

Optional[dict[str, Any]]

bittensor.core.extrinsics.async_registration.get_cpu_count()#
Return type:

int

async bittensor.core.extrinsics.async_registration.is_hotkey_registered(subtensor, netuid, hotkey_ss58)#

Checks to see if the hotkey is registered on a given netuid

Parameters:
Return type:

bool

bittensor.core.extrinsics.async_registration.legacy_torch_api_compat(func)#

Convert function operating on numpy Input&Output to legacy torch Input&Output API if use_torch() is True.

Parameters:

func (Callable) – Function with numpy Input/Output to be decorated.

Returns:

Decorated function

bittensor.core.extrinsics.async_registration.log_cuda_errors()#

Logs any CUDA errors.

Return type:

str

bittensor.core.extrinsics.async_registration.log_no_torch_error()#
async bittensor.core.extrinsics.async_registration.register_extrinsic(subtensor, wallet, netuid, wait_for_inclusion=False, wait_for_finalization=True, max_allowed_attempts=3, output_in_place=True, cuda=False, dev_id=0, tpb=256, num_processes=None, update_interval=None, log_verbose=False)#

Registers the wallet to the chain.

Parameters:
  • subtensor (bittensor.core.async_subtensor.AsyncSubtensor) – initialized AsyncSubtensor object to use for chain interactions

  • wallet (bittensor_wallet.Wallet) – Bittensor wallet object.

  • netuid (int) – The netuid of the subnet to register on.

  • wait_for_inclusion (bool) – If set, waits for the extrinsic to enter a block before returning True, or returns False if the extrinsic fails to enter the block within the timeout.

  • wait_for_finalization (bool) – If set, waits for the extrinsic to be finalized on the chain before returning True, or returns False if the extrinsic fails to be finalized within the timeout.

  • max_allowed_attempts (int) – Maximum number of attempts to register the wallet.

  • output_in_place (bool) – Whether the POW solving should be outputted to the console as it goes along.

  • cuda (bool) – If True, the wallet should be registered using CUDA device(s).

  • dev_id (Union[list[int], int]) – The CUDA device id to use, or a list of device ids.

  • tpb (int) – The number of threads per block (CUDA).

  • num_processes (Optional[int]) – The number of processes to use to register.

  • update_interval (Optional[int]) – The number of nonces to solve between updates.

  • log_verbose (bool) – If True, the registration process will log more information.

Returns:

True if extrinsic was finalized or included in the block. If we did not wait for finalization/inclusion, the response is True.

Return type:

bool

bittensor.core.extrinsics.async_registration.reset_cuda()#

Resets the CUDA environment.

async bittensor.core.extrinsics.async_registration.run_faucet_extrinsic(subtensor, wallet, wait_for_inclusion=False, wait_for_finalization=True, max_allowed_attempts=3, output_in_place=True, cuda=False, dev_id=0, tpb=256, num_processes=None, update_interval=None, log_verbose=False, max_successes=3)#

Runs a continual POW to get a faucet of TAO on the test net.

Parameters:
  • subtensor (bittensor.core.async_subtensor.AsyncSubtensor) – The subtensor interface object used to run the extrinsic

  • wallet (bittensor_wallet.Wallet) – Bittensor wallet object.

  • wait_for_inclusion (bool) – If set, waits for the extrinsic to enter a block before returning True, or returns False if the extrinsic fails to enter the block within the timeout.

  • wait_for_finalization (bool) – If set, waits for the extrinsic to be finalized on the chain before returning True, or returns False if the extrinsic fails to be finalized within the timeout.

  • max_allowed_attempts (int) – Maximum number of attempts to register the wallet.

  • output_in_place (bool) – Whether to output logging data as the process runs.

  • cuda (bool) – If True, the wallet should be registered using CUDA device(s).

  • dev_id (int) – The CUDA device id to use

  • tpb (int) – The number of threads per block (CUDA).

  • num_processes (Optional[int]) – The number of processes to use to register.

  • update_interval (Optional[int]) – The number of nonces to solve between updates.

  • log_verbose (bool) – If True, the registration process will log more information.

  • max_successes (int) – The maximum number of successful faucet runs for the wallet.

Returns:

True if extrinsic was finalized or included in the block. If we did not wait for finalization/inclusion, the response is also True

Return type:

tuple[bool, str]

bittensor.core.extrinsics.async_registration.solve_cuda(nonce_start, update_interval, tpb, block_and_hotkey_hash_bytes, difficulty, limit, dev_id=0)#

Solves the PoW problem using CUDA.

nonce_start: Starting nonce. update_interval: Number of nonces to solve before updating block information. tpb: Threads per block. block_and_hotkey_hash_bytes: Keccak(Bytes of the block hash + bytes of the hotkey) 64 bytes. difficulty: Difficulty of the PoW problem. limit: Upper limit of the nonce. dev_id: The CUDA device ID

Returns:

(nonce, seal) corresponding to the solution. Returns -1 for nonce if no solution is found.

Parameters:
  • nonce_start (numpy.int64)

  • update_interval (numpy.int64)

  • tpb (int)

  • block_and_hotkey_hash_bytes (bytes)

  • difficulty (int)

  • limit (int)

  • dev_id (int)

Return type:

tuple[numpy.int64, bytes]

bittensor.core.extrinsics.async_registration.torch#
bittensor.core.extrinsics.async_registration.use_torch()#

Force the use of torch over numpy for certain operations.

Return type:

bool