Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Table fixes / E2E Test - Senate command fix #100

Merged
merged 10 commits into from
Sep 21, 2024
16 changes: 11 additions & 5 deletions bittensor_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -1274,8 +1274,8 @@ def wallet_swap_hotkey(

USAGE

The command is used to swap the hotkey of a wallet for another hotkey on that same wallet.
The command is used to swap the hotkey of a wallet for another hotkey on that same wallet.

IMPORTANT

- Make sure that your original key pair (coldkeyA, hotkeyA) is already registered.
Expand Down Expand Up @@ -1441,7 +1441,7 @@ def wallet_faucet(
USAGE

The command uses the proof-of-work (POW) mechanism to validate the user's effort and rewards them with test TAO tokens. It is
typically used in local blockchain environments where transactions do not use real TAO tokens.
typically used in local blockchain environments where transactions do not use real TAO tokens.

EXAMPLE

Expand Down Expand Up @@ -1498,7 +1498,7 @@ def wallet_regen_coldkey(
[green]$[/green] btcli wallet regen-coldkey --mnemonic "word1 word2 ... word12"


[bold]Note[/bold]: This command is critical for users who need to regenerate their coldkey either for recovery or for security reasons.
[bold]Note[/bold]: This command is critical for users who need to regenerate their coldkey either for recovery or for security reasons.
"""
self.verbosity_handler(quiet, verbose)

Expand Down Expand Up @@ -2308,6 +2308,12 @@ def root_senate_vote(
prompt: bool = Options.prompt,
quiet: bool = Options.quiet,
verbose: bool = Options.verbose,
vote: bool = typer.Option(
None,
"--vote-aye/--vote-nay",
prompt="Enter y to vote Aye, or enter n to vote Nay",
help="The vote casted on the proposal",
),
):
"""
Cast a vote on an active proposal in Bittensor's governance protocol.
Expand All @@ -2332,7 +2338,7 @@ def root_senate_vote(
)
return self._run_command(
root.senate_vote(
wallet, self.initialize_chain(network, chain), proposal, prompt
wallet, self.initialize_chain(network, chain), proposal, vote, prompt
)
)

Expand Down
2 changes: 1 addition & 1 deletion bittensor_cli/src/commands/root.py
Original file line number Diff line number Diff line change
Expand Up @@ -1039,6 +1039,7 @@ async def senate_vote(
wallet: Wallet,
subtensor: SubtensorInterface,
proposal_hash: str,
vote: bool,
prompt: bool,
) -> bool:
"""Vote in Bittensor's governance protocol proposals"""
Expand Down Expand Up @@ -1074,7 +1075,6 @@ async def senate_vote(
err_console.print(":cross_mark: [red]Failed[/red]: Proposal not found.")
return False

vote: bool = Confirm.ask("Desired vote for proposal")
success = await vote_senate_extrinsic(
subtensor=subtensor,
wallet=wallet,
Expand Down
29 changes: 19 additions & 10 deletions bittensor_cli/src/commands/stake/stake.py
Original file line number Diff line number Diff line change
Expand Up @@ -965,10 +965,10 @@ async def get_stakes_from_delegates(
delegate_name = (
registered_delegate_info[dele.hotkey_ss58].display
if dele.hotkey_ss58 in registered_delegate_info
else dele.hotkey_ss58
else None
)
stakes[dele.hotkey_ss58] = {
"name": delegate_name,
"name": delegate_name if delegate_name else dele.hotkey_ss58,
"stake": nom[1],
"rate": dele.total_daily_return.tao
* (nom[1] / dele.total_stake.tao),
Expand Down Expand Up @@ -1005,7 +1005,9 @@ async def get_all_wallet_accounts(
":satellite: Retrieving account data...", spinner="aesthetic"
):
block_hash_ = await subtensor.substrate.get_chain_head()
registered_delegate_info = await subtensor.get_delegate_identities(block_hash=block_hash_)
registered_delegate_info = await subtensor.get_delegate_identities(
block_hash=block_hash_
)
accounts = await get_all_wallet_accounts(block_hash=block_hash_)

total_stake: float = 0.0
Expand All @@ -1022,14 +1024,17 @@ async def get_all_wallet_accounts(
)
total_balance += cast(Balance, acc["balance"]).tao
for key, value in cast(dict, acc["accounts"]).items():
if value["name"] and value["name"] != key:
account_display_name = f"[bright_cyan]({value['name']})[/bright_cyan] [bright_magenta]{key}[/bright_magenta]"
else:
account_display_name = f"[bright_cyan](~)[/bright_cyan] [bright_magenta]{key}[/bright_magenta]"
rows.append(
[
"",
"",
value["name"],
account_display_name,
str(value["stake"]),
str(value["rate"]),
key,
]
)
db_rows.append(
Expand Down Expand Up @@ -1087,7 +1092,7 @@ async def get_all_wallet_accounts(
style="dark_sea_green",
ratio=1,
),
Column("[bold white]Account", style="bright_cyan", ratio=1),
Column("[bold white]Hotkey", ratio=7, no_wrap=True),
Column(
"[bold white]Stake",
metadata["total_stake"],
Expand All @@ -1100,18 +1105,22 @@ async def get_all_wallet_accounts(
style="rgb(42,161,152)",
ratio=1,
),
Column(
"[bold white]Hotkey", style="bright_magenta", overflow="fold", ratio=2
),
title=f"[underline dark_orange]Stake Show[/underline dark_orange]\n[dark_orange]Network: {subtensor.network}\n",
show_footer=True,
show_edge=False,
expand=False,
border_style="bright_black",
)
for row in rows:

for i, row in enumerate(rows):
is_last_row = i + 1 == len(rows)
table.add_row(*row)

# If last row or new coldkey starting next
if is_last_row or (rows[i + 1][0] != ""):
table.add_row(end_section=True)
console.print(table)

else:
render_tree(
"stakeshow",
Expand Down
14 changes: 12 additions & 2 deletions bittensor_cli/src/commands/wallets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1349,9 +1349,14 @@ def neuron_row_maker(
):
rows.append(row)

for row in rows:
for i, row in enumerate(rows):
is_last_row = i + 1 == len(rows)
table.add_row(*row)

# If last row or new coldkey starting next
if is_last_row or (rows[i + 1][0] != ""):
table.add_row(end_section=True)

return console.print(table)


Expand Down Expand Up @@ -1454,7 +1459,12 @@ async def set_id(
):
"""Create a new or update existing identity on-chain."""

pgp_fingerprint_encoded = binascii.unhexlify(pgp_fingerprint.replace(" ", ""))
try:
pgp_fingerprint_encoded = binascii.unhexlify(pgp_fingerprint.replace(" ", ""))
except Exception as e:
print_error(f"The PGP is not in the correct format: {e}")
raise typer.Exit()

id_dict = {
"additional": [[]],
"display": display_name,
Expand Down
159 changes: 138 additions & 21 deletions tests/e2e_tests/test_senate.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* btcli root senate
* btcli root proposals
* btcli root senate-vote
* btcli root nominate
* btcli root register
"""

Expand All @@ -16,23 +15,32 @@ def test_senate(local_chain, wallet_setup):
"""
Test the senate functionality in Bittensor
Steps:
1. Create a wallet for Bob
2. Assert bob is not part of the senate
3. Execute root register for Bob
4. Assert Bob is now part of the senate
5. Manually add a proposal to the chain
1. Create a wallet for Bob & Alice
2. Assert bob is not part of the senate, and register to senate through
registering to root
3. Assert Bob is now part of the senate by fetching senate list
4. Manually add a proposal to the chain & verify
5. Vote on the proposal by Bob (vote aye) & assert
6. Register Alice on root (auto becomes a senator)
7. Vote on the proposal by Alice (vote nay) & assert


Raises:
AssertionError: If any of the checks or verifications fail
"""
print("Testing Senate commands 🧪")

wallet_path_bob = "//Bob"
wallet_path_alice = "//Alice"

# Create wallet for Bob
# Create wallet for Bob - he will vote aye
keypair_bob, wallet_bob, wallet_path_bob, exec_command_bob = wallet_setup(
wallet_path_bob
)
# Create wallet for Alice - she will vote nay
keypair_alice, wallet_alice, wallet_path_alice, exec_command_alice = wallet_setup(
wallet_path_alice
)

# Fetch existing senate list
root_senate = exec_command_bob(
Expand All @@ -41,7 +49,7 @@ def test_senate(local_chain, wallet_setup):
extra_args=[
"--chain",
"ws://127.0.0.1:9945",
]
],
)

# Assert Bob is not part of the senate yet
Expand Down Expand Up @@ -75,38 +83,147 @@ def test_senate(local_chain, wallet_setup):
extra_args=[
"--chain",
"ws://127.0.0.1:9945",
]
],
)

# Assert Bob is now part of the senate
assert wallet_bob.hotkey.ss58_address in root_senate_after_reg.stdout


# Manually add a proposal on the chain & assert
success = asyncio.run(call_add_proposal(local_chain, wallet_bob))
assert success is True

# Fetch proposals
# Fetch proposals after adding one
proposals = exec_command_bob(
command="root",
sub_command="proposals",
extra_args=[
"--chain",
"ws://127.0.0.1:9945",
]
],
)

proposals_output = proposals.stdout.splitlines()[8].split()

# Assert the hash is of correct length
assert len(proposals_output[0]) == 68

# Assert the hash is of correct format
assert len(proposals_output[0]) == 66
assert proposals_output[0][0:2] == "0x"

# 0 Ayes for the proposal
assert proposals_output[2] == '0'
assert proposals_output[2] == "0"

# 0 Nayes for the proposal
assert proposals_output[3] == '0'
assert proposals_output[3] == "0"

# Assert initial threshold is 3
assert proposals_output[1] == '3'

assert proposals_output[1] == "3"

# Vote on the proposal by Bob (vote aye)
vote_aye = exec_command_bob(
command="root",
sub_command="senate-vote",
extra_args=[
"--wallet-path",
wallet_path_bob,
"--chain",
"ws://127.0.0.1:9945",
"--wallet-name",
wallet_bob.name,
"--hotkey",
wallet_bob.hotkey_str,
"--proposal-hash",
proposals_output[0],
"--vote-aye",
"--no-prompt",
],
)
assert "✅ Vote cast" in vote_aye.stdout

# Fetch proposals after voting aye
proposals_after_aye = exec_command_bob(
command="root",
sub_command="proposals",
extra_args=[
"--chain",
"ws://127.0.0.1:9945",
],
)
proposals_after_aye_output = proposals_after_aye.stdout.splitlines()[8].split()

# Assert Bob's vote is shown as aye
assert proposals_after_aye_output[4].strip(":") == wallet_bob.hotkey.ss58_address
assert proposals_after_aye_output[5] == "Aye"

# Aye votes increased to 1
assert proposals_after_aye_output[2] == '1'

# Nay votes remain 0
assert proposals_after_aye_output[3] == '0'

# Register Alice to the root network (0)
# Registering to root automatically makes you a senator if eligible
root_register = exec_command_alice(
command="root",
sub_command="register",
extra_args=[
"--wallet-path",
wallet_path_alice,
"--chain",
"ws://127.0.0.1:9945",
"--wallet-name",
wallet_alice.name,
"--hotkey",
wallet_alice.hotkey_str,
"--network",
"local",
"--no-prompt",
],
)
assert "✅ Registered" in root_register.stdout

# Vote on the proposal by Alice (vote nay)
vote_nay = exec_command_alice(
command="root",
sub_command="senate-vote",
extra_args=[
"--wallet-path",
wallet_path_alice,
"--chain",
"ws://127.0.0.1:9945",
"--wallet-name",
wallet_alice.name,
"--hotkey",
wallet_alice.hotkey_str,
"--proposal-hash",
proposals_output[0],
"--vote-nay",
"--no-prompt",
],
)
assert "✅ Vote cast" in vote_nay.stdout

# Fetch proposals after voting
proposals_after_nay = exec_command_bob(
command="root",
sub_command="proposals",
extra_args=[
"--chain",
"ws://127.0.0.1:9945",
],
)
proposals_after_nay_output = proposals_after_nay.stdout.splitlines()

# Total Ayes to remain 1
proposals_after_nay_output[8].split()[2] == "1"

# Total Nays increased to 1
proposals_after_nay_output[8].split()[3] == "1"

# Assert Alice has voted Nay
proposals_after_nay_output[9].split()[0].strip(
":"
) == wallet_alice.hotkey.ss58_address

# Assert vote casted as Nay
proposals_after_nay_output[9].split()[1] == "Nay"


print("✅ Passed senate commands")
Loading
Loading