|
11 | 11 |
|
12 | 12 | from bittensor_wallet import Wallet |
13 | 13 |
|
14 | | -from bittensor.utils import format_error_message |
| 14 | +from bittensor.utils import format_error_message, unlock_key |
15 | 15 | from bittensor.utils.btlogging import logging |
16 | 16 | from bittensor.utils.registration import log_no_torch_error, create_pow_async |
17 | 17 |
|
@@ -263,3 +263,140 @@ async def register_extrinsic( |
263 | 263 | # Failed to register after max attempts. |
264 | 264 | logging.error("[red]No more attempts.[/red]") |
265 | 265 | return False |
| 266 | + |
| 267 | + |
| 268 | +async def _do_burned_register( |
| 269 | + subtensor: "AsyncSubtensor", |
| 270 | + netuid: int, |
| 271 | + wallet: "Wallet", |
| 272 | + wait_for_inclusion: bool = False, |
| 273 | + wait_for_finalization: bool = True, |
| 274 | +) -> tuple[bool, Optional[str]]: |
| 275 | + """ |
| 276 | + Performs a burned register extrinsic call to the Subtensor chain. |
| 277 | +
|
| 278 | + This method sends a registration transaction to the Subtensor blockchain using the burned register mechanism. |
| 279 | +
|
| 280 | + Args: |
| 281 | + subtensor (bittensor.core.async_subtensor.AsyncSubtensor): AsyncSubtensor instance. |
| 282 | + netuid (int): The network unique identifier to register on. |
| 283 | + wallet (bittensor_wallet.Wallet): The wallet to be registered. |
| 284 | + wait_for_inclusion (bool): Whether to wait for the transaction to be included in a block. Default is False. |
| 285 | + wait_for_finalization (bool): Whether to wait for the transaction to be finalized. Default is True. |
| 286 | +
|
| 287 | + Returns: |
| 288 | + Tuple[bool, Optional[str]]: A tuple containing a boolean indicating success or failure, and an optional error message. |
| 289 | + """ |
| 290 | + |
| 291 | + # create extrinsic call |
| 292 | + call = await subtensor.substrate.compose_call( |
| 293 | + call_module="SubtensorModule", |
| 294 | + call_function="burned_register", |
| 295 | + call_params={ |
| 296 | + "netuid": netuid, |
| 297 | + "hotkey": wallet.hotkey.ss58_address, |
| 298 | + }, |
| 299 | + ) |
| 300 | + extrinsic = await subtensor.substrate.create_signed_extrinsic( |
| 301 | + call=call, keypair=wallet.coldkey |
| 302 | + ) |
| 303 | + response = await subtensor.substrate.submit_extrinsic( |
| 304 | + extrinsic=extrinsic, |
| 305 | + wait_for_inclusion=wait_for_inclusion, |
| 306 | + wait_for_finalization=wait_for_finalization, |
| 307 | + ) |
| 308 | + |
| 309 | + # We only wait here if we expect finalization. |
| 310 | + if not wait_for_finalization and not wait_for_inclusion: |
| 311 | + return True, None |
| 312 | + |
| 313 | + # process if registration successful, try again if pow is still valid |
| 314 | + await response.process_events() |
| 315 | + if not await response.is_success: |
| 316 | + return False, format_error_message(error_message=await response.error_message) |
| 317 | + # Successful registration |
| 318 | + else: |
| 319 | + return True, None |
| 320 | + |
| 321 | + |
| 322 | +async def burned_register_extrinsic( |
| 323 | + subtensor: "AsyncSubtensor", |
| 324 | + wallet: "Wallet", |
| 325 | + netuid: int, |
| 326 | + wait_for_inclusion: bool = False, |
| 327 | + wait_for_finalization: bool = True, |
| 328 | +) -> bool: |
| 329 | + """Registers the wallet to chain by recycling TAO. |
| 330 | +
|
| 331 | + Args: |
| 332 | + subtensor (bittensor.core.async_subtensor.AsyncSubtensor): AsyncSubtensor instance. |
| 333 | + wallet (bittensor.wallet): Bittensor wallet object. |
| 334 | + netuid (int): The ``netuid`` of the subnet to register on. |
| 335 | + 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. |
| 336 | + 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. |
| 337 | +
|
| 338 | + Returns: |
| 339 | + success (bool): Flag is ``true`` if extrinsic was finalized or uncluded in the block. If we did not wait for finalization / inclusion, the response is ``true``. |
| 340 | + """ |
| 341 | + if not await subtensor.subnet_exists(netuid): |
| 342 | + logging.error( |
| 343 | + f":cross_mark: [red]Failed error:[/red] subnet [blue]{netuid}[/blue] does not exist." |
| 344 | + ) |
| 345 | + return False |
| 346 | + |
| 347 | + if not (unlock := unlock_key(wallet)).success: |
| 348 | + logging.error(unlock.message) |
| 349 | + return False |
| 350 | + |
| 351 | + logging.info( |
| 352 | + f":satellite: [magenta]Checking Account on subnet[/magenta] [blue]{netuid}[/blue][magenta] ...[/magenta]" |
| 353 | + ) |
| 354 | + neuron = await subtensor.get_neuron_for_pubkey_and_subnet( |
| 355 | + wallet.hotkey.ss58_address, netuid=netuid |
| 356 | + ) |
| 357 | + |
| 358 | + old_balance = await subtensor.get_balance(wallet.coldkeypub.ss58_address) |
| 359 | + |
| 360 | + if not neuron.is_null: |
| 361 | + logging.info(":white_heavy_check_mark: [green]Already Registered[/green]") |
| 362 | + logging.info(f"\t\tuid: [blue]{neuron.uid}[/blue]") |
| 363 | + logging.info(f"\t\tnetuid: [blue]{neuron.netuid}[/blue]") |
| 364 | + logging.info(f"\t\thotkey: [blue]{neuron.hotkey}[/blue]") |
| 365 | + logging.info(f"\t\tcoldkey: [blue]{neuron.coldkey}[/blue]") |
| 366 | + return True |
| 367 | + |
| 368 | + logging.info(":satellite: [magenta]Recycling TAO for Registration...[/magenta]") |
| 369 | + |
| 370 | + recycle_amount = await subtensor.recycle(netuid=netuid) |
| 371 | + logging.info(f"Recycling {recycle_amount} to register on subnet:{netuid}") |
| 372 | + |
| 373 | + success, err_msg = await _do_burned_register( |
| 374 | + subtensor=subtensor, |
| 375 | + netuid=netuid, |
| 376 | + wallet=wallet, |
| 377 | + wait_for_inclusion=wait_for_inclusion, |
| 378 | + wait_for_finalization=wait_for_finalization, |
| 379 | + ) |
| 380 | + |
| 381 | + if not success: |
| 382 | + logging.error(f":cross_mark: [red]Failed error:[/red] {err_msg}") |
| 383 | + await asyncio.sleep(0.5) |
| 384 | + return False |
| 385 | + # Successful registration, final check for neuron and pubkey |
| 386 | + else: |
| 387 | + logging.info(":satellite: [magenta]Checking Balance...[/magenta]") |
| 388 | + new_balance = await subtensor.get_balance(wallet.coldkeypub.ss58_address) |
| 389 | + |
| 390 | + logging.info( |
| 391 | + f"Balance: [blue]{old_balance}[/blue] :arrow_right: [green]{new_balance}[/green]" |
| 392 | + ) |
| 393 | + is_registered = await subtensor.is_hotkey_registered( |
| 394 | + netuid=netuid, hotkey_ss58=wallet.hotkey.ss58_address |
| 395 | + ) |
| 396 | + if is_registered: |
| 397 | + logging.info(":white_heavy_check_mark: [green]Registered[/green]") |
| 398 | + return True |
| 399 | + else: |
| 400 | + # neuron not found, try again |
| 401 | + logging.error(":cross_mark: [red]Unknown error. Neuron not found.[/red]") |
| 402 | + return False |
0 commit comments