From b58980699ba6af3198c71a3fd870e03d59fc8908 Mon Sep 17 00:00:00 2001 From: ibraheem-latent Date: Thu, 19 Feb 2026 14:43:26 -0800 Subject: [PATCH 01/11] bump drand --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 0cfe2953..74ea3ff1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,7 +33,7 @@ dependencies = [ "async-substrate-interface>=1.6.0", "aiohttp~=3.13", "backoff~=2.2.1", - "bittensor-drand>=1.2.0", + "bittensor-drand>=1.3.0", "GitPython>=3.0.0", "netaddr~=1.3.0", "numpy>=2.0.1,<3.0.0", From feed3b22cd535d8d6b9a76bd32860aa2c1b0f6bd Mon Sep 17 00:00:00 2001 From: ibraheem-latent Date: Thu, 19 Feb 2026 15:01:17 -0800 Subject: [PATCH 02/11] add error handling --- bittensor_cli/src/bittensor/subtensor_interface.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bittensor_cli/src/bittensor/subtensor_interface.py b/bittensor_cli/src/bittensor/subtensor_interface.py index 7eb93aa7..2711e882 100644 --- a/bittensor_cli/src/bittensor/subtensor_interface.py +++ b/bittensor_cli/src/bittensor/subtensor_interface.py @@ -1302,6 +1302,11 @@ async def create_signed(call_to_sign, n): return False, format_error_message(await response.error_message), None except SubstrateRequestException as e: err_msg = format_error_message(e) + if mev_protection and "'result': 'invalid'" in str(e).lower(): + err_msg = ( + f"MEV Shield extrinsic rejected as invalid. " + f"This usually means the MEV Shield NextKey changed between fetching and submission." + ) if proxy and "Invalid Transaction" in err_msg: extrinsic_fee, signer_balance = await asyncio.gather( self.get_extrinsic_fee( From 11aed9accea37999167c137e8b117a57b310f021 Mon Sep 17 00:00:00 2001 From: ibraheem-latent Date: Thu, 19 Feb 2026 15:07:39 -0800 Subject: [PATCH 03/11] update encrypt_extrinsic --- .../src/bittensor/extrinsics/mev_shield.py | 29 ++----------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/bittensor_cli/src/bittensor/extrinsics/mev_shield.py b/bittensor_cli/src/bittensor/extrinsics/mev_shield.py index 4eabbd2b..5ec84830 100644 --- a/bittensor_cli/src/bittensor/extrinsics/mev_shield.py +++ b/bittensor_cli/src/bittensor/extrinsics/mev_shield.py @@ -1,4 +1,3 @@ -import hashlib from typing import TYPE_CHECKING, Optional from async_substrate_interface import AsyncExtrinsicReceipt @@ -37,18 +36,15 @@ async def encrypt_extrinsic( plaintext = bytes(signed_extrinsic.data.data) # Encrypt using ML-KEM-768 - ciphertext = encrypt_mlkem768(ml_kem_768_public_key, plaintext) - - # Commitment: blake2_256(payload_core) - commitment_hash = hashlib.blake2b(plaintext, digest_size=32).digest() - commitment_hex = "0x" + commitment_hash.hex() + ciphertext = encrypt_mlkem768( + ml_kem_768_public_key, plaintext, include_key_hash=False + ) # Create the MevShield.submit_encrypted call encrypted_call = await subtensor.substrate.compose_call( call_module="MevShield", call_function="submit_encrypted", call_params={ - "commitment": commitment_hex, "ciphertext": ciphertext, }, ) @@ -56,25 +52,6 @@ async def encrypt_extrinsic( return encrypted_call -async def extract_mev_shield_id(response: "AsyncExtrinsicReceipt") -> Optional[str]: - """ - Extract the MEV Shield wrapper ID from an extrinsic response. - - After submitting a MEV Shield encrypted call, the EncryptedSubmitted event - contains the wrapper ID needed to track execution. - - Args: - response: The extrinsic receipt from submit_extrinsic. - - Returns: - The wrapper ID (hex string) or None if not found. - """ - for event in await response.triggered_events: - if event["event_id"] == "EncryptedSubmitted": - return event["attributes"]["id"] - return None - - async def wait_for_extrinsic_by_hash( subtensor: "SubtensorInterface", extrinsic_hash: str, From cb2e14f978c95a6cf20c358501c51c378363949a Mon Sep 17 00:00:00 2001 From: ibraheem-latent Date: Thu, 19 Feb 2026 15:08:02 -0800 Subject: [PATCH 04/11] update wait_for_extrinsic_by_hash --- .../src/bittensor/extrinsics/mev_shield.py | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/bittensor_cli/src/bittensor/extrinsics/mev_shield.py b/bittensor_cli/src/bittensor/extrinsics/mev_shield.py index 5ec84830..73c76548 100644 --- a/bittensor_cli/src/bittensor/extrinsics/mev_shield.py +++ b/bittensor_cli/src/bittensor/extrinsics/mev_shield.py @@ -55,7 +55,6 @@ async def encrypt_extrinsic( async def wait_for_extrinsic_by_hash( subtensor: "SubtensorInterface", extrinsic_hash: str, - shield_id: str, submit_block_hash: str, timeout_blocks: int = 2, status=None, @@ -89,7 +88,7 @@ async def _noop(_): return True starting_block = await subtensor.substrate.get_block_number(submit_block_hash) - current_block = starting_block + 1 + current_block = starting_block while current_block - starting_block <= timeout_blocks: if status: @@ -114,20 +113,6 @@ async def _noop(_): result_idx = idx break - # Failure: Decryption failed - call = extrinsic.value.get("call", {}) - if ( - call.get("call_module") == "MevShield" - and call.get("call_function") == "mark_decryption_failed" - ): - call_args = call.get("call_args", []) - for arg in call_args: - if arg.get("name") == "id" and arg.get("value") == shield_id: - result_idx = idx - break - if result_idx is not None: - break - if result_idx is not None: receipt = AsyncExtrinsicReceipt( substrate=subtensor.substrate, From e842f2e6590eee6d1e18fbbc870b6e402e572c24 Mon Sep 17 00:00:00 2001 From: ibraheem-latent Date: Thu, 19 Feb 2026 15:08:39 -0800 Subject: [PATCH 05/11] update wallet extrinsics --- bittensor_cli/src/commands/wallets.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/bittensor_cli/src/commands/wallets.py b/bittensor_cli/src/commands/wallets.py index abd76d35..84bd13c0 100644 --- a/bittensor_cli/src/commands/wallets.py +++ b/bittensor_cli/src/commands/wallets.py @@ -24,7 +24,6 @@ NeuronInfoLite, ) from bittensor_cli.src.bittensor.extrinsics.mev_shield import ( - extract_mev_shield_id, wait_for_extrinsic_by_hash, ) from bittensor_cli.src.bittensor.extrinsics.registration import ( @@ -2176,11 +2175,9 @@ async def announce_coldkey_swap( if mev_protection: inner_hash = err_msg - mev_shield_id = await extract_mev_shield_id(ext_receipt) mev_success, mev_error, ext_receipt = await wait_for_extrinsic_by_hash( subtensor=subtensor, extrinsic_hash=inner_hash, - shield_id=mev_shield_id, submit_block_hash=ext_receipt.block_hash, status=status, ) @@ -2307,7 +2304,7 @@ async def dispute_coldkey_swap( if not unlock_key(wallet).success: return False - with console.status(":satellite: Disputing coldkey swap on-chain..."): + with console.status(":satellite: Disputing coldkey swap on-chain...") as status: call = await subtensor.substrate.compose_call( call_module="SubtensorModule", call_function="dispute_coldkey_swap", @@ -2325,6 +2322,20 @@ async def dispute_coldkey_swap( print_error(f"Failed to dispute coldkey swap: {err_msg}") return False + if mev_protection: + inner_hash = err_msg + mev_success, mev_error, ext_receipt = await wait_for_extrinsic_by_hash( + subtensor=subtensor, + extrinsic_hash=inner_hash, + submit_block_hash=ext_receipt.block_hash, + status=status, + ) + if not mev_success: + print_error( + f"Failed to dispute coldkey swap: {mev_error}", status=status + ) + return False + print_success("[dark_sea_green3]Coldkey swap disputed.") await print_extrinsic_id(ext_receipt) @@ -2458,11 +2469,9 @@ async def execute_coldkey_swap( if mev_protection: inner_hash = err_msg - mev_shield_id = await extract_mev_shield_id(ext_receipt) mev_success, mev_error, ext_receipt = await wait_for_extrinsic_by_hash( subtensor=subtensor, extrinsic_hash=inner_hash, - shield_id=mev_shield_id, submit_block_hash=ext_receipt.block_hash, status=status, ) From 39f5a992588b554244857d9adc172d94cb75bf86 Mon Sep 17 00:00:00 2001 From: ibraheem-latent Date: Thu, 19 Feb 2026 15:08:53 -0800 Subject: [PATCH 06/11] add_stake --- bittensor_cli/src/commands/stake/add.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/bittensor_cli/src/commands/stake/add.py b/bittensor_cli/src/commands/stake/add.py index 7372d6a2..d44d4ff9 100644 --- a/bittensor_cli/src/commands/stake/add.py +++ b/bittensor_cli/src/commands/stake/add.py @@ -11,7 +11,6 @@ from bittensor_cli.src import COLOR_PALETTE from bittensor_cli.src.bittensor.balances import Balance from bittensor_cli.src.bittensor.extrinsics.mev_shield import ( - extract_mev_shield_id, wait_for_extrinsic_by_hash, ) from bittensor_cli.src.bittensor.utils import ( @@ -167,11 +166,9 @@ async def safe_stake_extrinsic( else: if mev_protection: inner_hash = err_msg - mev_shield_id = await extract_mev_shield_id(response) mev_success, mev_error, response = await wait_for_extrinsic_by_hash( subtensor=subtensor, extrinsic_hash=inner_hash, - shield_id=mev_shield_id, submit_block_hash=response.block_hash, status=status_, ) @@ -259,11 +256,9 @@ async def stake_extrinsic( else: if mev_protection: inner_hash = err_msg - mev_shield_id = await extract_mev_shield_id(response) mev_success, mev_error, response = await wait_for_extrinsic_by_hash( subtensor=subtensor, extrinsic_hash=inner_hash, - shield_id=mev_shield_id, submit_block_hash=response.block_hash, status=status_, ) From b6f5074efb31491db53b803bc9d363560f29f10a Mon Sep 17 00:00:00 2001 From: ibraheem-latent Date: Thu, 19 Feb 2026 15:09:03 -0800 Subject: [PATCH 07/11] move stake --- bittensor_cli/src/commands/stake/move.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/bittensor_cli/src/commands/stake/move.py b/bittensor_cli/src/commands/stake/move.py index 2e83e78c..b7b28c21 100644 --- a/bittensor_cli/src/commands/stake/move.py +++ b/bittensor_cli/src/commands/stake/move.py @@ -9,7 +9,6 @@ from bittensor_cli.src import COLOR_PALETTE from bittensor_cli.src.bittensor.balances import Balance from bittensor_cli.src.bittensor.extrinsics.mev_shield import ( - extract_mev_shield_id, wait_for_extrinsic_by_hash, ) from bittensor_cli.src.bittensor.utils import ( @@ -691,11 +690,9 @@ async def move_stake( if success_: if mev_protection: inner_hash = err_msg - mev_shield_id = await extract_mev_shield_id(response) mev_success, mev_error, response = await wait_for_extrinsic_by_hash( subtensor=subtensor, extrinsic_hash=inner_hash, - shield_id=mev_shield_id, submit_block_hash=response.block_hash, status=status, ) @@ -909,11 +906,9 @@ async def transfer_stake( if success_: if mev_protection: inner_hash = err_msg - mev_shield_id = await extract_mev_shield_id(response) mev_success, mev_error, response = await wait_for_extrinsic_by_hash( subtensor=subtensor, extrinsic_hash=inner_hash, - shield_id=mev_shield_id, submit_block_hash=response.block_hash, status=status, ) @@ -1147,11 +1142,9 @@ async def swap_stake( if success_: if mev_protection: inner_hash = err_msg - mev_shield_id = await extract_mev_shield_id(response) mev_success, mev_error, response = await wait_for_extrinsic_by_hash( subtensor=subtensor, extrinsic_hash=inner_hash, - shield_id=mev_shield_id, submit_block_hash=response.block_hash, status=status, ) From da203313024dd3a9e08a4f8abfb69e9cc6e6c2fb Mon Sep 17 00:00:00 2001 From: ibraheem-latent Date: Thu, 19 Feb 2026 15:09:14 -0800 Subject: [PATCH 08/11] stake removal --- bittensor_cli/src/commands/stake/remove.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/bittensor_cli/src/commands/stake/remove.py b/bittensor_cli/src/commands/stake/remove.py index 9cc782be..2c000eac 100644 --- a/bittensor_cli/src/commands/stake/remove.py +++ b/bittensor_cli/src/commands/stake/remove.py @@ -11,7 +11,6 @@ from bittensor_cli.src import COLOR_PALETTE from bittensor_cli.src.bittensor.extrinsics.mev_shield import ( - extract_mev_shield_id, wait_for_extrinsic_by_hash, ) from bittensor_cli.src.bittensor.balances import Balance @@ -652,11 +651,9 @@ async def _unstake_extrinsic( if success: if mev_protection: inner_hash = err_msg - mev_shield_id = await extract_mev_shield_id(response) mev_success, mev_error, response = await wait_for_extrinsic_by_hash( subtensor=subtensor, extrinsic_hash=inner_hash, - shield_id=mev_shield_id, submit_block_hash=response.block_hash, status=status, ) @@ -767,11 +764,9 @@ async def _safe_unstake_extrinsic( if success: if mev_protection: inner_hash = err_msg - mev_shield_id = await extract_mev_shield_id(response) mev_success, mev_error, response = await wait_for_extrinsic_by_hash( subtensor=subtensor, extrinsic_hash=inner_hash, - shield_id=mev_shield_id, submit_block_hash=response.block_hash, status=status, ) @@ -897,11 +892,9 @@ async def _unstake_all_extrinsic( if mev_protection: inner_hash = err_msg - mev_shield_id = await extract_mev_shield_id(response) mev_success, mev_error, response = await wait_for_extrinsic_by_hash( subtensor=subtensor, extrinsic_hash=inner_hash, - shield_id=mev_shield_id, submit_block_hash=response.block_hash, status=status, ) From 715892ca3cd0b364e07804f8c5d050e14c785231 Mon Sep 17 00:00:00 2001 From: ibraheem-latent Date: Thu, 19 Feb 2026 15:10:23 -0800 Subject: [PATCH 09/11] update subnets --- bittensor_cli/src/commands/subnets/subnets.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/bittensor_cli/src/commands/subnets/subnets.py b/bittensor_cli/src/commands/subnets/subnets.py index f627de7f..fcbc7dc0 100644 --- a/bittensor_cli/src/commands/subnets/subnets.py +++ b/bittensor_cli/src/commands/subnets/subnets.py @@ -20,7 +20,6 @@ ) from bittensor_cli.src.bittensor.extrinsics.root import root_register_extrinsic from bittensor_cli.src.bittensor.extrinsics.mev_shield import ( - extract_mev_shield_id, wait_for_extrinsic_by_hash, ) from rich.live import Live @@ -272,11 +271,9 @@ async def _find_event_attributes_in_extrinsic_receipt( # Check for MEV shield execution if mev_protection: inner_hash = err_msg - mev_shield_id = await extract_mev_shield_id(response) mev_success, mev_error, response = await wait_for_extrinsic_by_hash( subtensor=subtensor, extrinsic_hash=inner_hash, - shield_id=mev_shield_id, submit_block_hash=response.block_hash, status=status, ) From d400cc8ac367697fcdaaa11df34dd55395ae7552 Mon Sep 17 00:00:00 2001 From: ibraheem-latent Date: Thu, 19 Feb 2026 15:31:13 -0800 Subject: [PATCH 10/11] remove testing patch --- bittensor_cli/src/bittensor/extrinsics/mev_shield.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor_cli/src/bittensor/extrinsics/mev_shield.py b/bittensor_cli/src/bittensor/extrinsics/mev_shield.py index 73c76548..81750f2a 100644 --- a/bittensor_cli/src/bittensor/extrinsics/mev_shield.py +++ b/bittensor_cli/src/bittensor/extrinsics/mev_shield.py @@ -37,7 +37,7 @@ async def encrypt_extrinsic( # Encrypt using ML-KEM-768 ciphertext = encrypt_mlkem768( - ml_kem_768_public_key, plaintext, include_key_hash=False + ml_kem_768_public_key, plaintext, include_key_hash=True ) # Create the MevShield.submit_encrypted call From d647e5078d93c200bb4394706af5dfb102b9cb75 Mon Sep 17 00:00:00 2001 From: ibraheem-latent Date: Thu, 19 Feb 2026 17:14:14 -0800 Subject: [PATCH 11/11] bump ASI --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1bc704c5..798c8212 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,7 @@ classifiers = [ ] dependencies = [ "wheel", - "async-substrate-interface>=1.6.0", + "async-substrate-interface>=1.6.2", "aiohttp~=3.13", "backoff~=2.2.1", "bittensor-drand>=1.3.0",