Skip to content

Commit 2300a52

Browse files
Merge pull request #2732 from opentensor/fix/zyzniewski/burned_register_supports_root_subnet
Fix: burned_register supports root subnet (netuid=0 param)
2 parents 14b899a + 2756671 commit 2300a52

File tree

8 files changed

+314
-80
lines changed

8 files changed

+314
-80
lines changed

bittensor/core/async_subtensor.py

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2915,6 +2915,14 @@ async def burned_register(
29152915
bool: ``True`` if the registration is successful, False otherwise.
29162916
"""
29172917
async with self:
2918+
if netuid == 0:
2919+
return await root_register_extrinsic(
2920+
subtensor=self,
2921+
wallet=wallet,
2922+
wait_for_inclusion=wait_for_inclusion,
2923+
wait_for_finalization=wait_for_finalization,
2924+
)
2925+
29182926
return await burned_register_extrinsic(
29192927
subtensor=self,
29202928
wallet=wallet,
@@ -3205,35 +3213,6 @@ async def root_register(
32053213
Returns:
32063214
`True` if registration was successful, otherwise `False`.
32073215
"""
3208-
netuid = 0
3209-
logging.info(
3210-
f"Registering on netuid [blue]0[/blue] on network: [blue]{self.network}[/blue]"
3211-
)
3212-
3213-
# Check current recycle amount
3214-
logging.info("Fetching recycle amount & balance.")
3215-
block_hash = block_hash if block_hash else await self.get_block_hash()
3216-
3217-
try:
3218-
recycle_call, balance = await asyncio.gather(
3219-
self.get_hyperparameter(
3220-
param_name="Burn", netuid=netuid, block_hash=block_hash
3221-
),
3222-
self.get_balance(wallet.coldkeypub.ss58_address, block_hash=block_hash),
3223-
)
3224-
except TypeError as e:
3225-
logging.error(f"Unable to retrieve current recycle. {e}")
3226-
return False
3227-
3228-
current_recycle = Balance.from_rao(int(recycle_call))
3229-
3230-
# Check balance is sufficient
3231-
if balance < current_recycle:
3232-
logging.error(
3233-
f"[red]Insufficient balance {balance} to register neuron. "
3234-
f"Current recycle is {current_recycle} TAO[/red]."
3235-
)
3236-
return False
32373216

32383217
return await root_register_extrinsic(
32393218
subtensor=self,

bittensor/core/extrinsics/asyncex/root.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from bittensor.core.errors import SubstrateRequestException
99
from bittensor.utils import u16_normalized_float, format_error_message, unlock_key
10+
from bittensor.utils.balance import Balance
1011
from bittensor.utils.btlogging import logging
1112
from bittensor.utils.weight_utils import (
1213
normalize_max_weight,
@@ -62,6 +63,33 @@ async def root_register_extrinsic(
6263
the response is `True`.
6364
"""
6465
netuid = 0
66+
logging.info(
67+
f"Registering on netuid [blue]{netuid}[/blue] on network: [blue]{subtensor.network}[/blue]"
68+
)
69+
70+
logging.info("Fetching recycle amount & balance.")
71+
block_hash = await subtensor.get_block_hash()
72+
recycle_call, balance = await asyncio.gather(
73+
subtensor.get_hyperparameter(
74+
param_name="Burn",
75+
netuid=netuid,
76+
block_hash=block_hash,
77+
),
78+
subtensor.get_balance(
79+
wallet.coldkeypub.ss58_address,
80+
block_hash=block_hash,
81+
),
82+
)
83+
84+
current_recycle = Balance.from_rao(int(recycle_call))
85+
86+
if balance < current_recycle:
87+
logging.error(
88+
f"[red]Insufficient balance {balance} to register neuron. "
89+
f"Current recycle is {current_recycle} TAO[/red]."
90+
)
91+
return False
92+
6593
if not (unlock := unlock_key(wallet)).success:
6694
logging.error(unlock.message)
6795
return False

bittensor/core/extrinsics/root.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
unlock_key,
1212
torch,
1313
)
14+
from bittensor.utils.balance import Balance
1415
from bittensor.utils.btlogging import logging
1516
from bittensor.utils.weight_utils import (
1617
normalize_max_weight,
@@ -65,6 +66,30 @@ def root_register_extrinsic(
6566
response is `True`.
6667
"""
6768
netuid = 0
69+
logging.info(
70+
f"Registering on netuid [blue]{netuid}[/blue] on network: [blue]{subtensor.network}[/blue]"
71+
)
72+
73+
logging.info("Fetching recycle amount & balance.")
74+
block = subtensor.get_current_block()
75+
recycle_call = subtensor.get_hyperparameter(
76+
param_name="Burn",
77+
netuid=netuid,
78+
block=block,
79+
)
80+
balance = subtensor.get_balance(
81+
wallet.coldkeypub.ss58_address,
82+
block=block,
83+
)
84+
85+
current_recycle = Balance.from_rao(int(recycle_call))
86+
87+
if balance < current_recycle:
88+
logging.error(
89+
f"[red]Insufficient balance {balance} to register neuron. "
90+
f"Current recycle is {current_recycle} TAO[/red]."
91+
)
92+
return False
6893

6994
if not (unlock := unlock_key(wallet)).success:
7095
logging.error(unlock.message)

bittensor/core/subtensor.py

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2234,6 +2234,15 @@ def burned_register(
22342234
Returns:
22352235
bool: ``True`` if the registration is successful, False otherwise.
22362236
"""
2237+
2238+
if netuid == 0:
2239+
return root_register_extrinsic(
2240+
subtensor=self,
2241+
wallet=wallet,
2242+
wait_for_inclusion=wait_for_inclusion,
2243+
wait_for_finalization=wait_for_finalization,
2244+
)
2245+
22372246
return burned_register_extrinsic(
22382247
subtensor=self,
22392248
wallet=wallet,
@@ -2521,32 +2530,6 @@ def root_register(
25212530
Returns:
25222531
`True` if registration was successful, otherwise `False`.
25232532
"""
2524-
logging.info(
2525-
f"Registering on netuid [blue]0[/blue] on network: [blue]{self.network}[/blue]"
2526-
)
2527-
2528-
# Check current recycle amount
2529-
logging.info("Fetching recycle amount & balance.")
2530-
block = self.get_current_block()
2531-
2532-
try:
2533-
recycle_call = cast(
2534-
int, self.get_hyperparameter(param_name="Burn", netuid=0, block=block)
2535-
)
2536-
balance = self.get_balance(wallet.coldkeypub.ss58_address, block=block)
2537-
except TypeError as e:
2538-
logging.error(f"Unable to retrieve current recycle. {e}")
2539-
return False
2540-
2541-
current_recycle = Balance.from_rao(int(recycle_call))
2542-
2543-
# Check balance is sufficient
2544-
if balance < current_recycle:
2545-
logging.error(
2546-
f"[red]Insufficient balance {balance} to register neuron. "
2547-
f"Current recycle is {current_recycle} TAO[/red]."
2548-
)
2549-
return False
25502533

25512534
return root_register_extrinsic(
25522535
subtensor=self,

tests/unit_tests/extrinsics/asyncex/test_root.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from bittensor.core.errors import SubstrateRequestException
44
from bittensor.core.extrinsics.asyncex import root as async_root
55

6+
from bittensor.utils.balance import Balance
7+
68

79
@pytest.mark.asyncio
810
async def test_get_limits_success(subtensor, mocker):
@@ -62,6 +64,16 @@ async def test_root_register_extrinsic_success(subtensor, fake_wallet, mocker):
6264
"query",
6365
return_value=fake_uid,
6466
)
67+
mocker.patch.object(
68+
subtensor,
69+
"get_hyperparameter",
70+
return_value=Balance(0),
71+
)
72+
mocker.patch.object(
73+
subtensor,
74+
"get_balance",
75+
return_value=Balance(1),
76+
)
6577

6678
# Call
6779
result = await async_root.root_register_extrinsic(
@@ -86,10 +98,53 @@ async def test_root_register_extrinsic_success(subtensor, fake_wallet, mocker):
8698
assert result is True
8799

88100

101+
@pytest.mark.asyncio
102+
async def test_root_register_extrinsic_insufficient_balance(
103+
subtensor,
104+
fake_wallet,
105+
mocker,
106+
):
107+
mocker.patch.object(
108+
subtensor,
109+
"get_hyperparameter",
110+
return_value=Balance(1),
111+
)
112+
mocker.patch.object(
113+
subtensor,
114+
"get_balance",
115+
return_value=Balance(0),
116+
)
117+
118+
result = await async_root.root_register_extrinsic(
119+
subtensor=subtensor,
120+
wallet=fake_wallet,
121+
wait_for_inclusion=True,
122+
wait_for_finalization=True,
123+
)
124+
125+
assert result is False
126+
127+
subtensor.get_balance.assert_called_once_with(
128+
fake_wallet.coldkeypub.ss58_address,
129+
block_hash=subtensor.substrate.get_chain_head.return_value,
130+
)
131+
subtensor.substrate.submit_extrinsic.assert_not_called()
132+
133+
89134
@pytest.mark.asyncio
90135
async def test_root_register_extrinsic_unlock_failed(subtensor, fake_wallet, mocker):
91136
"""Tests registration fails due to unlock failure."""
92137
# Preps
138+
mocker.patch.object(
139+
subtensor,
140+
"get_hyperparameter",
141+
return_value=Balance(0),
142+
)
143+
mocker.patch.object(
144+
subtensor,
145+
"get_balance",
146+
return_value=Balance(1),
147+
)
93148
mocked_unlock_key = mocker.patch.object(
94149
async_root,
95150
"unlock_key",
@@ -117,6 +172,16 @@ async def test_root_register_extrinsic_already_registered(
117172
# Preps
118173
fake_wallet.hotkey.ss58_address = "fake_hotkey_address"
119174

175+
mocker.patch.object(
176+
subtensor,
177+
"get_hyperparameter",
178+
return_value=Balance(0),
179+
)
180+
mocker.patch.object(
181+
subtensor,
182+
"get_balance",
183+
return_value=Balance(1),
184+
)
120185
mocked_unlock_key = mocker.patch.object(
121186
async_root,
122187
"unlock_key",
@@ -152,6 +217,16 @@ async def test_root_register_extrinsic_transaction_failed(
152217
# Preps
153218
fake_wallet.hotkey.ss58_address = "fake_hotkey_address"
154219

220+
mocker.patch.object(
221+
subtensor,
222+
"get_hyperparameter",
223+
return_value=Balance(0),
224+
)
225+
mocker.patch.object(
226+
subtensor,
227+
"get_balance",
228+
return_value=Balance(1),
229+
)
155230
mocked_unlock_key = mocker.patch.object(
156231
async_root,
157232
"unlock_key",
@@ -193,6 +268,16 @@ async def test_root_register_extrinsic_uid_not_found(subtensor, fake_wallet, moc
193268
# Preps
194269
fake_wallet.hotkey.ss58_address = "fake_hotkey_address"
195270

271+
mocker.patch.object(
272+
subtensor,
273+
"get_hyperparameter",
274+
return_value=Balance(0),
275+
)
276+
mocker.patch.object(
277+
subtensor,
278+
"get_balance",
279+
return_value=Balance(1),
280+
)
196281
mocked_unlock_key = mocker.patch.object(
197282
async_root,
198283
"unlock_key",

tests/unit_tests/extrinsics/test_root.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pytest
22
from bittensor.core.subtensor import Subtensor
33
from bittensor.core.extrinsics import root
4+
from bittensor.utils.balance import Balance
45

56

67
@pytest.fixture
@@ -75,6 +76,11 @@ def test_root_register_extrinsic(
7576
"query",
7677
return_value=hotkey_registered[1],
7778
)
79+
mocker.patch.object(
80+
mock_subtensor,
81+
"get_balance",
82+
return_value=Balance(1),
83+
)
7884

7985
# Act
8086
result = root.root_register_extrinsic(
@@ -100,6 +106,31 @@ def test_root_register_extrinsic(
100106
)
101107

102108

109+
def test_root_register_extrinsic_insufficient_balance(
110+
mock_subtensor,
111+
mock_wallet,
112+
mocker,
113+
):
114+
mocker.patch.object(
115+
mock_subtensor,
116+
"get_balance",
117+
return_value=Balance(0),
118+
)
119+
120+
success = root.root_register_extrinsic(
121+
subtensor=mock_subtensor,
122+
wallet=mock_wallet,
123+
)
124+
125+
assert success is False
126+
127+
mock_subtensor.get_balance.assert_called_once_with(
128+
mock_wallet.coldkeypub.ss58_address,
129+
block=mock_subtensor.get_current_block.return_value,
130+
)
131+
mock_subtensor.substrate.submit_extrinsic.assert_not_called()
132+
133+
103134
@pytest.mark.parametrize(
104135
"wait_for_inclusion, wait_for_finalization, netuids, weights, expected_success",
105136
[

0 commit comments

Comments
 (0)