From 7519d2f217a53e9c487651bb2c591b3003492d34 Mon Sep 17 00:00:00 2001 From: Andreea Popescu Date: Wed, 20 Nov 2024 08:11:55 +0000 Subject: [PATCH] wip --- tests/e2e_tests/test_axon.py | 127 ------------- tests/e2e_tests/test_commit_weights.py | 172 ------------------ tests/e2e_tests/test_dendrite.py | 136 -------------- tests/e2e_tests/test_incentive.py | 186 ------------------- tests/e2e_tests/test_liquid_alpha.py | 187 -------------------- tests/e2e_tests/test_metagraph.py | 178 ------------------- tests/e2e_tests/test_neuron_certificate.py | 56 ++++++ tests/e2e_tests/test_subtensor_functions.py | 151 ---------------- tests/e2e_tests/test_transfer.py | 51 ------ 9 files changed, 56 insertions(+), 1188 deletions(-) delete mode 100644 tests/e2e_tests/test_axon.py delete mode 100644 tests/e2e_tests/test_commit_weights.py delete mode 100644 tests/e2e_tests/test_dendrite.py delete mode 100644 tests/e2e_tests/test_incentive.py delete mode 100644 tests/e2e_tests/test_liquid_alpha.py delete mode 100644 tests/e2e_tests/test_metagraph.py create mode 100644 tests/e2e_tests/test_neuron_certificate.py delete mode 100644 tests/e2e_tests/test_subtensor_functions.py delete mode 100644 tests/e2e_tests/test_transfer.py diff --git a/tests/e2e_tests/test_axon.py b/tests/e2e_tests/test_axon.py deleted file mode 100644 index a21c4ae532..0000000000 --- a/tests/e2e_tests/test_axon.py +++ /dev/null @@ -1,127 +0,0 @@ -import asyncio -import sys - -import pytest - -import bittensor -from bittensor.utils import networking -from bittensor.utils.btlogging import logging -from tests.e2e_tests.utils.chain_interactions import register_neuron, register_subnet -from tests.e2e_tests.utils.e2e_test_utils import ( - setup_wallet, - template_path, - templates_repo, -) - - -@pytest.mark.asyncio -async def test_axon(local_chain): - """ - Test the Axon mechanism and successful registration on the network. - - Steps: - 1. Register a subnet and register Alice - 2. Check if metagraph.axon is updated and check axon attributes - 3. Run Alice as a miner on the subnet - 4. Check the metagraph again after running the miner and verify all attributes - Raises: - AssertionError: If any of the checks or verifications fail - """ - - logging.info("Testing test_axon") - - netuid = 1 - # Register root as Alice - the subnet owner - alice_keypair, wallet = setup_wallet("//Alice") - - # Register a subnet, netuid 1 - assert register_subnet(local_chain, wallet), "Subnet wasn't created" - - # Verify subnet created successfully - assert local_chain.query( - "SubtensorModule", "NetworksAdded", [netuid] - ).serialize(), "Subnet wasn't created successfully" - - # Register Alice to the network - assert register_neuron( - local_chain, wallet, netuid - ), f"Neuron wasn't registered to subnet {netuid}" - - metagraph = bittensor.Metagraph(netuid=netuid, network="ws://localhost:9945") - - # Validate current metagraph stats - old_axon = metagraph.axons[0] - assert len(metagraph.axons) == 1, f"Expected 1 axon, but got {len(metagraph.axons)}" - assert old_axon.hotkey == alice_keypair.ss58_address, "Hotkey mismatch for the axon" - assert ( - old_axon.coldkey == alice_keypair.ss58_address - ), "Coldkey mismatch for the axon" - assert old_axon.ip == "0.0.0.0", f"Expected IP 0.0.0.0, but got {old_axon.ip}" - assert old_axon.port == 0, f"Expected port 0, but got {old_axon.port}" - assert old_axon.ip_type == 0, f"Expected IP type 0, but got {old_axon.ip_type}" - - # Prepare to run the miner - cmd = " ".join( - [ - f"{sys.executable}", - f'"{template_path}{templates_repo}/neurons/miner.py"', - "--netuid", - str(netuid), - "--subtensor.network", - "local", - "--subtensor.chain_endpoint", - "ws://localhost:9945", - "--wallet.path", - wallet.path, - "--wallet.name", - wallet.name, - "--wallet.hotkey", - "default", - ] - ) - - # Run the miner in the background - await asyncio.create_subprocess_shell( - cmd, - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE, - ) - - logging.info("Neuron Alice is now mining") - - # Waiting for 5 seconds for metagraph to be updated - await asyncio.sleep(5) - - # Refresh the metagraph - metagraph = bittensor.Metagraph(netuid=netuid, network="ws://localhost:9945") - updated_axon = metagraph.axons[0] - external_ip = networking.get_external_ip() - - # Assert updated attributes - assert ( - len(metagraph.axons) == 1 - ), f"Expected 1 axon, but got {len(metagraph.axons)} after mining" - - assert ( - len(metagraph.neurons) == 1 - ), f"Expected 1 neuron, but got {len(metagraph.neurons)}" - - assert ( - updated_axon.ip == external_ip - ), f"Expected IP {external_ip}, but got {updated_axon.ip}" - - assert ( - updated_axon.ip_type == networking.ip_version(external_ip) - ), f"Expected IP type {networking.ip_version(external_ip)}, but got {updated_axon.ip_type}" - - assert updated_axon.port == 8091, f"Expected port 8091, but got {updated_axon.port}" - - assert ( - updated_axon.hotkey == alice_keypair.ss58_address - ), "Hotkey mismatch after mining" - - assert ( - updated_axon.coldkey == alice_keypair.ss58_address - ), "Coldkey mismatch after mining" - - logging.info("✅ Passed test_axon") diff --git a/tests/e2e_tests/test_commit_weights.py b/tests/e2e_tests/test_commit_weights.py deleted file mode 100644 index 5c03a3788b..0000000000 --- a/tests/e2e_tests/test_commit_weights.py +++ /dev/null @@ -1,172 +0,0 @@ -import time - -import numpy as np -import pytest - -from bittensor.core.subtensor import Subtensor -from bittensor.utils.balance import Balance -from bittensor.utils.btlogging import logging -from bittensor.utils.weight_utils import convert_weights_and_uids_for_emit -from tests.e2e_tests.utils.chain_interactions import ( - add_stake, - register_neuron, - register_subnet, - sudo_set_hyperparameter_bool, - sudo_set_hyperparameter_values, - wait_interval, -) -from tests.e2e_tests.utils.e2e_test_utils import setup_wallet - - -@pytest.mark.asyncio -async def test_commit_and_reveal_weights(local_chain): - """ - Tests the commit/reveal weights mechanism with subprocess disabled (CR1.0) - - Steps: - 1. Register a subnet through Alice - 2. Register Alice's neuron and add stake - 3. Enable commit-reveal mechanism on the subnet - 4. Lower the commit_reveal interval and rate limit - 5. Commit weights and verify - 6. Wait interval & reveal weights and verify - Raises: - AssertionError: If any of the checks or verifications fail - """ - netuid = 1 - logging.info("Testing test_commit_and_reveal_weights") - # Register root as Alice - keypair, alice_wallet = setup_wallet("//Alice") - assert register_subnet(local_chain, alice_wallet), "Unable to register the subnet" - - # Verify subnet 1 created successfully - assert local_chain.query( - "SubtensorModule", "NetworksAdded", [1] - ).serialize(), "Subnet wasn't created successfully" - - assert register_neuron( - local_chain, alice_wallet, netuid - ), "Unable to register Alice as a neuron" - - # Stake to become to top neuron after the first epoch - add_stake(local_chain, alice_wallet, Balance.from_tao(100_000)) - - # Enable commit_reveal on the subnet - assert sudo_set_hyperparameter_bool( - local_chain, - alice_wallet, - "sudo_set_commit_reveal_weights_enabled", - True, - netuid, - ), "Unable to enable commit reveal on the subnet" - - subtensor = Subtensor(network="ws://localhost:9945") - assert subtensor.get_subnet_hyperparameters( - netuid=netuid, - ).commit_reveal_weights_enabled, "Failed to enable commit/reveal" - - # Lower the commit_reveal interval - assert sudo_set_hyperparameter_values( - local_chain, - alice_wallet, - call_function="sudo_set_commit_reveal_weights_interval", - call_params={"netuid": netuid, "interval": "1"}, - return_error_message=True, - ) - - assert ( - subtensor.get_subnet_hyperparameters( - netuid=netuid - ).commit_reveal_weights_interval - == 1 - ), "Failed to set commit/reveal periods" - - assert ( - subtensor.weights_rate_limit(netuid=netuid) > 0 - ), "Weights rate limit is below 0" - # Lower the rate limit - assert sudo_set_hyperparameter_values( - local_chain, - alice_wallet, - call_function="sudo_set_weights_set_rate_limit", - call_params={"netuid": netuid, "weights_set_rate_limit": "0"}, - return_error_message=True, - ) - - assert ( - subtensor.get_subnet_hyperparameters(netuid=netuid).weights_rate_limit == 0 - ), "Failed to set weights_rate_limit" - assert subtensor.weights_rate_limit(netuid=netuid) == 0 - - # Commit-reveal values - uids = np.array([0], dtype=np.int64) - weights = np.array([0.1], dtype=np.float32) - salt = [18, 179, 107, 0, 165, 211, 141, 197] - weight_uids, weight_vals = convert_weights_and_uids_for_emit( - uids=uids, weights=weights - ) - - # Commit weights - success, message = subtensor.commit_weights( - alice_wallet, - netuid, - salt=salt, - uids=weight_uids, - weights=weight_vals, - wait_for_inclusion=True, - wait_for_finalization=True, - ) - - assert success is True - - weight_commits = subtensor.query_module( - module="SubtensorModule", - name="WeightCommits", - params=[netuid, alice_wallet.hotkey.ss58_address], - ) - # Assert that the committed weights are set correctly - assert weight_commits.value is not None, "Weight commit not found in storage" - commit_hash, commit_block, reveal_block, expire_block = weight_commits.value[0] - assert commit_block > 0, f"Invalid block number: {commit_block}" - - # Query the WeightCommitRevealInterval storage map - reveal_periods = subtensor.query_module( - module="SubtensorModule", name="RevealPeriodEpochs", params=[netuid] - ) - periods = reveal_periods.value - assert periods > 0, "Invalid RevealPeriodEpochs" - - # Wait until the reveal block range - await wait_interval( - subtensor.get_subnet_hyperparameters(netuid=netuid).tempo, subtensor - ) - - # Reveal weights - success, message = subtensor.reveal_weights( - alice_wallet, - netuid, - uids=weight_uids, - weights=weight_vals, - salt=salt, - wait_for_inclusion=True, - wait_for_finalization=True, - ) - - assert success is True - - time.sleep(10) - - # Query the Weights storage map - revealed_weights = subtensor.query_module( - module="SubtensorModule", - name="Weights", - params=[netuid, 0], # netuid and uid - ) - - # Assert that the revealed weights are set correctly - assert revealed_weights.value is not None, "Weight reveal not found in storage" - - assert ( - weight_vals[0] == revealed_weights.value[0][1] - ), f"Incorrect revealed weights. Expected: {weights[0]}, Actual: {revealed_weights.value[0][1]}" - logging.info("✅ Passed test_commit_and_reveal_weights") diff --git a/tests/e2e_tests/test_dendrite.py b/tests/e2e_tests/test_dendrite.py deleted file mode 100644 index 24484f68d3..0000000000 --- a/tests/e2e_tests/test_dendrite.py +++ /dev/null @@ -1,136 +0,0 @@ -import asyncio -import sys - -import pytest - -from bittensor.core.metagraph import Metagraph -from bittensor.core.subtensor import Subtensor -from bittensor.utils.balance import Balance -from bittensor.utils.btlogging import logging -from tests.e2e_tests.utils.chain_interactions import ( - register_neuron, - register_subnet, - add_stake, - wait_epoch, -) -from tests.e2e_tests.utils.e2e_test_utils import ( - setup_wallet, - template_path, - templates_repo, -) - - -@pytest.mark.asyncio -async def test_dendrite(local_chain): - """ - Test the Dendrite mechanism - - Steps: - 1. Register a subnet through Alice - 2. Register Bob as a validator - 3. Add stake to Bob and ensure neuron is not a validator yet - 4. Run Bob as a validator and wait epoch - 5. Ensure Bob's neuron has all correct attributes of a validator - Raises: - AssertionError: If any of the checks or verifications fail - """ - - logging.info("Testing test_dendrite") - netuid = 1 - - # Register root as Alice - the subnet owner - alice_keypair, alice_wallet = setup_wallet("//Alice") - - # Register a subnet, netuid 1 - assert register_subnet(local_chain, alice_wallet), "Subnet wasn't created" - - # Verify subnet created successfully - assert local_chain.query( - "SubtensorModule", "NetworksAdded", [netuid] - ).serialize(), "Subnet wasn't created successfully" - - # Register Bob - bob_keypair, bob_wallet = setup_wallet("//Bob") - - # Register Bob to the network - assert register_neuron( - local_chain, bob_wallet, netuid - ), f"Neuron wasn't registered to subnet {netuid}" - - metagraph = Metagraph(netuid=netuid, network="ws://localhost:9945") - subtensor = Subtensor(network="ws://localhost:9945") - - # Assert one neuron is Bob - assert len(subtensor.neurons(netuid=netuid)) == 1 - neuron = metagraph.neurons[0] - assert neuron.hotkey == bob_keypair.ss58_address - assert neuron.coldkey == bob_keypair.ss58_address - - # Assert stake is 0 - assert neuron.stake.tao == 0 - - # Stake to become to top neuron after the first epoch - assert add_stake(local_chain, bob_wallet, Balance.from_tao(10_000)) - - # Refresh metagraph - metagraph = Metagraph(netuid=netuid, network="ws://localhost:9945") - old_neuron = metagraph.neurons[0] - - # Assert stake is 10000 - assert ( - old_neuron.stake.tao == 10_000.0 - ), f"Expected 10_000.0 staked TAO, but got {neuron.stake.tao}" - - # Assert neuron is not a validator yet - assert old_neuron.active is True - assert old_neuron.validator_permit is False - assert old_neuron.validator_trust == 0.0 - assert old_neuron.pruning_score == 0 - - # Prepare to run the validator - cmd = " ".join( - [ - f"{sys.executable}", - f'"{template_path}{templates_repo}/neurons/validator.py"', - "--netuid", - str(netuid), - "--subtensor.network", - "local", - "--subtensor.chain_endpoint", - "ws://localhost:9945", - "--wallet.path", - bob_wallet.path, - "--wallet.name", - bob_wallet.name, - "--wallet.hotkey", - "default", - ] - ) - - # Run the validator in the background - await asyncio.create_subprocess_shell( - cmd, - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE, - ) - logging.info("Neuron Alice is now validating") - await asyncio.sleep( - 5 - ) # wait for 5 seconds for the metagraph and subtensor to refresh with latest data - - await wait_epoch(subtensor, netuid=netuid) - - # Refresh metagraph - metagraph = Metagraph(netuid=netuid, network="ws://localhost:9945") - - # Refresh validator neuron - updated_neuron = metagraph.neurons[0] - - assert len(metagraph.neurons) == 1 - assert updated_neuron.active is True - assert updated_neuron.validator_permit is True - assert updated_neuron.hotkey == bob_keypair.ss58_address - assert updated_neuron.coldkey == bob_keypair.ss58_address - assert updated_neuron.pruning_score != 0 - - logging.info("✅ Passed test_dendrite") diff --git a/tests/e2e_tests/test_incentive.py b/tests/e2e_tests/test_incentive.py deleted file mode 100644 index e0c6837dc3..0000000000 --- a/tests/e2e_tests/test_incentive.py +++ /dev/null @@ -1,186 +0,0 @@ -import asyncio -import sys - -import pytest - -from bittensor import Subtensor, logging -from tests.e2e_tests.utils.chain_interactions import ( - add_stake, - register_neuron, - register_subnet, - wait_epoch, -) -from tests.e2e_tests.utils.e2e_test_utils import ( - setup_wallet, - template_path, - templates_repo, -) -from bittensor.utils.balance import Balance -from bittensor.core.extrinsics.set_weights import do_set_weights -from bittensor.core.metagraph import Metagraph - - -FAST_BLOCKS_SPEEDUP_FACTOR = 5 - - -@pytest.mark.asyncio -async def test_incentive(local_chain): - """ - Test the incentive mechanism and interaction of miners/validators - - Steps: - 1. Register a subnet and register Alice & Bob - 2. Add Stake by Alice - 3. Run Alice as validator & Bob as miner. Wait Epoch - 4. Verify miner has correct: trust, rank, consensus, incentive - 5. Verify validator has correct: validator_permit, validator_trust, dividends, stake - Raises: - AssertionError: If any of the checks or verifications fail - """ - - logging.info("Testing test_incentive") - netuid = 1 - - # Register root as Alice - the subnet owner and validator - alice_keypair, alice_wallet = setup_wallet("//Alice") - register_subnet(local_chain, alice_wallet) - - # Verify subnet created successfully - assert local_chain.query( - "SubtensorModule", "NetworksAdded", [netuid] - ).serialize(), "Subnet wasn't created successfully" - - # Register Bob as miner - bob_keypair, bob_wallet = setup_wallet("//Bob") - - # Register Alice as a neuron on the subnet - register_neuron(local_chain, alice_wallet, netuid) - - # Register Bob as a neuron on the subnet - register_neuron(local_chain, bob_wallet, netuid) - - subtensor = Subtensor(network="ws://localhost:9945") - # Assert two neurons are in network - assert ( - len(subtensor.neurons(netuid=netuid)) == 2 - ), "Alice & Bob not registered in the subnet" - - # Alice to stake to become to top neuron after the first epoch - add_stake(local_chain, alice_wallet, Balance.from_tao(10_000)) - - # Prepare to run Bob as miner - cmd = " ".join( - [ - f"{sys.executable}", - f'"{template_path}{templates_repo}/neurons/miner.py"', - "--netuid", - str(netuid), - "--subtensor.network", - "local", - "--subtensor.chain_endpoint", - "ws://localhost:9945", - "--wallet.path", - bob_wallet.path, - "--wallet.name", - bob_wallet.name, - "--wallet.hotkey", - "default", - "--logging.trace", - ] - ) - - # Run Bob as miner in the background - await asyncio.create_subprocess_shell( - cmd, - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE, - ) - logging.info("Neuron Bob is now mining") - await asyncio.sleep( - 5 - ) # wait for 5 seconds for the metagraph to refresh with latest data - - # Prepare to run Alice as validator - cmd = " ".join( - [ - f"{sys.executable}", - f'"{template_path}{templates_repo}/neurons/validator.py"', - "--netuid", - str(netuid), - "--subtensor.network", - "local", - "--subtensor.chain_endpoint", - "ws://localhost:9945", - "--wallet.path", - alice_wallet.path, - "--wallet.name", - alice_wallet.name, - "--wallet.hotkey", - "default", - "--logging.trace", - ] - ) - - # Run Alice as validator in the background - await asyncio.create_subprocess_shell( - cmd, - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE, - ) - logging.info("Neuron Alice is now validating") - await asyncio.sleep( - 5 - ) # wait for 5 seconds for the metagraph and subtensor to refresh with latest data - - # Get latest metagraph - metagraph = Metagraph(netuid=netuid, network="ws://localhost:9945") - - # Get current miner/validator stats - bob_neuron = metagraph.neurons[1] - assert bob_neuron.incentive == 0 - assert bob_neuron.consensus == 0 - assert bob_neuron.rank == 0 - assert bob_neuron.trust == 0 - - alice_neuron = metagraph.neurons[0] - assert alice_neuron.validator_permit is False - assert alice_neuron.dividends == 0 - assert alice_neuron.stake.tao == 10_000.0 - assert alice_neuron.validator_trust == 0 - - # Wait until next epoch - await wait_epoch(subtensor) - - # Set weights by Alice on the subnet - do_set_weights( - self=subtensor, - wallet=alice_wallet, - uids=[1], - vals=[65535], - netuid=netuid, - version_key=0, - wait_for_inclusion=True, - wait_for_finalization=True, - period=5 * FAST_BLOCKS_SPEEDUP_FACTOR, - ) - logging.info("Alice neuron set weights successfully") - - await wait_epoch(subtensor) - - # Refresh metagraph - metagraph = Metagraph(netuid=netuid, network="ws://localhost:9945") - - # Get current emissions and validate that Alice has gotten tao - bob_neuron = metagraph.neurons[1] - assert bob_neuron.incentive == 1 - assert bob_neuron.consensus == 1 - assert bob_neuron.rank == 1 - assert bob_neuron.trust == 1 - - alice_neuron = metagraph.neurons[0] - assert alice_neuron.validator_permit is True - assert alice_neuron.dividends == 1 - assert alice_neuron.stake.tao == 10_000.0 - assert alice_neuron.validator_trust == 1 - - logging.info("✅ Passed test_incentive") diff --git a/tests/e2e_tests/test_liquid_alpha.py b/tests/e2e_tests/test_liquid_alpha.py deleted file mode 100644 index 4725704f61..0000000000 --- a/tests/e2e_tests/test_liquid_alpha.py +++ /dev/null @@ -1,187 +0,0 @@ -from bittensor.core.subtensor import Subtensor -from bittensor.utils.balance import Balance -from bittensor.utils.btlogging import logging -from tests.e2e_tests.utils.chain_interactions import ( - add_stake, - register_neuron, - register_subnet, - sudo_set_hyperparameter_bool, - sudo_set_hyperparameter_values, -) -from tests.e2e_tests.utils.e2e_test_utils import setup_wallet - - -def liquid_alpha_call_params(netuid: int, alpha_values: str): - alpha_low, alpha_high = [v.strip() for v in alpha_values.split(",")] - return { - "netuid": netuid, - "alpha_low": alpha_low, - "alpha_high": alpha_high, - } - - -def test_liquid_alpha(local_chain): - """ - Test the liquid alpha mechanism - - Steps: - 1. Register a subnet through Alice - 2. Register Alice's neuron and add stake - 3. Verify we can't set alpha values without enabling liquid_alpha - 4. Test setting alpha values after enabling liquid_alpha - 5. Verify failures when setting incorrect values (upper and lower bounds) - Raises: - AssertionError: If any of the checks or verifications fail - """ - u16_max = 65535 - netuid = 1 - logging.info("Testing test_liquid_alpha_enabled") - - # Register root as Alice - keypair, alice_wallet = setup_wallet("//Alice") - register_subnet(local_chain, alice_wallet), "Unable to register the subnet" - - # Verify subnet 1 created successfully - assert local_chain.query("SubtensorModule", "NetworksAdded", [1]).serialize() - - # Register a neuron to the subnet - assert register_neuron( - local_chain, alice_wallet, netuid - ), "Unable to register Alice as a neuron" - - # Stake to become to top neuron after the first epoch - add_stake(local_chain, alice_wallet, Balance.from_tao(100_000)) - - # Assert liquid alpha is disabled - subtensor = Subtensor(network="ws://localhost:9945") - assert ( - subtensor.get_subnet_hyperparameters(netuid=netuid).liquid_alpha_enabled - is False - ), "Liquid alpha is enabled by default" - - # Attempt to set alpha high/low while disabled (should fail) - alpha_values = "6553, 53083" - call_params = liquid_alpha_call_params(netuid, alpha_values) - result, error_message = sudo_set_hyperparameter_values( - local_chain, - alice_wallet, - call_function="sudo_set_alpha_values", - call_params=call_params, - return_error_message=True, - ) - assert result is False, "Alpha values set while being disabled" - assert error_message["name"] == "LiquidAlphaDisabled" - - # Enabled liquid alpha on the subnet - assert sudo_set_hyperparameter_bool( - local_chain, alice_wallet, "sudo_set_liquid_alpha_enabled", True, netuid - ), "Unable to enable liquid alpha" - - assert subtensor.get_subnet_hyperparameters( - netuid=1 - ).liquid_alpha_enabled, "Failed to enable liquid alpha" - - # Attempt to set alpha high & low after enabling the hyperparameter - alpha_values = "87, 54099" - call_params = liquid_alpha_call_params(netuid, alpha_values) - assert sudo_set_hyperparameter_values( - local_chain, - alice_wallet, - call_function="sudo_set_alpha_values", - call_params=call_params, - ), "Unable to set alpha_values" - assert ( - subtensor.get_subnet_hyperparameters(netuid=1).alpha_high == 54099 - ), "Failed to set alpha high" - assert ( - subtensor.get_subnet_hyperparameters(netuid=1).alpha_low == 87 - ), "Failed to set alpha low" - - # Testing alpha high upper and lower bounds - - # 1. Test setting Alpha_high too low - alpha_high_too_low = ( - u16_max * 4 // 5 - ) - 1 # One less than the minimum acceptable value - call_params = liquid_alpha_call_params(netuid, f"6553, {alpha_high_too_low}") - result, error_message = sudo_set_hyperparameter_values( - local_chain, - alice_wallet, - call_function="sudo_set_alpha_values", - call_params=call_params, - return_error_message=True, - ) - - assert result is False, "Able to set incorrect alpha_high value" - assert error_message["name"] == "AlphaHighTooLow" - - # 2. Test setting Alpha_high too high - alpha_high_too_high = u16_max + 1 # One more than the max acceptable value - call_params = liquid_alpha_call_params(netuid, f"6553, {alpha_high_too_high}") - try: - sudo_set_hyperparameter_values( - local_chain, - alice_wallet, - call_function="sudo_set_alpha_values", - call_params=call_params, - return_error_message=True, - ) - except Exception as e: - assert str(e) == "65536 out of range for u16", f"Unexpected error: {e}" - - # Testing alpha low upper and lower bounds - - # 1. Test setting Alpha_low too low - alpha_low_too_low = 0 - call_params = liquid_alpha_call_params(netuid, f"{alpha_low_too_low}, 53083") - result, error_message = sudo_set_hyperparameter_values( - local_chain, - alice_wallet, - call_function="sudo_set_alpha_values", - call_params=call_params, - return_error_message=True, - ) - assert result is False, "Able to set incorrect alpha_low value" - assert error_message["name"] == "AlphaLowOutOfRange" - - # 2. Test setting Alpha_low too high - alpha_low_too_high = ( - u16_max * 4 // 5 - ) + 1 # One more than the maximum acceptable value - call_params = liquid_alpha_call_params(netuid, f"{alpha_low_too_high}, 53083") - result, error_message = sudo_set_hyperparameter_values( - local_chain, - alice_wallet, - call_function="sudo_set_alpha_values", - call_params=call_params, - return_error_message=True, - ) - assert result is False, "Able to set incorrect alpha_low value" - assert error_message["name"] == "AlphaLowOutOfRange" - - # Setting normal alpha values - alpha_values = "6553, 53083" - call_params = liquid_alpha_call_params(netuid, alpha_values) - assert sudo_set_hyperparameter_values( - local_chain, - alice_wallet, - call_function="sudo_set_alpha_values", - call_params=call_params, - ), "Unable to set liquid alpha values" - - assert ( - subtensor.get_subnet_hyperparameters(netuid=1).alpha_high == 53083 - ), "Failed to set alpha high" - assert ( - subtensor.get_subnet_hyperparameters(netuid=1).alpha_low == 6553 - ), "Failed to set alpha low" - - # Disable Liquid Alpha - assert sudo_set_hyperparameter_bool( - local_chain, alice_wallet, "sudo_set_liquid_alpha_enabled", False, netuid - ), "Unable to disable liquid alpha" - - assert ( - subtensor.get_subnet_hyperparameters(netuid=1).liquid_alpha_enabled is False - ), "Failed to disable liquid alpha" - logging.info("✅ Passed test_liquid_alpha") diff --git a/tests/e2e_tests/test_metagraph.py b/tests/e2e_tests/test_metagraph.py deleted file mode 100644 index 8999b30358..0000000000 --- a/tests/e2e_tests/test_metagraph.py +++ /dev/null @@ -1,178 +0,0 @@ -import time - -from bittensor.core.subtensor import Subtensor -from bittensor.utils.balance import Balance -from bittensor.utils.btlogging import logging -from tests.e2e_tests.utils.chain_interactions import ( - add_stake, - register_neuron, - register_subnet, -) -from tests.e2e_tests.utils.e2e_test_utils import ( - setup_wallet, -) - - -def neuron_to_dict(neuron): - """ - Convert a neuron object to a dictionary, excluding private attributes, methods, and specific fields. - Returns: - dict: A dictionary of the neuron's public attributes. - - Note: - Excludes 'weights' and 'bonds' fields. These are present in subtensor - but not in metagraph - """ - excluded_fields = {"weights", "bonds"} - return { - attr: getattr(neuron, attr) - for attr in dir(neuron) - if not attr.startswith("_") - and not callable(getattr(neuron, attr)) - and attr not in excluded_fields - } - - -def test_metagraph(local_chain): - """ - Tests the metagraph - - Steps: - 1. Register a subnet through Alice - 2. Assert metagraph's initial state - 3. Register Bob and validate info in metagraph - 4. Fetch neuron info of Bob through subtensor & metagraph and verify - 5. Register Dave and validate info in metagraph - 6. Verify low balance stake fails & add stake thru Bob and verify - 7. Load pre_dave metagraph from latest save and verify both instances - Raises: - AssertionError: If any of the checks or verifications fail - """ - logging.info("Testing test_metagraph_command") - netuid = 1 - - # Register Alice, Bob, and Dave - alice_keypair, alice_wallet = setup_wallet("//Alice") - bob_keypair, bob_wallet = setup_wallet("//Bob") - dave_keypair, dave_wallet = setup_wallet("//Dave") - - # Register the subnet through Alice - register_subnet(local_chain, alice_wallet), "Unable to register the subnet" - - # Verify subnet was created successfully - assert local_chain.query( - "SubtensorModule", "NetworksAdded", [1] - ).serialize(), "Subnet wasn't created successfully" - - # Initialize metagraph - subtensor = Subtensor(network="ws://localhost:9945") - metagraph = subtensor.metagraph(netuid=1) - - # Assert metagraph is empty - assert len(metagraph.uids) == 0, "Metagraph is not empty" - - # Register Bob to the subnet - assert register_neuron( - local_chain, bob_wallet, netuid - ), "Unable to register Bob as a neuron" - - # Refresh the metagraph - metagraph.sync(subtensor=subtensor) - - # Assert metagraph has Bob neuron - assert len(metagraph.uids) == 1, "Metagraph doesn't have exactly 1 neuron" - assert ( - metagraph.hotkeys[0] == bob_keypair.ss58_address - ), "Bob's hotkey doesn't match in metagraph" - assert len(metagraph.coldkeys) == 1, "Metagraph doesn't have exactly 1 coldkey" - assert metagraph.n.max() == 1, "Metagraph's max n is not 1" - assert metagraph.n.min() == 1, "Metagraph's min n is not 1" - assert len(metagraph.addresses) == 1, "Metagraph doesn't have exactly 1 address" - - # Fetch UID of Bob - uid = subtensor.get_uid_for_hotkey_on_subnet( - bob_keypair.ss58_address, netuid=netuid - ) - - # Fetch neuron info of Bob through subtensor and metagraph - neuron_info_bob = subtensor.neuron_for_uid(uid, netuid=netuid) - metagraph_dict = neuron_to_dict(metagraph.neurons[uid]) - subtensor_dict = neuron_to_dict(neuron_info_bob) - - # Verify neuron info is the same in both objects - assert ( - metagraph_dict == subtensor_dict - ), "Neuron info of Bob doesn't match b/w metagraph & subtensor" - - # Create pre_dave metagraph for future verifications - metagraph_pre_dave = subtensor.metagraph(netuid=1) - - # Register Dave as a neuron - assert register_neuron( - local_chain, dave_wallet, netuid - ), "Unable to register Dave as a neuron" - - metagraph.sync(subtensor=subtensor) - - # Assert metagraph now includes Dave's neuron - assert ( - len(metagraph.uids) == 2 - ), "Metagraph doesn't have exactly 2 neurons post Dave" - assert ( - metagraph.hotkeys[1] == dave_keypair.ss58_address - ), "Neuron's hotkey in metagraph doesn't match" - assert ( - len(metagraph.coldkeys) == 2 - ), "Metagraph doesn't have exactly 2 coldkeys post Dave" - assert metagraph.n.max() == 2, "Metagraph's max n is not 2 post Dave" - assert metagraph.n.min() == 2, "Metagraph's min n is not 2 post Dave" - assert len(metagraph.addresses) == 2, "Metagraph doesn't have 2 addresses post Dave" - - # Test staking with low balance - assert not add_stake( - local_chain, dave_wallet, Balance.from_tao(10_000) - ), "Low balance stake should fail" - - # Add stake by Bob - assert add_stake( - local_chain, bob_wallet, Balance.from_tao(10_000) - ), "Failed to add stake for Bob" - - # Assert stake is added after updating metagraph - metagraph.sync(subtensor=subtensor) - assert metagraph.neurons[0].stake == Balance.from_tao( - 10_000 - ), "Bob's stake not updated in metagraph" - - # Test the save() and load() mechanism - # We save the metagraph and pre_dave loads it - metagraph.save() - time.sleep(3) - metagraph_pre_dave.load() - - # Ensure data is synced between two metagraphs - assert len(metagraph.uids) == len( - metagraph_pre_dave.uids - ), "UID count mismatch after save and load" - assert ( - metagraph.uids == metagraph_pre_dave.uids - ).all(), "UIDs don't match after save and load" - - assert len(metagraph.axons) == len( - metagraph_pre_dave.axons - ), "Axon count mismatch after save and load" - assert ( - metagraph.axons[1].hotkey == metagraph_pre_dave.axons[1].hotkey - ), "Axon hotkey mismatch after save and load" - assert ( - metagraph.axons == metagraph_pre_dave.axons - ), "Axons don't match after save and load" - - assert len(metagraph.neurons) == len( - metagraph_pre_dave.neurons - ), "Neuron count mismatch after save and load" - assert ( - metagraph.neurons == metagraph_pre_dave.neurons - ), "Neurons don't match after save and load" - - logging.info("✅ Passed test_metagraph") diff --git a/tests/e2e_tests/test_neuron_certificate.py b/tests/e2e_tests/test_neuron_certificate.py new file mode 100644 index 0000000000..39937ede67 --- /dev/null +++ b/tests/e2e_tests/test_neuron_certificate.py @@ -0,0 +1,56 @@ +import pytest +from bittensor.core.subtensor import Subtensor +from bittensor.core.axon import Axon +from bittensor.utils.btlogging import logging +from tests.e2e_tests.utils.chain_interactions import ( + wait_epoch, + register_subnet, + register_neuron, +) +from tests.e2e_tests.utils.e2e_test_utils import ( + setup_wallet, +) + + +@pytest.mark.asyncio +async def test_neuron_certificate(local_chain): + """ + Tests the metagraph + + Steps: + 1. Register a subnet through Alice + 2. Serve alice axon with neuron certificate + 3. Verify neuron certificate + Raises: + AssertionError: If any of the checks or verifications fail + """ + logging.info("Testing neuron_certificate") + netuid = 1 + + # Register root as Alice - the subnet owner and validator + alice_keypair, alice_wallet = setup_wallet("//Alice") + register_subnet(local_chain, alice_wallet) + + # Verify subnet created successfully + assert local_chain.query( + "SubtensorModule", "NetworksAdded", [netuid] + ).serialize(), "Subnet wasn't created successfully" + + # Register Alice as a neuron on the subnet + register_neuron(local_chain, alice_wallet, netuid) + + subtensor = Subtensor(network="ws://localhost:9945") + + axon = Axon(wallet=alice_wallet) + logging.info(f"axon : {axon}") + + certificate = "FAKE_ALICE_CERT" + r = axon.serve(netuid=netuid, subtensor=subtensor, certificate=certificate) + logging.info(f"Serve response: {r}") + await wait_epoch(subtensor) + logging.info("Epoch started") + + assert subtensor.get_neuron_certificate(netuid=netuid, hotkey=alice_keypair.ss58_address) == certificate + + logging.info("✅ Passed test_neuron_certificate") + diff --git a/tests/e2e_tests/test_subtensor_functions.py b/tests/e2e_tests/test_subtensor_functions.py deleted file mode 100644 index d00e587fba..0000000000 --- a/tests/e2e_tests/test_subtensor_functions.py +++ /dev/null @@ -1,151 +0,0 @@ -import asyncio -import sys - -import pytest - -from bittensor.core.subtensor import Subtensor -from bittensor.utils.btlogging import logging -from tests.e2e_tests.utils.chain_interactions import ( - register_neuron, - register_subnet, -) -from tests.e2e_tests.utils.e2e_test_utils import ( - setup_wallet, - template_path, - templates_repo, -) - - -@pytest.mark.asyncio -async def test_subtensor_extrinsics(local_chain): - """ - Tests subtensor extrinsics - - Steps: - 1. Validate subnets in the chain before/after registering netuid = 1 - 2. Register Alice's neuron - 3. Verify Alice and Bob's participation in subnets (individually and global) - 4. Verify uids of Alice and Bob gets populated correctly - 5. Start Alice as a validator and verify neuroninfo before/after is different - Raises: - AssertionError: If any of the checks or verifications fail - """ - netuid = 1 - subtensor = Subtensor(network="ws://localhost:9945") - - # Subnets 0 and 3 are bootstrapped from the start - assert subtensor.get_subnets() == [0, 3] - assert subtensor.get_total_subnets() == 2 - - # Add wallets for Alice and Bob - alice_keypair, alice_wallet = setup_wallet("//Alice") - bob_keypair, bob_wallet = setup_wallet("//Bob") - - # Register subnet - register_subnet(local_chain, alice_wallet), "Unable to register the subnet" - - # Subnet 1 is added after registration - assert subtensor.get_subnets() == [0, 1, 3] - assert subtensor.get_total_subnets() == 3 - - # Verify subnet 1 created successfully - assert local_chain.query("SubtensorModule", "NetworksAdded", [1]).serialize() - assert subtensor.subnet_exists(netuid) - - # Register Alice to the subnet - assert register_neuron( - local_chain, alice_wallet, netuid - ), "Unable to register Alice as a neuron" - - # Verify Alice is registered to netuid 1 and Bob isn't registered to any - assert subtensor.get_netuids_for_hotkey(hotkey_ss58=alice_keypair.ss58_address) == [ - 1 - ], "Alice is not registered to netuid 1 as expected" - assert ( - subtensor.get_netuids_for_hotkey(hotkey_ss58=bob_keypair.ss58_address) == [] - ), "Bob is unexpectedly registered to some netuid" - - # Verify Alice's hotkey is registered to any subnet (currently netuid = 1) - assert subtensor.is_hotkey_registered_any( - hotkey_ss58=alice_keypair.ss58_address - ), "Alice's hotkey is not registered to any subnet" - assert not subtensor.is_hotkey_registered_any( - hotkey_ss58=bob_keypair.ss58_address - ), "Bob's hotkey is unexpectedly registered to a subnet" - - # Verify netuid = 1 only has Alice registered and not Bob - assert subtensor.is_hotkey_registered_on_subnet( - netuid=netuid, hotkey_ss58=alice_keypair.ss58_address - ), "Alice's hotkey is not registered on netuid 1" - assert not subtensor.is_hotkey_registered_on_subnet( - netuid=netuid, hotkey_ss58=bob_keypair.ss58_address - ), "Bob's hotkey is unexpectedly registered on netuid 1" - - # Verify Alice's UID on netuid 1 is 0 - assert ( - subtensor.get_uid_for_hotkey_on_subnet( - hotkey_ss58=alice_keypair.ss58_address, netuid=netuid - ) - == 0 - ), "UID for Alice's hotkey on netuid 1 is not 0 as expected" - - # Register Bob to the subnet - assert register_neuron( - local_chain, bob_wallet, netuid - ), "Unable to register Alice as a neuron" - - # Verify Bob's UID on netuid 1 is 1 - assert ( - subtensor.get_uid_for_hotkey_on_subnet( - hotkey_ss58=bob_keypair.ss58_address, netuid=netuid - ) - == 1 - ), "UID for Bob's hotkey on netuid 1 is not 1 as expected" - - neuron_info_old = subtensor.get_neuron_for_pubkey_and_subnet( - alice_keypair.ss58_address, netuid=netuid - ) - - # Prepare to run Alice as validator - cmd = " ".join( - [ - f"{sys.executable}", - f'"{template_path}{templates_repo}/neurons/validator.py"', - "--netuid", - str(netuid), - "--subtensor.network", - "local", - "--subtensor.chain_endpoint", - "ws://localhost:9945", - "--wallet.path", - alice_wallet.path, - "--wallet.name", - alice_wallet.name, - "--wallet.hotkey", - "default", - "--logging.trace", - ] - ) - - # Run Alice as validator in the background - await asyncio.create_subprocess_shell( - cmd, - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE, - ) - logging.info("Neuron Alice is now validating") - - await asyncio.sleep( - 5 - ) # wait for 5 seconds for the metagraph and subtensor to refresh with latest data - subtensor = Subtensor(network="ws://localhost:9945") - - # Verify neuron info is updated after running as a validator - neuron_info = subtensor.get_neuron_for_pubkey_and_subnet( - alice_keypair.ss58_address, netuid=netuid - ) - assert ( - neuron_info_old.axon_info != neuron_info.axon_info - ), "Neuron info not updated after running validator" - - logging.info("✅ Passed test_subtensor_extrinsics") diff --git a/tests/e2e_tests/test_transfer.py b/tests/e2e_tests/test_transfer.py deleted file mode 100644 index 62cf9723cc..0000000000 --- a/tests/e2e_tests/test_transfer.py +++ /dev/null @@ -1,51 +0,0 @@ -from bittensor import Subtensor, logging -from bittensor.core.subtensor import transfer_extrinsic -from tests.e2e_tests.utils.e2e_test_utils import setup_wallet - - -def test_transfer(local_chain): - """ - Test the transfer mechanism on the chain - - Steps: - 1. Create a wallet for Alice - 2. Calculate existing balance and transfer 2 Tao - 3. Calculate balance after extrinsic call and verify calculations - Raises: - AssertionError: If any of the checks or verifications fail - """ - - logging.info("Testing test_transfer") - - # Set up Alice wallet - keypair, wallet = setup_wallet("//Alice") - - # Account details before transfer - acc_before = local_chain.query("System", "Account", [keypair.ss58_address]) - - # Transfer Tao using extrinsic - subtensor = Subtensor(network="ws://localhost:9945") - transfer_extrinsic( - subtensor=subtensor, - wallet=wallet, - dest="5GpzQgpiAKHMWNSH3RN4GLf96GVTDct9QxYEFAY7LWcVzTbx", - amount=2, - wait_for_finalization=True, - wait_for_inclusion=True, - ) - - # Account details after transfer - acc_after = local_chain.query("System", "Account", [keypair.ss58_address]) - - # Transfer calculation assertions - expected_transfer = 2_000_000_000 - tolerance = 200_000 # Tx fee tolerance - - actual_difference = ( - acc_before.value["data"]["free"] - acc_after.value["data"]["free"] - ) - assert ( - expected_transfer <= actual_difference <= expected_transfer + tolerance - ), f"Expected transfer with tolerance: {expected_transfer} <= {actual_difference} <= {expected_transfer + tolerance}" - - logging.info("✅ Passed test_transfer")