From e900f03eb3460c11bc5de4f6ebf1813ccd4bc089 Mon Sep 17 00:00:00 2001 From: Watchmaker Date: Mon, 22 Jul 2024 12:56:17 -0700 Subject: [PATCH 01/13] Removing from the "main" branch the doc to run subtensor locally As per this Discord thread: https://discord.com/channels/799672011265015819/1260678915186495509 Docs issue: https://github.com/opentensor/developer-docs/issues/221 --- docs/running-subtensor-locally.md | 205 +----------------------------- 1 file changed, 1 insertion(+), 204 deletions(-) diff --git a/docs/running-subtensor-locally.md b/docs/running-subtensor-locally.md index 505fe2fb53..82bb87356d 100644 --- a/docs/running-subtensor-locally.md +++ b/docs/running-subtensor-locally.md @@ -1,206 +1,3 @@ # Running subtensor node locally -- [Method 1: Using Docker](#method-1-using-docker) -- [Method 2: Using Source Code](#method-2-using-source-code) -- [Running on Cloud](#running-on-cloud) - -## Method 1: Using Docker - -To run a subtensor node with Docker, follow the below steps. - -If you are already running a subtensor node using Docker, then go directly to [Step 5 Prepare to Run](#step-5-prepare-to-run) to restart the Docker container. The below steps 1 through 4 are for first time users only. - -### Step 1: Install git - -Make sure you installed `git` on your machine. See [GitHub docs](https://docs.github.com/en/get-started). - -### Step 2: Install Docker - -Follow Docker's [official installation guides](https://docs.docker.com/engine/install/) and install Docker. - -**Run Docker first** -Before you proceed, make sure that Docker is running. - -### Step 3: Clone the subtensor repo - -Clone the subtensor repo: - -```bash -git clone https://github.com/opentensor/subtensor.git -``` - -### Step 4: Go into subtensor directory - -Then `cd` into the subtensor directory: - -```bash -cd subtensor -``` - -### Step 5: Prepare to run - -Execute the below three commands in this order: - -Make sure you are on the `main` branch. If not, switch to it: - -```bash -git checkout main -``` - -Pull the latest `main` branch contents: - -```bash -git pull -``` - -Stop the currently running Docker containers: - -```bash -docker compose down --volumes -``` - -### Run a lite node on mainchain - -To run a lite node connected to the Bittensor mainchain, run the below command. - -```bash -sudo ./scripts/run/subtensor.sh -e docker --network mainnet --node-type lite -``` - -### Run an archive node on mainchain - -To run an archive node connected to the Bittensor mainchain, run the below command. - -```bash -sudo ./scripts/run/subtensor.sh -e docker --network mainnet --node-type archive -``` - -### Run a lite node on testchain - -To run a lite node connected to the Bittensor testchain, run the below command. - -```bash -sudo ./scripts/run/subtensor.sh -e docker --network testnet --node-type lite -``` - -### Run an archive node on testchain - -To run an archive node connected to the Bittensor testchain, run the below command. - -```bash -sudo ./scripts/run/subtensor.sh -e docker --network testnet --node-type archive -``` - ---- - -## Method 2: Using Source Code - -To install and run a subtensor node by compiling the source code, follow the below steps. - -## Install basic packages - -Install the basic requirements by running the below commands on a Linux terminal. - -```bash title="On Linux" -sudo apt-get update -sudo apt install build-essential -sudo apt-get install clang -sudo apt-get install curl -sudo apt-get install git -sudo apt-get install make -sudo apt install --assume-yes git clang curl libssl-dev protobuf-compiler -sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler -``` - -## Install Rust - -Next, install Rust and update the environment by running the following commands: - -```bash -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -source ~/.cargo/env -``` - -Next, install Rust toolchain: - -```bash -rustup default stable -rustup update -rustup target add wasm32-unknown-unknown -rustup toolchain install nightly -rustup target add --toolchain nightly wasm32-unknown-unknown -``` - -## Compile subtensor code - -Next, to compile the subtensor source code, follow the below steps: - -Clone the subtensor repo: - -```bash -git clone https://github.com/opentensor/subtensor.git -``` - -`cd` into the subtensor directory: - -```bash -cd subtensor -``` - -Make sure you are on the `main` branch. If not, switch to it: - -```bash -git checkout main -``` - -Remove previous chain state: - -```bash -rm -rf /tmp/blockchain -``` - -Install subtensor by compiling with `cargo`: - -```bash -cargo build --profile production --features=runtime-benchmarks -``` - -## Run the subtensor node - -You can now run the public subtensor node either as a lite node or as an archive node. See below: - -### Lite node on mainchain - -To run a lite node connected to the mainchain, execute the below command (note the `--sync=warp` flag which runs the subtensor node in lite mode): - -```bash title="With --sync=warp setting, for lite node" -./target/production/node-subtensor --chain raw_spec.json --base-path /tmp/blockchain --sync=warp --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /ip4/13.58.175.193/tcp/30333/p2p/12D3KooWDe7g2JbNETiKypcKT1KsCEZJbTzEHCn8hpd4PHZ6pdz5 --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external -``` - -### Archive node on mainchain - -To run an archive node connected to the mainchain, execute the below command (note the `--sync=full` which syncs the node to the full chain and `--pruning archive` flags, which disables the node's automatic pruning of older historical data): - -```bash title="With --sync=full and --pruning archive setting, for archive node" -./target/production/node-subtensor --chain raw_spec.json --base-path /tmp/blockchain --sync=full --pruning archive --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /ip4/13.58.175.193/tcp/30333/p2p/12D3KooWDe7g2JbNETiKypcKT1KsCEZJbTzEHCn8hpd4PHZ6pdz5 --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external -``` - -### Lite node on testchain - -To run a lite node connected to the testchain, execute the below command: - -```bash title="With bootnodes set to testnet and --sync=warp setting, for lite node." -./target/production/node-subtensor --chain raw_testspec.json --base-path /tmp/blockchain --sync=warp --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /dns/bootnode.test.finney.opentensor.ai/tcp/30333/p2p/12D3KooWPM4mLcKJGtyVtkggqdG84zWrd7Rij6PGQDoijh1X86Vr --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external -``` - -### Archive node on testchain - -To run an archive node connected to the testchain, execute the below command: - -```bash title="With bootnodes set to testnet and --sync=full and --pruning archive setting, for archive node" -./target/production/node-subtensor --chain raw_testspec.json --base-path /tmp/blockchain --sync=full --pruning archive --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /dns/bootnode.test.finney.opentensor.ai/tcp/30333/p2p/12D3KooWPM4mLcKJGtyVtkggqdG84zWrd7Rij6PGQDoijh1X86Vr --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external -``` - -## Running on cloud - -We have not tested these installation scripts on any cloud service. In addition, if you are using Runpod cloud service, then note that this service is already [containerized](https://docs.runpod.io/pods/overview). Hence, the only option available to you is to compile from the source, as described in the above [Method 2: Using Source Code](#method-2-using-source-code) section. Note that these scripts have not been tested on Runpod. +See the [**Subtensor Nodes** section in Bittensor Developer Documentation](https://docs.bittensor.com/subtensor-nodes). From 55e6d0681d7521eaf314d6b6c6643fd0f54a4ae8 Mon Sep 17 00:00:00 2001 From: Watchmaker Date: Mon, 22 Jul 2024 13:11:09 -0700 Subject: [PATCH 02/13] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 47639b6407..30f36ffab5 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Requirements: ## For Subnet Development -If you are developing and testing subnet incentive mechanism, you will need to run a local subtensor node. Follow the detailed step-by-step instructions provided in the document [Running subtensor locally](./docs/running-subtensor-locally.md) to run either a lite node or an archive node. Also see the [**Subtensor Nodes** section in Bittensor Developer Documentation](https://docs.bittensor.com/subtensor-nodes). +If you are developing and testing subnet incentive mechanism, you will need to run a local subtensor node. Follow the detailed step-by-step instructions provided in the [**Subtensor Nodes** section in Bittensor Developer Documentation](https://docs.bittensor.com/subtensor-nodes). ### Lite node vs Archive node From aec052a099de7f3977964a3d6117b8222cc351a2 Mon Sep 17 00:00:00 2001 From: Unconst <32490803+unconst@users.noreply.github.com> Date: Tue, 23 Jul 2024 12:38:54 -0500 Subject: [PATCH 03/13] Update CODEOWNERS --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 5fefbd608e..ffc01511bb 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1 @@ -* @sacha-l @lisa-parity +* @unconst From e0ff0739f374f1bc35f8d4b27f12efc04e74f4f3 Mon Sep 17 00:00:00 2001 From: John Reed <87283488+JohnReedV@users.noreply.github.com> Date: Tue, 30 Jul 2024 09:31:47 -0700 Subject: [PATCH 04/13] custom errors signed extension --- pallets/subtensor/src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index f7824e2a30..ff4297ae2c 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -2425,7 +2425,7 @@ where ..Default::default() }) } else { - Err(InvalidTransaction::Call.into()) + Err(InvalidTransaction::Custom(1).into()) } } Some(Call::reveal_weights { netuid, .. }) => { @@ -2437,7 +2437,7 @@ where ..Default::default() }) } else { - Err(InvalidTransaction::Call.into()) + Err(InvalidTransaction::Custom(2).into()) } } Some(Call::set_weights { netuid, .. }) => { @@ -2449,7 +2449,7 @@ where ..Default::default() }) } else { - Err(InvalidTransaction::Call.into()) + Err(InvalidTransaction::Custom(3).into()) } } Some(Call::set_root_weights { netuid, hotkey, .. }) => { @@ -2461,7 +2461,7 @@ where ..Default::default() }) } else { - Err(InvalidTransaction::Call.into()) + Err(InvalidTransaction::Custom(4).into()) } } Some(Call::add_stake { .. }) => Ok(ValidTransaction { @@ -2480,7 +2480,7 @@ where if registrations_this_interval >= (max_registrations_per_interval.saturating_mul(3)) { // If the registration limit for the interval is exceeded, reject the transaction - return InvalidTransaction::ExhaustsResources.into(); + return Err(InvalidTransaction::Custom(5).into()); } Ok(ValidTransaction { priority: Self::get_priority_vanilla(), @@ -2493,7 +2493,7 @@ where }), Some(Call::dissolve_network { .. }) => { if Pallet::::coldkey_in_arbitration(who) { - Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) + Err(InvalidTransaction::Custom(6).into()) } else { Ok(ValidTransaction { priority: Self::get_priority_vanilla(), From 18879258d792d3b8597f4fef3d5b9701386c69c3 Mon Sep 17 00:00:00 2001 From: John Reed <87283488+JohnReedV@users.noreply.github.com> Date: Tue, 30 Jul 2024 11:47:46 -0700 Subject: [PATCH 05/13] update tests --- pallets/subtensor/tests/registration.rs | 4 ++-- pallets/subtensor/tests/weights.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pallets/subtensor/tests/registration.rs b/pallets/subtensor/tests/registration.rs index bd95ae3b14..74a493e04e 100644 --- a/pallets/subtensor/tests/registration.rs +++ b/pallets/subtensor/tests/registration.rs @@ -276,7 +276,7 @@ fn test_registration_rate_limit_exceeded() { let result = extension.validate(&who, &call.into(), &info, 10); // Expectation: The transaction should be rejected - assert_err!(result, InvalidTransaction::ExhaustsResources); + assert_err!(result, InvalidTransaction::Custom(5)); let current_registrants = SubtensorModule::get_registrations_this_interval(netuid); assert!(current_registrants <= max_registrants); @@ -362,7 +362,7 @@ fn test_burned_registration_rate_limit_exceeded() { // Expectation: The transaction should be rejected assert_err!( burned_register_result, - InvalidTransaction::ExhaustsResources + InvalidTransaction::Custom(5) ); let current_registrants = SubtensorModule::get_registrations_this_interval(netuid); diff --git a/pallets/subtensor/tests/weights.rs b/pallets/subtensor/tests/weights.rs index 2344bd4257..88b8aaf250 100644 --- a/pallets/subtensor/tests/weights.rs +++ b/pallets/subtensor/tests/weights.rs @@ -109,7 +109,7 @@ fn test_set_rootweights_validate() { assert_err!( // Should get an invalid transaction error result_no_stake, - TransactionValidityError::Invalid(InvalidTransaction::Call,) + TransactionValidityError::Invalid(InvalidTransaction::Custom(4)) ); // Increase the stake to be equal to the minimum @@ -209,7 +209,7 @@ fn test_commit_weights_validate() { assert_err!( // Should get an invalid transaction error result_no_stake, - TransactionValidityError::Invalid(InvalidTransaction::Call,) + TransactionValidityError::Invalid(InvalidTransaction::Custom(1)) ); // Increase the stake to be equal to the minimum @@ -308,7 +308,7 @@ fn test_reveal_weights_validate() { assert_err!( // Should get an invalid transaction error result_no_stake, - TransactionValidityError::Invalid(InvalidTransaction::Call,) + TransactionValidityError::Invalid(InvalidTransaction::Custom(2)) ); // Increase the stake to be equal to the minimum From 75e7299f96907f51a04a4e27dae6d717df19361e Mon Sep 17 00:00:00 2001 From: John Reed <87283488+JohnReedV@users.noreply.github.com> Date: Tue, 30 Jul 2024 11:58:24 -0700 Subject: [PATCH 06/13] clippy --- pallets/collective/src/lib.rs | 6 +++--- pallets/subtensor/tests/difficulty.rs | 1 - pallets/subtensor/tests/epoch.rs | 1 - pallets/subtensor/tests/mock.rs | 4 ++++ pallets/subtensor/tests/neuron_info.rs | 1 - pallets/subtensor/tests/registration.rs | 1 - pallets/subtensor/tests/serving.rs | 2 -- pallets/subtensor/tests/staking.rs | 3 --- pallets/subtensor/tests/weights.rs | 3 --- 9 files changed, 7 insertions(+), 15 deletions(-) diff --git a/pallets/collective/src/lib.rs b/pallets/collective/src/lib.rs index 96040f99ca..6aae3c85e9 100644 --- a/pallets/collective/src/lib.rs +++ b/pallets/collective/src/lib.rs @@ -951,9 +951,9 @@ impl, I: 'static> Pallet { /// /// If not `approved`: /// - one event deposited. - /// Two removals, one mutation. - /// Computation and i/o `O(P)` where: - /// - `P` is number of active proposals + /// - two removals, one mutation. + /// - computation and i/o `O(P)` where: + /// - `P` is number of active proposals fn do_approve_proposal( seats: MemberCount, yes_votes: MemberCount, diff --git a/pallets/subtensor/tests/difficulty.rs b/pallets/subtensor/tests/difficulty.rs index 05238bc43a..c3023b829f 100644 --- a/pallets/subtensor/tests/difficulty.rs +++ b/pallets/subtensor/tests/difficulty.rs @@ -5,7 +5,6 @@ mod mock; use sp_core::U256; #[test] -#[cfg(not(tarpaulin))] fn test_registration_difficulty_adjustment() { new_test_ext(1).execute_with(|| { // Create Net 1 diff --git a/pallets/subtensor/tests/epoch.rs b/pallets/subtensor/tests/epoch.rs index 676b3cd35a..e2b911525d 100644 --- a/pallets/subtensor/tests/epoch.rs +++ b/pallets/subtensor/tests/epoch.rs @@ -2107,7 +2107,6 @@ fn test_zero_weights() { // Test that epoch assigns validator permits to highest stake uids, varies uid interleaving and stake values. #[test] -#[cfg(not(tarpaulin))] fn test_validator_permits() { let netuid: u16 = 1; let tempo: u16 = u16::MAX - 1; // high tempo to skip automatic epochs in on_initialize, use manual epochs instead diff --git a/pallets/subtensor/tests/mock.rs b/pallets/subtensor/tests/mock.rs index fc784f46f2..3b4ee8de88 100644 --- a/pallets/subtensor/tests/mock.rs +++ b/pallets/subtensor/tests/mock.rs @@ -262,6 +262,7 @@ impl CollectiveInterface for TriumvirateVotes { } // We call pallet_collective TriumvirateCollective +#[allow(dead_code)] type TriumvirateCollective = pallet_collective::Instance1; impl pallet_collective::Config for Test { type RuntimeOrigin = RuntimeOrigin; @@ -279,6 +280,7 @@ impl pallet_collective::Config for Test { } // We call council members Triumvirate +#[allow(dead_code)] type TriumvirateMembership = pallet_membership::Instance1; impl pallet_membership::Config for Test { type RuntimeEvent = RuntimeEvent; @@ -295,6 +297,7 @@ impl pallet_membership::Config for Test { // This is a dummy collective instance for managing senate members // Probably not the best solution, but fastest implementation +#[allow(dead_code)] type SenateCollective = pallet_collective::Instance2; impl pallet_collective::Config for Test { type RuntimeOrigin = RuntimeOrigin; @@ -312,6 +315,7 @@ impl pallet_collective::Config for Test { } // We call our top K delegates membership Senate +#[allow(dead_code)] type SenateMembership = pallet_membership::Instance2; impl pallet_membership::Config for Test { type RuntimeEvent = RuntimeEvent; diff --git a/pallets/subtensor/tests/neuron_info.rs b/pallets/subtensor/tests/neuron_info.rs index 10df1c07da..3494fdc5ff 100644 --- a/pallets/subtensor/tests/neuron_info.rs +++ b/pallets/subtensor/tests/neuron_info.rs @@ -15,7 +15,6 @@ fn test_get_neuron_none() { } #[test] -#[cfg(not(tarpaulin))] fn test_get_neuron_some() { new_test_ext(1).execute_with(|| { let netuid: u16 = 1; diff --git a/pallets/subtensor/tests/registration.rs b/pallets/subtensor/tests/registration.rs index 74a493e04e..8c1c6e6bdf 100644 --- a/pallets/subtensor/tests/registration.rs +++ b/pallets/subtensor/tests/registration.rs @@ -539,7 +539,6 @@ fn test_burn_adjustment() { } #[test] -#[cfg(not(tarpaulin))] fn test_registration_too_many_registrations_per_block() { new_test_ext(1).execute_with(|| { let netuid: u16 = 1; diff --git a/pallets/subtensor/tests/serving.rs b/pallets/subtensor/tests/serving.rs index 41e9888ccb..b87b7fd10a 100644 --- a/pallets/subtensor/tests/serving.rs +++ b/pallets/subtensor/tests/serving.rs @@ -161,7 +161,6 @@ fn test_serving_set_metadata_update() { } #[test] -#[cfg(not(tarpaulin))] fn test_axon_serving_rate_limit_exceeded() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(1); @@ -379,7 +378,6 @@ fn test_prometheus_serving_set_metadata_update() { } #[test] -#[cfg(not(tarpaulin))] fn test_prometheus_serving_rate_limit_exceeded() { new_test_ext(1).execute_with(|| { let hotkey_account_id = U256::from(1); diff --git a/pallets/subtensor/tests/staking.rs b/pallets/subtensor/tests/staking.rs index cb2cac4efe..12d299d8fc 100644 --- a/pallets/subtensor/tests/staking.rs +++ b/pallets/subtensor/tests/staking.rs @@ -22,7 +22,6 @@ use sp_runtime::traits::SignedExtension; ************************************************************/ #[test] -#[cfg(not(tarpaulin))] fn test_add_stake_dispatch_info_ok() { new_test_ext(1).execute_with(|| { let hotkey = U256::from(0); @@ -528,7 +527,6 @@ fn test_remove_stake_rate_limit_exceeded() { } #[test] -#[cfg(not(tarpaulin))] fn test_remove_stake_dispatch_info_ok() { new_test_ext(1).execute_with(|| { let hotkey = U256::from(0); @@ -1201,7 +1199,6 @@ fn test_delegate_stake_division_by_zero_check() { } #[test] -#[cfg(not(tarpaulin))] fn test_full_with_delegating() { new_test_ext(1).execute_with(|| { let netuid = 1; diff --git a/pallets/subtensor/tests/weights.rs b/pallets/subtensor/tests/weights.rs index 88b8aaf250..c87f818b22 100644 --- a/pallets/subtensor/tests/weights.rs +++ b/pallets/subtensor/tests/weights.rs @@ -21,7 +21,6 @@ use substrate_fixed::types::I32F32; // Test the call passes through the subtensor module. #[test] -#[cfg(not(tarpaulin))] fn test_set_weights_dispatch_info_ok() { new_test_ext(0).execute_with(|| { let dests = vec![1, 1]; @@ -41,7 +40,6 @@ fn test_set_weights_dispatch_info_ok() { }); } #[test] -#[cfg(not(tarpaulin))] fn test_set_rootweights_dispatch_info_ok() { new_test_ext(0).execute_with(|| { let dests = vec![1, 1]; @@ -404,7 +402,6 @@ fn test_weights_err_no_validator_permit() { // To execute this test: cargo test --package pallet-subtensor --test weights test_set_weights_min_stake_failed -- --nocapture` #[test] -#[cfg(not(tarpaulin))] fn test_set_weights_min_stake_failed() { new_test_ext(0).execute_with(|| { let dests = vec![0]; From 38ad5169256aafe913b2389bb8ce5e925362edc6 Mon Sep 17 00:00:00 2001 From: John Reed <87283488+JohnReedV@users.noreply.github.com> Date: Tue, 30 Jul 2024 12:01:30 -0700 Subject: [PATCH 07/13] fmt --- pallets/subtensor/tests/registration.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pallets/subtensor/tests/registration.rs b/pallets/subtensor/tests/registration.rs index 8c1c6e6bdf..4d235cb7ee 100644 --- a/pallets/subtensor/tests/registration.rs +++ b/pallets/subtensor/tests/registration.rs @@ -360,10 +360,7 @@ fn test_burned_registration_rate_limit_exceeded() { extension.validate(&who, &call_burned_register.into(), &info, 10); // Expectation: The transaction should be rejected - assert_err!( - burned_register_result, - InvalidTransaction::Custom(5) - ); + assert_err!(burned_register_result, InvalidTransaction::Custom(5)); let current_registrants = SubtensorModule::get_registrations_this_interval(netuid); assert!(current_registrants <= max_registrants); From 826e55c1f26322adc3f84dd3b74207de5795f84b Mon Sep 17 00:00:00 2001 From: John Reed <87283488+JohnReedV@users.noreply.github.com> Date: Tue, 30 Jul 2024 12:35:52 -0700 Subject: [PATCH 08/13] add custom error 7 & fix clippy --- pallets/subtensor/src/lib.rs | 18 ++++++++---------- pallets/subtensor/tests/staking.rs | 6 ++---- runtime/src/lib.rs | 2 ++ 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index ff4297ae2c..f5d70362fa 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -2403,16 +2403,14 @@ where _len: usize, ) -> TransactionValidity { // Check if the call is one of the balance transfer types we want to reject - if let Some(balances_call) = call.is_sub_type() { - match balances_call { - BalancesCall::transfer_allow_death { .. } - | BalancesCall::transfer_keep_alive { .. } - | BalancesCall::transfer_all { .. } => { - if Pallet::::coldkey_in_arbitration(who) { - return Err(TransactionValidityError::Invalid(InvalidTransaction::Call)); - } - } - _ => {} // Other Balances calls are allowed + if let Some( + BalancesCall::transfer_allow_death { .. } + | BalancesCall::transfer_keep_alive { .. } + | BalancesCall::transfer_all { .. }, + ) = call.is_sub_type() + { + if Pallet::::coldkey_in_arbitration(who) { + return Err(InvalidTransaction::Custom(7).into()); } } match call.is_sub_type() { diff --git a/pallets/subtensor/tests/staking.rs b/pallets/subtensor/tests/staking.rs index 12d299d8fc..fff6749fc5 100644 --- a/pallets/subtensor/tests/staking.rs +++ b/pallets/subtensor/tests/staking.rs @@ -1,9 +1,7 @@ #![allow(clippy::unwrap_used)] #![allow(clippy::arithmetic_side_effects)] -use frame_support::pallet_prelude::{ - InvalidTransaction, TransactionValidity, TransactionValidityError, -}; +use frame_support::pallet_prelude::{InvalidTransaction, TransactionValidity}; use frame_support::traits::{OnFinalize, OnIdle, OnInitialize}; use frame_support::weights::Weight; use frame_support::{assert_err, assert_noop, assert_ok, traits::Currency}; @@ -3876,7 +3874,7 @@ fn test_transfer_coldkey_in_arbitration() { assert_eq!( validate_transaction(&coldkey_account_id, &call), - Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) + Err(InvalidTransaction::Custom(7).into()) ); }); } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index a4abd124ff..303e7040f6 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -516,6 +516,7 @@ impl pallet_collective::Config for Runtime { } // We call council members Triumvirate +#[allow(dead_code)] type TriumvirateMembership = pallet_membership::Instance1; impl pallet_membership::Config for Runtime { type RuntimeEvent = RuntimeEvent; @@ -531,6 +532,7 @@ impl pallet_membership::Config for Runtime { } // We call our top K delegates membership Senate +#[allow(dead_code)] type SenateMembership = pallet_membership::Instance2; impl pallet_membership::Config for Runtime { type RuntimeEvent = RuntimeEvent; From beadf9f51b1a54c472c3afa6a29a51145878c4bd Mon Sep 17 00:00:00 2001 From: John Reed <87283488+JohnReedV@users.noreply.github.com> Date: Wed, 31 Jul 2024 08:49:30 -0700 Subject: [PATCH 09/13] add missing validate tests --- pallets/subtensor/tests/root.rs | 114 +++++++++++++++++++++++++++-- pallets/subtensor/tests/weights.rs | 60 +++++++++++++++ 2 files changed, 169 insertions(+), 5 deletions(-) diff --git a/pallets/subtensor/tests/root.rs b/pallets/subtensor/tests/root.rs index 7c66226702..9e5cdbb3b6 100644 --- a/pallets/subtensor/tests/root.rs +++ b/pallets/subtensor/tests/root.rs @@ -1,12 +1,16 @@ #![allow(clippy::indexing_slicing, clippy::unwrap_used)] use crate::mock::*; -use frame_support::{assert_err, assert_ok}; -use frame_system::Config; -use frame_system::{EventRecord, Phase}; -use pallet_subtensor::migration; -use pallet_subtensor::Error; +use frame_support::{assert_err, assert_ok, dispatch::DispatchInfo}; +use frame_system::{Config, EventRecord, Phase}; +use pallet_subtensor::{ + migration, BaseDifficulty, ColdkeySwapDestinations, Error, MIN_BALANCE_TO_PERFORM_COLDKEY_SWAP, +}; use sp_core::{Get, H256, U256}; +use sp_runtime::{ + traits::{DispatchInfoOf, SignedExtension}, + transaction_validity::{InvalidTransaction, TransactionValidityError}, +}; mod mock; @@ -974,3 +978,103 @@ fn test_dissolve_network_does_not_exist_err() { ); }); } + +#[test] +fn test_dissolve_network_validate() { + fn generate_valid_pow(coldkey: &U256, block_number: u64, difficulty: U256) -> (H256, u64) { + let mut nonce: u64 = 0; + loop { + let work = SubtensorModule::create_seal_hash(block_number, nonce, coldkey); + if SubtensorModule::hash_meets_difficulty(&work, difficulty) { + return (work, nonce); + } + nonce += 1; + } + } + // Testing the signed extension validate function + // correctly filters the `dissolve_network` transaction. + + new_test_ext(0).execute_with(|| { + let netuid: u16 = 1; + let delegate_coldkey = U256::from(1); + let delegate_hotkey = U256::from(2); + let new_coldkey = U256::from(3); + let current_block = 0u64; + + add_network(netuid, 0, 0); + register_ok_neuron(netuid, delegate_hotkey, delegate_coldkey, 0); + + // Make delegate a delegate + assert_ok!(SubtensorModule::become_delegate( + RuntimeOrigin::signed(delegate_coldkey), + delegate_hotkey + )); + + // Add more than 500 TAO of stake to the delegate's hotkey + let stake_amount = 501_000_000_000; // 501 TAO in RAO + let delegator = U256::from(4); + SubtensorModule::add_balance_to_coldkey_account(&delegator, stake_amount); + assert_ok!(SubtensorModule::add_stake( + RuntimeOrigin::signed(delegator), + delegate_hotkey, + stake_amount + )); + + // Ensure the delegate's coldkey has less than minimum balance + assert!( + SubtensorModule::get_coldkey_balance(&delegate_coldkey) + < MIN_BALANCE_TO_PERFORM_COLDKEY_SWAP, + "Delegate coldkey balance should be less than minimum required" + ); + + // Ensure the delegate's hotkey has more than 500 TAO delegated + assert!( + SubtensorModule::get_total_delegated_stake(&delegate_coldkey) >= 500_000_000_000, + "Delegate hotkey should have at least 500 TAO delegated" + ); + + // Generate valid PoW + let (work, nonce) = generate_valid_pow( + &delegate_coldkey, + current_block, + U256::from(4) * U256::from(BaseDifficulty::::get()), + ); + + // Schedule coldkey swap + assert_ok!(SubtensorModule::do_schedule_coldkey_swap( + &delegate_coldkey, + &new_coldkey, + work.to_fixed_bytes().to_vec(), + current_block, + nonce, + )); + + // Verify that the swap was scheduled + assert_eq!( + ColdkeySwapDestinations::::get(delegate_coldkey), + vec![new_coldkey] + ); + + // Check if the coldkey is in arbitration + assert!( + SubtensorModule::coldkey_in_arbitration(&delegate_coldkey), + "Delegate coldkey should be in arbitration after swap" + ); + + let who = delegate_coldkey; // The coldkey signs this transaction + let call = RuntimeCall::SubtensorModule(SubtensorCall::dissolve_network { netuid }); + + let info: DispatchInfo = + DispatchInfoOf::<::RuntimeCall>::default(); + + let extension = pallet_subtensor::SubtensorSignedExtension::::new(); + + // Submit to the signed extension validate function + let result_in_arbitration = extension.validate(&who, &call.clone(), &info, 10); + // Should fail with InvalidTransaction::Custom(6) because coldkey is in arbitration + assert_err!( + result_in_arbitration, + TransactionValidityError::Invalid(InvalidTransaction::Custom(6)) + ); + }); +} diff --git a/pallets/subtensor/tests/weights.rs b/pallets/subtensor/tests/weights.rs index c87f818b22..214e3add06 100644 --- a/pallets/subtensor/tests/weights.rs +++ b/pallets/subtensor/tests/weights.rs @@ -259,6 +259,66 @@ fn test_reveal_weights_dispatch_info_ok() { }); } +#[test] +fn test_set_weights_validate() { + // Testing the signed extension validate function + // correctly filters the `set_weights` transaction. + + new_test_ext(0).execute_with(|| { + let netuid: u16 = 1; + let coldkey = U256::from(0); + let hotkey: U256 = U256::from(1); + assert_ne!(hotkey, coldkey); + + let who = hotkey; // The hotkey signs this transaction + + let call = RuntimeCall::SubtensorModule(SubtensorCall::set_weights { + netuid, + dests: vec![1, 1], + weights: vec![1, 1], + version_key: 0, + }); + + // Create netuid + add_network(netuid, 0, 0); + // Register the hotkey + SubtensorModule::append_neuron(netuid, &hotkey, 0); + Owner::::insert(hotkey, coldkey); + + let min_stake = 500_000_000_000; + // Set the minimum stake + SubtensorModule::set_weights_min_stake(min_stake); + + // Verify stake is less than minimum + assert!(SubtensorModule::get_total_stake_for_hotkey(&hotkey) < min_stake); + let info: DispatchInfo = + DispatchInfoOf::<::RuntimeCall>::default(); + + let extension = pallet_subtensor::SubtensorSignedExtension::::new(); + // Submit to the signed extension validate function + let result_no_stake = extension.validate(&who, &call.clone(), &info, 10); + // Should fail due to insufficient stake + assert_err!( + result_no_stake, + TransactionValidityError::Invalid(InvalidTransaction::Custom(3)) + ); + + // Increase the stake to be equal to the minimum + SubtensorModule::increase_stake_on_hotkey_account(&hotkey, min_stake); + + // Verify stake is equal to minimum + assert_eq!( + SubtensorModule::get_total_stake_for_hotkey(&hotkey), + min_stake + ); + + // Submit to the signed extension validate function + let result_min_stake = extension.validate(&who, &call.clone(), &info, 10); + // Now the call should pass + assert_ok!(result_min_stake); + }); +} + #[test] fn test_reveal_weights_validate() { // Testing the signed extension validate function From d35d20bcfdad66731fdb2e4d090551e279ec6f1f Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Sun, 4 Aug 2024 12:50:33 +0400 Subject: [PATCH 10/13] chore: bump spec --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 303e7040f6..fd23d1fd33 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -139,7 +139,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 165, + spec_version: 193, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From 02325f3620fba06bc405e986b7acfc4c1514f469 Mon Sep 17 00:00:00 2001 From: Samuel Dare Date: Sun, 4 Aug 2024 13:08:13 +0400 Subject: [PATCH 11/13] bump spec , formats --- pallets/subtensor/src/lib.rs | 10 --- pallets/subtensor/tests/root.rs | 104 ----------------------------- pallets/subtensor/tests/staking.rs | 3 - 3 files changed, 117 deletions(-) diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index dd6948c565..6388e03315 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -1347,20 +1347,10 @@ where priority: Self::get_priority_vanilla(), ..Default::default() }), -<<<<<<< HEAD - - Ok(ValidTransaction { - priority: Self::get_priority_vanilla(), - ..Default::default() - }) - } - } -======= Some(Call::dissolve_network { .. }) => Ok(ValidTransaction { priority: Self::get_priority_vanilla(), ..Default::default() }), ->>>>>>> origin/devnet-ready _ => Ok(ValidTransaction { priority: Self::get_priority_vanilla(), ..Default::default() diff --git a/pallets/subtensor/tests/root.rs b/pallets/subtensor/tests/root.rs index 9cc694a529..84df71d837 100644 --- a/pallets/subtensor/tests/root.rs +++ b/pallets/subtensor/tests/root.rs @@ -7,10 +7,6 @@ use frame_system::{EventRecord, Phase}; use pallet_subtensor::migrations; use pallet_subtensor::Error; use sp_core::{Get, H256, U256}; -use sp_runtime::{ - traits::{DispatchInfoOf, SignedExtension}, - transaction_validity::{InvalidTransaction, TransactionValidityError}, -}; mod mock; @@ -983,103 +979,3 @@ fn test_dissolve_network_does_not_exist_err() { ); }); } - -#[test] -fn test_dissolve_network_validate() { - fn generate_valid_pow(coldkey: &U256, block_number: u64, difficulty: U256) -> (H256, u64) { - let mut nonce: u64 = 0; - loop { - let work = SubtensorModule::create_seal_hash(block_number, nonce, coldkey); - if SubtensorModule::hash_meets_difficulty(&work, difficulty) { - return (work, nonce); - } - nonce += 1; - } - } - // Testing the signed extension validate function - // correctly filters the `dissolve_network` transaction. - - new_test_ext(0).execute_with(|| { - let netuid: u16 = 1; - let delegate_coldkey = U256::from(1); - let delegate_hotkey = U256::from(2); - let new_coldkey = U256::from(3); - let current_block = 0u64; - - add_network(netuid, 0, 0); - register_ok_neuron(netuid, delegate_hotkey, delegate_coldkey, 0); - - // Make delegate a delegate - assert_ok!(SubtensorModule::become_delegate( - RuntimeOrigin::signed(delegate_coldkey), - delegate_hotkey - )); - - // Add more than 500 TAO of stake to the delegate's hotkey - let stake_amount = 501_000_000_000; // 501 TAO in RAO - let delegator = U256::from(4); - SubtensorModule::add_balance_to_coldkey_account(&delegator, stake_amount); - assert_ok!(SubtensorModule::add_stake( - RuntimeOrigin::signed(delegator), - delegate_hotkey, - stake_amount - )); - - // Ensure the delegate's coldkey has less than minimum balance - assert!( - SubtensorModule::get_coldkey_balance(&delegate_coldkey) - < MIN_BALANCE_TO_PERFORM_COLDKEY_SWAP, - "Delegate coldkey balance should be less than minimum required" - ); - - // Ensure the delegate's hotkey has more than 500 TAO delegated - assert!( - SubtensorModule::get_total_delegated_stake(&delegate_coldkey) >= 500_000_000_000, - "Delegate hotkey should have at least 500 TAO delegated" - ); - - // Generate valid PoW - let (work, nonce) = generate_valid_pow( - &delegate_coldkey, - current_block, - U256::from(4) * U256::from(BaseDifficulty::::get()), - ); - - // Schedule coldkey swap - assert_ok!(SubtensorModule::do_schedule_coldkey_swap( - &delegate_coldkey, - &new_coldkey, - work.to_fixed_bytes().to_vec(), - current_block, - nonce, - )); - - // Verify that the swap was scheduled - assert_eq!( - ColdkeySwapDestinations::::get(delegate_coldkey), - vec![new_coldkey] - ); - - // Check if the coldkey is in arbitration - assert!( - SubtensorModule::coldkey_in_arbitration(&delegate_coldkey), - "Delegate coldkey should be in arbitration after swap" - ); - - let who = delegate_coldkey; // The coldkey signs this transaction - let call = RuntimeCall::SubtensorModule(SubtensorCall::dissolve_network { netuid }); - - let info: DispatchInfo = - DispatchInfoOf::<::RuntimeCall>::default(); - - let extension = pallet_subtensor::SubtensorSignedExtension::::new(); - - // Submit to the signed extension validate function - let result_in_arbitration = extension.validate(&who, &call.clone(), &info, 10); - // Should fail with InvalidTransaction::Custom(6) because coldkey is in arbitration - assert_err!( - result_in_arbitration, - TransactionValidityError::Invalid(InvalidTransaction::Custom(6)) - ); - }); -} diff --git a/pallets/subtensor/tests/staking.rs b/pallets/subtensor/tests/staking.rs index 3cf9609d73..5bf95841ab 100644 --- a/pallets/subtensor/tests/staking.rs +++ b/pallets/subtensor/tests/staking.rs @@ -1,9 +1,6 @@ #![allow(clippy::unwrap_used)] #![allow(clippy::arithmetic_side_effects)] -use frame_support::pallet_prelude::{InvalidTransaction, TransactionValidity}; -use frame_support::traits::{OnFinalize, OnIdle, OnInitialize}; -use frame_support::weights::Weight; use frame_support::{assert_err, assert_noop, assert_ok, traits::Currency}; use frame_system::Config; mod mock; From 9ef28bf25c01967a686eb5e276904c48129f83d2 Mon Sep 17 00:00:00 2001 From: John Reed <87283488+JohnReedV@users.noreply.github.com> Date: Mon, 12 Aug 2024 10:34:22 -0700 Subject: [PATCH 12/13] add line --- pallets/subtensor/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 6388e03315..9fab3be0e8 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -1356,6 +1356,7 @@ where ..Default::default() }), } + } // NOTE: Add later when we put in a pre and post dispatch step. From 58196b18babd28089f8d1bbdd35dd6d002762828 Mon Sep 17 00:00:00 2001 From: John Reed <87283488+JohnReedV@users.noreply.github.com> Date: Mon, 12 Aug 2024 10:34:30 -0700 Subject: [PATCH 13/13] remove line --- pallets/subtensor/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index 9fab3be0e8..6388e03315 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -1356,7 +1356,6 @@ where ..Default::default() }), } - } // NOTE: Add later when we put in a pre and post dispatch step.