diff --git a/.cargo-husky/hooks/post-commit b/.cargo-husky/hooks/post-commit index 06581a469..b259a331d 100755 --- a/.cargo-husky/hooks/post-commit +++ b/.cargo-husky/hooks/post-commit @@ -25,7 +25,7 @@ __hey_listen__() { fi } -while read -rd '' _path; do +while read -r _path; do if rustup run nightly -- rustfmt --check --quiet -- "${_path}" 1>/dev/null 2>&1; then __hey_listen__ "Skipping -> ${_path}" continue 1 diff --git a/.cargo-husky/hooks/pre-push b/.cargo-husky/hooks/pre-push index 7d4d5a5b7..9ca4284ac 100755 --- a/.cargo-husky/hooks/pre-push +++ b/.cargo-husky/hooks/pre-push @@ -16,6 +16,8 @@ # ``` ## +export PATH="$HOME/.cargo/bin:$PATH" + set -EeT __hey_listen__() { diff --git a/.cargo-husky/hooks/prepare-commit-msg b/.cargo-husky/hooks/prepare-commit-msg new file mode 100755 index 000000000..1661f5de6 --- /dev/null +++ b/.cargo-husky/hooks/prepare-commit-msg @@ -0,0 +1,18 @@ +#!/bin/sh +# +# git prepare-commit-msg hook for automatically prepending an issue key +# from the start of the current branch name to commit messages. + +# check if commit is merge commit or a commit ammend +if [ $2 = "merge" ] || [ $2 = "commit" ]; then + exit +fi +ISSUE_KEY=`git branch | grep -o "\* \(.*/\)*[A-Z]\{2,\}-[0-9]\+" | grep -o "[A-Z]\{2,\}-[0-9]\+"` +if [ $? -ne 0 ]; then + # no issue key in branch, use the default message + exit +fi +# issue key matched from branch prefix, prepend to commit message +TEMP=`mktemp /tmp/commitmsg-XXXXX` +(echo "$ISSUE_KEY: $(cat $1)") > $TEMP +cat $TEMP > $1 \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 4aa2478e6..367708fa4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4194,6 +4194,7 @@ dependencies = [ "pallet-grandpa", "pallet-insecure-randomness-collective-flip", "pallet-membership", + "pallet-multisig", "pallet-subtensor", "pallet-sudo", "pallet-timestamp", @@ -4528,6 +4529,22 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-multisig" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-session" version = "4.0.0-dev" @@ -8675,7 +8692,7 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", "digest 0.10.6", - "rand 0.7.3", + "rand 0.8.5", "static_assertions", ] diff --git a/README.md b/README.md index 20c3d2423..4e9f8d5cc 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,7 @@ SKIP_WASM_BUILD=1 \ Running code coverage ```bash -SKIP_WASM_BUILD=1 RUST_LOG=runtime=debug cargo tarpaulin --skip-clean +bash scripts/code-coverage.sh ``` > Note; above requires `cargo-tarpaulin` is installed to the host, eg. `cargo install cargo-tarpaulin` diff --git a/hyperparameters.md b/hyperparameters.md index a03084aac..da0a0d04a 100644 --- a/hyperparameters.md +++ b/hyperparameters.md @@ -8,10 +8,10 @@ TxRateLimit: u64 = 1; // [1 @ 64,888] ```rust Rho: u16 = 10; Kappa: u16 = 32_767; // 0.5 = 65535/2 -MaxAllowedUids: u16 = 128; +MaxAllowedUids: u16 = 1024; Issuance: u64 = 0; MinAllowedWeights: u16 = 8; -EmissionValue: u64 = 50_000_000; +EmissionValue: u64 = 142_223_000; MaxWeightsLimit: u16 = 32768; // 50% of u16 ValidatorBatchSize: u16 = 1; ValidatorSequenceLen: u16 = 2048; // 2048 @@ -22,17 +22,17 @@ ValidatorPruneLen: u64 = 1; ValidatorLogitsDivergence: u16 = 1310; // 2% of u16 ScalingLawPower: u16 = 50; // 0.5 SynergyScalingLawPower: u16 = 50; // 0.5 -MaxAllowedValidators: u16 = 8; +MaxAllowedValidators: u16 = 128; Tempo: u16 = 99; Difficulty: u64 = 10_000_000; AdjustmentInterval: u16 = 225; -TargetRegistrationsPerInterval: u16 = 1; +TargetRegistrationsPerInterval: u16 = 2; ImmunityPeriod: u16 = 7200; ActivityCutoff: u16 = 5000; MaxRegistrationsPerBlock: u16 = 1; PruningScore : u16 = u16::MAX; BondsMovingAverage: u64 = 900_000; -WeightsVersionKey: u64 = 370; +WeightsVersionKey: u64 = 1000; MinDifficulty: u64 = 10_000_000; MaxDifficulty: u64 = u64::MAX / 4; ServingRateLimit: u64 = 10; @@ -49,7 +49,7 @@ Kappa: u16 = 32_767; // 0.5 = 65535/2 MaxAllowedUids: u16 = 4096; Issuance: u64 = 0; MinAllowedWeights: u16 = 50; -EmissionValue: u64 = 950_000_000; +EmissionValue: u64 = 857_777_000; MaxWeightsLimit: u16 = 655; // 655/2^16 = 0.01 [655 @ 7,160] ValidatorBatchSize: u16 = 32; // 32 ValidatorSequenceLen: u16 = 256; // 256 diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index 275892124..e57e999cb 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -179,7 +179,7 @@ pub fn finney_mainnet_config() -> Result { Some("bittensor"), None, // Properties - None, + Some(properties), // Extensions None, )) @@ -541,3 +541,125 @@ fn finney_genesis( } } } + +pub fn localnet_config() -> Result { + let path: PathBuf = std::path::PathBuf::from("./snapshot.json"); + let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; + + // We mmap the file into memory first, as this is *a lot* faster than using + // `serde_json::from_reader`. See https://github.com/serde-rs/json/issues/160 + let file = File::open(&path) + .map_err(|e| format!("Error opening genesis file `{}`: {}", path.display(), e))?; + + // SAFETY: `mmap` is fundamentally unsafe since technically the file can change + // underneath us while it is mapped; in practice it's unlikely to be a problem + let bytes = unsafe { + memmap2::Mmap::map(&file) + .map_err(|e| format!("Error mmaping genesis file `{}`: {}", path.display(), e))? + }; + + let old_state: ColdkeyHotkeys = + json::from_slice(&bytes).map_err(|e| format!("Error parsing genesis file: {}", e))?; + + let mut processed_stakes: Vec<(sp_runtime::AccountId32, Vec<(sp_runtime::AccountId32, (u64, u16))>)> = Vec::new(); + for (coldkey_str, hotkeys) in old_state.stakes.iter() { + let coldkey = ::from_ss58check(&coldkey_str).unwrap(); + let coldkey_account = sp_runtime::AccountId32::from(coldkey); + + let mut processed_hotkeys: Vec<(sp_runtime::AccountId32, (u64, u16))> = Vec::new(); + + for (hotkey_str, amount_uid) in hotkeys.iter() { + let (amount, uid) = amount_uid; + let hotkey = ::from_ss58check(&hotkey_str).unwrap(); + let hotkey_account = sp_runtime::AccountId32::from(hotkey); + + processed_hotkeys.push((hotkey_account, (*amount, *uid))); + } + + processed_stakes.push((coldkey_account, processed_hotkeys)); + } + + let mut balances_issuance: u64 = 0; + let mut processed_balances: Vec<(sp_runtime::AccountId32, u64)> = Vec::new(); + for (key_str, amount) in old_state.balances.iter() { + let key = ::from_ss58check(&key_str).unwrap(); + let key_account = sp_runtime::AccountId32::from(key); + + processed_balances.push((key_account, *amount)); + balances_issuance += *amount; + } + + // Give front-ends necessary data to present to users + let mut properties = sc_service::Properties::new(); + properties.insert("tokenSymbol".into(), "TAO".into()); + properties.insert("tokenDecimals".into(), 9.into()); + properties.insert("ss58Format".into(), 13116.into()); + + Ok(ChainSpec::from_genesis( + // Name + "Bittensor", + // ID + "bittensor", + ChainType::Development, + move || { + localnet_genesis( + wasm_binary, + // Initial PoA authorities (Validators) + // aura | grandpa + vec![ + // Keys for debug + authority_keys_from_seed("Alice"), + authority_keys_from_seed("Bob"), + ], + // Pre-funded accounts + true, + ) + }, + // Bootnodes + vec![], + // Telemetry + None, + // Protocol ID + Some("bittensor"), + None, + // Properties + Some(properties), + // Extensions + None, + )) +} + +fn localnet_genesis( + wasm_binary: &[u8], + initial_authorities: Vec<(AuraId, GrandpaId)>, + _enable_println: bool, +) -> GenesisConfig { + GenesisConfig { + system: SystemConfig { + // Add Wasm runtime to storage. + code: wasm_binary.to_vec(), + }, + balances: BalancesConfig { + // Configure sudo balance + balances: vec![ + (get_account_id_from_seed::("Alice"), 1000000000000), + (get_account_id_from_seed::("Bob"), 1000000000000), + (get_account_id_from_seed::("Charlie"), 1000000000000), + (get_account_id_from_seed::("Dave"), 2000000000), + (get_account_id_from_seed::("Eve"), 2000000000), + (get_account_id_from_seed::("Ferdie"), 2000000000), + ] + }, + aura: AuraConfig { + authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), + }, + grandpa: GrandpaConfig { + authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect(), + }, + sudo: SudoConfig { + key: Some(get_account_id_from_seed::("Alice")), + }, + transaction_payment: Default::default(), + subtensor_module: Default::default(), + } +} diff --git a/node/src/command.rs b/node/src/command.rs index 48ae023ff..a8627a99c 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -19,7 +19,7 @@ use sc_service::PartialComponents; impl SubstrateCli for Cli { fn impl_name() -> String { - "Substrate Node".into() + "Subtensor Node".into() } fn impl_version() -> String { @@ -44,6 +44,7 @@ impl SubstrateCli for Cli { fn load_spec(&self, id: &str) -> Result, String> { Ok(match id { + "local" => Box::new(chain_spec::localnet_config()?), "finney" => Box::new(chain_spec::finney_mainnet_config()?), "" |"test_finney" => Box::new(chain_spec::finney_testnet_config()?), "local" => Box::new(chain_spec::localnet_config()?), diff --git a/pallets/subtensor/src/benchmarks.rs b/pallets/subtensor/src/benchmarks.rs index 48434f5cd..4a22ced81 100644 --- a/pallets/subtensor/src/benchmarks.rs +++ b/pallets/subtensor/src/benchmarks.rs @@ -27,16 +27,14 @@ benchmarks! { let block_number: u64 = Subtensor::::get_current_block_as_u64(); let start_nonce: u64 = (39420842u64 + 100u64*netuid as u64).into(); - let hotkey: T::AccountId = account("Alice", 0, seed); - let (nonce, work): (u64, Vec) = Subtensor::::create_work_for_block_number( netuid, block_number, start_nonce, &hotkey); + let (nonce, work): (u64, Vec) = Subtensor::::create_work_for_block_number( netuid, block_number, start_nonce, &caller); assert_ok!(Subtensor::::do_add_network( RawOrigin::Root.into(), netuid.try_into().unwrap(), tempo.into(), modality.into())); + assert_ok!(Subtensor::::do_sudo_set_network_registration_allowed( RawOrigin::Root.into(), netuid.try_into().unwrap(), true.into())); let block_number: u64 = Subtensor::::get_current_block_as_u64(); - let hotkey: T::AccountId = account("Alice", 0, seed); let coldkey: T::AccountId = account("Test", 0, seed); - - }: register( RawOrigin::Signed( hotkey.clone() ), netuid, block_number, nonce, work, hotkey.clone(), coldkey.clone() ) + }: register( RawOrigin::Signed( caller.clone() ), netuid, block_number, nonce, work, caller.clone(), coldkey ) benchmark_set_weights { @@ -49,8 +47,9 @@ benchmarks! { assert_ok!( Subtensor::::do_add_network( RawOrigin::Root.into(), netuid.try_into().unwrap(), tempo.into(), modality.into())); Subtensor::::set_max_allowed_uids( netuid, 4096 ); - assert_ok!(Subtensor::::do_sudo_set_max_registrations_per_block(RawOrigin::Root.into(), netuid.try_into().unwrap(), 4096 )); - Subtensor::::set_target_registrations_per_interval(netuid.try_into().unwrap(), 4096); + assert_ok!(Subtensor::::do_sudo_set_network_registration_allowed( RawOrigin::Root.into(), netuid.try_into().unwrap(), true.into())); + assert_ok!(Subtensor::::do_sudo_set_max_registrations_per_block(RawOrigin::Root.into(), netuid.try_into().unwrap(), 4096 )); + assert_ok!(Subtensor::::do_sudo_set_target_registrations_per_interval(RawOrigin::Root.into(), netuid.try_into().unwrap(), 4096 )); let mut seed : u32 = 1; let mut dests: Vec = vec![]; @@ -62,8 +61,8 @@ benchmarks! { let coldkey: T::AccountId = account("Test", 0, seed); seed = seed +1; - Subtensor::::set_burn(netuid, 1); - let amoun_to_be_staked = Subtensor::::u64_to_balance( 1000000 ); + Subtensor::::set_burn(netuid, 1); + let amoun_to_be_staked = Subtensor::::u64_to_balance( 1000000 ); Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), amoun_to_be_staked.unwrap()); Subtensor::::do_burned_registration(RawOrigin::Signed(coldkey.clone()).into(), netuid, hotkey.clone())?; @@ -88,21 +87,21 @@ benchmarks! { let seed : u32 = 1; assert_ok!( Subtensor::::do_add_network( RawOrigin::Root.into(), netuid.try_into().unwrap(), tempo.into(), modality.into())); - Subtensor::::set_max_allowed_uids( netuid, 4096 ); - Subtensor::::set_burn(netuid, 1); + Subtensor::::set_burn(netuid, 1); + Subtensor::::set_max_allowed_uids( netuid, 4096 ); + assert_ok!(Subtensor::::do_sudo_set_network_registration_allowed( RawOrigin::Root.into(), netuid.try_into().unwrap(), true.into())); assert_eq!(Subtensor::::get_max_allowed_uids(netuid), 4096); let coldkey: T::AccountId = account("Test", 0, seed); let hotkey: T::AccountId = account("Alice", 0, seed); - let amoun_to_be_staked = Subtensor::::u64_to_balance( 1000000000); + let amoun_to_be_staked = Subtensor::::u64_to_balance( 1000000000); Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), amoun_to_be_staked.unwrap()); - assert_ok!(Subtensor::::do_burned_registration(RawOrigin::Signed(coldkey.clone()).into(), netuid, hotkey.clone())); + assert_ok!(Subtensor::::do_burned_registration(RawOrigin::Signed(coldkey.clone()).into(), netuid, hotkey.clone())); }: become_delegate(RawOrigin::Signed( coldkey.clone() ), hotkey.clone()) - benchmark_add_stake { let caller: T::AccountId = whitelisted_caller::>(); let caller_origin = ::RuntimeOrigin::from(RawOrigin::Signed(caller.clone())); @@ -113,9 +112,11 @@ benchmarks! { let seed : u32 = 1; assert_ok!( Subtensor::::do_add_network( RawOrigin::Root.into(), netuid.try_into().unwrap(), tempo.into(), modality.into())); - Subtensor::::set_max_allowed_uids( netuid, 4096 ); - Subtensor::::set_burn(netuid, 1); + Subtensor::::set_burn(netuid, 1); + assert_ok!(Subtensor::::do_sudo_set_network_registration_allowed( RawOrigin::Root.into(), netuid.try_into().unwrap(), true.into())); + + Subtensor::::set_max_allowed_uids( netuid, 4096 ); assert_eq!(Subtensor::::get_max_allowed_uids(netuid), 4096); let coldkey: T::AccountId = account("Test", 0, seed); @@ -125,7 +126,7 @@ benchmarks! { let amoun_to_be_staked = Subtensor::::u64_to_balance( 1000000000); Subtensor::::add_balance_to_coldkey_account(&coldkey.clone(), amoun_to_be_staked.unwrap()); - assert_ok!(Subtensor::::do_burned_registration(RawOrigin::Signed(coldkey.clone()).into(), netuid, hotkey.clone())); + assert_ok!(Subtensor::::do_burned_registration(RawOrigin::Signed(coldkey.clone()).into(), netuid, hotkey.clone())); }: add_stake(RawOrigin::Signed( coldkey.clone() ), hotkey, amount) benchmark_remove_stake{ @@ -141,6 +142,8 @@ benchmarks! { Subtensor::::increase_total_stake(1_000_000_000_000); assert_ok!( Subtensor::::do_add_network( RawOrigin::Root.into(), netuid.try_into().unwrap(), tempo.into(), modality.into())); + assert_ok!(Subtensor::::do_sudo_set_network_registration_allowed( RawOrigin::Root.into(), netuid.try_into().unwrap(), true.into())); + Subtensor::::set_max_allowed_uids( netuid, 4096 ); assert_eq!(Subtensor::::get_max_allowed_uids(netuid), 4096); @@ -169,7 +172,7 @@ benchmarks! { let caller: T::AccountId = whitelisted_caller::>(); let caller_origin = ::RuntimeOrigin::from(RawOrigin::Signed(caller.clone())); let netuid: u16 = 1; - let tempo: u16 = 1; + let tempo: u16 = 1; let modality: u16 = 0; let version: u32 = 2; @@ -698,5 +701,22 @@ benchmarks! { assert_ok!(Subtensor::::do_join_senate(RawOrigin::Signed(coldkey.clone()).into(), &hotkey)); }: leave_senate(RawOrigin::Signed(coldkey.clone()), hotkey.clone()) -} + benchmark_sudo_set_registration_allowed { + let netuid: u16 = 1; + let tempo: u16 = 1; + let modality: u16 = 0; + + assert_ok!( Subtensor::::do_add_network( RawOrigin::Root.into(), netuid.try_into().unwrap(), tempo.into(), modality.into())); + }: sudo_set_registration_allowed(RawOrigin::>::Root, netuid, true) + + benchmark_sudo_set_tempo { + let netuid: u16 = 1; + let tempo_default: u16 = 1; + let tempo: u16 = 15; + let modality: u16 = 0; + + assert_ok!( Subtensor::::do_add_network( RawOrigin::Root.into(), netuid.try_into().unwrap(), tempo_default.into(), modality.into())); + + }: sudo_set_tempo(RawOrigin::>::Root, netuid, tempo) +} diff --git a/pallets/subtensor/src/block_step.rs b/pallets/subtensor/src/block_step.rs index 42bfae645..073385fbb 100644 --- a/pallets/subtensor/src/block_step.rs +++ b/pallets/subtensor/src/block_step.rs @@ -53,7 +53,7 @@ impl Pallet { } pub fn has_loaded_emission_tuples( netuid: u16 ) -> bool { LoadedEmission::::contains_key( netuid ) } - pub fn get_loaded_emission_tuples( netuid: u16 ) -> Vec<(T::AccountId, u64)> { LoadedEmission::::get( netuid ).unwrap() } + pub fn get_loaded_emission_tuples( netuid: u16 ) -> Vec<(T::AccountId, u64, u64)> { LoadedEmission::::get( netuid ).unwrap() } // Reads from the loaded emission storage which contains lists of pending emission tuples ( hotkey, amount ) // and distributes small chunks of them at a time. @@ -62,11 +62,11 @@ impl Pallet { // --- 1. We iterate across each network. for ( netuid, _ ) in as IterableStorageMap>::iter() { if !Self::has_loaded_emission_tuples( netuid ) { continue } // There are no tuples to emit. - let tuples_to_drain: Vec<(T::AccountId, u64)> = Self::get_loaded_emission_tuples( netuid ); + let tuples_to_drain: Vec<(T::AccountId, u64, u64)> = Self::get_loaded_emission_tuples( netuid ); let mut total_emitted: u64 = 0; - for (hotkey, amount) in tuples_to_drain.iter() { - Self::emit_inflation_through_hotkey_account( &hotkey, *amount ); - total_emitted += *amount; + for (hotkey, server_amount, validator_amount) in tuples_to_drain.iter() { + Self::emit_inflation_through_hotkey_account( &hotkey, *server_amount, *validator_amount ); + total_emitted += *server_amount + *validator_amount; } LoadedEmission::::remove( netuid ); TotalIssuance::::put( TotalIssuance::::get().saturating_add( total_emitted ) ); @@ -94,22 +94,22 @@ impl Pallet { } // --- 4 This network is at tempo and we are running its epoch. - // First frain the queued emission. + // First drain the queued emission. let emission_to_drain:u64 = PendingEmission::::get( netuid ); PendingEmission::::insert( netuid, 0 ); // --- 5. Run the epoch mechanism and return emission tuples for hotkeys in the network. - let emission_tuples_this_block: Vec<(T::AccountId, u64)> = Self::epoch( netuid, emission_to_drain ); + let emission_tuples_this_block: Vec<(T::AccountId, u64, u64)> = Self::epoch( netuid, emission_to_drain ); // --- 6. Check that the emission does not exceed the allowed total. - let emission_sum: u128 = emission_tuples_this_block.iter().map( |(_account_id, e)| *e as u128 ).sum(); + let emission_sum: u128 = emission_tuples_this_block.iter().map( |(_account_id, ve, se)| *ve as u128 + *se as u128 ).sum(); if emission_sum > emission_to_drain as u128 { continue } // Saftey check. // --- 7. Sink the emission tuples onto the already loaded. - let mut concat_emission_tuples: Vec<(T::AccountId, u64)> = emission_tuples_this_block.clone(); + let mut concat_emission_tuples: Vec<(T::AccountId, u64, u64)> = emission_tuples_this_block.clone(); if Self::has_loaded_emission_tuples( netuid ) { // 7.a We already have loaded emission tuples, so we concat the new ones. - let mut current_emission_tuples: Vec<(T::AccountId, u64)> = Self::get_loaded_emission_tuples( netuid ); + let mut current_emission_tuples: Vec<(T::AccountId, u64, u64)> = Self::get_loaded_emission_tuples( netuid ); concat_emission_tuples.append( &mut current_emission_tuples ); } LoadedEmission::::insert( netuid, concat_emission_tuples ); @@ -123,35 +123,40 @@ impl Pallet { // is distributed onto the accounts in proportion of the stake delegated minus the take. This function // is called after an epoch to distribute the newly minted stake according to delegation. // - pub fn emit_inflation_through_hotkey_account( hotkey: &T::AccountId, emission: u64) { - + pub fn emit_inflation_through_hotkey_account( hotkey: &T::AccountId, server_emission: u64, validator_emission: u64 ) { // --- 1. Check if the hotkey is a delegate. If not, we simply pass the stake through to the // coldkey - hotkey account as normal. if !Self::hotkey_is_delegate( hotkey ) { - Self::increase_stake_on_hotkey_account( &hotkey, emission ); + Self::increase_stake_on_hotkey_account( &hotkey, server_emission + validator_emission ); return; } + // Then this is a delegate, we distribute validator_emission, then server_emission. - // --- 2. The hotkey is a delegate. We first distribute a proportion of the emission to the hotkey + // --- 2. The hotkey is a delegate. We first distribute a proportion of the validator_emission to the hotkey // directly as a function of its 'take' let total_hotkey_stake: u64 = Self::get_total_stake_for_hotkey( hotkey ); - let delegate_take: u64 = Self::calculate_delegate_proportional_take( hotkey, emission ); - let remaining_emission: u64 = emission - delegate_take; + let delegate_take: u64 = Self::calculate_delegate_proportional_take( hotkey, validator_emission ); + let validator_emission_minus_take: u64 = validator_emission - delegate_take; + let mut remaining_validator_emission: u64 = validator_emission_minus_take; // 3. -- The remaining emission goes to the owners in proportion to the stake delegated. for ( owning_coldkey_i, stake_i ) in < Stake as IterableStorageDoubleMap>::iter_prefix( hotkey ) { // --- 4. The emission proportion is remaining_emission * ( stake / total_stake ). - let stake_proportion: u64 = Self::calculate_stake_proportional_emission( stake_i, total_hotkey_stake, remaining_emission ); + let stake_proportion: u64 = Self::calculate_stake_proportional_emission( stake_i, total_hotkey_stake, validator_emission_minus_take ); Self::increase_stake_on_coldkey_hotkey_account( &owning_coldkey_i, &hotkey, stake_proportion ); log::debug!("owning_coldkey_i: {:?} hotkey: {:?} emission: +{:?} ", owning_coldkey_i, hotkey, stake_proportion ); - + remaining_validator_emission -= stake_proportion; } // --- 5. Last increase final account balance of delegate after 4, since 5 will change the stake proportion of // the delegate and effect calculation in 4. - Self::increase_stake_on_hotkey_account( &hotkey, delegate_take ); - log::debug!("delkey: {:?} delegate_take: +{:?} ", hotkey,delegate_take ); + Self::increase_stake_on_hotkey_account( &hotkey, delegate_take + remaining_validator_emission ); + log::debug!("delkey: {:?} delegate_take: +{:?} ", hotkey, delegate_take ); + // Also emit the server_emission to the hotkey + // The server emission is distributed in-full to the delegate owner. + // We do this after 4. for the same reason as above. + Self::increase_stake_on_hotkey_account( &hotkey, server_emission ); } // Increases the stake on the cold - hot pairing by increment while also incrementing other counters. @@ -227,29 +232,44 @@ impl Pallet { let burn_registrations_this_interval: u16 = Self::get_burn_registrations_this_interval( netuid ); let target_registrations_this_interval: u16 = Self::get_target_registrations_per_interval( netuid ); // --- 5. Adjust burn + pow - // There are four cases to consider. A, B, C, D + // There are six cases to consider. A, B, C, D, E, F if registrations_this_interval > target_registrations_this_interval { if pow_registrations_this_interval > burn_registrations_this_interval { // A. There are too many registrations this interval and most of them are pow registrations // this triggers an increase in the pow difficulty. // pow_difficulty ++ Self::set_difficulty( netuid, Self::adjust_difficulty( netuid, current_difficulty, registrations_this_interval, target_registrations_this_interval ) ); - } else { + } else if pow_registrations_this_interval < burn_registrations_this_interval { // B. There are too many registrations this interval and most of them are burn registrations // this triggers an increase in the burn cost. // burn_cost ++ Self::set_burn( netuid, Self::adjust_burn( netuid, current_burn, registrations_this_interval, target_registrations_this_interval ) ); + } else { + // F. There are too many registrations this interval and the pow and burn registrations are equal + // this triggers an increase in the burn cost and pow difficulty + // burn_cost ++ + Self::set_burn( netuid, Self::adjust_burn( netuid, current_burn, registrations_this_interval, target_registrations_this_interval ) ); + // pow_difficulty ++ + Self::set_difficulty( netuid, Self::adjust_difficulty( netuid, current_difficulty, registrations_this_interval, target_registrations_this_interval ) ); } } else { + // Not enough registrations this interval. if pow_registrations_this_interval > burn_registrations_this_interval { // C. There are not enough registrations this interval and most of them are pow registrations // this triggers a decrease in the burn cost // burn_cost -- Self::set_burn( netuid, Self::adjust_burn( netuid, current_burn, registrations_this_interval, target_registrations_this_interval ) ); - } else { + } else if pow_registrations_this_interval < burn_registrations_this_interval{ // D. There are not enough registrations this interval and most of them are burn registrations // this triggers a decrease in the pow difficulty - // pow_difficulty ++ + // pow_difficulty -- + Self::set_difficulty( netuid, Self::adjust_difficulty( netuid, current_difficulty, registrations_this_interval, target_registrations_this_interval ) ); + } else { + // E. There are not enough registrations this interval and the pow and burn registrations are equal + // this triggers a decrease in the burn cost and pow difficulty + // burn_cost -- + Self::set_burn( netuid, Self::adjust_burn( netuid, current_burn, registrations_this_interval, target_registrations_this_interval ) ); + // pow_difficulty -- Self::set_difficulty( netuid, Self::adjust_difficulty( netuid, current_difficulty, registrations_this_interval, target_registrations_this_interval ) ); } } diff --git a/pallets/subtensor/src/epoch.rs b/pallets/subtensor/src/epoch.rs index d1d1e354a..55444b003 100644 --- a/pallets/subtensor/src/epoch.rs +++ b/pallets/subtensor/src/epoch.rs @@ -9,7 +9,7 @@ impl Pallet { // Calculates reward consensus and returns the emissions for uids/hotkeys in a given `netuid`. // (Dense version used only for testing purposes.) - pub fn epoch_dense( netuid: u16, rao_emission: u64 ) -> Vec<(T::AccountId, u64)> { + pub fn epoch_dense( netuid: u16, rao_emission: u64 ) -> Vec<(T::AccountId, u64, u64)> { // Get subnetwork size. let n: u16 = Self::get_subnetwork_n( netuid ); @@ -183,33 +183,61 @@ impl Pallet { // ================================= // Compute emission scores. - let mut normalized_emission: Vec = incentive.iter().zip( dividends.clone() ).map( |(ii, di)| ii + di ).collect(); - inplace_normalize( &mut normalized_emission ); - + + // Compute normalized emission scores. range: I32F32(0, 1) + // Compute normalized emission scores. range: I32F32(0, 1) + let combined_emission: Vec = incentive.iter().zip( dividends.clone() ).map( |(ii, di)| ii + di ).collect(); + let emission_sum: I32F32 = combined_emission.iter().sum(); + + let mut normalized_server_emission: Vec = incentive.clone(); // Servers get incentive. + let mut normalized_validator_emission: Vec = dividends.clone(); // Validators get dividends. + let mut normalized_combined_emission: Vec = combined_emission.clone(); + // Normalize on the sum of incentive + dividends. + inplace_normalize_using_sum( &mut normalized_server_emission, emission_sum ); + inplace_normalize_using_sum( &mut normalized_validator_emission, emission_sum ); + inplace_normalize( &mut normalized_combined_emission ); + // If emission is zero, replace emission with normalized stake. - if is_zero( &normalized_emission ) { // no weights set | outdated weights | self_weights + if emission_sum == I32F32::from(0) { // no weights set | outdated weights | self_weights if is_zero( &active_stake ) { // no active stake - normalized_emission = stake.clone(); // do not mask inactive, assumes stake is normalized + normalized_validator_emission = stake.clone(); // do not mask inactive, assumes stake is normalized + normalized_combined_emission = stake.clone(); } else { - normalized_emission = active_stake.clone(); // emission proportional to inactive-masked normalized stake + normalized_validator_emission = active_stake.clone(); // emission proportional to inactive-masked normalized stake + normalized_combined_emission = active_stake.clone(); } } - + // Compute rao based emission scores. range: I96F32(0, rao_emission) let float_rao_emission: I96F32 = I96F32::from_num( rao_emission ); - let emission: Vec = normalized_emission.iter().map( |e: &I32F32| I96F32::from_num( *e ) * float_rao_emission ).collect(); - let emission: Vec = emission.iter().map( |e: &I96F32| e.to_num::() ).collect(); - log::trace!( "E: {:?}", &emission ); - // Set pruning scores. - let pruning_scores: Vec = normalized_emission.clone(); + let server_emission: Vec = normalized_server_emission.iter().map( |se: &I32F32| I96F32::from_num( *se ) * float_rao_emission ).collect(); + let server_emission: Vec = server_emission.iter().map( |e: &I96F32| e.to_num::() ).collect(); + + let validator_emission: Vec = normalized_validator_emission.iter().map( |ve: &I32F32| I96F32::from_num( *ve ) * float_rao_emission ).collect(); + let validator_emission: Vec = validator_emission.iter().map( |e: &I96F32| e.to_num::() ).collect(); + + // Used only to track combined emission in the storage. + let combined_emission: Vec = normalized_combined_emission.iter().map( |ce: &I32F32| I96F32::from_num( *ce ) * float_rao_emission ).collect(); + let combined_emission: Vec = combined_emission.iter().map( |e: &I96F32| e.to_num::() ).collect(); + + log::trace!( "nSE: {:?}", &normalized_server_emission ); + log::trace!( "SE: {:?}", &server_emission ); + log::trace!( "nVE: {:?}", &normalized_validator_emission ); + log::trace!( "VE: {:?}", &validator_emission ); + log::trace!( "nCE: {:?}", &normalized_combined_emission ); + log::trace!( "CE: {:?}", &combined_emission ); + + + // Set pruning scores using combined emission scores. + let pruning_scores: Vec = normalized_combined_emission.clone(); log::trace!( "P: {:?}", &pruning_scores ); // =================== // == Value storage == // =================== - let cloned_emission: Vec = emission.clone(); + let cloned_emission: Vec = combined_emission.clone(); let cloned_ranks: Vec = ranks.iter().map(|xi| fixed_proportion_to_u16(*xi)).collect::>(); let cloned_trust: Vec = trust.iter().map(|xi| fixed_proportion_to_u16(*xi)).collect::>(); let cloned_consensus: Vec = consensus.iter().map(|xi| fixed_proportion_to_u16(*xi)).collect::>(); @@ -243,9 +271,9 @@ impl Pallet { } } - let mut result: Vec<(T::AccountId, u64)> = vec![]; + let mut result: Vec<(T::AccountId, u64, u64)> = vec![]; for ( uid_i, hotkey ) in hotkeys.iter() { - result.push( ( hotkey.clone(), emission[ *uid_i as usize ] ) ); + result.push( ( hotkey.clone(), server_emission[ *uid_i as usize ], validator_emission[ *uid_i as usize ] ) ); } result @@ -264,7 +292,7 @@ impl Pallet { // * 'debug' ( bool ): // - Print debugging outputs. // - pub fn epoch( netuid: u16, rao_emission: u64 ) -> Vec<(T::AccountId, u64)> { + pub fn epoch( netuid: u16, rao_emission: u64 ) -> Vec<(T::AccountId, u64, u64)> { // Get subnetwork size. let n: u16 = Self::get_subnetwork_n( netuid ); log::trace!( "n: {:?}", n ); @@ -454,34 +482,58 @@ impl Pallet { // ================================= // Compute normalized emission scores. range: I32F32(0, 1) - let mut normalized_emission: Vec = incentive.iter().zip( dividends.clone() ).map( |(ii, di)| ii + di ).collect(); - inplace_normalize( &mut normalized_emission ); + let combined_emission: Vec = incentive.iter().zip( dividends.clone() ).map( |(ii, di)| ii + di ).collect(); + let emission_sum: I32F32 = combined_emission.iter().sum(); + + let mut normalized_server_emission: Vec = incentive.clone(); // Servers get incentive. + let mut normalized_validator_emission: Vec = dividends.clone(); // Validators get dividends. + let mut normalized_combined_emission: Vec = combined_emission.clone(); + // Normalize on the sum of incentive + dividends. + inplace_normalize_using_sum( &mut normalized_server_emission, emission_sum ); + inplace_normalize_using_sum( &mut normalized_validator_emission, emission_sum ); + inplace_normalize( &mut normalized_combined_emission ); // If emission is zero, replace emission with normalized stake. - if is_zero( &normalized_emission ) { // no weights set | outdated weights | self_weights + if emission_sum == I32F32::from(0) { // no weights set | outdated weights | self_weights if is_zero( &active_stake ) { // no active stake - normalized_emission = stake.clone(); // do not mask inactive, assumes stake is normalized + normalized_validator_emission = stake.clone(); // do not mask inactive, assumes stake is normalized + normalized_combined_emission = stake.clone(); } else { - normalized_emission = active_stake.clone(); // emission proportional to inactive-masked normalized stake + normalized_validator_emission = active_stake.clone(); // emission proportional to inactive-masked normalized stake + normalized_combined_emission = active_stake.clone(); } } // Compute rao based emission scores. range: I96F32(0, rao_emission) let float_rao_emission: I96F32 = I96F32::from_num( rao_emission ); - let emission: Vec = normalized_emission.iter().map( |e: &I32F32| I96F32::from_num( *e ) * float_rao_emission ).collect(); - let emission: Vec = emission.iter().map( |e: &I96F32| e.to_num::() ).collect(); - log::trace!( "nE: {:?}", &normalized_emission ); - log::trace!( "E: {:?}", &emission ); - // Set pruning scores. - let pruning_scores: Vec = normalized_emission.clone(); + let server_emission: Vec = normalized_server_emission.iter().map( |se: &I32F32| I96F32::from_num( *se ) * float_rao_emission ).collect(); + let server_emission: Vec = server_emission.iter().map( |e: &I96F32| e.to_num::() ).collect(); + + let validator_emission: Vec = normalized_validator_emission.iter().map( |ve: &I32F32| I96F32::from_num( *ve ) * float_rao_emission ).collect(); + let validator_emission: Vec = validator_emission.iter().map( |e: &I96F32| e.to_num::() ).collect(); + + // Only used to track emission in storage. + let combined_emission: Vec = normalized_combined_emission.iter().map( |ce: &I32F32| I96F32::from_num( *ce ) * float_rao_emission ).collect(); + let combined_emission: Vec = combined_emission.iter().map( |e: &I96F32| e.to_num::() ).collect(); + + log::trace!( "nSE: {:?}", &normalized_server_emission ); + log::trace!( "SE: {:?}", &server_emission ); + log::trace!( "nVE: {:?}", &normalized_validator_emission ); + log::trace!( "VE: {:?}", &validator_emission ); + log::trace!( "nCE: {:?}", &normalized_combined_emission ); + log::trace!( "CE: {:?}", &combined_emission ); + + + // Set pruning scores using combined emission scores. + let pruning_scores: Vec = normalized_combined_emission.clone(); log::trace!( "P: {:?}", &pruning_scores ); // =================== // == Value storage == // =================== - let cloned_emission: Vec = emission.clone(); + let cloned_emission: Vec = combined_emission.clone(); let cloned_ranks: Vec = ranks.iter().map(|xi| fixed_proportion_to_u16(*xi)).collect::>(); let cloned_trust: Vec = trust.iter().map(|xi| fixed_proportion_to_u16(*xi)).collect::>(); let cloned_consensus: Vec = consensus.iter().map(|xi| fixed_proportion_to_u16(*xi)).collect::>(); @@ -515,10 +567,10 @@ impl Pallet { } } - // Emission tuples ( hotkeys, u64 emission) - let mut result: Vec<(T::AccountId, u64)> = vec![]; + // Emission tuples ( hotkeys, server_emission, validator_emission ) + let mut result: Vec<(T::AccountId, u64, u64)> = vec![]; for ( uid_i, hotkey ) in hotkeys.iter() { - result.push( ( hotkey.clone(), emission[ *uid_i as usize ] ) ); + result.push( ( hotkey.clone(), server_emission[ *uid_i as usize ], validator_emission[ *uid_i as usize ] ) ); } result } diff --git a/pallets/subtensor/src/lib.rs b/pallets/subtensor/src/lib.rs index c17b59d4d..0e2b08f43 100644 --- a/pallets/subtensor/src/lib.rs +++ b/pallets/subtensor/src/lib.rs @@ -73,6 +73,7 @@ pub mod subnet_info; // apparently this is stabilized since rust 1.36 extern crate alloc; +mod migration; #[frame_support::pallet] pub mod pallet { @@ -90,9 +91,14 @@ pub mod pallet { #[cfg(feature = "std")] use sp_std::prelude::Box; + // Tracks version for migrations. Should be monotonic with respect to the + // order of migrations. (i.e. always increasing) + const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); + #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] #[pallet::without_storage_info] + #[pallet::storage_version(STORAGE_VERSION)] pub struct Pallet(_); // Configure the pallet by specifying the parameters and types on which it depends. @@ -123,11 +129,11 @@ pub mod pallet { type InitialIssuance: Get; #[pallet::constant] // Initial min allowed weights setting. type InitialMinAllowedWeights: Get; - #[pallet::constant] // Initial Emission Ratio + #[pallet::constant] // Initial Emission Ratio. type InitialEmissionValue: Get; #[pallet::constant] // Initial max weight limit. type InitialMaxWeightsLimit: Get; - #[pallet::constant] // Tempo for each network + #[pallet::constant] // Tempo for each network. type InitialTempo: Get; #[pallet::constant] // Initial Difficulty. type InitialDifficulty: Get; @@ -149,15 +155,15 @@ pub mod pallet { type InitialBondsMovingAverage: Get; #[pallet::constant] // Initial target registrations per interval. type InitialTargetRegistrationsPerInterval: Get; - #[pallet::constant] // Rho constant + #[pallet::constant] // Rho constant. type InitialRho: Get; - #[pallet::constant] // Kappa constant + #[pallet::constant] // Kappa constant. type InitialKappa: Get; #[pallet::constant] // Max UID constant. type InitialMaxAllowedUids: Get; - #[pallet::constant] // Default Batch size. + #[pallet::constant] // Default batch size. type InitialValidatorBatchSize: Get; - #[pallet::constant] // Default Batch size. + #[pallet::constant] // Default Sequence length. type InitialValidatorSequenceLen: Get; #[pallet::constant] // Default Epoch length. type InitialValidatorEpochLen: Get; @@ -175,13 +181,13 @@ pub mod pallet { type InitialSynergyScalingLawPower: Get; #[pallet::constant] // Immunity Period Constant. type InitialImmunityPeriod: Get; - #[pallet::constant] // Activity constant + #[pallet::constant] // Activity constant. type InitialActivityCutoff: Get; #[pallet::constant] // Initial max registrations per block. type InitialMaxRegistrationsPerBlock: Get; - #[pallet::constant] // Initial pruning score for each neuron + #[pallet::constant] // Initial pruning score for each neuron. type InitialPruningScore: Get; - #[pallet::constant] // Initial allowed validators per network. + #[pallet::constant] // Initial maximum allowed validators per network. type InitialMaxAllowedValidators: Get; #[pallet::constant] // Initial default delegation take. type InitialDefaultTake: Get; @@ -236,7 +242,7 @@ pub mod pallet { pub type Owner = StorageMap<_, Blake2_128Concat, T::AccountId, T::AccountId, ValueQuery, DefaultAccount>; #[pallet::storage] // --- MAP ( hot ) --> take | Returns the hotkey delegation take. And signals that this key is open for delegation. pub type Delegates = StorageMap<_, Blake2_128Concat, T::AccountId, u16, ValueQuery, DefaultDefaultTake>; - #[pallet::storage] // --- DMAP ( hot, cold ) --> stake | Returns the stake under a hotkey prefixed by hotkey. + #[pallet::storage] // --- DMAP ( hot, cold ) --> stake | Returns the stake under a coldkey prefixed by hotkey. pub type Stake = StorageDoubleMap<_, Blake2_128Concat, T::AccountId, Identity, T::AccountId, u64, ValueQuery, DefaultAccountTake>; // ===================================== @@ -265,7 +271,7 @@ pub mod pallet { #[pallet::storage] // ---- StorageItem Global Used Work. pub type UsedWork = StorageMap<_, Identity, Vec, u64, ValueQuery>; - #[pallet::storage] // --- MAP ( netuid ) --> Difficulty + #[pallet::storage] // --- MAP ( netuid ) --> Burn pub type Burn = StorageMap<_, Identity, u16, u64, ValueQuery, DefaultBurn >; #[pallet::storage] // --- MAP ( netuid ) --> Difficulty pub type Difficulty = StorageMap<_, Identity, u16, u64, ValueQuery, DefaultDifficulty >; @@ -279,7 +285,7 @@ pub mod pallet { pub type MaxDifficulty = StorageMap<_, Identity, u16, u64, ValueQuery, DefaultMaxDifficulty >; #[pallet::storage] // --- MAP ( netuid ) --> Block at last adjustment. pub type LastAdjustmentBlock = StorageMap<_, Identity, u16, u64, ValueQuery, DefaultLastAdjustmentBlock >; - #[pallet::storage] // --- MAP ( netuid ) --> Registration this Block. + #[pallet::storage] // --- MAP ( netuid ) --> Registrations of this Block. pub type RegistrationsThisBlock = StorageMap<_, Identity, u16, u16, ValueQuery, DefaultRegistrationsThisBlock>; #[pallet::storage] // --- ITEM( global_max_registrations_per_block ) pub type MaxRegistrationsPerBlock = StorageMap<_, Identity, u16, u16, ValueQuery, DefaultMaxRegistrationsPerBlock >; @@ -299,9 +305,11 @@ pub mod pallet { pub fn DefaultNeworksAdded() -> bool { false } #[pallet::type_value] pub fn DefaultIsNetworkMember() -> bool { false } + #[pallet::type_value] + pub fn DefaultRegistrationAllowed() -> bool { false } - #[pallet::storage] // --- ITEM( tota_number_of_existing_networks ) + #[pallet::storage] // --- ITEM( total_number_of_existing_networks ) pub type TotalNetworks = StorageValue<_, u16, ValueQuery>; #[pallet::storage] // --- MAP ( netuid ) --> subnetwork_n (Number of UIDs in the network). pub type SubnetworkN = StorageMap< _, Identity, u16, u16, ValueQuery, DefaultN >; @@ -313,6 +321,8 @@ pub mod pallet { pub type NetworkConnect = StorageDoubleMap<_, Identity, u16, Identity, u16, u16, OptionQuery>; #[pallet::storage] // --- DMAP ( hotkey, netuid ) --> bool pub type IsNetworkMember = StorageDoubleMap<_, Blake2_128Concat, T::AccountId, Identity, u16, bool, ValueQuery, DefaultIsNetworkMember>; + #[pallet::storage] // --- MAP ( netuid ) --> network_registration_allowed + pub type NetworkRegistrationAllowed = StorageMap<_, Identity, u16, bool, ValueQuery, DefaultRegistrationAllowed>; // ============================== // ==== Subnetwork Features ===== @@ -517,8 +527,8 @@ pub mod pallet { pub(super) type Uids = StorageDoubleMap<_, Identity, u16, Blake2_128Concat, T::AccountId, u16, OptionQuery>; #[pallet::storage] // --- DMAP ( netuid, uid ) --> hotkey pub(super) type Keys = StorageDoubleMap<_, Identity, u16, Identity, u16, T::AccountId, ValueQuery, DefaultKey >; - #[pallet::storage] // --- DMAP ( netuid ) --> emission - pub(super) type LoadedEmission = StorageMap< _, Identity, u16, Vec<(T::AccountId, u64)>, OptionQuery >; + #[pallet::storage] // --- DMAP ( netuid ) --> (hotkey, se, ve) + pub(super) type LoadedEmission = StorageMap< _, Identity, u16, Vec<(T::AccountId, u64, u64)>, OptionQuery >; #[pallet::storage] // --- DMAP ( netuid ) --> active pub(super) type Active = StorageMap< _, Identity, u16, Vec, ValueQuery, EmptyBoolVec >; @@ -532,7 +542,7 @@ pub mod pallet { pub(super) type Incentive = StorageMap< _, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> dividends pub(super) type Dividends = StorageMap< _, Identity, u16, Vec, ValueQuery, EmptyU16Vec>; - #[pallet::storage] // --- DMAP ( netuid ) --> dividends + #[pallet::storage] // --- DMAP ( netuid ) --> emission pub(super) type Emission = StorageMap< _, Identity, u16, Vec, ValueQuery, EmptyU64Vec>; #[pallet::storage] // --- DMAP ( netuid ) --> last_update pub(super) type LastUpdate = StorageMap< _, Identity, u16, Vec, ValueQuery, EmptyU64Vec>; @@ -559,22 +569,22 @@ pub mod pallet { NetworkRemoved( u16 ), // --- Event created when a network is removed. StakeAdded( T::AccountId, u64 ), // --- Event created when stake has been transfered from the a coldkey account onto the hotkey staking account. StakeRemoved( T::AccountId, u64 ), // --- Event created when stake has been removed from the hotkey staking account onto the coldkey account. - WeightsSet( u16, u16 ), // ---- Event created when a caller successfully set's their weights on a subnetwork. + WeightsSet( u16, u16 ), // ---- Event created when a caller successfully sets their weights on a subnetwork. NeuronRegistered( u16, u16, T::AccountId ), // --- Event created when a new neuron account has been registered to the chain. BulkNeuronsRegistered( u16, u16 ), // --- Event created when multiple uids have been concurrently registered. - BulkBalancesSet(u16, u16), - MaxAllowedUidsSet( u16, u16 ), // --- Event created when max allowed uids has been set for a subnetwor. - MaxWeightLimitSet( u16, u16 ), // --- Event created when the max weight limit has been set. + BulkBalancesSet(u16, u16), // --- FIXME: Not used yet + MaxAllowedUidsSet( u16, u16 ), // --- Event created when max allowed uids has been set for a subnetwork. + MaxWeightLimitSet( u16, u16 ), // --- Event created when the max weight limit has been set for a subnetwork. DifficultySet( u16, u64 ), // --- Event created when the difficulty has been set for a subnet. AdjustmentIntervalSet( u16, u16 ), // --- Event created when the adjustment interval is set for a subnet. RegistrationPerIntervalSet( u16, u16 ), // --- Event created when registeration per interval is set for a subnet. - MaxRegistrationsPerBlockSet( u16, u16), // --- Event created when we set max registrations per block + MaxRegistrationsPerBlockSet( u16, u16), // --- Event created when we set max registrations per block. ActivityCutoffSet( u16, u16 ), // --- Event created when an activity cutoff is set for a subnet. RhoSet( u16, u16 ), // --- Event created when Rho value is set. - KappaSet( u16, u16 ), // --- Event created when kappa is set for a subnet. + KappaSet( u16, u16 ), // --- Event created when Kappa is set for a subnet. MinAllowedWeightSet( u16, u16 ), // --- Event created when minimun allowed weight is set for a subnet. ValidatorBatchSizeSet( u16, u16 ), // --- Event created when validator batch size is set for a subnet. - ValidatorSequenceLengthSet( u16, u16 ), // --- Event created when validator sequence length i set for a subnet. + ValidatorSequenceLengthSet( u16, u16 ), // --- Event created when validator sequence length is set for a subnet. ValidatorEpochPerResetSet( u16, u16 ), // --- Event created when validator epoch per reset is set for a subnet. ValidatorExcludeQuantileSet( u16, u16 ), // --- Event created when the validator exclude quantile has been set for a subnet. ValidatorEpochLengthSet( u16, u16 ), // --- Event created when the validator epoch length has been set for a subnet. @@ -582,16 +592,16 @@ pub mod pallet { ValidatorPruneLenSet( u16, u64 ), // --- Event created when the validator pruning length has been set. ScalingLawPowerSet( u16, u16 ), // --- Event created when the scaling law power has been set for a subnet. SynergyScalingLawPowerSet( u16, u16 ), // --- Event created when the synergy scaling law has been set for a subnet. - WeightsSetRateLimitSet( u16, u64 ), // --- Event create when weights set rate limit has been set for a subnet. + WeightsSetRateLimitSet( u16, u64 ), // --- Event created when weights set rate limit has been set for a subnet. ImmunityPeriodSet( u16, u16), // --- Event created when immunity period is set for a subnet. BondsMovingAverageSet( u16, u64), // --- Event created when bonds moving average is set for a subnet. MaxAllowedValidatorsSet( u16, u16), // --- Event created when setting the max number of allowed validators on a subnet. AxonServed( u16, T::AccountId ), // --- Event created when the axon server information is added to the network. - PrometheusServed( u16, T::AccountId ), // --- Event created when the axon server information is added to the network. - EmissionValuesSet(), // --- Event created when emission ratios fr all networks is set. + PrometheusServed( u16, T::AccountId ), // --- Event created when the prometheus server information is added to the network. + EmissionValuesSet(), // --- Event created when emission ratios for all networks is set. NetworkConnectionAdded( u16, u16, u16 ), // --- Event created when a network connection requirement is added. NetworkConnectionRemoved( u16, u16 ), // --- Event created when a network connection requirement is removed. - DelegateAdded( T::AccountId, T::AccountId, u16 ), // --- Event created to signal a hotkey has become a delegate. + DelegateAdded( T::AccountId, T::AccountId, u16 ), // --- Event created to signal that a hotkey has become a delegate. DefaultTakeSet( u16 ), // --- Event created when the default take is set. WeightsVersionKeySet( u16, u64 ), // --- Event created when weights version key is set for a network. MinDifficultySet( u16, u64 ), // --- Event created when setting min difficutly on a network. @@ -602,6 +612,8 @@ pub mod pallet { MinBurnSet( u16, u64 ), // --- Event created when setting min burn on a network. TxRateLimitSet( u64 ), // --- Event created when setting the transaction rate limit. Sudid ( DispatchResult ), // --- Event created when a sudo call is done. + RegistrationAllowed( u16, bool ), // --- Event created when registration is allowed/disallowed for a subnet. + TempoSet(u16, u16), // --- Event created when setting tempo on a network RAORecycledForRegistrationSet( u16, u64 ), // Event created when setting the RAO recycled for registration. } @@ -610,16 +622,16 @@ pub mod pallet { pub enum Error { InvalidConnectionRequirement, // --- Thrown if we are attempting to create an invalid connection requirement. NetworkDoesNotExist, // --- Thrown when the network does not exist. - NetworkExist, // --- Thrown when the network already exist. + NetworkExist, // --- Thrown when the network already exists. InvalidModality, // --- Thrown when an invalid modality attempted on serve. InvalidIpType, // ---- Thrown when the user tries to serve an axon which is not of type 4 (IPv4) or 6 (IPv6). InvalidIpAddress, // --- Thrown when an invalid IP address is passed to the serve function. InvalidPort, // --- Thrown when an invalid port is passed to the serve function. NotRegistered, // ---- Thrown when the caller requests setting or removing data from a neuron which does not exist in the active set. NonAssociatedColdKey, // ---- Thrown when a stake, unstake or subscribe request is made by a coldkey which is not associated with the hotkey account. - NotEnoughStaketoWithdraw, // ---- Thrown when the caller requests removing more stake then there exists in the staking account. See: fn remove_stake. + NotEnoughStaketoWithdraw, // ---- Thrown when the caller requests removing more stake than there exists in the staking account. See: fn remove_stake. NotEnoughBalanceToStake, // ---- Thrown when the caller requests adding more stake than there exists in the cold key account. See: fn add_stake - BalanceWithdrawalError, // ---- Thrown when the caller tries to add stake, but for some reason the requested amount could not be withdrawn from the coldkey account + BalanceWithdrawalError, // ---- Thrown when the caller tries to add stake, but for some reason the requested amount could not be withdrawn from the coldkey account. NoValidatorPermit, // ---- Thrown when the caller attempts to set non-self weights without being a permitted validator. WeightVecNotEqualSize, // ---- Thrown when the caller attempts to set the weight keys and values but these vectors have different size. DuplicateUids, // ---- Thrown when the caller attempts to set weights with duplicate uids in the weight matrix. @@ -627,37 +639,37 @@ pub mod pallet { NotSettingEnoughWeights, // ---- Thrown when the dispatch attempts to set weights on chain with fewer elements than are allowed. TooManyRegistrationsThisBlock, // ---- Thrown when registrations this block exceeds allowed number. AlreadyRegistered, // ---- Thrown when the caller requests registering a neuron which already exists in the active set. - InvalidWorkBlock, // ---- Thrown if the supplied pow hash block is in the future or negative + InvalidWorkBlock, // ---- Thrown if the supplied pow hash block is in the future or negative. InvalidDifficulty, // ---- Thrown if the supplied pow hash block does not meet the network difficulty. InvalidSeal, // ---- Thrown if the supplied pow hash seal does not match the supplied work. - MaxAllowedUIdsNotAllowed, // --- Thrown if the vaule is invalid for MaxAllowedUids + MaxAllowedUIdsNotAllowed, // --- Thrown if the vaule is invalid for MaxAllowedUids. CouldNotConvertToBalance, // ---- Thrown when the dispatch attempts to convert between a u64 and T::balance but the call fails. - StakeAlreadyAdded, // --- Thrown when the caller requests adding stake for a hotkey to the total stake which already added + StakeAlreadyAdded, // --- Thrown when the caller requests adding stake for a hotkey to the total stake which already added. MaxWeightExceeded, // --- Thrown when the dispatch attempts to set weights on chain with where any normalized weight is more than MaxWeightLimit. StorageValueOutOfRange, // --- Thrown when the caller attempts to set a storage value outside of its allowed range. - TempoHasNotSet, // --- Thrown when tempo has not set - InvalidTempo, // --- Thrown when tempo is not valid - EmissionValuesDoesNotMatchNetworks, // --- Thrown when number or recieved emission rates does not match number of networks - InvalidEmissionValues, // --- Thrown when emission ratios are not valid (did not sum up to 10^9) - DidNotPassConnectedNetworkRequirement, // --- Thrown when a hotkey attempts to register into a network without passing the registration requirment from another network. - AlreadyDelegate, // --- Thrown if the hotkey attempt to become delegate when they are already. - SettingWeightsTooFast, // --- Thrown if the hotkey attempts to set weights twice withing net_tempo/2 blocks. - IncorrectNetworkVersionKey, // --- Thrown of a validator attempts to set weights from a validator with incorrect code base key. + TempoHasNotSet, // --- Thrown when tempo has not set. + InvalidTempo, // --- Thrown when tempo is not valid. + EmissionValuesDoesNotMatchNetworks, // --- Thrown when number or recieved emission rates does not match number of networks. + InvalidEmissionValues, // --- Thrown when emission ratios are not valid (did not sum up to 10^9). + DidNotPassConnectedNetworkRequirement, // --- Thrown when a hotkey attempts to register into a network without passing the registration requirment from another network. + AlreadyDelegate, // --- Thrown if the hotkey attempts to become delegate when they are already. + SettingWeightsTooFast, // --- Thrown if the hotkey attempts to set weights twice within net_tempo/2 blocks. + IncorrectNetworkVersionKey, // --- Thrown when a validator attempts to set weights from a validator with incorrect code base key. ServingRateLimitExceeded, // --- Thrown when an axon or prometheus serving exceeds the rate limit for a registered neuron. - BalanceSetError, // --- Thrown when an error occurs setting a balance - MaxAllowedUidsExceeded, // --- Thrown when number of accounts going to be registered exceed MaxAllowedUids for the network. + BalanceSetError, // --- Thrown when an error occurs while setting a balance. + MaxAllowedUidsExceeded, // --- Thrown when number of accounts going to be registered exceeds MaxAllowedUids for the network. TooManyUids, // ---- Thrown when the caller attempts to set weights with more uids than allowed. TxRateLimitExceeded, // --- Thrown when a transactor exceeds the rate limit for transactions. RegistrationDisabled, // --- Thrown when registration is disabled TooManyRegistrationsThisInterval, // --- Thrown when registration attempt exceeds allowed in interval BenchmarkingOnly, // --- Thrown when a function is only available for benchmarking HotkeyOriginMismatch, // --- Thrown when the hotkey passed is not the origin, but it should be - // Senate errors NotSenateMember, // --- Thrown when a hotkey attempts to do something only senate members can do AlreadySenateMember, // --- Thrown when a hotkey attempts to join the senate while already being a member BelowStakeThreshold, // --- Thrown when a hotkey attempts to join the senate without enough stake NotDelegate, // --- Thrown when a hotkey attempts to join the senate without being a delegate first + IncorrectNetuidsLength, // --- Thrown when an incorrect amount of Netuids are passed as input } // ================== @@ -790,9 +802,16 @@ pub mod pallet { .saturating_add(T::DbWeight::get().reads(8304 as u64)) .saturating_add(T::DbWeight::get().writes(110 as u64)); } + + fn on_runtime_upgrade() -> frame_support::weights::Weight { + // --- Migrate to v2 + use crate::migration; + + migration::migrate_to_v2_separate_emission::() + } } - // Dispatchable functions allows users to interact with the pallet and invoke state changes. + // Dispatchable functions allow users to interact with the pallet and invoke state changes. // These functions materialize as "extrinsics", which are often compared to transactions. // Dispatchable functions must be annotated with a weight and must return a DispatchResult. #[pallet::call] @@ -1340,7 +1359,7 @@ pub mod pallet { pub fn sudo_set_tx_rate_limit( origin:OriginFor, tx_rate_limit: u64 ) -> DispatchResult { Self::do_sudo_set_tx_rate_limit( origin, tx_rate_limit ) } - + #[pallet::call_index(17)] #[pallet::weight((0, DispatchClass::Operational, Pays::No))] pub fn sudo_set_max_burn( origin:OriginFor, netuid: u16, max_burn: u64 ) -> DispatchResult { @@ -1576,8 +1595,16 @@ pub mod pallet { pub fn sudo_set_total_issuance(origin: OriginFor, total_issuance: u64 ) -> DispatchResult { Self::do_set_total_issuance(origin, total_issuance) } - - #[pallet::call_index(50)] + + #[pallet::call_index(47)] + #[pallet::weight((Weight::from_ref_time(15_000_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)), DispatchClass::Operational, Pays::No))] + pub fn sudo_set_tempo(origin:OriginFor, netuid: u16, tempo: u16) -> DispatchResult { + Self::do_sudo_set_tempo(origin, netuid, tempo) + } + + #[pallet::call_index(48)] #[pallet::weight((0, DispatchClass::Operational, Pays::No))] pub fn sudo_set_rao_recycled(origin: OriginFor, netuid: u16, rao_recycled: u64 ) -> DispatchResult { Self::do_set_rao_recycled(origin, netuid, rao_recycled) @@ -1668,6 +1695,15 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { Self::do_vote_senate(origin, &hotkey, proposal, index, approve) } + + // Sudo call for setting registration allowed + #[pallet::call_index(49)] + #[pallet::weight((Weight::from_ref_time(4_000_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(T::DbWeight::get().writes(1)), DispatchClass::Operational, Pays::No))] + pub fn sudo_set_registration_allowed( origin:OriginFor, netuid: u16, registration_allowed: bool ) -> DispatchResult { + Self::do_sudo_set_network_registration_allowed( origin, netuid, registration_allowed ) + } } // ---- Subtensor helper functions. diff --git a/pallets/subtensor/src/math.rs b/pallets/subtensor/src/math.rs index 43697c30c..4da8014bb 100644 --- a/pallets/subtensor/src/math.rs +++ b/pallets/subtensor/src/math.rs @@ -1,5 +1,6 @@ use frame_support::sp_std::vec; use frame_support::inherent::Vec; +use sp_runtime::traits::CheckedAdd; use substrate_fixed::transcendental::exp; use substrate_fixed::types::{I32F32, I64F64}; @@ -86,6 +87,25 @@ pub fn check_vec_max_limited( vec: &Vec, max_limit: u16 ) -> bool { #[allow(dead_code)] pub fn sum( x: &Vec ) -> I32F32 { x.iter().sum() } +#[allow(dead_code)] +// Sums a Vector of type that has CheckedAdd trait. +// Returns None if overflow occurs during sum using T::checked_add. +// Returns Some(T::default()) if input vector is empty. +pub fn checked_sum( x: &Vec ) -> Option + where T: Copy + Default + CheckedAdd +{ + if x.len() == 0 { return Some(T::default()) } + + let mut sum: T = x[0]; + for i in x[1..].iter() { + match sum.checked_add( i ) { + Some(val) => sum = val, + None => return None + } + } + Some(sum) +} + // Return true when vector sum is zero. #[allow(dead_code)] pub fn is_zero( vector: &Vec ) -> bool { @@ -170,6 +190,15 @@ pub fn inplace_normalize( x: &mut Vec ) { } } +// Normalizes (sum to 1 except 0) the input vector directly in-place, using the sum arg. +#[allow(dead_code)] +pub fn inplace_normalize_using_sum( x: &mut Vec, x_sum: I32F32 ) { + if x_sum == I32F32::from_num( 0.0 as f32 ){ return } + for i in 0..x.len() { + x[i] = x[i]/x_sum; + } +} + // Normalizes (sum to 1 except 0) the I64F64 input vector directly in-place. #[allow(dead_code)] pub fn inplace_normalize_64( x: &mut Vec ) { @@ -2700,5 +2729,25 @@ mod tests { let bad_input = vec![ I64F64::from_num(i64::MAX) ]; vec_fixed64_to_fixed32(bad_input); } + + #[test] + #[allow(arithmetic_overflow)] + fn test_checked_sum() { + let overflowing_input = vec![ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, u64::MAX ]; + // Expect None when overflow occurs + assert_eq!(checked_sum(&overflowing_input), None); + + let normal_input = vec![ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; + // Expect Some when no overflow occurs + assert_eq!(checked_sum(&normal_input), Some(55)); + + let empty_input: Vec = vec![ ]; + // Expect Some(u16::default()) when input is empty + assert_eq!(checked_sum(&empty_input), Some(u16::default())); + + let single_input = vec![ 1 ]; + // Expect Some(...) when input is a single value + assert_eq!(checked_sum(&single_input), Some(1)); + } } diff --git a/pallets/subtensor/src/migration.rs b/pallets/subtensor/src/migration.rs new file mode 100644 index 000000000..9eb9d1958 --- /dev/null +++ b/pallets/subtensor/src/migration.rs @@ -0,0 +1,83 @@ +use super::*; +use log::{info}; +use frame_support::{ + traits::{Get, StorageVersion, GetStorageVersion}, + weights::Weight, storage_alias, + pallet_prelude::{ + Identity, OptionQuery + }, + inherent::Vec +}; + +// TODO (camfairchild): TEST MIGRATION + +const LOG_TARGET: &str = "loadedemissionmigration"; + +pub mod deprecated_loaded_emission_format { + use super::*; + + type AccountIdOf = ::AccountId; + + #[storage_alias] + pub(super) type LoadedEmission = StorageMap< Pallet, Identity, u16, Vec<(AccountIdOf, u64)>, OptionQuery >; +} + +pub fn migrate_to_v2_separate_emission() -> Weight { + use deprecated_loaded_emission_format as old; + // Check storage version + let mut weight = T::DbWeight::get().reads_writes(1, 0); + + // Grab current version + let onchain_version = Pallet::::on_chain_storage_version(); + + // Only runs if we haven't already updated version to 2. + if onchain_version < 2 { + info!(target: LOG_TARGET, ">>> Updating the LoadedEmission to a new format {:?}", onchain_version); + + // We transform the storage values from the old into the new format. + + // Start by removing any undecodable entries. + let curr_loaded_emission: Vec = old::LoadedEmission::::iter_keys().collect(); + for netuid in curr_loaded_emission { + // Iterates over the netuids + weight.saturating_accrue(T::DbWeight::get().reads(1)); + if let Err(_) = old::LoadedEmission::::try_get(netuid) { + weight.saturating_accrue(T::DbWeight::get().writes(1)); + old::LoadedEmission::::remove(netuid); + log::warn!("Was unable to decode old loaded_emisssion for netuid {}", netuid); + } + } + + // Translate the old storage values into the new format. + LoadedEmission::::translate::, u64)>, _>( + |netuid: u16, netuid_emissions: Vec<(AccountIdOf, u64)>| -> Option, u64, u64)>> { + info!(target: LOG_TARGET, " Do migration of netuid: {:?}...", netuid); + + // We will assume all loaded emission is validator emissions, + // so this will get distributed over delegatees (nominators), if there are any + // This will NOT effect any servers that are not (also) a delegate validator. + // server_emission will be 0 for any alread loaded emission. + + let mut new_netuid_emissions = Vec::new(); + for (server, validator_emission) in netuid_emissions { + new_netuid_emissions.push((server, 0 as u64, validator_emission)); + } + + // One read (old) and write (new) per netuid + weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); + + Some(new_netuid_emissions) + } + ); + + // Update storage version. + StorageVersion::new(1).put::>(); // Update to version 2 so we don't run this again. + // One write to storage version + weight.saturating_accrue(T::DbWeight::get().writes(1)); + + weight + } else { + info!(target: LOG_TARGET, "Migration to v2 already done!"); + Weight::zero() + } +} \ No newline at end of file diff --git a/pallets/subtensor/src/networks.rs b/pallets/subtensor/src/networks.rs index d738fcf81..f827ffb9e 100644 --- a/pallets/subtensor/src/networks.rs +++ b/pallets/subtensor/src/networks.rs @@ -2,6 +2,7 @@ use super::*; use frame_support::{sp_std::vec}; use sp_std::vec::Vec; use frame_system::ensure_root; +use crate::math::checked_sum; impl Pallet { @@ -190,7 +191,7 @@ impl Pallet { ensure!( netuids.len() == emission.len(), Error::::WeightVecNotEqualSize ); // --- 3. Ensure we are setting emission for all networks. - ensure!( netuids.len() as u16 == TotalNetworks::::get(), Error::::NotSettingEnoughWeights ); + ensure!( netuids.len() == TotalNetworks::::get() as usize, Error::::IncorrectNetuidsLength ); // --- 4. Ensure the passed uids contain no duplicates. ensure!( !Self::has_duplicate_netuids( &netuids ), Error::::DuplicateUids ); @@ -198,8 +199,11 @@ impl Pallet { // --- 5. Ensure that the passed uids are valid for the network. ensure!( !Self::contains_invalid_netuids( &netuids ), Error::::InvalidUid ); - // --- 6. check if sum of emission rates is equal to 1. - ensure!( emission.iter().sum::() as u64 == Self::get_block_emission(), Error::::InvalidEmissionValues); + // --- 6. check if sum of emission rates is equal to the block emission. + // Be sure to check for overflow during sum. + let emission_sum: Option = checked_sum::( &emission ); + ensure!( emission_sum.is_some(), Error::::InvalidEmissionValues ); + ensure!( emission_sum.unwrap() == Self::get_block_emission(), Error::::InvalidEmissionValues); // --- 7. Add emission values for each network Self::set_emission_values( &netuids, &emission ); @@ -392,6 +396,12 @@ impl Pallet { return NetworksAdded::::get( netuid ); } + // Returns true if the subnetwork allows registration. + // + pub fn if_subnet_allows_registration( netuid: u16 ) -> bool{ + return NetworkRegistrationAllowed::::get( netuid ); + } + // Returns true if the passed modality is allowed. // pub fn if_modality_is_valid( modality: u16 ) -> bool{ diff --git a/pallets/subtensor/src/registration.rs b/pallets/subtensor/src/registration.rs index 94043db7d..f60d695cc 100644 --- a/pallets/subtensor/src/registration.rs +++ b/pallets/subtensor/src/registration.rs @@ -100,7 +100,10 @@ impl Pallet { // --- 2. Ensure the passed network is valid. ensure!( Self::if_subnet_exist( netuid ), Error::::NetworkDoesNotExist ); - // --- 3. Ensure we are not exceeding the max allowed registrations per block. + // --- 3. Ensure the passed network allows registrations. + ensure!( Self::if_subnet_allows_registration( netuid ), Error::::RegistrationDisabled ); + + // --- 4. Ensure we are not exceeding the max allowed registrations per block. ensure!( Self::get_registrations_this_block( netuid ) < Self::get_max_registrations_per_block( netuid ), Error::::TooManyRegistrationsThisBlock ); // --- 4. Ensure we are not exceeding the max allowed registrations per interval. @@ -109,28 +112,28 @@ impl Pallet { // --- 4. Ensure that the key is not already registered. ensure!( !Uids::::contains_key( netuid, &hotkey ), Error::::AlreadyRegistered ); - // --- 5. Ensure that the key passes the registration requirement + // --- 6. Ensure that the key passes the registration requirement ensure!( Self::passes_network_connection_requirement( netuid, &hotkey ), Error::::DidNotPassConnectedNetworkRequirement ); - // --- 6. Ensure the callers coldkey has enough stake to perform the transaction. + // --- 7. Ensure the callers coldkey has enough stake to perform the transaction. let current_block_number: u64 = Self::get_current_block_as_u64(); let registration_cost_as_u64 = Self::get_burn_as_u64( netuid ); let registration_cost_as_balance = Self::u64_to_balance( registration_cost_as_u64 ).unwrap(); ensure!( Self::can_remove_balance_from_coldkey_account( &coldkey, registration_cost_as_balance ), Error::::NotEnoughBalanceToStake ); - // --- 7. Ensure the remove operation from the coldkey is a success. + // --- 8. Ensure the remove operation from the coldkey is a success. ensure!( Self::remove_balance_from_coldkey_account( &coldkey, registration_cost_as_balance ) == true, Error::::BalanceWithdrawalError ); // The burn occurs here. TotalIssuance::::put( TotalIssuance::::get().saturating_sub( Self::get_burn_as_u64( netuid ) ) ); - // --- 8. If the network account does not exist we will create it here. + // --- 9. If the network account does not exist we will create it here. Self::create_account_if_non_existent( &coldkey, &hotkey); - // --- 9. Ensure that the pairing is correct. + // --- 10. Ensure that the pairing is correct. ensure!( Self::coldkey_owns_hotkey( &coldkey, &hotkey ), Error::::NonAssociatedColdKey ); - // --- 10. Append neuron or prune it. + // --- 11. Append neuron or prune it. let subnetwork_uid: u16; let current_subnetwork_n: u16 = Self::get_subnetwork_n( netuid ); @@ -138,34 +141,34 @@ impl Pallet { ensure!( Self::get_max_allowed_uids( netuid ) != 0, Error::::NetworkDoesNotExist ); if current_subnetwork_n < Self::get_max_allowed_uids( netuid ) { - // --- 11.1.1 No replacement required, the uid appends the subnetwork. + // --- 12.1.1 No replacement required, the uid appends the subnetwork. // We increment the subnetwork count here but not below. subnetwork_uid = current_subnetwork_n; - // --- 11.1.2 Expand subnetwork with new account. + // --- 12.1.2 Expand subnetwork with new account. Self::append_neuron( netuid, &hotkey, current_block_number ); log::info!("add new neuron account"); } else { - // --- 12.1.1 Replacement required. + // --- 13.1.1 Replacement required. // We take the neuron with the lowest pruning score here. subnetwork_uid = Self::get_neuron_to_prune( netuid ); - // --- 12.1.1 Replace the neuron account with the new info. + // --- 13.1.1 Replace the neuron account with the new info. Self::replace_neuron( netuid, subnetwork_uid, &hotkey, current_block_number ); log::info!("prune neuron"); } - // --- 13. Record the registration and increment block and interval counters. + // --- 14. Record the registration and increment block and interval counters. BurnRegistrationsThisInterval::::mutate( netuid, |val| *val += 1 ); RegistrationsThisInterval::::mutate( netuid, |val| *val += 1 ); RegistrationsThisBlock::::mutate( netuid, |val| *val += 1 ); Self::increase_rao_recycled( netuid, Self::get_burn_as_u64( netuid ) ); - // --- 14. Deposit successful event. + // --- 15. Deposit successful event. log::info!("NeuronRegistered( netuid:{:?} uid:{:?} hotkey:{:?} ) ", netuid, subnetwork_uid, hotkey ); Self::deposit_event( Event::NeuronRegistered( netuid, subnetwork_uid, hotkey ) ); - // --- 15. Ok and done. + // --- 16. Ok and done. Ok(()) } @@ -236,22 +239,25 @@ impl Pallet { // --- 2. Ensure the passed network is valid. ensure!( Self::if_subnet_exist( netuid ), Error::::NetworkDoesNotExist ); - // --- 3. Ensure we are not exceeding the max allowed registrations per block. + // --- 3. Ensure the passed network allows registrations. + ensure!( Self::if_subnet_allows_registration( netuid ), Error::::RegistrationDisabled ); + + // --- 4. Ensure we are not exceeding the max allowed registrations per block. ensure!( Self::get_registrations_this_block( netuid ) < Self::get_max_registrations_per_block( netuid ), Error::::TooManyRegistrationsThisBlock ); - // --- 5. Ensure we are not exceeding the max allowed registrations per interval. - ensure!( Self::get_registrations_this_interval( netuid ) < Self::get_target_registrations_per_interval( netuid ) * 3 , Error::::TooManyRegistrationsThisInterval ); + // --- 5. Ensure we are not exceeding the max allowed registrations per interval. + ensure!( Self::get_registrations_this_interval( netuid ) < Self::get_target_registrations_per_interval( netuid ) * 3 , Error::::TooManyRegistrationsThisInterval ); - // --- 5. Ensure that the key is not already registered. + // --- 6. Ensure that the key is not already registered. ensure!( !Uids::::contains_key( netuid, &hotkey ), Error::::AlreadyRegistered ); - // --- 5. Ensure the passed block number is valid, not in the future or too old. + // --- 7. Ensure the passed block number is valid, not in the future or too old. // Work must have been done within 3 blocks (stops long range attacks). let current_block_number: u64 = Self::get_current_block_as_u64(); ensure! (block_number <= current_block_number, Error::::InvalidWorkBlock); ensure! (current_block_number - block_number < 3, Error::::InvalidWorkBlock ); - // --- 6. Ensure the supplied work passes the difficulty. + // --- 8. Ensure the supplied work passes the difficulty. let difficulty: U256 = Self::get_difficulty( netuid ); let work_hash: H256 = Self::vec_to_hash( work.clone() ); ensure! ( Self::hash_meets_difficulty( &work_hash, difficulty ), Error::::InvalidDifficulty ); // Check that the work meets difficulty. @@ -278,7 +284,6 @@ impl Pallet { ensure!( Self::get_max_allowed_uids( netuid ) != 0, Error::::NetworkDoesNotExist ); if current_subnetwork_n < Self::get_max_allowed_uids( netuid ) { - // --- 11.1.1 No replacement required, the uid appends the subnetwork. // We increment the subnetwork count here but not below. subnetwork_uid = current_subnetwork_n; diff --git a/pallets/subtensor/src/utils.rs b/pallets/subtensor/src/utils.rs index 1f5227e64..a692cec7f 100644 --- a/pallets/subtensor/src/utils.rs +++ b/pallets/subtensor/src/utils.rs @@ -345,7 +345,7 @@ impl Pallet { pub fn do_sudo_set_max_allowed_uids( origin:T::RuntimeOrigin, netuid: u16, max_allowed_uids: u16 ) -> DispatchResult { ensure_root( origin )?; ensure!( Self::if_subnet_exist(netuid), Error::::NetworkDoesNotExist ); - ensure!(Self::get_max_allowed_uids(netuid)< max_allowed_uids, Error::::MaxAllowedUIdsNotAllowed); + ensure!( Self::get_subnetwork_n(netuid) < max_allowed_uids, Error::::MaxAllowedUIdsNotAllowed); Self::set_max_allowed_uids( netuid, max_allowed_uids ); log::info!("MaxAllowedUidsSet( netuid: {:?} max_allowed_uids: {:?} ) ", netuid, max_allowed_uids); Self::deposit_event( Event::MaxAllowedUidsSet( netuid, max_allowed_uids) ); @@ -384,6 +384,17 @@ impl Pallet { Self::deposit_event( Event::ActivityCutoffSet( netuid, activity_cutoff) ); Ok(()) } + + // Registration Toggle utils + pub fn get_network_registration_allowed( netuid: u16 ) -> bool { NetworkRegistrationAllowed::::get( netuid ) } + pub fn set_network_registration_allowed( netuid: u16, registration_allowed: bool ) { NetworkRegistrationAllowed::::insert( netuid, registration_allowed ) } + pub fn do_sudo_set_network_registration_allowed( origin: T::RuntimeOrigin, netuid: u16, registration_allowed: bool ) -> DispatchResult { + ensure_root( origin )?; + Self::set_network_registration_allowed( netuid, registration_allowed ); + log::info!("NetworkRegistrationAllowed( registration_allowed: {:?} ) ", registration_allowed ); + Self::deposit_event( Event::RegistrationAllowed( netuid, registration_allowed ) ); + Ok(()) + } pub fn get_target_registrations_per_interval( netuid: u16 ) -> u16 { TargetRegistrationsPerInterval::::get( netuid ) } pub fn set_target_registrations_per_interval( netuid: u16, target_registrations_per_interval: u16 ) { TargetRegistrationsPerInterval::::insert( netuid, target_registrations_per_interval ); } @@ -476,6 +487,19 @@ impl Pallet { Self::deposit_event( Event::MaxRegistrationsPerBlockSet( netuid, max_registrations_per_block) ); Ok(()) } + pub fn do_sudo_set_tempo ( + origin: T::RuntimeOrigin, + netuid: u16, + tempo: u16 + ) -> DispatchResult { + ensure_root( origin )?; + ensure!(Self::if_subnet_exist(netuid), Error::::NetworkDoesNotExist); + ensure!( Self::if_tempo_is_valid( tempo ), Error::::InvalidTempo ); + Self::set_tempo(netuid, tempo); + log::info!("TempoSet( netuid: {:?} tempo: {:?} ) ", netuid, tempo ); + Self::deposit_event( Event::TempoSet(netuid, tempo) ); + Ok(()) + } pub fn do_set_total_issuance(origin: T::RuntimeOrigin, total_issuance: u64) -> DispatchResult{ ensure_root( origin )?; TotalIssuance::::put( total_issuance ); diff --git a/pallets/subtensor/tests/block_step.rs b/pallets/subtensor/tests/block_step.rs index 7f6c2a401..1eca57174 100644 --- a/pallets/subtensor/tests/block_step.rs +++ b/pallets/subtensor/tests/block_step.rs @@ -125,6 +125,473 @@ fn test_blocks_until_epoch(){ } +/******************************************** + block_step::adjust_registration_terms_for_networks tests +*********************************************/ + +#[test] +fn test_burn_adjustment() { + new_test_ext().execute_with(|| { + let netuid: u16 = 1; + let tempo: u16 = 13; + let burn_cost:u64 = 1000; + let adjustment_interval = 1; + let target_registrations_per_interval = 1; + SubtensorModule::set_burn( netuid, burn_cost); + SubtensorModule::set_adjustment_interval( netuid, adjustment_interval ); + SubtensorModule::set_target_registrations_per_interval( netuid, target_registrations_per_interval); + add_network(netuid, tempo, 0); + + // Register key 1. + let hotkey_account_id_1 = U256::from(1); + let coldkey_account_id_1 = U256::from(1); + SubtensorModule::add_balance_to_coldkey_account( &coldkey_account_id_1, 10000 ); + assert_ok!(SubtensorModule::burned_register(<::RuntimeOrigin>::signed(hotkey_account_id_1), netuid, hotkey_account_id_1)); + + // Register key 2. + let hotkey_account_id_2 =U256::from(2); + let coldkey_account_id_2 = U256::from(2); + SubtensorModule::add_balance_to_coldkey_account( &coldkey_account_id_2, 10000 ); + assert_ok!(SubtensorModule::burned_register(<::RuntimeOrigin>::signed(hotkey_account_id_2), netuid, hotkey_account_id_2)); + + // We are over the number of regs allowed this interval. + // Step the block and trigger the adjustment. + step_block( 1 ); + + // Check the adjusted burn. + assert_eq!(SubtensorModule::get_burn_as_u64(netuid), 1500); + }); +} + +#[test] +#[allow(unused_assignments)] +fn test_burn_adjustment_case_a() { + // Test case A of the difficulty and burn adjustment algorithm. + // ==================== + // There are too many registrations this interval and most of them are pow registrations + // this triggers an increase in the pow difficulty. + new_test_ext().execute_with(|| { + let netuid: u16 = 1; + let tempo: u16 = 13; + let burn_cost:u64 = 1000; + let adjustment_interval = 1; + let target_registrations_per_interval = 1; + let start_diff: u64 = 10_000; + let mut curr_block_num = 0; + SubtensorModule::set_burn( netuid, burn_cost); + SubtensorModule::set_difficulty(netuid, start_diff); + SubtensorModule::set_adjustment_interval( netuid, adjustment_interval ); + SubtensorModule::set_target_registrations_per_interval( netuid, target_registrations_per_interval); + add_network(netuid, tempo, 0); + + // Register key 1. This is a burn registration. + let hotkey_account_id_1 = U256::from(1); + let coldkey_account_id_1 = U256::from(1); + SubtensorModule::add_balance_to_coldkey_account( &coldkey_account_id_1, 10000 ); + assert_ok!(SubtensorModule::burned_register(<::RuntimeOrigin>::signed(hotkey_account_id_1), netuid, hotkey_account_id_1)); + + // Register key 2. This is a POW registration + let hotkey_account_id_2 =U256::from(2); + let coldkey_account_id_2 = U256::from(2); + let (nonce0, work0): (u64, Vec) = SubtensorModule::create_work_for_block_number( netuid, curr_block_num, 0, &hotkey_account_id_2); + let result0 = SubtensorModule::register( + <::RuntimeOrigin>::signed(hotkey_account_id_2), + netuid, + curr_block_num, + nonce0, work0, + hotkey_account_id_2, + coldkey_account_id_2 + ); + assert_ok!(result0); + + // Register key 3. This is a POW registration + let hotkey_account_id_3 =U256::from(3); + let coldkey_account_id_3 = U256::from(3); + let (nonce1, work1): (u64, Vec) = SubtensorModule::create_work_for_block_number( netuid, curr_block_num, 11231312312, &hotkey_account_id_3); + let result1 = SubtensorModule::register( + <::RuntimeOrigin>::signed(hotkey_account_id_3), + netuid, + curr_block_num, + nonce1, work1, + hotkey_account_id_3, + coldkey_account_id_3 + ); + assert_ok!(result1); + + // We are over the number of regs allowed this interval. + // Most of them are POW registrations (2 out of 3) + // Step the block and trigger the adjustment. + step_block( 1 ); + curr_block_num += 1; + + // Check the adjusted POW difficulty has INCREASED. + // and the burn has not changed. + let adjusted_burn = SubtensorModule::get_burn_as_u64(netuid); + assert_eq!(adjusted_burn, burn_cost); + + let adjusted_diff = SubtensorModule::get_difficulty_as_u64(netuid); + assert!(adjusted_diff > start_diff); + assert_eq!(adjusted_diff, 20_000); + }); +} + +#[test] +#[allow(unused_assignments)] +fn test_burn_adjustment_case_b() { + // Test case B of the difficulty and burn adjustment algorithm. + // ==================== + // There are too many registrations this interval and most of them are burn registrations + // this triggers an increase in the burn cost. + new_test_ext().execute_with(|| { + let netuid: u16 = 1; + let tempo: u16 = 13; + let burn_cost:u64 = 1000; + let adjustment_interval = 1; + let target_registrations_per_interval = 1; + let start_diff: u64 = 10_000; + let mut curr_block_num = 0; + SubtensorModule::set_burn( netuid, burn_cost); + SubtensorModule::set_difficulty(netuid, start_diff); + SubtensorModule::set_adjustment_interval( netuid, adjustment_interval ); + SubtensorModule::set_target_registrations_per_interval( netuid, target_registrations_per_interval); + add_network(netuid, tempo, 0); + + // Register key 1. + let hotkey_account_id_1 = U256::from(1); + let coldkey_account_id_1 = U256::from(1); + SubtensorModule::add_balance_to_coldkey_account( &coldkey_account_id_1, 10000 ); + assert_ok!(SubtensorModule::burned_register(<::RuntimeOrigin>::signed(hotkey_account_id_1), netuid, hotkey_account_id_1)); + + // Register key 2. + let hotkey_account_id_2 =U256::from(2); + let coldkey_account_id_2 = U256::from(2); + SubtensorModule::add_balance_to_coldkey_account( &coldkey_account_id_2, 10000 ); + assert_ok!(SubtensorModule::burned_register(<::RuntimeOrigin>::signed(hotkey_account_id_2), netuid, hotkey_account_id_2)); + + // Register key 3. This one is a POW registration + let hotkey_account_id_3 = U256::from(3); + let coldkey_account_id_3 = U256::from(3); + let (nonce, work): (u64, Vec) = SubtensorModule::create_work_for_block_number( netuid, curr_block_num, 0, &hotkey_account_id_3); + let result = SubtensorModule::register(<::RuntimeOrigin>::signed(hotkey_account_id_3), netuid, curr_block_num, nonce, work, hotkey_account_id_3, coldkey_account_id_3); + assert_ok!(result); + + // We are over the number of regs allowed this interval. + // Most of them are burn registrations (2 out of 3) + // Step the block and trigger the adjustment. + step_block( 1 ); + curr_block_num += 1; + + // Check the adjusted burn has INCREASED. + // and the difficulty has not changed. + let adjusted_burn = SubtensorModule::get_burn_as_u64(netuid); + assert!(adjusted_burn > burn_cost); + assert_eq!(adjusted_burn, 2_000); + + let adjusted_diff = SubtensorModule::get_difficulty_as_u64(netuid); + assert_eq!(adjusted_diff, start_diff); + }); +} + +#[test] +#[allow(unused_assignments)] +fn test_burn_adjustment_case_c() { + // Test case C of the difficulty and burn adjustment algorithm. + // ==================== + // There are not enough registrations this interval and most of them are POW registrations + // this triggers a decrease in the burn cost + new_test_ext().execute_with(|| { + let netuid: u16 = 1; + let tempo: u16 = 13; + let burn_cost:u64 = 1000; + let adjustment_interval = 1; + let target_registrations_per_interval = 4; // Needs registrations < 4 to trigger + let start_diff: u64 = 10_000; + let mut curr_block_num = 0; + SubtensorModule::set_burn( netuid, burn_cost); + SubtensorModule::set_difficulty(netuid, start_diff); + SubtensorModule::set_adjustment_interval( netuid, adjustment_interval ); + SubtensorModule::set_target_registrations_per_interval( netuid, target_registrations_per_interval); + add_network(netuid, tempo, 0); + + // Register key 1. This is a BURN registration + let hotkey_account_id_1 = U256::from(1); + let coldkey_account_id_1 = U256::from(1); + SubtensorModule::add_balance_to_coldkey_account( &coldkey_account_id_1, 10000 ); + assert_ok!(SubtensorModule::burned_register(<::RuntimeOrigin>::signed(hotkey_account_id_1), netuid, hotkey_account_id_1)); + + // Register key 2. This is a POW registration + let hotkey_account_id_2 =U256::from(2); + let coldkey_account_id_2 = U256::from(2); + let (nonce0, work0): (u64, Vec) = SubtensorModule::create_work_for_block_number( netuid, curr_block_num, 0, &hotkey_account_id_2); + let result0 = SubtensorModule::register( + <::RuntimeOrigin>::signed(hotkey_account_id_2), + netuid, + curr_block_num, + nonce0, work0, + hotkey_account_id_2, + coldkey_account_id_2 + ); + assert_ok!(result0); + + // Register key 3. This is a POW registration + let hotkey_account_id_3 =U256::from(3); + let coldkey_account_id_3 = U256::from(3); + let (nonce1, work1): (u64, Vec) = SubtensorModule::create_work_for_block_number( netuid, curr_block_num, 11231312312, &hotkey_account_id_3); + let result1 = SubtensorModule::register( + <::RuntimeOrigin>::signed(hotkey_account_id_3), + netuid, + curr_block_num, + nonce1, work1, + hotkey_account_id_3, + coldkey_account_id_3 + ); + assert_ok!(result1); + + // We are UNDER the number of regs allowed this interval. + // Most of them are POW registrations (2 out of 3) + // Step the block and trigger the adjustment. + step_block( 1 ); + curr_block_num += 1; + + // Check the adjusted burn has DECREASED. + // and the difficulty has not changed. + let adjusted_burn = SubtensorModule::get_burn_as_u64(netuid); + assert!(adjusted_burn < burn_cost); + assert_eq!(adjusted_burn, 875); + + let adjusted_diff = SubtensorModule::get_difficulty_as_u64(netuid); + assert_eq!(adjusted_diff, start_diff); + }); +} + +#[test] +#[allow(unused_assignments)] +fn test_burn_adjustment_case_d() { + // Test case D of the difficulty and burn adjustment algorithm. + // ==================== + // There are not enough registrations this interval and most of them are BURN registrations + // this triggers a decrease in the POW difficulty + new_test_ext().execute_with(|| { + let netuid: u16 = 1; + let tempo: u16 = 13; + let burn_cost:u64 = 1000; + let adjustment_interval = 1; + let target_registrations_per_interval = 4; // Needs registrations < 4 to trigger + let start_diff: u64 = 10_000; + let mut curr_block_num = 0; + SubtensorModule::set_burn( netuid, burn_cost); + SubtensorModule::set_difficulty(netuid, start_diff); + SubtensorModule::set_adjustment_interval( netuid, adjustment_interval ); + SubtensorModule::set_target_registrations_per_interval( netuid, target_registrations_per_interval); + add_network(netuid, tempo, 0); + + // Register key 1. This is a BURN registration + let hotkey_account_id_1 = U256::from(1); + let coldkey_account_id_1 = U256::from(1); + SubtensorModule::add_balance_to_coldkey_account( &coldkey_account_id_1, 10000 ); + assert_ok!(SubtensorModule::burned_register(<::RuntimeOrigin>::signed(hotkey_account_id_1), netuid, hotkey_account_id_1)); + + // Register key 2. This is a BURN registration + let hotkey_account_id_2 = U256::from(2); + let coldkey_account_id_2 = U256::from(2); + SubtensorModule::add_balance_to_coldkey_account( &coldkey_account_id_2, 10000 ); + assert_ok!(SubtensorModule::burned_register(<::RuntimeOrigin>::signed(hotkey_account_id_2), netuid, hotkey_account_id_2)); + + // Register key 3. This is a POW registration + let hotkey_account_id_3 =U256::from(3); + let coldkey_account_id_3 = U256::from(3); + let (nonce1, work1): (u64, Vec) = SubtensorModule::create_work_for_block_number( netuid, curr_block_num, 11231312312, &hotkey_account_id_3); + let result1 = SubtensorModule::register( + <::RuntimeOrigin>::signed(hotkey_account_id_3), + netuid, + curr_block_num, + nonce1, work1, + hotkey_account_id_3, + coldkey_account_id_3 + ); + assert_ok!(result1); + + // We are UNDER the number of regs allowed this interval. + // Most of them are BURN registrations (2 out of 3) + // Step the block and trigger the adjustment. + step_block( 1 ); + curr_block_num += 1; + + // Check the adjusted POW difficulty has DECREASED. + // and the burn has not changed. + let adjusted_burn = SubtensorModule::get_burn_as_u64(netuid); + assert_eq!(adjusted_burn, burn_cost); + + let adjusted_diff = SubtensorModule::get_difficulty_as_u64(netuid); + assert!(adjusted_diff < start_diff); + assert_eq!(adjusted_diff, 8750); + }); +} + +#[test] +#[allow(unused_assignments)] +fn test_burn_adjustment_case_e() { + // Test case E of the difficulty and burn adjustment algorithm. + // ==================== + // There are not enough registrations this interval and nobody registered either POW or BURN + // this triggers a decrease in the BURN cost and POW difficulty + new_test_ext().execute_with(|| { + let netuid: u16 = 1; + let tempo: u16 = 13; + let burn_cost:u64 = 1000; + let adjustment_interval = 1; + let target_registrations_per_interval: u16 = 3; + let start_diff: u64 = 10_000; + let mut curr_block_num = 0; + SubtensorModule::set_max_registrations_per_block( netuid, 10 ); + SubtensorModule::set_burn( netuid, burn_cost); + SubtensorModule::set_difficulty(netuid, start_diff); + SubtensorModule::set_adjustment_interval( netuid, adjustment_interval ); + SubtensorModule::set_target_registrations_per_interval( netuid, target_registrations_per_interval); + add_network(netuid, tempo, 0); + + // Register key 1. This is a POW registration + let hotkey_account_id_1 =U256::from(1); + let coldkey_account_id_1 = U256::from(1); + let (nonce1, work1): (u64, Vec) = SubtensorModule::create_work_for_block_number( netuid, curr_block_num, 11231312312, &hotkey_account_id_1); + let result1 = SubtensorModule::register( + <::RuntimeOrigin>::signed(hotkey_account_id_1), + netuid, + curr_block_num, + nonce1, work1, + hotkey_account_id_1, + coldkey_account_id_1 + ); + assert_ok!(result1); + + // Register key 2. This is a BURN registration + let hotkey_account_id_2 = U256::from(2); + let coldkey_account_id_2 = U256::from(2); + SubtensorModule::add_balance_to_coldkey_account( &coldkey_account_id_2, 10000 ); + assert_ok!(SubtensorModule::burned_register(<::RuntimeOrigin>::signed(hotkey_account_id_2), netuid, hotkey_account_id_2)); + + + step_block( 1 ); + curr_block_num += 1; + + // We are UNDER the number of regs allowed this interval. + // And the number of regs of each type is equal + + // Check the adjusted BURN has DECREASED. + let adjusted_burn = SubtensorModule::get_burn_as_u64(netuid); + assert!(adjusted_burn < burn_cost); + assert_eq!(adjusted_burn, 833); + + // Check the adjusted POW difficulty has DECREASED. + let adjusted_diff = SubtensorModule::get_difficulty_as_u64(netuid); + assert!(adjusted_diff < start_diff); + assert_eq!(adjusted_diff, 8_333); + }); +} + +#[test] +#[allow(unused_assignments)] +fn test_burn_adjustment_case_f() { + // Test case F of the difficulty and burn adjustment algorithm. + // ==================== + // There are too many registrations this interval and the pow and burn registrations are equal + // this triggers an increase in the burn cost and pow difficulty + new_test_ext().execute_with(|| { + let netuid: u16 = 1; + let tempo: u16 = 13; + let burn_cost:u64 = 1000; + let adjustment_interval = 1; + let target_registrations_per_interval: u16 = 1; + let start_diff: u64 = 10_000; + let mut curr_block_num = 0; + SubtensorModule::set_max_registrations_per_block( netuid, 10 ); + SubtensorModule::set_burn( netuid, burn_cost); + SubtensorModule::set_difficulty(netuid, start_diff); + SubtensorModule::set_adjustment_interval( netuid, adjustment_interval ); + SubtensorModule::set_target_registrations_per_interval( netuid, target_registrations_per_interval); + add_network(netuid, tempo, 0); + + // Register key 1. This is a POW registration + let hotkey_account_id_1 =U256::from(1); + let coldkey_account_id_1 = U256::from(1); + let (nonce1, work1): (u64, Vec) = SubtensorModule::create_work_for_block_number( netuid, curr_block_num, 11231312312, &hotkey_account_id_1); + let result1 = SubtensorModule::register( + <::RuntimeOrigin>::signed(hotkey_account_id_1), + netuid, + curr_block_num, + nonce1, work1, + hotkey_account_id_1, + coldkey_account_id_1 + ); + assert_ok!(result1); + + // Register key 2. This is a BURN registration + let hotkey_account_id_2 = U256::from(2); + let coldkey_account_id_2 = U256::from(2); + SubtensorModule::add_balance_to_coldkey_account( &coldkey_account_id_2, 10000 ); + assert_ok!(SubtensorModule::burned_register(<::RuntimeOrigin>::signed(hotkey_account_id_2), netuid, hotkey_account_id_2)); + + step_block( 1 ); + curr_block_num += 1; + // We are OVER the number of regs allowed this interval. + // And the number of regs of each type is equal + + + // Check the adjusted BURN has INCREASED. + let adjusted_burn = SubtensorModule::get_burn_as_u64(netuid); + assert!(adjusted_burn > burn_cost); + assert_eq!(adjusted_burn, 1_500); + + // Check the adjusted POW difficulty has INCREASED. + let adjusted_diff = SubtensorModule::get_difficulty_as_u64(netuid); + assert!(adjusted_diff > start_diff); + assert_eq!(adjusted_diff, 15_000); + }); +} + + +#[test] +fn test_burn_adjustment_case_e_zero_registrations() { + // Test case E of the difficulty and burn adjustment algorithm. + // ==================== + // There are not enough registrations this interval and nobody registered either POW or BURN + // this triggers a decrease in the BURN cost and POW difficulty + + // BUT there are zero registrations this interval. + new_test_ext().execute_with(|| { + let netuid: u16 = 1; + let tempo: u16 = 13; + let burn_cost:u64 = 1000; + let adjustment_interval = 1; + let target_registrations_per_interval: u16 = 1; + let start_diff: u64 = 10_000; + SubtensorModule::set_max_registrations_per_block( netuid, 10 ); + SubtensorModule::set_burn( netuid, burn_cost); + SubtensorModule::set_difficulty(netuid, start_diff); + SubtensorModule::set_adjustment_interval( netuid, adjustment_interval ); + SubtensorModule::set_target_registrations_per_interval( netuid, target_registrations_per_interval); + add_network(netuid, tempo, 0); + + // No registrations this interval of any kind. + step_block( 1 ); + + // We are UNDER the number of regs allowed this interval. + // And the number of regs of each type is equal + + // Check the adjusted BURN has DECREASED. + let adjusted_burn = SubtensorModule::get_burn_as_u64(netuid); + assert!(adjusted_burn < burn_cost); + assert_eq!(adjusted_burn, 500); + + // Check the adjusted POW difficulty has DECREASED. + let adjusted_diff = SubtensorModule::get_difficulty_as_u64(netuid); + assert!(adjusted_diff < start_diff); + assert_eq!(adjusted_diff, 5_000); + }); +} + + + // add_network( netuid1, tempo1, 0 ); // add_network( netuid2, tempo2, 0 ); diff --git a/pallets/subtensor/tests/difficulty.rs b/pallets/subtensor/tests/difficulty.rs index 0d726ebfc..39d84d873 100644 --- a/pallets/subtensor/tests/difficulty.rs +++ b/pallets/subtensor/tests/difficulty.rs @@ -3,6 +3,7 @@ mod mock; use sp_core::U256; #[test] +#[cfg(not(tarpaulin))] fn test_registration_difficulty_adjustment() { new_test_ext().execute_with(|| { @@ -16,6 +17,7 @@ fn test_registration_difficulty_adjustment() { assert_eq!( SubtensorModule::get_registrations_this_block( netuid ), 0 ); // No registrations this block. assert_eq!( SubtensorModule::get_target_registrations_per_interval( netuid ), 2 ); // Target is default. assert_eq!( SubtensorModule::get_adjustment_interval( netuid ), 100 ); // Default adustment intrerval. + assert_eq!( SubtensorModule::get_network_registration_allowed( netuid ), true ); // Default registration allowed. // Set values and check. SubtensorModule::set_difficulty( netuid, 20000 ); @@ -23,11 +25,13 @@ fn test_registration_difficulty_adjustment() { SubtensorModule::set_target_registrations_per_interval( netuid, 1 ); SubtensorModule::set_max_registrations_per_block( netuid, 3 ); SubtensorModule::set_max_allowed_uids( netuid, 3 ); + SubtensorModule::set_network_registration_allowed( netuid, true ); assert_eq!( SubtensorModule::get_difficulty_as_u64( netuid ), 20000 ); // Check set difficutly. assert_eq!( SubtensorModule::get_adjustment_interval( netuid ), 1 ); // Check set adjustment interval. assert_eq!( SubtensorModule::get_target_registrations_per_interval( netuid ), 1 ); // Check set adjustment interval. assert_eq!( SubtensorModule::get_max_registrations_per_block( netuid ), 3 ); // Check set registrations per block. assert_eq!( SubtensorModule::get_max_allowed_uids( netuid ), 3 ); // Check set registrations per block. + assert_eq!( SubtensorModule::get_network_registration_allowed( netuid ), true ); // Check set registration allowed // Lets register 3 neurons... let hotkey0 = U256::from(0); @@ -126,4 +130,4 @@ fn test_registration_difficulty_adjustment() { assert_eq!( SubtensorModule::get_difficulty_as_u64( netuid ), 5833 ); // Difficulty unchanged }); -} \ No newline at end of file +} diff --git a/pallets/subtensor/tests/epoch.rs b/pallets/subtensor/tests/epoch.rs index 933626c15..9da80fd59 100644 --- a/pallets/subtensor/tests/epoch.rs +++ b/pallets/subtensor/tests/epoch.rs @@ -1251,6 +1251,7 @@ 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 = 0; 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 e59ad0938..771ffbc34 100644 --- a/pallets/subtensor/tests/mock.rs +++ b/pallets/subtensor/tests/mock.rs @@ -411,6 +411,7 @@ pub fn register_ok_neuron( netuid: u16, hotkey_account_id: U256, coldkey_account #[allow(dead_code)] pub fn add_network(netuid: u16, tempo: u16, modality: u16){ let result = SubtensorModule::do_add_network(<::RuntimeOrigin>::root(), netuid, tempo, modality); + SubtensorModule::set_network_registration_allowed( netuid, true ); assert_ok!(result); } diff --git a/pallets/subtensor/tests/networks.rs b/pallets/subtensor/tests/networks.rs index dfc6d4ae7..4ca5c5be5 100644 --- a/pallets/subtensor/tests/networks.rs +++ b/pallets/subtensor/tests/networks.rs @@ -164,7 +164,7 @@ fn test_network_set_emission_invalid_netuids() { let netuids: Vec = vec![ 1, 2 ]; let emission: Vec = vec![ 100000000, 900000000 ]; add_network(1, 0, 0); - assert_eq!( SubtensorModule::sudo_set_emission_values(<::RuntimeOrigin>::root(), netuids, emission ), Err(Error::::NotSettingEnoughWeights.into()) ); + assert_eq!( SubtensorModule::sudo_set_emission_values(<::RuntimeOrigin>::root(), netuids, emission ), Err(Error::::IncorrectNetuidsLength.into()) ); });} #[test] @@ -191,4 +191,125 @@ fn test_multi_tempo_with_emission(){ new_test_ext().execute_with(|| { let netuid: u16 = 1; assert_eq!(SubtensorModule::sudo_set_difficulty(<::RuntimeOrigin>::root(), netuid, 120000) , Err(Error::::NetworkDoesNotExist.into()) ); -});} \ No newline at end of file +});} + + +#[test] +// Required by the test otherwise it would panic if compiled in debug mode +#[allow(arithmetic_overflow)] +fn test_set_emission_values_errors_on_emission_sum_overflow() { + new_test_ext().execute_with(|| { + let netuids: Vec = vec![ 1,2 ]; + // u64(u64::MAX + 1..000..1) equals to 1_000_000_000 which is the same as + // the value of Self::get_block_emission() expected by the extrinsic + let emission: Vec = vec![ u64::MAX, 1_000_000_001 ]; + add_network(1, 0, 0); + add_network(2, 0, 0); + assert_eq!( + SubtensorModule::sudo_set_emission_values(<::RuntimeOrigin>::root(), netuids, emission ), + Err(Error::::InvalidEmissionValues.into()) + ); + }); +} + +#[test] +#[allow(arithmetic_overflow)] +fn test_set_emission_values_no_errors() { + new_test_ext().execute_with(|| { + let netuids: Vec = vec![ 1,2 ]; + let emission: Vec = vec![ 600_000_000, 400_000_000 ]; + + add_network(1, 0, 0); + add_network(2, 0, 0); + assert_eq!( + SubtensorModule::sudo_set_emission_values(<::RuntimeOrigin>::root(), netuids, emission ), + Ok(()) + ); + }); +} + +#[test] +// Required by the test otherwise it would panic if compiled in debug mode +#[allow(arithmetic_overflow)] +fn test_set_emission_values_sum_too_large() { + new_test_ext().execute_with(|| { + let netuids: Vec = vec![ 1,2 ]; + // u64(1_000_000_000 + 1) equals to 1_000_000_001 which is more than + // the value of Self::get_block_emission() expected by the extrinsic + let emission: Vec = vec![ 1_000_000_000, 1 ]; + add_network(1, 0, 0); + add_network(2, 0, 0); + assert_eq!( + SubtensorModule::sudo_set_emission_values(<::RuntimeOrigin>::root(), netuids, emission ), + Err(Error::::InvalidEmissionValues.into()) + ); + }); +} + +#[test] +// Required by the test otherwise it would panic if compiled in debug mode +#[allow(arithmetic_overflow)] +fn test_set_emission_values_sum_too_small() { + new_test_ext().execute_with(|| { + let netuids: Vec = vec![ 1,2 ]; + // u64(1 + 2_000) equals to 2_001 which is LESS than + // the value of Self::get_block_emission() expected by the extrinsic + let emission: Vec = vec![ 1, 2_000 ]; + add_network(1, 0, 0); + add_network(2, 0, 0); + assert_eq!( + SubtensorModule::sudo_set_emission_values(<::RuntimeOrigin>::root(), netuids, emission ), + Err(Error::::InvalidEmissionValues.into()) + ); + }); +} + + +#[test] +fn test_set_emission_values_too_many_netuids() { + new_test_ext().execute_with(|| { + let netuids: Vec = vec![ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; + + // Sums to 1_000_000_000 and has 10 elements + let emission: Vec = vec![ 1_000_000_000, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; + add_network(1, 0, 0); + add_network(2, 0, 0); + // We only add 2 networks, so this should fail + assert_eq!( + SubtensorModule::sudo_set_emission_values(<::RuntimeOrigin>::root(), netuids, emission ), + Err(Error::::IncorrectNetuidsLength.into()) + ); + }); +} + +#[test] +fn test_set_emission_values_over_u16_max_values() { + new_test_ext().execute_with(|| { + // Make vec of u16 with length 2^16 + 2 + let netuids: Vec = vec![0; 0x10002]; + // This is greater than u16::MAX + assert!(netuids.len() > u16::MAX as usize); + // On cast to u16, this will be 2 + assert!(netuids.len() as u16 == 2); + + // Sums to 1_000_000_000 and the length is 65536 + let mut emission: Vec = vec![ 0; netuids.len() ]; + emission[0] = 1_000_000_000; + + add_network(1, 0, 0); + add_network(2, 0, 0); + // We only add 2 networks, so this should fail + // but if we cast to u16 during length comparison, + // the length will be 2 and the check will pass + assert_eq!( + SubtensorModule::sudo_set_emission_values(<::RuntimeOrigin>::root(), netuids, emission ), + Err(Error::::IncorrectNetuidsLength.into()) + ); + }); +} \ No newline at end of file diff --git a/pallets/subtensor/tests/neuron_info.rs b/pallets/subtensor/tests/neuron_info.rs index e075222df..de78703aa 100644 --- a/pallets/subtensor/tests/neuron_info.rs +++ b/pallets/subtensor/tests/neuron_info.rs @@ -19,6 +19,7 @@ fn test_get_neuron_none() { } #[test] +#[cfg(not(tarpaulin))] fn test_get_neuron_some() { new_test_ext().execute_with(|| { let netuid: u16 = 1; diff --git a/pallets/subtensor/tests/registration.rs b/pallets/subtensor/tests/registration.rs index 39de4cfe5..f3561817f 100644 --- a/pallets/subtensor/tests/registration.rs +++ b/pallets/subtensor/tests/registration.rs @@ -99,6 +99,11 @@ fn test_registration_ok() { }); } + +/******************************************** + registration::do_burned_registration tests +*********************************************/ + #[test] fn test_burned_registration_ok() { new_test_ext().execute_with(|| { @@ -166,6 +171,7 @@ fn test_burn_adjustment() { } #[test] +#[cfg(not(tarpaulin))] fn test_registration_too_many_registrations_per_block() { new_test_ext().execute_with(|| { @@ -832,4 +838,28 @@ fn test_registration_origin_hotkey_mismatch() { ); assert_eq!( result, Err(Error::::HotkeyOriginMismatch.into()) ); }); +} + +#[test] +fn test_registration_disabled() { + new_test_ext().execute_with(|| { + let block_number: u64 = 0; + let netuid: u16 = 1; + let tempo: u16 = 13; + let hotkey_account_id: U256 = U256::from(1); + let coldkey_account_id: U256 = U256::from(668); + let (nonce, work): (u64, Vec) = SubtensorModule::create_work_for_block_number( netuid, block_number, 0, &hotkey_account_id); + + //add network + add_network(netuid, tempo, 0); + SubtensorModule::set_network_registration_allowed(netuid, false); + + let result = SubtensorModule::register( + <::RuntimeOrigin>::signed(hotkey_account_id), + netuid, block_number, nonce, work.clone(), + hotkey_account_id, + coldkey_account_id + ); + assert_eq!( result, Err(Error::::RegistrationDisabled.into()) ); + }); } \ No newline at end of file diff --git a/pallets/subtensor/tests/serving.rs b/pallets/subtensor/tests/serving.rs index 4e2ad9b21..6a0a4bfa0 100644 --- a/pallets/subtensor/tests/serving.rs +++ b/pallets/subtensor/tests/serving.rs @@ -118,6 +118,7 @@ fn test_serving_set_metadata_update() { } #[test] +#[cfg(not(tarpaulin))] fn test_axon_serving_rate_limit_exceeded() { new_test_ext().execute_with(|| { let hotkey_account_id = U256::from(1); @@ -240,6 +241,7 @@ fn test_prometheus_serving_set_metadata_update() { } #[test] +#[cfg(not(tarpaulin))] fn test_prometheus_serving_rate_limit_exceeded() { new_test_ext().execute_with(|| { let hotkey_account_id = U256::from(1); diff --git a/pallets/subtensor/tests/staking.rs b/pallets/subtensor/tests/staking.rs index b3ed501d1..fc0a3824e 100644 --- a/pallets/subtensor/tests/staking.rs +++ b/pallets/subtensor/tests/staking.rs @@ -12,6 +12,7 @@ use sp_core::U256; ************************************************************/ #[test] +#[cfg(not(tarpaulin))] fn test_add_stake_dispatch_info_ok() { new_test_ext().execute_with(|| { let hotkey = U256::from(0); @@ -286,6 +287,7 @@ fn test_add_stake_total_issuance_no_change() { // ************************************************************/ #[test] +#[cfg(not(tarpaulin))] fn test_remove_stake_dispatch_info_ok() { new_test_ext().execute_with(|| { let hotkey = U256::from(0); @@ -794,11 +796,12 @@ fn test_delegate_stake_division_by_zero_check(){ add_network( netuid, tempo, 0 ); register_ok_neuron( netuid, hotkey, coldkey, 2341312 ); assert_ok!(SubtensorModule::become_delegate(<::RuntimeOrigin>::signed(coldkey), hotkey) ); - SubtensorModule::emit_inflation_through_hotkey_account( &hotkey, 1000 ); + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey, 0, 1000 ); }); } #[test] +#[cfg(not(tarpaulin))] fn test_full_with_delegating() { new_test_ext().execute_with(|| { let netuid = 1; @@ -871,8 +874,8 @@ fn test_full_with_delegating() { assert_eq!(SubtensorModule::remove_stake(<::RuntimeOrigin>::signed(coldkey1), hotkey0, 10), Err(Error::::NonAssociatedColdKey.into())); // Emit inflation through non delegates. - SubtensorModule::emit_inflation_through_hotkey_account( &hotkey0, 100 ); - SubtensorModule::emit_inflation_through_hotkey_account( &hotkey1, 100 ); + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey0, 0, 100 ); + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey1, 0, 100 ); assert_eq!( SubtensorModule::get_total_stake_for_hotkey( &hotkey0 ), 200); assert_eq!( SubtensorModule::get_total_stake_for_hotkey( &hotkey1 ), 200 ); @@ -909,13 +912,13 @@ fn test_full_with_delegating() { assert_eq!( SubtensorModule::get_total_stake(), 900 ); // Lets emit inflation through the hot and coldkeys. - SubtensorModule::emit_inflation_through_hotkey_account( &hotkey0, 1000 ); - SubtensorModule::emit_inflation_through_hotkey_account( &hotkey1, 1000 ); - assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 599 ); // 200 + 1000 x ( 200 / 500 ) = 200 + 400 = 600 ~= 599 + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey0, 0, 1000 ); + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey1, 0, 1000 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 601 ); // 200 + 1000 x ( 200 / 500 ) = 200 + 400 = 600 ~= 601 assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey1 ), 700 ); // 200 + 1000 x ( 200 / 400 ) = 200 + 500 = 700 assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey0 ), 899 ); // 300 + 1000 x ( 300 / 500 ) = 300 + 600 = 900 ~= 899 assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey1 ), 700 ); // 200 + 1000 x ( 200 / 400 ) = 300 + 600 = 700 - assert_eq!( SubtensorModule::get_total_stake(), 2898 ); // 600 + 700 + 900 + 700 = 2900 ~= 2898 + assert_eq!( SubtensorModule::get_total_stake(), 2900 ); // 600 + 700 + 900 + 700 = 2900 // // Try unstaking too much. assert_eq!(SubtensorModule::remove_stake(<::RuntimeOrigin>::signed(coldkey0), hotkey0, 100000), Err(Error::::NotEnoughStaketoWithdraw.into())); @@ -930,7 +933,7 @@ fn test_full_with_delegating() { assert_ok!(SubtensorModule::remove_stake(<::RuntimeOrigin>::signed(coldkey1), hotkey0, 100) ); // All the amounts have been decreased. - assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 499 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 501 ); assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey1 ), 600 ); assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey0 ), 799 ); assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey1 ), 600 ); @@ -960,14 +963,14 @@ fn test_full_with_delegating() { assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey2 ), 1_000 ); assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey2 ), 1_000 ); assert_eq!( SubtensorModule::get_total_stake_for_hotkey( &hotkey2 ), 3_000 ); - assert_eq!( SubtensorModule::get_total_stake(), 5_498 ); + assert_eq!( SubtensorModule::get_total_stake(), 5_500 ); // Lets emit inflation through this new key with distributed ownership. - SubtensorModule::emit_inflation_through_hotkey_account( &hotkey2, 1000 ); - assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey2, &hotkey2 ), 1_665 ); // 1000 + 500 + 500 * (1000/3000) = 1500 + 166.6666666667 = 1,666.6666666667 + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey2, 0, 1000 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey2, &hotkey2 ), 1_668 ); // 1000 + 500 + 500 * (1000/3000) = 1500 + 166.6666666667 = 1,668 assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey2 ), 1_166 ); // 1000 + 500 * (1000/3000) = 1000 + 166.6666666667 = 1166.6 assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey2 ), 1_166 ); // 1000 + 500 * (1000/3000) = 1000 + 166.6666666667 = 1166.6 - assert_eq!( SubtensorModule::get_total_stake(), 6_495 ); + assert_eq!( SubtensorModule::get_total_stake(), 6_500 ); // before + 1_000 = 5_500 + 1_000 = 6_500 step_block(1); @@ -989,18 +992,250 @@ fn test_full_with_delegating() { assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey2, &hotkey3 ), 1000 ); assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey3, &hotkey3 ), 1000 ); assert_eq!( SubtensorModule::get_total_stake_for_hotkey( &hotkey3 ), 4000 ); - assert_eq!( SubtensorModule::get_total_stake(), 10_495 ); - SubtensorModule::emit_inflation_through_hotkey_account( &hotkey3, 1000 ); + assert_eq!( SubtensorModule::get_total_stake(), 10_500 ); + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey3, 0, 1000 ); assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey3 ), 1000 ); assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey3 ), 1000 ); assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey2, &hotkey3 ), 1000 ); assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey3, &hotkey3 ), 2000 ); - assert_eq!( SubtensorModule::get_total_stake(), 11_495 ); + assert_eq!( SubtensorModule::get_total_stake(), 11_500 ); // before + 1_000 = 10_500 + 1_000 = 11_500 }); } +// Verify delegates with servers get the full server inflation. +#[test] +fn test_full_with_delegating_some_servers() { + new_test_ext().execute_with(|| { + let netuid = 1; + // Make two accounts. + let hotkey0 = U256::from(1); + let hotkey1 = U256::from(2); + + let coldkey0 = U256::from(3); + let coldkey1 = U256::from(4); + SubtensorModule::set_max_registrations_per_block(netuid,4); + SubtensorModule::set_max_allowed_uids(netuid, 10); // Allow at least 10 to be registered at once, so no unstaking occurs + + // Neither key can add stake because they dont have fundss. + assert_eq!(SubtensorModule::add_stake(<::RuntimeOrigin>::signed(coldkey0), hotkey0, 60000), Err(Error::::NotEnoughBalanceToStake.into())); + assert_eq!(SubtensorModule::add_stake(<::RuntimeOrigin>::signed(coldkey1), hotkey1, 60000), Err(Error::::NotEnoughBalanceToStake.into())); + + // Add balances. + SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 60000); + SubtensorModule::add_balance_to_coldkey_account(&coldkey1, 60000); + + // Register the 2 neurons to a new network. + let netuid = 1; + add_network(netuid, 0, 0); + register_ok_neuron( netuid, hotkey0, coldkey0, 124124 ); + register_ok_neuron( netuid, hotkey1, coldkey1, 987907 ); + assert_eq!( SubtensorModule::get_owning_coldkey_for_hotkey( &hotkey0 ), coldkey0 ); + assert_eq!( SubtensorModule::get_owning_coldkey_for_hotkey( &hotkey1 ), coldkey1 ); + assert!( SubtensorModule::coldkey_owns_hotkey( &coldkey0, &hotkey0 ) ); + assert!( SubtensorModule::coldkey_owns_hotkey( &coldkey1, &hotkey1 ) ); + + // We stake and all is ok. + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 0 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 0 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 0 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 0 ); + assert_ok!(SubtensorModule::add_stake(<::RuntimeOrigin>::signed(coldkey0), hotkey0, 100) ); + assert_ok!(SubtensorModule::add_stake(<::RuntimeOrigin>::signed(coldkey1), hotkey1, 100) ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 100 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey1 ), 0 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey0 ), 0 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey1 ), 100 ); + assert_eq!( SubtensorModule::get_total_stake_for_hotkey( &hotkey0 ), 100 ); + assert_eq!( SubtensorModule::get_total_stake_for_hotkey( &hotkey1 ), 100 ); + assert_eq!( SubtensorModule::get_total_stake(), 200 ); + + // Emit inflation through non delegates. + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey0, 0, 100 ); + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey1, 0, 100 ); + assert_eq!( SubtensorModule::get_total_stake_for_hotkey( &hotkey0 ), 200); + assert_eq!( SubtensorModule::get_total_stake_for_hotkey( &hotkey1 ), 200 ); + + // Become delegates all is ok. + assert_ok!( SubtensorModule::do_become_delegate(<::RuntimeOrigin>::signed(coldkey0), hotkey0, 10) ); + assert_ok! (SubtensorModule::do_become_delegate(<::RuntimeOrigin>::signed(coldkey1), hotkey1, 10) ); + assert!( SubtensorModule::hotkey_is_delegate( &hotkey0 ) ); + assert!( SubtensorModule::hotkey_is_delegate( &hotkey1 ) ); + + // This add stake works for delegates. + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 200 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey1 ), 0 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey0 ), 0 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey1 ), 200 ); + assert_ok!(SubtensorModule::add_stake(<::RuntimeOrigin>::signed(coldkey0), hotkey1, 200) ); + assert_ok!(SubtensorModule::add_stake(<::RuntimeOrigin>::signed(coldkey1), hotkey0, 300) ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 200 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey1 ), 200 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey0 ), 300 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey1 ), 200 ); + assert_eq!( SubtensorModule::get_total_stake_for_hotkey( &hotkey0 ), 500 ); + assert_eq!( SubtensorModule::get_total_stake_for_hotkey( &hotkey1 ), 400 ); + assert_eq!( SubtensorModule::get_total_stake(), 900 ); + + // Lets emit inflation through the hot and coldkeys. + // fist emission arg is for a server. This should only go to the owner of the hotkey. + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey0, 200, 1_000 ); // 1_200 total emission. + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey1, 123, 2_000 ); // 2_123 total emission. + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 801 ); // 200 + (200 + 1000 x ( 200 / 500 )) = 200 + (200 + 400) = 800 ~= 801 + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey0 ), 899 ); // 300 + 1000 x ( 300 / 500 ) = 300 + 600 = 900 ~= 899 + assert_eq!( SubtensorModule::get_total_stake_for_hotkey( &hotkey0 ), 1_700 ); // initial + server emission + validator emission = 799 + 899 = 1_698 + + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey1 ), 1_200 ); // 200 + (0 + 2000 x ( 200 / 400 )) = 200 + (1000) = 1_200 + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey1 ), 1_323 ); // 200 + (123 + 2000 x ( 200 / 400 )) = 200 + (1_200) = 1_323 + assert_eq!( SubtensorModule::get_total_stake_for_hotkey( &hotkey1 ), 2_523 ); // 400 + 2_123 + assert_eq!( SubtensorModule::get_total_stake(), 4_223 ); // 1_700 + 2_523 = 4_223 + + // Lets emit MORE inflation through the hot and coldkeys. + // This time only server emission. This should go to the owner of the hotkey. + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey0, 350, 0 ); + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey1, 150, 0 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 1_151 ); // + 350 = 1_151 + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey1 ), 1_200 ); // No change. + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey0 ), 899 ); // No change. + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey1 ), 1_473 ); // 1_323 + 150 = 1_473 + assert_eq!( SubtensorModule::get_total_stake(), 4_723 ); // 4_223 + 500 = 4_823 + + // Lets register and stake a new key. + let hotkey2 = U256::from(5); + let coldkey2 = U256::from(6); + register_ok_neuron( netuid, hotkey2, coldkey2, 248123 ); + SubtensorModule::add_balance_to_coldkey_account(&coldkey2, 60_000); + assert_ok!(SubtensorModule::add_stake(<::RuntimeOrigin>::signed(coldkey2), hotkey2, 1_000) ); + assert_ok!(SubtensorModule::remove_stake(<::RuntimeOrigin>::signed(coldkey2), hotkey2, 100) ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey2, &hotkey2 ), 900 ); + assert_eq!(SubtensorModule::remove_stake(<::RuntimeOrigin>::signed(coldkey0), hotkey2, 10), Err(Error::::NonAssociatedColdKey.into())); + assert_eq!(SubtensorModule::remove_stake(<::RuntimeOrigin>::signed(coldkey1), hotkey2, 10), Err(Error::::NonAssociatedColdKey.into())); + + assert_eq!(SubtensorModule::get_total_stake(), 5_623 ); // 4_723 + 900 = 5_623 + + // Lets make this new key a delegate with a 50% take. + assert_ok!( SubtensorModule::do_become_delegate(<::RuntimeOrigin>::signed(coldkey2), hotkey2, u16::MAX/2) ); + + // Add nominate some stake. + assert_ok!(SubtensorModule::add_stake(<::RuntimeOrigin>::signed(coldkey0), hotkey2, 1000) ); + assert_ok!(SubtensorModule::add_stake(<::RuntimeOrigin>::signed(coldkey1), hotkey2, 1000) ); + assert_ok!(SubtensorModule::add_stake(<::RuntimeOrigin>::signed(coldkey2), hotkey2, 100) ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey2, &hotkey2 ), 1000 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey2 ), 1000 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey2 ), 1000 ); + assert_eq!( SubtensorModule::get_total_stake_for_hotkey( &hotkey2 ), 3_000 ); + assert_eq!( SubtensorModule::get_total_stake(), 7_723 ); // 5_623 + (1_000 + 1_000 + 100) = 7_723 + + // Lets emit inflation through this new key with distributed ownership. + // We will emit 100 server emission, which should go in-full to the owner of the hotkey. + // We will emit 1000 validator emission, which should be distributed in-part to the nominators. + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey2, 100, 1000 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey2, &hotkey2 ), 1_768 ); // 1000 + 100 + 500 + 500 * (1000/3000) = 100 + 1500 + 166.6666666667 ~= 1,768.6666666667 + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey2 ), 1_166 ); // 1000 + 500 * (1000/3000) = 1000 + 166.6666666667 = 1166.6 + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey2 ), 1_166 ); // 1000 + 500 * (1000/3000) = 1000 + 166.6666666667 = 1166.6 + assert_eq!( SubtensorModule::get_total_stake(), 8_823 ); // 7_723 + 1_100 = 8_823 + + // Lets emit MORE inflation through this new key with distributed ownership. + // This time we do ONLY server emission + // We will emit 123 server emission, which should go in-full to the owner of the hotkey. + // We will emit *0* validator emission. + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey2, 123, 0 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey2, &hotkey2 ), 1_891 ); // 1_768 + 123 = 1_891 + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey2 ), 1_166 ); // No change. + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey2 ), 1_166 ); // No change. + assert_eq!( SubtensorModule::get_total_stake(), 8_946 ); // 8_823 + 123 = 8_946 + }); +} + + +#[test] +fn test_full_block_emission_occurs() { + new_test_ext().execute_with(|| { + let netuid = 1; + // Make two accounts. + let hotkey0 = U256::from(1); + let hotkey1 = U256::from(2); + + let coldkey0 = U256::from(3); + let coldkey1 = U256::from(4); + SubtensorModule::set_max_registrations_per_block(netuid,4); + SubtensorModule::set_max_allowed_uids(netuid, 10); // Allow at least 10 to be registered at once, so no unstaking occurs + + // Neither key can add stake because they dont have fundss. + assert_eq!(SubtensorModule::add_stake(<::RuntimeOrigin>::signed(coldkey0), hotkey0, 60000), Err(Error::::NotEnoughBalanceToStake.into())); + assert_eq!(SubtensorModule::add_stake(<::RuntimeOrigin>::signed(coldkey1), hotkey1, 60000), Err(Error::::NotEnoughBalanceToStake.into())); + + // Add balances. + SubtensorModule::add_balance_to_coldkey_account(&coldkey0, 60000); + SubtensorModule::add_balance_to_coldkey_account(&coldkey1, 60000); + + // Register the 2 neurons to a new network. + let netuid = 1; + add_network(netuid, 0, 0); + register_ok_neuron( netuid, hotkey0, coldkey0, 124124 ); + register_ok_neuron( netuid, hotkey1, coldkey1, 987907 ); + assert_eq!( SubtensorModule::get_owning_coldkey_for_hotkey( &hotkey0 ), coldkey0 ); + assert_eq!( SubtensorModule::get_owning_coldkey_for_hotkey( &hotkey1 ), coldkey1 ); + assert!( SubtensorModule::coldkey_owns_hotkey( &coldkey0, &hotkey0 ) ); + assert!( SubtensorModule::coldkey_owns_hotkey( &coldkey1, &hotkey1 ) ); + + // We stake and all is ok. + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 0 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 0 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 0 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 0 ); + assert_ok!(SubtensorModule::add_stake(<::RuntimeOrigin>::signed(coldkey0), hotkey0, 100) ); + assert_ok!(SubtensorModule::add_stake(<::RuntimeOrigin>::signed(coldkey1), hotkey1, 100) ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey0 ), 100 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey0, &hotkey1 ), 0 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey0 ), 0 ); + assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &coldkey1, &hotkey1 ), 100 ); + assert_eq!( SubtensorModule::get_total_stake_for_hotkey( &hotkey0 ), 100 ); + assert_eq!( SubtensorModule::get_total_stake_for_hotkey( &hotkey1 ), 100 ); + assert_eq!( SubtensorModule::get_total_stake(), 200 ); + + // Emit inflation through non delegates. + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey0, 0, 111 ); + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey1, 0, 234 ); + // Verify the full emission occurs. + assert_eq!( SubtensorModule::get_total_stake(), 200 + 111 + 234 ); // 200 + 111 + 234 = 545 + + // Become delegates all is ok. + assert_ok!( SubtensorModule::do_become_delegate(<::RuntimeOrigin>::signed(coldkey0), hotkey0, 10) ); + assert_ok! (SubtensorModule::do_become_delegate(<::RuntimeOrigin>::signed(coldkey1), hotkey1, 10) ); + assert!( SubtensorModule::hotkey_is_delegate( &hotkey0 ) ); + assert!( SubtensorModule::hotkey_is_delegate( &hotkey1 ) ); + + // Add some delegate stake + assert_ok!(SubtensorModule::add_stake(<::RuntimeOrigin>::signed(coldkey0), hotkey1, 200) ); + assert_ok!(SubtensorModule::add_stake(<::RuntimeOrigin>::signed(coldkey1), hotkey0, 300) ); + + assert_eq!( SubtensorModule::get_total_stake(), 545 + 500 ); // 545 + 500 = 1045 + + // Lets emit inflation with delegatees, with both validator and server emission + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey0, 200, 1_000 ); // 1_200 total emission. + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey1, 123, 2_000 ); // 2_123 total emission. + + assert_eq!( SubtensorModule::get_total_stake(), 1045 + 1_200 + 2_123 ); // before + 1_200 + 2_123 = 4_368 + + // Lets emit MORE inflation through the hot and coldkeys. + // This time JUSt server emission + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey0, 350, 0 ); + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey1, 150, 0 ); + + assert_eq!( SubtensorModule::get_total_stake(), 4_368 + 350 + 150 ); // before + 350 + 150 = 4_868 + + // Lastly, do only validator emission + + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey0, 0, 12_948); + SubtensorModule::emit_inflation_through_hotkey_account( &hotkey1, 0, 1_874 ); + + assert_eq!( SubtensorModule::get_total_stake(), 4_868 + 12_948 + 1_874 ); // before + 12_948 + 1_874 = 19_690 + }); +} + + /************************************************************ staking::unstake_all_coldkeys_from_hotkey_account() tests ************************************************************/ @@ -1111,4 +1346,4 @@ fn test_unstake_all_coldkeys_from_hotkey_account_single_staker() { // Verify free balance is correct for single coldkey assert_eq!(Balances::free_balance(coldkey0_id), amount); }); -} \ No newline at end of file +} diff --git a/pallets/subtensor/tests/sudo.rs b/pallets/subtensor/tests/sudo.rs index 5265f4eca..eaabbffcc 100644 --- a/pallets/subtensor/tests/sudo.rs +++ b/pallets/subtensor/tests/sudo.rs @@ -1,8 +1,8 @@ -use frame_support::{assert_ok}; +use frame_support::assert_ok; use frame_system::Config; mod mock; -use mock::*; use frame_support::sp_runtime::DispatchError; +use mock::*; use pallet_subtensor::{Error, Event}; use sp_core::U256; @@ -11,554 +11,1290 @@ fn test_defaults() { new_test_ext().execute_with(|| { let netuid = 0; add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::get_number_of_subnets(), 1 ); // There is a single network. - assert_eq!( SubtensorModule::get_subnetwork_n( netuid ), 0 ); // Network size is zero. - assert_eq!( SubtensorModule::get_rho( netuid ), 30 ); - assert_eq!( SubtensorModule::get_tempo( netuid ), 10 ); - assert_eq!( SubtensorModule::get_kappa( netuid ), 32_767 ); - assert_eq!( SubtensorModule::get_min_difficulty( netuid ), 1 ); - assert_eq!( SubtensorModule::get_max_difficulty( netuid ), u64::MAX ); - assert_eq!( SubtensorModule::get_difficulty_as_u64( netuid ), 10000 ); - assert_eq!( SubtensorModule::get_immunity_period( netuid ), 2 ); - assert_eq!( SubtensorModule::get_emission_value( netuid ), 0 ); - assert_eq!( SubtensorModule::get_activity_cutoff( netuid ), 5000 ); - assert_eq!( SubtensorModule::get_pending_emission( netuid ), 0 ); - assert_eq!( SubtensorModule::get_max_weight_limit( netuid ), u16::MAX ); - assert_eq!( SubtensorModule::get_max_allowed_uids( netuid ), 2 ); - assert_eq!( SubtensorModule::get_min_allowed_weights( netuid ), 0 ); - assert_eq!( SubtensorModule::get_adjustment_interval( netuid ), 100 ); - assert_eq!( SubtensorModule::get_bonds_moving_average( netuid ), 900_000 ); - assert_eq!( SubtensorModule::get_validator_batch_size( netuid ), 10 ); - assert_eq!( SubtensorModule::get_last_adjustment_block( netuid ), 0 ); - assert_eq!( SubtensorModule::get_last_mechanism_step_block( netuid ), 0 ); - assert_eq!( SubtensorModule::get_blocks_since_last_step( netuid ), 0 ); - assert_eq!( SubtensorModule::get_registrations_this_block( netuid ), 0 ); - assert_eq!( SubtensorModule::get_validator_epochs_per_reset( netuid ), 10 ); - assert_eq!( SubtensorModule::get_validator_sequence_length( netuid ), 10 ); - assert_eq!( SubtensorModule::get_validator_exclude_quantile( netuid ), 10 ); - assert_eq!( SubtensorModule::get_validator_logits_divergence( netuid ), 0 ); - assert_eq!( SubtensorModule::get_validator_prune_len( netuid ), 0 ); - assert_eq!( SubtensorModule::get_scaling_law_power( netuid ), 50 ); - assert_eq!( SubtensorModule::get_synergy_scaling_law_power( netuid ), 50 ); - assert_eq!( SubtensorModule::get_registrations_this_interval( netuid ), 0 ); - assert_eq!( SubtensorModule::get_max_registrations_per_block( netuid ), 3 ); - assert_eq!( SubtensorModule::get_target_registrations_per_interval( netuid ), 2 ); + assert_eq!(SubtensorModule::get_number_of_subnets(), 1); // There is a single network. + assert_eq!(SubtensorModule::get_subnetwork_n(netuid), 0); // Network size is zero. + assert_eq!(SubtensorModule::get_rho(netuid), 30); + assert_eq!(SubtensorModule::get_tempo(netuid), 10); + assert_eq!(SubtensorModule::get_kappa(netuid), 32_767); + assert_eq!(SubtensorModule::get_min_difficulty(netuid), 1); + assert_eq!(SubtensorModule::get_max_difficulty(netuid), u64::MAX); + assert_eq!(SubtensorModule::get_difficulty_as_u64(netuid), 10000); + assert_eq!(SubtensorModule::get_immunity_period(netuid), 2); + assert_eq!(SubtensorModule::get_emission_value(netuid), 0); + assert_eq!(SubtensorModule::get_activity_cutoff(netuid), 5000); + assert_eq!(SubtensorModule::get_pending_emission(netuid), 0); + assert_eq!(SubtensorModule::get_max_weight_limit(netuid), u16::MAX); + assert_eq!(SubtensorModule::get_max_allowed_uids(netuid), 2); + assert_eq!(SubtensorModule::get_min_allowed_weights(netuid), 0); + assert_eq!(SubtensorModule::get_adjustment_interval(netuid), 100); + assert_eq!(SubtensorModule::get_bonds_moving_average(netuid), 900_000); + assert_eq!(SubtensorModule::get_validator_batch_size(netuid), 10); + assert_eq!(SubtensorModule::get_last_adjustment_block(netuid), 0); + assert_eq!(SubtensorModule::get_last_mechanism_step_block(netuid), 0); + assert_eq!(SubtensorModule::get_blocks_since_last_step(netuid), 0); + assert_eq!(SubtensorModule::get_registrations_this_block(netuid), 0); + assert_eq!(SubtensorModule::get_validator_epochs_per_reset(netuid), 10); + assert_eq!(SubtensorModule::get_validator_sequence_length(netuid), 10); + assert_eq!(SubtensorModule::get_validator_exclude_quantile(netuid), 10); + assert_eq!(SubtensorModule::get_validator_logits_divergence(netuid), 0); + assert_eq!(SubtensorModule::get_validator_prune_len(netuid), 0); + assert_eq!(SubtensorModule::get_scaling_law_power(netuid), 50); + assert_eq!(SubtensorModule::get_synergy_scaling_law_power(netuid), 50); + assert_eq!(SubtensorModule::get_registrations_this_interval(netuid), 0); + assert_eq!(SubtensorModule::get_max_registrations_per_block(netuid), 3); + assert_eq!( + SubtensorModule::get_target_registrations_per_interval(netuid), + 2 + ); }); } #[test] fn test_sudo_registration() { - new_test_ext().execute_with(|| { - add_network( 0, 0, 0 ); - SubtensorModule::set_max_allowed_uids( 0, 10 ); - assert_ok!( SubtensorModule::sudo_register(<::RuntimeOrigin>::root(), 0, U256::from(0), U256::from(0), 10, 11) ); - assert_ok!( SubtensorModule::sudo_register(<::RuntimeOrigin>::root(), 0, U256::from(1), U256::from(1), 10, 11) ); - assert_ok!( SubtensorModule::sudo_register(<::RuntimeOrigin>::root(), 0, U256::from(2), U256::from(2), 10, 11) ); - assert_ok!( SubtensorModule::sudo_register(<::RuntimeOrigin>::root(), 0, U256::from(3), U256::from(3), 10, 11) ); - assert_ok!( SubtensorModule::sudo_register(<::RuntimeOrigin>::root(), 0, U256::from(4), U256::from(4), 10, 11) ); - assert_ok!( SubtensorModule::sudo_register(<::RuntimeOrigin>::root(), 0, U256::from(5), U256::from(5), 10, 11) ); - assert_ok!( SubtensorModule::sudo_register(<::RuntimeOrigin>::root(), 0, U256::from(6), U256::from(6), 10, 11) ); - assert_ok!( SubtensorModule::sudo_register(<::RuntimeOrigin>::root(), 0, U256::from(7), U256::from(7), 10, 11) ); - assert_ok!( SubtensorModule::sudo_register(<::RuntimeOrigin>::root(), 0, U256::from(8), U256::from(8), 10, 11) ); - assert_eq!( SubtensorModule::get_coldkey_balance( &U256::from(0) ), 11 ); - assert_eq!( SubtensorModule::get_coldkey_balance( &U256::from(1) ), 11 ); - assert_eq!( SubtensorModule::get_coldkey_balance( &U256::from(2) ), 11 ); - assert_eq!( SubtensorModule::get_coldkey_balance( &U256::from(3) ), 11 ); - assert_eq!( SubtensorModule::get_coldkey_balance( &U256::from(4) ), 11 ); - assert_eq!( SubtensorModule::get_coldkey_balance( &U256::from(5) ), 11 ); - assert_eq!( SubtensorModule::get_coldkey_balance( &U256::from(6) ), 11 ); - assert_eq!( SubtensorModule::get_coldkey_balance( &U256::from(7) ), 11 ); - assert_eq!( SubtensorModule::get_coldkey_balance( &U256::from(8) ), 11 ); - assert_eq!( SubtensorModule::get_hotkey_for_net_and_uid( 0, 0).unwrap(), U256::from(0) ); - assert_eq!( SubtensorModule::get_hotkey_for_net_and_uid( 0, 1).unwrap(), U256::from(1) ); - assert_eq!( SubtensorModule::get_hotkey_for_net_and_uid( 0, 2).unwrap(), U256::from(2) ); - assert_eq!( SubtensorModule::get_hotkey_for_net_and_uid( 0, 3).unwrap(), U256::from(3) ); - assert_eq!( SubtensorModule::get_hotkey_for_net_and_uid( 0, 4).unwrap(), U256::from(4) ); - assert_eq!( SubtensorModule::get_hotkey_for_net_and_uid( 0, 5).unwrap(), U256::from(5) ); - assert_eq!( SubtensorModule::get_hotkey_for_net_and_uid( 0, 6).unwrap(), U256::from(6) ); - assert_eq!( SubtensorModule::get_hotkey_for_net_and_uid( 0, 7).unwrap(), U256::from(7) ); - assert_eq!( SubtensorModule::get_hotkey_for_net_and_uid( 0, 8).unwrap(), U256::from(8) ); - assert_eq!( SubtensorModule::get_total_stake(), 90 ); - assert!( SubtensorModule::coldkey_owns_hotkey( &U256::from(0), &U256::from(0) ) ); - assert_eq!( SubtensorModule::get_owning_coldkey_for_hotkey( &U256::from(0) ), U256::from(0) ); - assert_eq!( SubtensorModule::get_stake_for_coldkey_and_hotkey( &U256::from(0), &U256::from(0) ), 10 ); + new_test_ext().execute_with(|| { + add_network(0, 0, 0); + SubtensorModule::set_max_allowed_uids(0, 10); + assert_ok!(SubtensorModule::sudo_register( + <::RuntimeOrigin>::root(), + 0, + U256::from(0), + U256::from(0), + 10, + 11 + )); + assert_ok!(SubtensorModule::sudo_register( + <::RuntimeOrigin>::root(), + 0, + U256::from(1), + U256::from(1), + 10, + 11 + )); + assert_ok!(SubtensorModule::sudo_register( + <::RuntimeOrigin>::root(), + 0, + U256::from(2), + U256::from(2), + 10, + 11 + )); + assert_ok!(SubtensorModule::sudo_register( + <::RuntimeOrigin>::root(), + 0, + U256::from(3), + U256::from(3), + 10, + 11 + )); + assert_ok!(SubtensorModule::sudo_register( + <::RuntimeOrigin>::root(), + 0, + U256::from(4), + U256::from(4), + 10, + 11 + )); + assert_ok!(SubtensorModule::sudo_register( + <::RuntimeOrigin>::root(), + 0, + U256::from(5), + U256::from(5), + 10, + 11 + )); + assert_ok!(SubtensorModule::sudo_register( + <::RuntimeOrigin>::root(), + 0, + U256::from(6), + U256::from(6), + 10, + 11 + )); + assert_ok!(SubtensorModule::sudo_register( + <::RuntimeOrigin>::root(), + 0, + U256::from(7), + U256::from(7), + 10, + 11 + )); + assert_ok!(SubtensorModule::sudo_register( + <::RuntimeOrigin>::root(), + 0, + U256::from(8), + U256::from(8), + 10, + 11 + )); + assert_eq!(SubtensorModule::get_coldkey_balance(&U256::from(0)), 11); + assert_eq!(SubtensorModule::get_coldkey_balance(&U256::from(1)), 11); + assert_eq!(SubtensorModule::get_coldkey_balance(&U256::from(2)), 11); + assert_eq!(SubtensorModule::get_coldkey_balance(&U256::from(3)), 11); + assert_eq!(SubtensorModule::get_coldkey_balance(&U256::from(4)), 11); + assert_eq!(SubtensorModule::get_coldkey_balance(&U256::from(5)), 11); + assert_eq!(SubtensorModule::get_coldkey_balance(&U256::from(6)), 11); + assert_eq!(SubtensorModule::get_coldkey_balance(&U256::from(7)), 11); + assert_eq!(SubtensorModule::get_coldkey_balance(&U256::from(8)), 11); + assert_eq!( + SubtensorModule::get_hotkey_for_net_and_uid(0, 0).unwrap(), + U256::from(0) + ); + assert_eq!( + SubtensorModule::get_hotkey_for_net_and_uid(0, 1).unwrap(), + U256::from(1) + ); + assert_eq!( + SubtensorModule::get_hotkey_for_net_and_uid(0, 2).unwrap(), + U256::from(2) + ); + assert_eq!( + SubtensorModule::get_hotkey_for_net_and_uid(0, 3).unwrap(), + U256::from(3) + ); + assert_eq!( + SubtensorModule::get_hotkey_for_net_and_uid(0, 4).unwrap(), + U256::from(4) + ); + assert_eq!( + SubtensorModule::get_hotkey_for_net_and_uid(0, 5).unwrap(), + U256::from(5) + ); + assert_eq!( + SubtensorModule::get_hotkey_for_net_and_uid(0, 6).unwrap(), + U256::from(6) + ); + assert_eq!( + SubtensorModule::get_hotkey_for_net_and_uid(0, 7).unwrap(), + U256::from(7) + ); + assert_eq!( + SubtensorModule::get_hotkey_for_net_and_uid(0, 8).unwrap(), + U256::from(8) + ); + assert_eq!(SubtensorModule::get_total_stake(), 90); + assert!(SubtensorModule::coldkey_owns_hotkey( + &U256::from(0), + &U256::from(0) + )); + assert_eq!( + SubtensorModule::get_owning_coldkey_for_hotkey(&U256::from(0)), + U256::from(0) + ); + assert_eq!( + SubtensorModule::get_stake_for_coldkey_and_hotkey(&U256::from(0), &U256::from(0)), + 10 + ); }); } #[test] fn test_sudo_set_default_take() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let to_be_set: u16 = 10; let init_value: u16 = SubtensorModule::get_default_take(); - assert_eq!( SubtensorModule::sudo_set_default_take(<::RuntimeOrigin>::signed(U256::from(0)), to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::get_default_take(), init_value); - assert_ok!( SubtensorModule::sudo_set_default_take(<::RuntimeOrigin>::root(), to_be_set) ); - assert_eq!( SubtensorModule::get_default_take(), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_default_take( + <::RuntimeOrigin>::signed(U256::from(0)), + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!(SubtensorModule::get_default_take(), init_value); + assert_ok!(SubtensorModule::sudo_set_default_take( + <::RuntimeOrigin>::root(), + to_be_set + )); + assert_eq!(SubtensorModule::get_default_take(), to_be_set); }); } #[test] fn test_sudo_set_serving_rate_limit() { - new_test_ext().execute_with(|| { - let netuid: u16 = 3; + new_test_ext().execute_with(|| { + let netuid: u16 = 3; let to_be_set: u64 = 10; let init_value: u64 = SubtensorModule::get_serving_rate_limit(netuid); - assert_eq!( SubtensorModule::sudo_set_serving_rate_limit(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::get_serving_rate_limit(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_serving_rate_limit(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_serving_rate_limit(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_serving_rate_limit( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!(SubtensorModule::get_serving_rate_limit(netuid), init_value); + assert_ok!(SubtensorModule::sudo_set_serving_rate_limit( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_serving_rate_limit(netuid), to_be_set); }); } #[test] fn test_sudo_set_min_difficulty() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u64 = 10; - let init_value: u64 = SubtensorModule::get_min_difficulty( netuid ); + let init_value: u64 = SubtensorModule::get_min_difficulty(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_min_difficulty(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_min_difficulty(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_min_difficulty(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_min_difficulty(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_min_difficulty(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_min_difficulty( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_min_difficulty( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!(SubtensorModule::get_min_difficulty(netuid), init_value); + assert_ok!(SubtensorModule::sudo_set_min_difficulty( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_min_difficulty(netuid), to_be_set); }); } #[test] fn test_sudo_set_max_difficulty() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u64 = 10; - let init_value: u64 = SubtensorModule::get_max_difficulty( netuid ); + let init_value: u64 = SubtensorModule::get_max_difficulty(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_max_difficulty(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_max_difficulty(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_max_difficulty(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_max_difficulty(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_max_difficulty(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_max_difficulty( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_max_difficulty( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!(SubtensorModule::get_max_difficulty(netuid), init_value); + assert_ok!(SubtensorModule::sudo_set_max_difficulty( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_max_difficulty(netuid), to_be_set); }); } - #[test] fn test_sudo_set_weights_version_key() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u64 = 10; - let init_value: u64 = SubtensorModule::get_weights_version_key( netuid ); + let init_value: u64 = SubtensorModule::get_weights_version_key(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_weights_version_key(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_weights_version_key(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_weights_version_key(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_weights_version_key(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_weights_version_key(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_weights_version_key( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_weights_version_key( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!(SubtensorModule::get_weights_version_key(netuid), init_value); + assert_ok!(SubtensorModule::sudo_set_weights_version_key( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_weights_version_key(netuid), to_be_set); }); } #[test] fn test_sudo_set_weights_set_rate_limit() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u64 = 10; - let init_value: u64 = SubtensorModule::get_weights_set_rate_limit( netuid ); + let init_value: u64 = SubtensorModule::get_weights_set_rate_limit(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_weights_set_rate_limit(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_weights_set_rate_limit(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_weights_set_rate_limit(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_weights_set_rate_limit(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_weights_set_rate_limit(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_weights_set_rate_limit( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_weights_set_rate_limit( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!( + SubtensorModule::get_weights_set_rate_limit(netuid), + init_value + ); + assert_ok!(SubtensorModule::sudo_set_weights_set_rate_limit( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!( + SubtensorModule::get_weights_set_rate_limit(netuid), + to_be_set + ); }); } - #[test] fn test_sudo_set_adjustment_interval() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 10; - let init_value: u16 = SubtensorModule::get_adjustment_interval( netuid ); + let init_value: u16 = SubtensorModule::get_adjustment_interval(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_adjustment_interval(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_adjustment_interval(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_adjustment_interval(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_adjustment_interval(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_adjustment_interval(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_adjustment_interval( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_adjustment_interval( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!(SubtensorModule::get_adjustment_interval(netuid), init_value); + assert_ok!(SubtensorModule::sudo_set_adjustment_interval( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_adjustment_interval(netuid), to_be_set); }); } - #[test] fn test_sudo_set_validator_exclude_quantile() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 10; - let init_value: u16 = SubtensorModule::get_validator_exclude_quantile( netuid ); + let init_value: u16 = SubtensorModule::get_validator_exclude_quantile(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_validator_exclude_quantile(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_validator_exclude_quantile(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_validator_exclude_quantile(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_validator_exclude_quantile(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_validator_exclude_quantile(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_validator_exclude_quantile( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_validator_exclude_quantile( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!( + SubtensorModule::get_validator_exclude_quantile(netuid), + init_value + ); + assert_ok!(SubtensorModule::sudo_set_validator_exclude_quantile( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!( + SubtensorModule::get_validator_exclude_quantile(netuid), + to_be_set + ); }); } #[test] fn test_sudo_validator_prune_len() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u64 = 10; - let init_value: u64 = SubtensorModule::get_validator_prune_len( netuid ); + let init_value: u64 = SubtensorModule::get_validator_prune_len(netuid); add_network(netuid, 10, 0); - - assert_eq!( SubtensorModule::sudo_set_validator_prune_len(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_validator_prune_len(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_validator_prune_len(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_validator_prune_len(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_validator_prune_len(netuid), to_be_set); + + assert_eq!( + SubtensorModule::sudo_set_validator_prune_len( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_validator_prune_len( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!(SubtensorModule::get_validator_prune_len(netuid), init_value); + assert_ok!(SubtensorModule::sudo_set_validator_prune_len( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_validator_prune_len(netuid), to_be_set); }); } #[test] fn test_sudo_validator_logits_divergence() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 10; - let init_value: u16 = SubtensorModule::get_validator_logits_divergence( netuid ); + let init_value: u16 = SubtensorModule::get_validator_logits_divergence(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_validator_logits_divergence(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_validator_logits_divergence(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_validator_logits_divergence(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_validator_logits_divergence(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_validator_logits_divergence(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_validator_logits_divergence( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_validator_logits_divergence( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!( + SubtensorModule::get_validator_logits_divergence(netuid), + init_value + ); + assert_ok!(SubtensorModule::sudo_set_validator_logits_divergence( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!( + SubtensorModule::get_validator_logits_divergence(netuid), + to_be_set + ); }); } #[test] fn test_sudo_set_scaling_law_power() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 50; - let init_value: u16 = SubtensorModule::get_scaling_law_power( netuid ); + let init_value: u16 = SubtensorModule::get_scaling_law_power(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_scaling_law_power(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_scaling_law_power(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_scaling_law_power(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_scaling_law_power(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_scaling_law_power(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_scaling_law_power( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_scaling_law_power( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!(SubtensorModule::get_scaling_law_power(netuid), init_value); + assert_ok!(SubtensorModule::sudo_set_scaling_law_power( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_scaling_law_power(netuid), to_be_set); }); } #[test] fn test_sudo_set_synergy_scaling_law_power() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 50; - let init_value: u16 = SubtensorModule::get_synergy_scaling_law_power( netuid ); + let init_value: u16 = SubtensorModule::get_synergy_scaling_law_power(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_synergy_scaling_law_power(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_synergy_scaling_law_power(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_synergy_scaling_law_power(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_synergy_scaling_law_power(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_synergy_scaling_law_power(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_synergy_scaling_law_power( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_synergy_scaling_law_power( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!( + SubtensorModule::get_synergy_scaling_law_power(netuid), + init_value + ); + assert_ok!(SubtensorModule::sudo_set_synergy_scaling_law_power( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!( + SubtensorModule::get_synergy_scaling_law_power(netuid), + to_be_set + ); }); } #[test] fn test_sudo_set_max_weight_limit() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 10; - let init_value: u16 = SubtensorModule::get_max_weight_limit( netuid ); + let init_value: u16 = SubtensorModule::get_max_weight_limit(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_max_weight_limit(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_max_weight_limit(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_max_weight_limit(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_max_weight_limit(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_max_weight_limit(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_max_weight_limit( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_max_weight_limit( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!(SubtensorModule::get_max_weight_limit(netuid), init_value); + assert_ok!(SubtensorModule::sudo_set_max_weight_limit( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_max_weight_limit(netuid), to_be_set); }); } #[test] fn test_sudo_set_issuance() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let to_be_set: u64 = 10; - assert_eq!( SubtensorModule::sudo_set_total_issuance(<::RuntimeOrigin>::signed(U256::from(0)), to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_ok!( SubtensorModule::sudo_set_total_issuance(<::RuntimeOrigin>::root(), to_be_set) ); - assert_eq!( SubtensorModule::get_total_issuance(), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_total_issuance( + <::RuntimeOrigin>::signed(U256::from(0)), + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_ok!(SubtensorModule::sudo_set_total_issuance( + <::RuntimeOrigin>::root(), + to_be_set + )); + assert_eq!(SubtensorModule::get_total_issuance(), to_be_set); }); } #[test] fn test_sudo_set_immunity_period() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 10; - let init_value: u16 = SubtensorModule::get_immunity_period( netuid ); + let init_value: u16 = SubtensorModule::get_immunity_period(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_immunity_period(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_immunity_period(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_immunity_period(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_immunity_period(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_immunity_period(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_immunity_period( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_immunity_period( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!(SubtensorModule::get_immunity_period(netuid), init_value); + assert_ok!(SubtensorModule::sudo_set_immunity_period( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_immunity_period(netuid), to_be_set); }); } - #[test] fn test_sudo_set_validator_epochs_per_reset() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 10; - let init_value: u16 = SubtensorModule::get_validator_epochs_per_reset( netuid ); + let init_value: u16 = SubtensorModule::get_validator_epochs_per_reset(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_validator_epochs_per_reset(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_validator_epochs_per_reset(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_validator_epochs_per_reset(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_validator_epochs_per_reset(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_validator_epochs_per_reset(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_validator_epochs_per_reset( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_validator_epochs_per_reset( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!( + SubtensorModule::get_validator_epochs_per_reset(netuid), + init_value + ); + assert_ok!(SubtensorModule::sudo_set_validator_epochs_per_reset( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!( + SubtensorModule::get_validator_epochs_per_reset(netuid), + to_be_set + ); }); } #[test] fn test_sudo_set_validator_sequence_length() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 10; - let init_value: u16 = SubtensorModule::get_validator_sequence_length( netuid ); + let init_value: u16 = SubtensorModule::get_validator_sequence_length(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_validator_sequence_length(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_validator_sequence_length(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_validator_sequence_length(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_validator_sequence_length(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_validator_sequence_length(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_validator_sequence_length( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_validator_sequence_length( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!( + SubtensorModule::get_validator_sequence_length(netuid), + init_value + ); + assert_ok!(SubtensorModule::sudo_set_validator_sequence_length( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!( + SubtensorModule::get_validator_sequence_length(netuid), + to_be_set + ); }); } #[test] fn test_sudo_set_validator_batch_size() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 10; - let init_value: u16 = SubtensorModule::get_validator_batch_size( netuid ); + let init_value: u16 = SubtensorModule::get_validator_batch_size(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_validator_batch_size(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_validator_batch_size(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_validator_batch_size(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_validator_batch_size(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_validator_batch_size(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_validator_batch_size( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_validator_batch_size( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!( + SubtensorModule::get_validator_batch_size(netuid), + init_value + ); + assert_ok!(SubtensorModule::sudo_set_validator_batch_size( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_validator_batch_size(netuid), to_be_set); }); } #[test] fn test_sudo_set_min_allowed_weights() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 10; - let init_value: u16 = SubtensorModule::get_min_allowed_weights( netuid ); + let init_value: u16 = SubtensorModule::get_min_allowed_weights(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_min_allowed_weights(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_min_allowed_weights(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_min_allowed_weights(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_min_allowed_weights(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_min_allowed_weights(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_min_allowed_weights( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_min_allowed_weights( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!(SubtensorModule::get_min_allowed_weights(netuid), init_value); + assert_ok!(SubtensorModule::sudo_set_min_allowed_weights( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_min_allowed_weights(netuid), to_be_set); }); } #[test] fn test_sudo_set_max_allowed_uids() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 10; - let init_value: u16 = SubtensorModule::get_max_allowed_uids( netuid ); + let init_value: u16 = SubtensorModule::get_max_allowed_uids(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_max_allowed_uids(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_max_allowed_uids(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_max_allowed_uids(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_max_allowed_uids(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_max_allowed_uids(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_max_allowed_uids( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_max_allowed_uids( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!(SubtensorModule::get_max_allowed_uids(netuid), init_value); + assert_ok!(SubtensorModule::sudo_set_max_allowed_uids( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_max_allowed_uids(netuid), to_be_set); }); } #[test] fn test_sudo_set_and_decrease_max_allowed_uids() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 10; - let init_value: u16 = SubtensorModule::get_max_allowed_uids( netuid ); + let init_value: u16 = SubtensorModule::get_max_allowed_uids(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_max_allowed_uids(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_max_allowed_uids(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_max_allowed_uids(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_max_allowed_uids(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::sudo_set_max_allowed_uids(<::RuntimeOrigin>::root(), netuid, to_be_set-1), Err(Error::::MaxAllowedUIdsNotAllowed.into())); + assert_eq!( + SubtensorModule::sudo_set_max_allowed_uids( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_max_allowed_uids( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!(SubtensorModule::get_max_allowed_uids(netuid), init_value); + assert_ok!(SubtensorModule::sudo_set_max_allowed_uids( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_ok!(SubtensorModule::sudo_set_max_allowed_uids( + <::RuntimeOrigin>::root(), + netuid, + to_be_set - 1 + )); }); } #[test] fn test_sudo_set_kappa() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 10; - let init_value: u16 = SubtensorModule::get_kappa( netuid ); + let init_value: u16 = SubtensorModule::get_kappa(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_kappa(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_kappa(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_kappa(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_kappa(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_kappa(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_kappa( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_kappa( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!(SubtensorModule::get_kappa(netuid), init_value); + assert_ok!(SubtensorModule::sudo_set_kappa( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_kappa(netuid), to_be_set); }); } - #[test] fn test_sudo_set_rho() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 10; - let init_value: u16 = SubtensorModule::get_rho( netuid ); + let init_value: u16 = SubtensorModule::get_rho(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_rho(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_rho(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_rho(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_rho(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_rho(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_rho( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_rho( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!(SubtensorModule::get_rho(netuid), init_value); + assert_ok!(SubtensorModule::sudo_set_rho( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_rho(netuid), to_be_set); }); } #[test] fn test_sudo_set_activity_cutoff() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 10; - let init_value: u16 = SubtensorModule::get_activity_cutoff( netuid ); + let init_value: u16 = SubtensorModule::get_activity_cutoff(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_activity_cutoff(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_activity_cutoff(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_activity_cutoff(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_activity_cutoff(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_activity_cutoff(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_activity_cutoff( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_activity_cutoff( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!(SubtensorModule::get_activity_cutoff(netuid), init_value); + assert_ok!(SubtensorModule::sudo_set_activity_cutoff( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_activity_cutoff(netuid), to_be_set); }); } - - + #[test] fn test_sudo_set_target_registrations_per_interval() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 10; - let init_value: u16 = SubtensorModule::get_target_registrations_per_interval( netuid ); + let init_value: u16 = SubtensorModule::get_target_registrations_per_interval(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_target_registrations_per_interval(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_target_registrations_per_interval(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_target_registrations_per_interval(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_target_registrations_per_interval(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_target_registrations_per_interval(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_target_registrations_per_interval( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_target_registrations_per_interval( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!( + SubtensorModule::get_target_registrations_per_interval(netuid), + init_value + ); + assert_ok!(SubtensorModule::sudo_set_target_registrations_per_interval( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!( + SubtensorModule::get_target_registrations_per_interval(netuid), + to_be_set + ); }); } - + #[test] fn test_sudo_set_difficulty() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u64 = 10; - let init_value: u64 = SubtensorModule::get_difficulty_as_u64( netuid ); + let init_value: u64 = SubtensorModule::get_difficulty_as_u64(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_difficulty(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_difficulty(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_difficulty_as_u64(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_difficulty(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_difficulty_as_u64(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_difficulty( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_difficulty( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!(SubtensorModule::get_difficulty_as_u64(netuid), init_value); + assert_ok!(SubtensorModule::sudo_set_difficulty( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_difficulty_as_u64(netuid), to_be_set); }); } - #[test] fn test_sudo_set_max_allowed_validators() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u16 = 10; - let init_value: u16 = SubtensorModule::get_max_allowed_validators( netuid ); + let init_value: u16 = SubtensorModule::get_max_allowed_validators(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_max_allowed_validators(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_max_allowed_validators(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_max_allowed_validators(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_max_allowed_validators(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_max_allowed_validators(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_max_allowed_validators( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_max_allowed_validators( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!( + SubtensorModule::get_max_allowed_validators(netuid), + init_value + ); + assert_ok!(SubtensorModule::sudo_set_max_allowed_validators( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!( + SubtensorModule::get_max_allowed_validators(netuid), + to_be_set + ); }); } - #[test] fn test_sudo_set_bonds_moving_average() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u64 = 10; let init_value: u64 = SubtensorModule::get_bonds_moving_average(netuid); add_network(netuid, 10, 0); - assert_eq!( SubtensorModule::sudo_set_bonds_moving_average(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_bonds_moving_average(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_bonds_moving_average(netuid), init_value); - assert_ok!( SubtensorModule::sudo_set_bonds_moving_average(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_bonds_moving_average(netuid), to_be_set); + assert_eq!( + SubtensorModule::sudo_set_bonds_moving_average( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_bonds_moving_average( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!( + SubtensorModule::get_bonds_moving_average(netuid), + init_value + ); + assert_ok!(SubtensorModule::sudo_set_bonds_moving_average( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_bonds_moving_average(netuid), to_be_set); }); } #[test] fn test_sudo_set_network_connection_requirement() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid_a: u16 = 1; let netuid_b: u16 = 2; let requirement: u16 = u16::MAX; - assert_eq!( SubtensorModule::sudo_add_network_connection_requirement(<::RuntimeOrigin>::signed(U256::from(0)), netuid_a, netuid_b, requirement), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_add_network_connection_requirement(<::RuntimeOrigin>::root(), netuid_a, netuid_b, requirement), Err(Error::::NetworkDoesNotExist.into()) ); - add_network( netuid_a, 10, 0 ); - assert_eq!( SubtensorModule::sudo_add_network_connection_requirement(<::RuntimeOrigin>::root(), netuid_a, netuid_a, requirement), Err(Error::::InvalidConnectionRequirement.into()) ); - assert_eq!( SubtensorModule::sudo_add_network_connection_requirement(<::RuntimeOrigin>::root(), netuid_a, netuid_b, requirement), Err(Error::::NetworkDoesNotExist.into()) ); - add_network( netuid_b, 10, 0 ); - assert_ok!( SubtensorModule::sudo_add_network_connection_requirement(<::RuntimeOrigin>::root(), netuid_a, netuid_b, requirement)); - assert_eq!( SubtensorModule::get_network_connection_requirement( netuid_a, netuid_b ), requirement); - assert_eq!( SubtensorModule::sudo_remove_network_connection_requirement(<::RuntimeOrigin>::signed(U256::from(0)), netuid_a, netuid_b), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_remove_network_connection_requirement(<::RuntimeOrigin>::root(), 5 as u16, 5 as u16), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::sudo_remove_network_connection_requirement(<::RuntimeOrigin>::root(), netuid_a, 5 as u16), Err(Error::::NetworkDoesNotExist.into()) ); - assert_ok!( SubtensorModule::sudo_remove_network_connection_requirement(<::RuntimeOrigin>::root(), netuid_a, netuid_b) ); - assert_eq!( SubtensorModule::network_connection_requirement_exists( netuid_a, netuid_b ), false ); + assert_eq!( + SubtensorModule::sudo_add_network_connection_requirement( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid_a, + netuid_b, + requirement + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_add_network_connection_requirement( + <::RuntimeOrigin>::root(), + netuid_a, + netuid_b, + requirement + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + add_network(netuid_a, 10, 0); + assert_eq!( + SubtensorModule::sudo_add_network_connection_requirement( + <::RuntimeOrigin>::root(), + netuid_a, + netuid_a, + requirement + ), + Err(Error::::InvalidConnectionRequirement.into()) + ); + assert_eq!( + SubtensorModule::sudo_add_network_connection_requirement( + <::RuntimeOrigin>::root(), + netuid_a, + netuid_b, + requirement + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + add_network(netuid_b, 10, 0); + assert_ok!(SubtensorModule::sudo_add_network_connection_requirement( + <::RuntimeOrigin>::root(), + netuid_a, + netuid_b, + requirement + )); + assert_eq!( + SubtensorModule::get_network_connection_requirement(netuid_a, netuid_b), + requirement + ); + assert_eq!( + SubtensorModule::sudo_remove_network_connection_requirement( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid_a, + netuid_b + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_remove_network_connection_requirement( + <::RuntimeOrigin>::root(), + 5 as u16, + 5 as u16 + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!( + SubtensorModule::sudo_remove_network_connection_requirement( + <::RuntimeOrigin>::root(), + netuid_a, + 5 as u16 + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_ok!(SubtensorModule::sudo_remove_network_connection_requirement( + <::RuntimeOrigin>::root(), + netuid_a, + netuid_b + )); + assert_eq!( + SubtensorModule::network_connection_requirement_exists(netuid_a, netuid_b), + false + ); }); } #[test] fn test_sudo_set_rao_recycled() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid: u16 = 1; let to_be_set: u64 = 10; - let init_value: u64 = SubtensorModule::get_rao_recycled( netuid ); + let init_value: u64 = SubtensorModule::get_rao_recycled(netuid); add_network(netuid, 10, 0); // Need to run from genesis block run_to_block(1); - assert_eq!( SubtensorModule::sudo_set_rao_recycled(<::RuntimeOrigin>::signed(U256::from(0)), netuid, to_be_set), Err(DispatchError::BadOrigin.into()) ); - assert_eq!( SubtensorModule::sudo_set_rao_recycled(<::RuntimeOrigin>::root(), netuid + 1, to_be_set), Err(Error::::NetworkDoesNotExist.into()) ); - assert_eq!( SubtensorModule::get_rao_recycled(netuid), init_value); + assert_eq!( + SubtensorModule::sudo_set_rao_recycled( + <::RuntimeOrigin>::signed(U256::from(0)), + netuid, + to_be_set + ), + Err(DispatchError::BadOrigin.into()) + ); + assert_eq!( + SubtensorModule::sudo_set_rao_recycled( + <::RuntimeOrigin>::root(), + netuid + 1, + to_be_set + ), + Err(Error::::NetworkDoesNotExist.into()) + ); + assert_eq!(SubtensorModule::get_rao_recycled(netuid), init_value); // Verify no events emitted matching the expected event - assert_eq!(System::events().iter().filter(|r| r.event == RuntimeEvent::SubtensorModule( Event::RAORecycledForRegistrationSet(netuid, to_be_set) )).count(), 0); + assert_eq!( + System::events() + .iter() + .filter(|r| r.event + == RuntimeEvent::SubtensorModule(Event::RAORecycledForRegistrationSet( + netuid, to_be_set + ))) + .count(), + 0 + ); - assert_ok!( SubtensorModule::sudo_set_rao_recycled(<::RuntimeOrigin>::root(), netuid, to_be_set) ); - assert_eq!( SubtensorModule::get_rao_recycled(netuid), to_be_set); + assert_ok!(SubtensorModule::sudo_set_rao_recycled( + <::RuntimeOrigin>::root(), + netuid, + to_be_set + )); + assert_eq!(SubtensorModule::get_rao_recycled(netuid), to_be_set); // Verify event emitted with correct values - assert_eq!(System::events().last().expect( - format!("Expected there to be events: {:?}", System::events().to_vec()).as_str() - ).event, RuntimeEvent::SubtensorModule( Event::RAORecycledForRegistrationSet(netuid, to_be_set) )); + assert_eq!( + System::events() + .last() + .expect( + format!( + "Expected there to be events: {:?}", + System::events().to_vec() + ) + .as_str() + ) + .event, + RuntimeEvent::SubtensorModule(Event::RAORecycledForRegistrationSet(netuid, to_be_set)) + ); }); } // -------- tests for PendingEmissionValues -------- #[test] fn test_sudo_test_tempo_pending_emissions_ok() { - new_test_ext().execute_with(|| { + new_test_ext().execute_with(|| { let netuid0: u16 = 1; let netuid1: u16 = 2; let netuid2: u16 = 3; @@ -568,7 +1304,7 @@ fn test_sudo_test_tempo_pending_emissions_ok() { let tempo2: u16 = 3; let tempo3: u16 = 5; add_network(netuid0, tempo0, 0); - add_network(netuid1, tempo1, 0); + add_network(netuid1, tempo1, 0); add_network(netuid2, tempo2, 0); add_network(netuid3, tempo3, 0); assert_eq!(SubtensorModule::get_tempo(netuid0), tempo0); @@ -579,9 +1315,13 @@ fn test_sudo_test_tempo_pending_emissions_ok() { assert_eq!(SubtensorModule::get_emission_value(netuid1), 0); assert_eq!(SubtensorModule::get_emission_value(netuid2), 0); assert_eq!(SubtensorModule::get_emission_value(netuid3), 0); - let netuids: Vec = vec![ 1, 2, 3, 5 ]; - let emission: Vec = vec![ 100000000, 400000000, 200000000, 300000000]; - assert_ok!(SubtensorModule::sudo_set_emission_values(<::RuntimeOrigin>::root(), netuids, emission )); + let netuids: Vec = vec![1, 2, 3, 5]; + let emission: Vec = vec![100000000, 400000000, 200000000, 300000000]; + assert_ok!(SubtensorModule::sudo_set_emission_values( + <::RuntimeOrigin>::root(), + netuids, + emission + )); assert_eq!(SubtensorModule::get_emission_value(netuid0), 100000000); assert_eq!(SubtensorModule::get_emission_value(netuid1), 400000000); assert_eq!(SubtensorModule::get_emission_value(netuid2), 200000000); @@ -590,7 +1330,6 @@ fn test_sudo_test_tempo_pending_emissions_ok() { assert_eq!(SubtensorModule::get_pending_emission(netuid1), 0); assert_eq!(SubtensorModule::get_pending_emission(netuid2), 0); assert_eq!(SubtensorModule::get_pending_emission(netuid3), 0); - }); } @@ -603,13 +1342,17 @@ pub fn test_sudo_test_pending_emission_ok() { let netuid2: u16 = 2; let tempo2: u16 = 7; - let netuids: Vec = vec![ 1, 2 ]; - let emission: Vec = vec![ 250000000, 750000000]; + let netuids: Vec = vec![1, 2]; + let emission: Vec = vec![250000000, 750000000]; add_network(netuid1, tempo1, 0); add_network(netuid2, tempo2, 0); - assert_ok!(SubtensorModule::sudo_set_emission_values(<::RuntimeOrigin>::root(), netuids, emission )); + assert_ok!(SubtensorModule::sudo_set_emission_values( + <::RuntimeOrigin>::root(), + netuids, + emission + )); assert_eq!(SubtensorModule::get_emission_value(netuid1), 250000000); step_block(3); @@ -617,4 +1360,4 @@ pub fn test_sudo_test_pending_emission_ok() { assert_eq!(SubtensorModule::get_pending_emission(netuid1), 0); // emission drained at block 3 for tempo 5 assert_eq!(SubtensorModule::get_pending_emission(netuid2), 2250000000); // 750000000 + 750000000 + 750000000 }); -} \ No newline at end of file +} diff --git a/pallets/subtensor/tests/weights.rs b/pallets/subtensor/tests/weights.rs index d87d084a1..49eb5adc2 100644 --- a/pallets/subtensor/tests/weights.rs +++ b/pallets/subtensor/tests/weights.rs @@ -14,6 +14,7 @@ use sp_core::U256; // Test the call passes through the subtensor module. #[test] +#[cfg(not(tarpaulin))] fn test_set_weights_dispatch_info_ok() { new_test_ext().execute_with(|| { let dests = vec![1, 1]; @@ -727,4 +728,4 @@ fn test_check_len_uids_within_allowed_not_within_network_pool() { let result = SubtensorModule::check_len_uids_within_allowed(netuid, &uids); assert_eq!(expected, result, "Failed to detect incompatible uids for network"); }); -} \ No newline at end of file +} diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 2b69d0b37..c10ed1fe4 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "node-subtensor-runtime" version = "4.0.0-dev" -description = "A fresh FRAME-based Substrate node, ready for hacking." -authors = ["Substrate DevHub "] -homepage = "https://substrate.io/" +description = "Subtensor network" +authors = ["Opentensor Foundation "] +homepage = "https://opentensor.ai/" edition = "2021" license = "Unlicense" publish = false -repository = "https://github.com/substrate-developer-hub/substrate-node-subtensor/" +repository = "https://github.com/opentensor/subtensor/" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] @@ -52,6 +52,9 @@ pallet-sudo = { version = "4.0.0-dev", default-features = false, git = "https:// pallet-collective = { version = "4.0.0-dev", default-features = false, path = "../pallets/collective" } pallet-membership = {version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.39" } +# Multisig +pallet-multisig = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.39" } + # Used for the node subtensor's RPCs frame-system-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.39" } pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.39" } @@ -86,6 +89,7 @@ std = [ "pallet-transaction-payment/std", "pallet-utility/std", "pallet-sudo/std", + "pallet-multisig/std", "sp-api/std", "sp-block-builder/std", "sp-consensus-aura/std", @@ -131,4 +135,5 @@ try-runtime = [ "pallet-subtensor/try-runtime", "pallet-collective/try-runtime", "pallet-membership/try-runtime", + "pallet-multisig/try-runtime", ] diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index dc2dd7c5f..335f4f610 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -472,6 +472,24 @@ impl pallet_sudo::Config for Runtime { type RuntimeCall = RuntimeCall; } +parameter_types! { + // One storage item; key size is 32; value is size 4+4+16+32 bytes = 56 bytes. + pub const DepositBase: Balance = (1) as Balance * 2_000 * 10_000_000 + (88 as Balance) * 100 * 1_000_000; + // Additional storage item size of 32 bytes. + pub const DepositFactor: Balance = (0) as Balance * 2_000 * 10_000_000 + (32 as Balance) * 100 * 1_000_000; + pub const MaxSignatories: u32 = 100; +} + +impl pallet_multisig::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type DepositBase = DepositBase; + type DepositFactor = DepositFactor; + type MaxSignatories = MaxSignatories; + type WeightInfo = pallet_multisig::weights::SubstrateWeight; +} + // Configure the pallet subtensor. parameter_types! { pub const SubtensorInitialRho: u16 = 10; @@ -582,6 +600,7 @@ construct_runtime!( SenateMembers: pallet_membership::::{Pallet, Call, Storage, Event, Config}, Utility: pallet_utility, Sudo: pallet_sudo, + Multisig: pallet_multisig } ); diff --git a/scripts/benchmark.sh b/scripts/benchmark.sh new file mode 100644 index 000000000..a3d798655 --- /dev/null +++ b/scripts/benchmark.sh @@ -0,0 +1 @@ +./target/release/node-subtensor benchmark pallet --chain=specs/finney.json --execution=native --wasm-execution=compiled --pallet pallet-subtensor --extrinsic '*' --output benchmarking.txt \ No newline at end of file diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100644 index 000000000..b3f63171b --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1 @@ +cargo build --release --features runtime-benchmarks \ No newline at end of file diff --git a/scripts/code-coverage.sh b/scripts/code-coverage.sh new file mode 100755 index 000000000..146240d88 --- /dev/null +++ b/scripts/code-coverage.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +set -TeE + +## Find true directory this script resides in +__SOURCE__="${BASH_SOURCE[0]}" +while [[ -h "${__SOURCE__}" ]]; do + __SOURCE__="$(find "${__SOURCE__}" -type l -ls | sed -n 's@^.* -> \(.*\)@\1@p')" +done +__DIR__="$(cd -P "$(dirname "${__SOURCE__}")" && pwd)" +__G_DIR__="$(dirname "${__DIR__}")" + +## Sub-directory name under: ../target/ +_target_dir_name='tarpaulin' + +_tarpaulin_options=( + --skip-clean + --no-fail-fast + --ignore-tests + --exclude-files "${__G_DIR__}/target/*" +) + +if (( VERBOSE )); then + _tarpaulin_options+=( --verbose ) +fi + +## +# Do not fool around with contents of: ../target/debug +# - https://lib.rs/crates/cargo-tarpaulin#readme-recompilation +_tarpaulin_options+=( + --target-dir "${__G_DIR__}/target/${_target_dir_name}" +) + +## +# Allow additional CLI parameters too +_extra_arguments=("${@}") +if ((${#_extra_arguments[@]})); then + _tarpaulin_options+=( "${_extra_arguments[@]}" ) +fi + +SKIP_WASM_BUILD=1 cargo +nightly tarpaulin "${_tarpaulin_options[@]}" | + grep -vE '^\|\|\s+(target/debug)' + diff --git a/scripts/husky.sh b/scripts/husky.sh new file mode 100755 index 000000000..67af28fd2 --- /dev/null +++ b/scripts/husky.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# This script is meant to be run on Unix/Linux based systems +set -e + +echo "*** Cleaning repository..." + +cargo clean -p cargo-husky +cargo clean -p integration-tests + +echo "*** Running test to trigger husky hook insertion..." + +cargo test -p integration-tests \ No newline at end of file diff --git a/scripts/localnet.sh b/scripts/localnet.sh index 3eba8cb5e..7b88dd15b 100755 --- a/scripts/localnet.sh +++ b/scripts/localnet.sh @@ -6,6 +6,11 @@ FULL_PATH="$SPEC_PATH$CHAIN.json" +if [ ! -d "$SPEC_PATH" ]; then + echo "*** Creating directory ${SPEC_PATH}..." + mkdir $SPEC_PATH +fi + if [[ $BUILD_BINARY == "1" ]]; then echo "*** Building substrate binary..." cargo build --release --features runtime-benchmarks 1>/dev/null