Skip to content

Commit 52d0c75

Browse files
e2e tests for bonds and get_vote_data (with minor refactoring)
1 parent 9730f51 commit 52d0c75

File tree

7 files changed

+197
-23
lines changed

7 files changed

+197
-23
lines changed

bittensor/core/async_subtensor.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1909,10 +1909,11 @@ async def get_vote_data(
19091909
block_hash=block_hash,
19101910
reuse_block_hash=reuse_block,
19111911
)
1912+
19121913
if vote_data is None:
19131914
return None
1914-
else:
1915-
return ProposalVoteData(vote_data)
1915+
1916+
return ProposalVoteData.from_dict(vote_data)
19161917

19171918
async def get_uid_for_hotkey_on_subnet(
19181919
self,
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,27 @@
1+
from dataclasses import dataclass
2+
3+
from bittensor.core.chain_data.info_base import InfoBase
14
from bittensor.core.chain_data.utils import decode_account_id
25

36

4-
# Senate / Proposal data
5-
class ProposalVoteData:
7+
@dataclass
8+
class ProposalVoteData(InfoBase):
9+
"""
10+
Senate / Proposal data
11+
"""
12+
613
index: int
714
threshold: int
815
ayes: list[str]
916
nays: list[str]
1017
end: int
1118

12-
def __init__(self, proposal_dict: dict) -> None:
13-
self.index = proposal_dict["index"]
14-
self.threshold = proposal_dict["threshold"]
15-
self.ayes = self.decode_ss58_tuples(proposal_dict["ayes"])
16-
self.nays = self.decode_ss58_tuples(proposal_dict["nays"])
17-
self.end = proposal_dict["end"]
18-
19-
@staticmethod
20-
def decode_ss58_tuples(line: tuple):
21-
"""Decodes a tuple of ss58 addresses formatted as bytes tuples."""
22-
return [decode_account_id(line[x][0]) for x in range(len(line))]
19+
@classmethod
20+
def from_dict(cls, proposal_dict: dict) -> "ProposalVoteData":
21+
return cls(
22+
ayes=[decode_account_id(key) for key in proposal_dict["ayes"]],
23+
end=proposal_dict["end"],
24+
index=proposal_dict["index"],
25+
nays=[decode_account_id(key) for key in proposal_dict["nays"]],
26+
threshold=proposal_dict["threshold"],
27+
)

bittensor/core/subtensor.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1468,10 +1468,11 @@ def get_vote_data(
14681468
params=[proposal_hash],
14691469
block_hash=self.determine_block_hash(block),
14701470
)
1471+
14711472
if vote_data is None:
14721473
return None
1473-
else:
1474-
return ProposalVoteData(vote_data)
1474+
1475+
return ProposalVoteData.from_dict(vote_data)
14751476

14761477
def get_uid_for_hotkey_on_subnet(
14771478
self, hotkey_ss58: str, netuid: int, block: Optional[int] = None

tests/e2e_tests/test_delegate.py

+106
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@
33
import bittensor
44
from bittensor.core.chain_data.chain_identity import ChainIdentity
55
from bittensor.core.chain_data.delegate_info import DelegatedInfo, DelegateInfo
6+
from bittensor.core.chain_data.proposal_vote_data import ProposalVoteData
67
from bittensor.utils.balance import Balance
78
from tests.e2e_tests.utils.chain_interactions import (
9+
propose,
810
set_identity,
911
sudo_set_admin_utils,
12+
vote,
1013
)
14+
from tests.helpers.helpers import CLOSE_IN_VALUE
1115

1216
DEFAULT_DELEGATE_TAKE = 0.179995422293431
1317

@@ -321,3 +325,105 @@ def test_nominator_min_required_stake(local_chain, subtensor, alice_wallet, bob_
321325
)
322326

323327
assert stake == Balance(0)
328+
329+
330+
def test_get_vote_data(subtensor, alice_wallet):
331+
"""
332+
Tests:
333+
- Sends Propose
334+
- Checks existing Proposals
335+
- Votes
336+
- Checks Proposal is updated
337+
"""
338+
339+
subtensor.root_register(alice_wallet)
340+
341+
proposals = subtensor.query_map(
342+
"Triumvirate",
343+
"ProposalOf",
344+
params=[],
345+
)
346+
347+
assert proposals.records == []
348+
349+
success, error = propose(
350+
subtensor,
351+
alice_wallet,
352+
proposal=subtensor.substrate.compose_call(
353+
call_module="Triumvirate",
354+
call_function="set_members",
355+
call_params={
356+
"new_members": [],
357+
"prime": None,
358+
"old_count": 0,
359+
},
360+
),
361+
duration=1_000_000,
362+
)
363+
364+
assert error == ""
365+
assert success is True
366+
367+
proposals = subtensor.query_map(
368+
"Triumvirate",
369+
"ProposalOf",
370+
params=[],
371+
)
372+
proposals = {
373+
bytes(proposal_hash[0]): proposal.value for proposal_hash, proposal in proposals
374+
}
375+
376+
assert list(proposals.values()) == [
377+
{
378+
"Triumvirate": (
379+
{
380+
"set_members": {
381+
"new_members": (),
382+
"prime": None,
383+
"old_count": 0,
384+
},
385+
},
386+
),
387+
},
388+
]
389+
390+
proposal_hash = list(proposals.keys())[0]
391+
proposal_hash = f"0x{proposal_hash.hex()}"
392+
393+
proposal = subtensor.get_vote_data(
394+
proposal_hash,
395+
)
396+
397+
assert proposal == ProposalVoteData(
398+
ayes=[],
399+
end=CLOSE_IN_VALUE(1_000_000, subtensor.block),
400+
index=0,
401+
nays=[],
402+
threshold=3,
403+
)
404+
405+
success, error = vote(
406+
subtensor,
407+
alice_wallet,
408+
alice_wallet.hotkey.ss58_address,
409+
proposal_hash,
410+
index=0,
411+
approve=True,
412+
)
413+
414+
assert error == ""
415+
assert success is True
416+
417+
proposal = subtensor.get_vote_data(
418+
proposal_hash,
419+
)
420+
421+
assert proposal == ProposalVoteData(
422+
ayes=[
423+
alice_wallet.hotkey.ss58_address,
424+
],
425+
end=CLOSE_IN_VALUE(1_000_000, subtensor.block),
426+
index=0,
427+
nays=[],
428+
threshold=3,
429+
)

tests/e2e_tests/test_incentive.py

+17
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,26 @@ async def test_incentive(local_chain, subtensor, templates, alice_wallet, bob_wa
100100
assert alice_neuron.rank < 0.5
101101

102102
bob_neuron = metagraph.neurons[1]
103+
103104
assert bob_neuron.incentive > 0.5
104105
assert bob_neuron.consensus > 0.5
105106
assert bob_neuron.rank > 0.5
106107
assert bob_neuron.trust == 1
107108

109+
bonds = subtensor.bonds(netuid)
110+
111+
assert bonds == [
112+
(
113+
0,
114+
[
115+
(0, 65535),
116+
(1, 65535),
117+
],
118+
),
119+
(
120+
1,
121+
[],
122+
),
123+
]
124+
108125
print("✅ Passed test_incentive")

tests/e2e_tests/utils/chain_interactions.py

+42
Original file line numberDiff line numberDiff line change
@@ -261,3 +261,45 @@ def set_identity(
261261
wait_for_inclusion=True,
262262
wait_for_finalization=True,
263263
)
264+
265+
266+
def propose(subtensor, wallet, proposal, duration):
267+
return subtensor.sign_and_send_extrinsic(
268+
subtensor.substrate.compose_call(
269+
call_module="Triumvirate",
270+
call_function="propose",
271+
call_params={
272+
"proposal": proposal,
273+
"length_bound": len(proposal.data),
274+
"duration": duration,
275+
},
276+
),
277+
wallet,
278+
wait_for_finalization=True,
279+
wait_for_inclusion=True,
280+
)
281+
282+
283+
def vote(
284+
subtensor,
285+
wallet,
286+
hotkey,
287+
proposal,
288+
index,
289+
approve,
290+
):
291+
return subtensor.sign_and_send_extrinsic(
292+
subtensor.substrate.compose_call(
293+
call_module="SubtensorModule",
294+
call_function="vote",
295+
call_params={
296+
"approve": approve,
297+
"hotkey": hotkey,
298+
"index": index,
299+
"proposal": proposal,
300+
},
301+
),
302+
wallet,
303+
wait_for_inclusion=True,
304+
wait_for_finalization=True,
305+
)

tests/unit_tests/test_async_subtensor.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,17 @@ def test_decode_ss58_tuples_in_proposal_vote_data(mocker):
4747
}
4848

4949
# Call
50-
async_subtensor.ProposalVoteData(fake_proposal_dict)
50+
async_subtensor.ProposalVoteData.from_dict(fake_proposal_dict)
5151

5252
# Asserts
5353
assert mocked_decode_account_id.call_count == len(fake_proposal_dict["ayes"]) + len(
5454
fake_proposal_dict["nays"]
5555
)
5656
assert mocked_decode_account_id.mock_calls == [
57-
mocker.call("0"),
58-
mocker.call("1"),
59-
mocker.call("2"),
60-
mocker.call("3"),
57+
mocker.call("0 line"),
58+
mocker.call("1 line"),
59+
mocker.call("2 line"),
60+
mocker.call("3 line"),
6161
]
6262

6363

@@ -2054,7 +2054,9 @@ async def test_get_vote_data_success(subtensor, mocker):
20542054

20552055
mocked_proposal_vote_data = mocker.Mock()
20562056
mocker.patch.object(
2057-
async_subtensor, "ProposalVoteData", return_value=mocked_proposal_vote_data
2057+
async_subtensor.ProposalVoteData,
2058+
"from_dict",
2059+
return_value=mocked_proposal_vote_data,
20582060
)
20592061

20602062
# Call

0 commit comments

Comments
 (0)