Skip to content

Commit b557952

Browse files
fix: burned_register supports root (0) subnet
1 parent d6ae4fa commit b557952

File tree

8 files changed

+324
-80
lines changed

8 files changed

+324
-80
lines changed

bittensor/core/async_subtensor.py

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2901,6 +2901,14 @@ async def burned_register(
29012901
bool: ``True`` if the registration is successful, False otherwise.
29022902
"""
29032903
async with self:
2904+
if netuid == 0:
2905+
return await root_register_extrinsic(
2906+
subtensor=self,
2907+
wallet=wallet,
2908+
wait_for_inclusion=wait_for_inclusion,
2909+
wait_for_finalization=wait_for_finalization,
2910+
)
2911+
29042912
return await burned_register_extrinsic(
29052913
subtensor=self,
29062914
wallet=wallet,
@@ -3191,35 +3199,6 @@ async def root_register(
31913199
Returns:
31923200
`True` if registration was successful, otherwise `False`.
31933201
"""
3194-
netuid = 0
3195-
logging.info(
3196-
f"Registering on netuid [blue]0[/blue] on network: [blue]{self.network}[/blue]"
3197-
)
3198-
3199-
# Check current recycle amount
3200-
logging.info("Fetching recycle amount & balance.")
3201-
block_hash = block_hash if block_hash else await self.get_block_hash()
3202-
3203-
try:
3204-
recycle_call, balance = await asyncio.gather(
3205-
self.get_hyperparameter(
3206-
param_name="Burn", netuid=netuid, block_hash=block_hash
3207-
),
3208-
self.get_balance(wallet.coldkeypub.ss58_address, block_hash=block_hash),
3209-
)
3210-
except TypeError as e:
3211-
logging.error(f"Unable to retrieve current recycle. {e}")
3212-
return False
3213-
3214-
current_recycle = Balance.from_rao(int(recycle_call))
3215-
3216-
# Check balance is sufficient
3217-
if balance < current_recycle:
3218-
logging.error(
3219-
f"[red]Insufficient balance {balance} to register neuron. "
3220-
f"Current recycle is {current_recycle} TAO[/red]."
3221-
)
3222-
return False
32233202

32243203
return await root_register_extrinsic(
32253204
subtensor=self,

bittensor/core/extrinsics/asyncex/root.py

Lines changed: 33 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,38 @@ 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+
73+
try:
74+
recycle_call, balance = await asyncio.gather(
75+
subtensor.get_hyperparameter(
76+
param_name="Burn",
77+
netuid=netuid,
78+
block_hash=block_hash,
79+
),
80+
subtensor.get_balance(
81+
wallet.coldkeypub.ss58_address,
82+
block_hash=block_hash,
83+
),
84+
)
85+
except TypeError as e:
86+
logging.error(f"Unable to retrieve current recycle. {e}")
87+
return False
88+
89+
current_recycle = Balance.from_rao(int(recycle_call))
90+
91+
if balance < current_recycle:
92+
logging.error(
93+
f"[red]Insufficient balance {balance} to register neuron. "
94+
f"Current recycle is {current_recycle} TAO[/red]."
95+
)
96+
return False
97+
6598
if not (unlock := unlock_key(wallet)).success:
6699
logging.error(unlock.message)
67100
return False

bittensor/core/extrinsics/root.py

Lines changed: 30 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,35 @@ 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+
76+
try:
77+
recycle_call = subtensor.get_hyperparameter(
78+
param_name="Burn",
79+
netuid=netuid,
80+
block=block,
81+
)
82+
balance = subtensor.get_balance(
83+
wallet.coldkeypub.ss58_address,
84+
block=block,
85+
)
86+
except TypeError as e:
87+
logging.error(f"Unable to retrieve current recycle. {e}")
88+
return False
89+
90+
current_recycle = Balance.from_rao(int(recycle_call))
91+
92+
if balance < current_recycle:
93+
logging.error(
94+
f"[red]Insufficient balance {balance} to register neuron. "
95+
f"Current recycle is {current_recycle} TAO[/red]."
96+
)
97+
return False
6898

6999
if not (unlock := unlock_key(wallet)).success:
70100
logging.error(unlock.message)

bittensor/core/subtensor.py

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2219,6 +2219,15 @@ def burned_register(
22192219
Returns:
22202220
bool: ``True`` if the registration is successful, False otherwise.
22212221
"""
2222+
2223+
if netuid == 0:
2224+
return root_register_extrinsic(
2225+
subtensor=self,
2226+
wallet=wallet,
2227+
wait_for_inclusion=wait_for_inclusion,
2228+
wait_for_finalization=wait_for_finalization,
2229+
)
2230+
22222231
return burned_register_extrinsic(
22232232
subtensor=self,
22242233
wallet=wallet,
@@ -2506,32 +2515,6 @@ def root_register(
25062515
Returns:
25072516
`True` if registration was successful, otherwise `False`.
25082517
"""
2509-
logging.info(
2510-
f"Registering on netuid [blue]0[/blue] on network: [blue]{self.network}[/blue]"
2511-
)
2512-
2513-
# Check current recycle amount
2514-
logging.info("Fetching recycle amount & balance.")
2515-
block = self.get_current_block()
2516-
2517-
try:
2518-
recycle_call = cast(
2519-
int, self.get_hyperparameter(param_name="Burn", netuid=0, block=block)
2520-
)
2521-
balance = self.get_balance(wallet.coldkeypub.ss58_address, block=block)
2522-
except TypeError as e:
2523-
logging.error(f"Unable to retrieve current recycle. {e}")
2524-
return False
2525-
2526-
current_recycle = Balance.from_rao(int(recycle_call))
2527-
2528-
# Check balance is sufficient
2529-
if balance < current_recycle:
2530-
logging.error(
2531-
f"[red]Insufficient balance {balance} to register neuron. "
2532-
f"Current recycle is {current_recycle} TAO[/red]."
2533-
)
2534-
return False
25352518

25362519
return root_register_extrinsic(
25372520
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)