Skip to content

Commit 6400f72

Browse files
committed
Adds nonce protection for staking/unstaking calls.
1 parent d244791 commit 6400f72

File tree

6 files changed

+85
-74
lines changed

6 files changed

+85
-74
lines changed

bittensor/core/extrinsics/asyncex/staking.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
from bittensor.utils.balance import Balance
77
from bittensor.utils.btlogging import logging
88
from bittensor.core.extrinsics.utils import get_old_stakes
9+
from bittensor.core.extrinsics.utils import (
10+
async_sign_and_send_with_nonce as sign_and_send_with_nonce,
11+
)
912

1013
if TYPE_CHECKING:
1114
from bittensor_wallet import Wallet
@@ -111,8 +114,8 @@ async def add_stake_extrinsic(
111114
"netuid": netuid,
112115
},
113116
)
114-
staking_response, err_msg = await subtensor.sign_and_send_extrinsic(
115-
call, wallet, wait_for_inclusion, wait_for_finalization
117+
staking_response, err_msg = await sign_and_send_with_nonce(
118+
subtensor, call, wallet, wait_for_inclusion, wait_for_finalization
116119
)
117120
if staking_response is True: # If we successfully staked.
118121
# We only wait here if we expect finalization.
@@ -295,8 +298,8 @@ async def add_stake_multiple_extrinsic(
295298
"netuid": netuid,
296299
},
297300
)
298-
staking_response, err_msg = await subtensor.sign_and_send_extrinsic(
299-
call, wallet, wait_for_inclusion, wait_for_finalization
301+
staking_response, err_msg = await sign_and_send_with_nonce(
302+
subtensor, call, wallet, wait_for_inclusion, wait_for_finalization
300303
)
301304

302305
if staking_response is True: # If we successfully staked.

bittensor/core/extrinsics/asyncex/unstaking.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
from typing import Optional, TYPE_CHECKING
33

44
from bittensor.core.errors import StakeError, NotRegisteredError
5+
from bittensor.core.extrinsics.utils import (
6+
async_sign_and_send_with_nonce as sign_and_send_with_nonce,
7+
)
58
from bittensor.utils import unlock_key
69
from bittensor.utils.balance import Balance
710
from bittensor.utils.btlogging import logging
@@ -97,8 +100,8 @@ async def unstake_extrinsic(
97100
"netuid": netuid,
98101
},
99102
)
100-
staking_response, err_msg = await subtensor.sign_and_send_extrinsic(
101-
call, wallet, wait_for_inclusion, wait_for_finalization
103+
staking_response, err_msg = await sign_and_send_with_nonce(
104+
subtensor, call, wallet, wait_for_inclusion, wait_for_finalization
102105
)
103106

104107
if staking_response is True: # If we successfully unstaked.
@@ -261,8 +264,9 @@ async def unstake_multiple_extrinsic(
261264
"netuid": netuid,
262265
},
263266
)
264-
staking_response, err_msg = await subtensor.sign_and_send_extrinsic(
265-
call, wallet, wait_for_inclusion, wait_for_finalization
267+
268+
staking_response, err_msg = await sign_and_send_with_nonce(
269+
subtensor, call, wallet, wait_for_inclusion, wait_for_finalization
266270
)
267271

268272
if staking_response is True: # If we successfully unstaked.

bittensor/core/extrinsics/asyncex/weights.py

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,47 +9,14 @@
99
from bittensor.core.settings import version_as_int
1010
from bittensor.utils import format_error_message
1111
from bittensor.utils.btlogging import logging
12+
from bittensor.core.extrinsics.utils import (
13+
async_sign_and_send_with_nonce as sign_and_send_with_nonce,
14+
)
1215

1316
if TYPE_CHECKING:
1417
from bittensor_wallet import Wallet
1518
from bittensor.core.async_subtensor import AsyncSubtensor
1619
from bittensor.utils.registration import torch
17-
from scalecodec.types import GenericCall
18-
19-
20-
async def sign_and_send_with_nonce(
21-
subtensor: "AsyncSubtensor",
22-
call: "GenericCall",
23-
wallet: "Wallet",
24-
wait_for_inclusion: bool,
25-
wait_for_finalization: bool,
26-
period: Optional[int] = None,
27-
):
28-
"""
29-
Signs an extrinsic call with the wallet hotkey, adding an optional era for period
30-
"""
31-
next_nonce = await subtensor.substrate.get_account_next_index(
32-
wallet.hotkey.ss58_address
33-
)
34-
35-
extrinsic_data = {"call": call, "keypair": wallet.hotkey, "nonce": next_nonce}
36-
if period is not None:
37-
extrinsic_data["era"] = {"period": period}
38-
39-
extrinsic = await subtensor.substrate.create_signed_extrinsic(**extrinsic_data)
40-
response = await subtensor.substrate.submit_extrinsic(
41-
extrinsic=extrinsic,
42-
wait_for_inclusion=wait_for_inclusion,
43-
wait_for_finalization=wait_for_finalization,
44-
)
45-
46-
if not wait_for_finalization and not wait_for_inclusion:
47-
return True, None
48-
49-
if await response.is_success:
50-
return True, None
51-
52-
return False, format_error_message(await response.error_message)
5320

5421

5522
async def _do_commit_weights(

bittensor/core/extrinsics/commit_weights.py

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from typing import TYPE_CHECKING, Optional
44

5+
from bittensor.core.extrinsics.utils import sign_and_send_with_nonce
56
from bittensor.utils import format_error_message
67
from bittensor.utils.btlogging import logging
78

@@ -10,30 +11,6 @@
1011
from bittensor.core.subtensor import Subtensor
1112

1213

13-
def sign_and_send_with_nonce(
14-
subtensor: "Subtensor", call, wallet, wait_for_inclusion, wait_for_finalization
15-
):
16-
next_nonce = subtensor.substrate.get_account_next_index(wallet.hotkey.ss58_address)
17-
extrinsic = subtensor.substrate.create_signed_extrinsic(
18-
call=call,
19-
keypair=wallet.hotkey,
20-
nonce=next_nonce,
21-
)
22-
response = subtensor.substrate.submit_extrinsic(
23-
extrinsic=extrinsic,
24-
wait_for_inclusion=wait_for_inclusion,
25-
wait_for_finalization=wait_for_finalization,
26-
)
27-
28-
if not wait_for_finalization and not wait_for_inclusion:
29-
return True, None
30-
31-
if response.is_success:
32-
return True, None
33-
34-
return False, format_error_message(response.error_message)
35-
36-
3714
def _do_commit_weights(
3815
subtensor: "Subtensor",
3916
wallet: "Wallet",

bittensor/core/extrinsics/unstaking.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from bittensor.utils import unlock_key
77
from bittensor.utils.balance import Balance
88
from bittensor.utils.btlogging import logging
9+
from bittensor.core.extrinsics.utils import sign_and_send_with_nonce
910

1011
if TYPE_CHECKING:
1112
from bittensor_wallet import Wallet
@@ -92,8 +93,8 @@ def unstake_extrinsic(
9293
"netuid": netuid,
9394
},
9495
)
95-
staking_response, err_msg = subtensor.sign_and_send_extrinsic(
96-
call, wallet, wait_for_inclusion, wait_for_finalization
96+
staking_response, err_msg = sign_and_send_with_nonce(
97+
subtensor, call, wallet, wait_for_inclusion, wait_for_finalization
9798
)
9899

99100
if staking_response is True: # If we successfully unstaked.
@@ -247,8 +248,8 @@ def unstake_multiple_extrinsic(
247248
"netuid": netuid,
248249
},
249250
)
250-
staking_response, err_msg = subtensor.sign_and_send_extrinsic(
251-
call, wallet, wait_for_inclusion, wait_for_finalization
251+
staking_response, err_msg = sign_and_send_with_nonce(
252+
subtensor, call, wallet, wait_for_inclusion, wait_for_finalization
252253
)
253254

254255
if staking_response is True: # If we successfully unstaked.

bittensor/core/extrinsics/utils.py

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Module with helper functions for extrinsics."""
22

3-
from typing import TYPE_CHECKING
3+
from typing import TYPE_CHECKING, Optional
44

55
from async_substrate_interface.errors import SubstrateRequestException
66

@@ -17,7 +17,66 @@
1717
)
1818
from bittensor.core.subtensor import Subtensor
1919
from bittensor.core.chain_data import StakeInfo
20-
from scalecodec.types import GenericExtrinsic
20+
from scalecodec.types import GenericExtrinsic, GenericCall
21+
22+
23+
async def async_sign_and_send_with_nonce(
24+
subtensor: "AsyncSubtensor",
25+
call: "GenericCall",
26+
wallet: "Wallet",
27+
wait_for_inclusion: bool,
28+
wait_for_finalization: bool,
29+
period: Optional[int] = None,
30+
):
31+
"""
32+
Signs an extrinsic call with the wallet hotkey, adding an optional era for period
33+
"""
34+
next_nonce = await subtensor.substrate.get_account_next_index(
35+
wallet.hotkey.ss58_address
36+
)
37+
38+
extrinsic_data = {"call": call, "keypair": wallet.hotkey, "nonce": next_nonce}
39+
if period is not None:
40+
extrinsic_data["era"] = {"period": period}
41+
42+
extrinsic = await subtensor.substrate.create_signed_extrinsic(**extrinsic_data)
43+
response = await subtensor.substrate.submit_extrinsic(
44+
extrinsic=extrinsic,
45+
wait_for_inclusion=wait_for_inclusion,
46+
wait_for_finalization=wait_for_finalization,
47+
)
48+
49+
if not wait_for_finalization and not wait_for_inclusion:
50+
return True, None
51+
52+
if await response.is_success:
53+
return True, None
54+
55+
return False, format_error_message(await response.error_message)
56+
57+
58+
def sign_and_send_with_nonce(
59+
subtensor: "Subtensor", call, wallet, wait_for_inclusion, wait_for_finalization
60+
):
61+
next_nonce = subtensor.substrate.get_account_next_index(wallet.hotkey.ss58_address)
62+
extrinsic = subtensor.substrate.create_signed_extrinsic(
63+
call=call,
64+
keypair=wallet.hotkey,
65+
nonce=next_nonce,
66+
)
67+
response = subtensor.substrate.submit_extrinsic(
68+
extrinsic=extrinsic,
69+
wait_for_inclusion=wait_for_inclusion,
70+
wait_for_finalization=wait_for_finalization,
71+
)
72+
73+
if not wait_for_finalization and not wait_for_inclusion:
74+
return True, None
75+
76+
if response.is_success:
77+
return True, None
78+
79+
return False, format_error_message(response.error_message)
2180

2281

2382
def submit_extrinsic(

0 commit comments

Comments
 (0)