Skip to content

Commit b09aec0

Browse files
authored
Merge branch 'staging' into patch-2
2 parents 2fd2024 + 39288bb commit b09aec0

File tree

16 files changed

+308
-166
lines changed

16 files changed

+308
-166
lines changed

.github/workflows/e2e-subtensor-tests.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ jobs:
3939
id: get-tests
4040
run: |
4141
test_files=$(find tests/e2e_tests -name "test*.py" | jq -R -s -c 'split("\n") | map(select(. != ""))')
42+
# keep it here for future debug
43+
# test_files=$(find tests/e2e_tests -type f -name "test*.py" | grep -E 'test_(incentive|commit_weights|set_weights)\.py$' | jq -R -s -c 'split("\n") | map(select(. != ""))')
4244
echo "::set-output name=test-files::$test_files"
4345
shell: bash
4446

@@ -61,7 +63,7 @@ jobs:
6163
path: subtensor-localnet.tar
6264

6365
# Job to run tests in parallel
64-
run:
66+
run-e2e-test:
6567
name: ${{ matrix.test-file }} / Python ${{ matrix.python-version }}
6668
needs:
6769
- find-tests
@@ -70,7 +72,7 @@ jobs:
7072
timeout-minutes: 45
7173
strategy:
7274
fail-fast: false # Allow other matrix jobs to run even if this job fails
73-
max-parallel: 32 # Set the maximum number of parallel jobs (same as we have cores in SubtensorCI runner)
75+
max-parallel: 32 # Set the maximum number of parallel jobs (same as we have cores in ubuntu-latest runner)
7476
matrix:
7577
os:
7678
- ubuntu-latest

bittensor/core/async_subtensor.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3813,6 +3813,7 @@ async def set_weights(
38133813
wait_for_finalization: bool = False,
38143814
max_retries: int = 5,
38153815
block_time: float = 12.0,
3816+
period: int = 5,
38163817
):
38173818
"""
38183819
Sets the inter-neuronal weights for the specified neuron. This process involves specifying the influence or
@@ -3833,6 +3834,7 @@ async def set_weights(
38333834
``False``.
38343835
max_retries (int): The number of maximum attempts to set weights. Default is ``5``.
38353836
block_time (float): The amount of seconds for block duration. Default is 12.0 seconds.
3837+
period (int, optional): The period in seconds to wait for extrinsic inclusion or finalization. Defaults to 5.
38363838
38373839
Returns:
38383840
tuple[bool, str]: ``True`` if the setting of weights is successful, False otherwise. And `msg`, a string
@@ -3907,6 +3909,7 @@ async def _blocks_weight_limit() -> bool:
39073909
version_key=version_key,
39083910
wait_for_inclusion=wait_for_inclusion,
39093911
wait_for_finalization=wait_for_finalization,
3912+
period=period,
39103913
)
39113914
except Exception as e:
39123915
logging.error(f"Error setting weights: {e}")

bittensor/core/extrinsics/asyncex/weights.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ async def set_weights_extrinsic(
287287
version_key: int = 0,
288288
wait_for_inclusion: bool = False,
289289
wait_for_finalization: bool = False,
290+
period: int = 5,
290291
) -> tuple[bool, str]:
291292
"""Sets the given weights and values on chain for wallet hotkey account.
292293
@@ -302,6 +303,7 @@ async def set_weights_extrinsic(
302303
returns ``False`` if the extrinsic fails to enter the block within the timeout.
303304
wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning
304305
``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout.
306+
period (int, optional): The period in seconds to wait for extrinsic inclusion or finalization. Defaults to 5.
305307
306308
Returns:
307309
success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. If we did not wait for
@@ -331,6 +333,7 @@ async def set_weights_extrinsic(
331333
version_key=version_key,
332334
wait_for_finalization=wait_for_finalization,
333335
wait_for_inclusion=wait_for_inclusion,
336+
period=period,
334337
)
335338

336339
if not wait_for_finalization and not wait_for_inclusion:

bittensor/core/extrinsics/set_weights.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ def set_weights_extrinsic(
9191
version_key: int = 0,
9292
wait_for_inclusion: bool = False,
9393
wait_for_finalization: bool = False,
94+
period: int = 5,
9495
) -> tuple[bool, str]:
9596
"""Sets the given weights and values on chain for wallet hotkey account.
9697
@@ -106,6 +107,7 @@ def set_weights_extrinsic(
106107
returns ``False`` if the extrinsic fails to enter the block within the timeout.
107108
wait_for_finalization (bool): If set, waits for the extrinsic to be finalized on the chain before returning
108109
``True``, or returns ``False`` if the extrinsic fails to be finalized within the timeout.
110+
period (int, optional): The period in seconds to wait for extrinsic inclusion or finalization. Defaults to 5.
109111
110112
Returns:
111113
success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. If we did not wait for
@@ -135,6 +137,7 @@ def set_weights_extrinsic(
135137
version_key=version_key,
136138
wait_for_finalization=wait_for_finalization,
137139
wait_for_inclusion=wait_for_inclusion,
140+
period=period,
138141
)
139142

140143
if not wait_for_finalization and not wait_for_inclusion:

bittensor/core/subtensor.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3100,6 +3100,7 @@ def set_weights(
31003100
wait_for_finalization: bool = False,
31013101
max_retries: int = 5,
31023102
block_time: float = 12.0,
3103+
period: int = 5,
31033104
) -> tuple[bool, str]:
31043105
"""
31053106
Sets the inter-neuronal weights for the specified neuron. This process involves specifying the influence or
@@ -3120,6 +3121,7 @@ def set_weights(
31203121
``False``.
31213122
max_retries (int): The number of maximum attempts to set weights. Default is ``5``.
31223123
block_time (float): The amount of seconds for block duration. Default is 12.0 seconds.
3124+
period (int, optional): The period in seconds to wait for extrinsic inclusion or finalization. Defaults to 5.
31233125
31243126
Returns:
31253127
tuple[bool, str]: ``True`` if the setting of weights is successful, False otherwise. And `msg`, a string
@@ -3183,6 +3185,7 @@ def _blocks_weight_limit() -> bool:
31833185
version_key=version_key,
31843186
wait_for_inclusion=wait_for_inclusion,
31853187
wait_for_finalization=wait_for_finalization,
3188+
period=period,
31863189
)
31873190
except Exception as e:
31883191
logging.error(f"Error setting weights: {e}")

bittensor/utils/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,16 @@ def format_error_message(error_message: Union[dict, Exception]) -> str:
250250
err_docs = error_message.get("docs", [err_description])
251251
err_description = err_docs[0] if err_docs else err_description
252252

253+
elif error_message.get("code") and error_message.get("message"):
254+
err_type = error_message.get("code", err_name)
255+
err_name = "Custom type"
256+
err_description = error_message.get("message", err_description)
257+
258+
else:
259+
logging.error(
260+
f"String representation of real error_message: {str(error_message)}"
261+
)
262+
253263
return f"Subtensor returned `{err_name}({err_type})` error. This means: `{err_description}`."
254264

255265

pyproject.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[build-system]
2-
requires = ["setuptools~=70.0.0", "wheel"]
2+
requires = ["setuptools>=70.0.0", "wheel"]
33
build-backend = "setuptools.build_meta"
44

55
[project]
@@ -40,11 +40,11 @@ dependencies = [
4040

4141
[project.optional-dependencies]
4242
dev = [
43-
"pytest==7.2.0",
44-
"pytest-asyncio==0.23.7",
45-
"pytest-mock==3.12.0",
46-
"pytest-split==0.8.0",
47-
"pytest-xdist==3.0.2",
43+
"pytest==8.3.5",
44+
"pytest-asyncio==0.26.0",
45+
"pytest-mock==3.14.0",
46+
"pytest-split==0.10.0",
47+
"pytest-xdist==3.6.1",
4848
"pytest-rerunfailures==10.2",
4949
"coveralls==3.3.1",
5050
"pytest-cov==4.0.0",

tests/e2e_tests/test_commit_reveal_v3.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ async def test_commit_and_reveal_weights_cr3(local_chain, subtensor, alice_walle
9696

9797
# Fetch current block and calculate next tempo for the subnet
9898
current_block = subtensor.get_current_block()
99-
upcoming_tempo = next_tempo(current_block, tempo, netuid)
99+
upcoming_tempo = next_tempo(current_block, tempo)
100100
logging.console.info(
101101
f"Checking if window is too low with Current block: {current_block}, next tempo: {upcoming_tempo}"
102102
)
@@ -114,7 +114,7 @@ async def test_commit_and_reveal_weights_cr3(local_chain, subtensor, alice_walle
114114
)
115115
current_block = subtensor.get_current_block()
116116
latest_drand_round = subtensor.last_drand_round()
117-
upcoming_tempo = next_tempo(current_block, tempo, netuid)
117+
upcoming_tempo = next_tempo(current_block, tempo)
118118
logging.console.info(
119119
f"Post first wait_interval (to ensure window isnt too low): {current_block}, next tempo: {upcoming_tempo}, drand: {latest_drand_round}"
120120
)
@@ -142,7 +142,7 @@ async def test_commit_and_reveal_weights_cr3(local_chain, subtensor, alice_walle
142142

143143
current_block = subtensor.get_current_block()
144144
latest_drand_round = subtensor.last_drand_round()
145-
upcoming_tempo = next_tempo(current_block, tempo, netuid)
145+
upcoming_tempo = next_tempo(current_block, tempo)
146146
logging.console.info(
147147
f"After setting weights: Current block: {current_block}, next tempo: {upcoming_tempo}, drand: {latest_drand_round}"
148148
)
@@ -177,6 +177,9 @@ async def test_commit_and_reveal_weights_cr3(local_chain, subtensor, alice_walle
177177
f"Latest drand round after waiting for tempo: {latest_drand_round}"
178178
)
179179

180+
# for fast-block 3 seconds (drand round period) is 12 fast blocks. Let's make sure this round passed.
181+
subtensor.wait_for_block(subtensor.block + 12)
182+
180183
# Fetch weights on the chain as they should be revealed now
181184
revealed_weights_ = subtensor.weights(netuid=netuid)
182185

tests/e2e_tests/test_commit_weights.py

Lines changed: 66 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import asyncio
2-
31
import numpy as np
42
import pytest
3+
import retry
54

5+
from bittensor.utils.btlogging import logging
66
from bittensor.utils.weight_utils import convert_weights_and_uids_for_emit
77
from tests.e2e_tests.utils.chain_interactions import (
88
sudo_set_admin_utils,
99
sudo_set_hyperparameter_bool,
10-
use_and_wait_for_next_nonce,
10+
execute_and_wait_for_next_nonce,
1111
wait_epoch,
1212
)
1313

@@ -165,17 +165,30 @@ async def test_commit_weights_uses_next_nonce(local_chain, subtensor, alice_wall
165165
Raises:
166166
AssertionError: If any of the checks or verifications fail
167167
"""
168+
subnet_tempo = 50
169+
netuid = 2
170+
168171
# Wait for 2 tempos to pass as CR3 only reveals weights after 2 tempos
169-
subtensor.wait_for_block(20)
172+
subtensor.wait_for_block(subnet_tempo * 2 + 1)
170173

171-
netuid = 2
172174
print("Testing test_commit_and_reveal_weights")
173175
# Register root as Alice
174176
assert subtensor.register_subnet(alice_wallet), "Unable to register the subnet"
175177

176178
# Verify subnet 1 created successfully
177179
assert subtensor.subnet_exists(netuid), "Subnet wasn't created successfully"
178180

181+
# weights sensitive to epoch changes
182+
assert sudo_set_admin_utils(
183+
local_chain,
184+
alice_wallet,
185+
call_function="sudo_set_tempo",
186+
call_params={
187+
"netuid": netuid,
188+
"tempo": subnet_tempo,
189+
},
190+
)
191+
179192
# Enable commit_reveal on the subnet
180193
assert sudo_set_hyperparameter_bool(
181194
local_chain,
@@ -203,72 +216,67 @@ async def test_commit_weights_uses_next_nonce(local_chain, subtensor, alice_wall
203216
call_params={"netuid": netuid, "weights_set_rate_limit": "0"},
204217
)
205218

206-
assert error is None
207-
assert status is True
219+
assert error is None and status is True, f"Failed to set rate limit: {error}"
208220

209221
assert (
210222
subtensor.get_subnet_hyperparameters(netuid=netuid).weights_rate_limit == 0
211223
), "Failed to set weights_rate_limit"
212224
assert subtensor.weights_rate_limit(netuid=netuid) == 0
213225

214-
# Commit-reveal values
215-
uids = np.array([0], dtype=np.int64)
216-
weights = np.array([0.1], dtype=np.float32)
217-
salt = [18, 179, 107, 0, 165, 211, 141, 197]
218-
weight_uids, weight_vals = convert_weights_and_uids_for_emit(
219-
uids=uids, weights=weights
220-
)
221-
222-
# Make a second salt
223-
salt2 = salt.copy()
224-
salt2[0] += 1 # Increment the first byte to produce a different commit hash
225-
226-
# Make a third salt
227-
salt3 = salt.copy()
228-
salt3[0] += 2 # Increment the first byte to produce a different commit hash
229-
230-
# Commit all three salts
231-
async with use_and_wait_for_next_nonce(subtensor, alice_wallet):
232-
success, message = subtensor.commit_weights(
233-
alice_wallet,
234-
netuid,
235-
salt=salt,
236-
uids=weight_uids,
237-
weights=weight_vals,
238-
wait_for_inclusion=False, # Don't wait for inclusion, we are testing the nonce when there is a tx in the pool
239-
wait_for_finalization=False,
226+
# wait while weights_rate_limit changes applied.
227+
subtensor.wait_for_block(subnet_tempo + 1)
228+
229+
# create different commited data to avoid coming into pool black list with the error
230+
# Failed to commit weights: Subtensor returned `Custom type(1012)` error. This means: `Transaction is temporarily
231+
# banned`.Failed to commit weights: Subtensor returned `Custom type(1012)` error. This means: `Transaction is
232+
# temporarily banned`.`
233+
def get_weights_and_salt(counter: int):
234+
# Commit-reveal values
235+
salt_ = [18, 179, 107, counter, 165, 211, 141, 197]
236+
uids_ = np.array([0], dtype=np.int64)
237+
weights_ = np.array([counter / 10], dtype=np.float32)
238+
weight_uids_, weight_vals_ = convert_weights_and_uids_for_emit(
239+
uids=uids_, weights=weights_
240240
)
241+
return salt_, weight_uids_, weight_vals_
241242

242-
assert success is True
243+
logging.console.info(
244+
f"[orange]Nonce before first commit_weights: "
245+
f"{subtensor.substrate.get_account_next_index(alice_wallet.hotkey.ss58_address)}[/orange]"
246+
)
243247

244-
async with use_and_wait_for_next_nonce(subtensor, alice_wallet):
248+
# 3 time doing call if nonce wasn't updated, then raise error
249+
@retry.retry(exceptions=Exception, tries=3, delay=1)
250+
@execute_and_wait_for_next_nonce(subtensor=subtensor, wallet=alice_wallet)
251+
def send_commit(salt_, weight_uids_, weight_vals_):
245252
success, message = subtensor.commit_weights(
246-
alice_wallet,
247-
netuid,
248-
salt=salt2,
249-
uids=weight_uids,
250-
weights=weight_vals,
251-
wait_for_inclusion=False,
252-
wait_for_finalization=False,
253+
wallet=alice_wallet,
254+
netuid=netuid,
255+
salt=salt_,
256+
uids=weight_uids_,
257+
weights=weight_vals_,
258+
wait_for_inclusion=True,
259+
wait_for_finalization=True,
253260
)
261+
assert success is True, message
254262

255-
assert success is True
263+
# send some amount of commit weights
264+
AMOUNT_OF_COMMIT_WEIGHTS = 3
265+
for call in range(AMOUNT_OF_COMMIT_WEIGHTS):
266+
weight_uids, weight_vals, salt = get_weights_and_salt(call)
256267

257-
async with use_and_wait_for_next_nonce(subtensor, alice_wallet):
258-
success, message = subtensor.commit_weights(
259-
alice_wallet,
260-
netuid,
261-
salt=salt3,
262-
uids=weight_uids,
263-
weights=weight_vals,
264-
wait_for_inclusion=False,
265-
wait_for_finalization=False,
266-
)
268+
send_commit(salt, weight_uids, weight_vals)
267269

268-
assert success is True
270+
# let's wait for 3 (12 fast blocks) seconds between transactions
271+
subtensor.wait_for_block(subtensor.block + 12)
272+
273+
logging.console.info(
274+
f"[orange]Nonce after third commit_weights: "
275+
f"{subtensor.substrate.get_account_next_index(alice_wallet.hotkey.ss58_address)}[/orange]"
276+
)
269277

270278
# Wait a few blocks
271-
await asyncio.sleep(10) # Wait for the txs to be included in the chain
279+
subtensor.wait_for_block(subtensor.block + subtensor.tempo(netuid) * 2)
272280

273281
# Query the WeightCommits storage map for all three salts
274282
weight_commits = subtensor.query_module(
@@ -282,4 +290,6 @@ async def test_commit_weights_uses_next_nonce(local_chain, subtensor, alice_wall
282290
assert commit_block > 0, f"Invalid block number: {commit_block}"
283291

284292
# Check for three commits in the WeightCommits storage map
285-
assert len(weight_commits.value) == 3, "Expected 3 weight commits"
293+
assert (
294+
len(weight_commits.value) == AMOUNT_OF_COMMIT_WEIGHTS
295+
), "Expected exact list of weight commits"

0 commit comments

Comments
 (0)