diff --git a/CHANGELOG.md b/CHANGELOG.md index eac9c038..02d752d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +spec version `124` + +enforcing whitelist on genral subnet, lowering the min weights to 1 + spec version `123` fix metadata removal upon module registration diff --git a/Cargo.lock b/Cargo.lock index c1c8f337..20a08533 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4818,7 +4818,7 @@ dependencies = [ [[package]] name = "node-subspace-runtime" -version = "1.8.4" +version = "1.8.5" dependencies = [ "fp-account", "fp-evm", @@ -5410,7 +5410,7 @@ dependencies = [ [[package]] name = "pallet-subspace" -version = "1.8.4" +version = "1.8.5" dependencies = [ "frame-benchmarking", "frame-support", diff --git a/pallets/subspace/Cargo.toml b/pallets/subspace/Cargo.toml index cddccc1b..175ef99a 100644 --- a/pallets/subspace/Cargo.toml +++ b/pallets/subspace/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-subspace" -version = "1.8.4" +version = "1.8.5" description = "FRAME pallet for runtime logic of Subspace Blockchain." authors = ["Commune Community"] homepage = "https://commune.com" diff --git a/pallets/subspace/src/lib.rs b/pallets/subspace/src/lib.rs index 6f3620ef..79178d13 100644 --- a/pallets/subspace/src/lib.rs +++ b/pallets/subspace/src/lib.rs @@ -65,7 +65,7 @@ pub mod pallet { use sp_core::{ConstU16, ConstU64, ConstU8}; pub use sp_std::{vec, vec::Vec}; - const STORAGE_VERSION: StorageVersion = StorageVersion::new(13); + const STORAGE_VERSION: StorageVersion = StorageVersion::new(14); #[pallet::pallet] #[pallet::storage_version(STORAGE_VERSION)] @@ -102,6 +102,8 @@ pub mod pallet { /// The weight information of this pallet. type WeightInfo: WeightInfo; + /// Should enforce legit whitelist on general subnet + type EnforceWhitelist: Get; } pub type BalanceOf = @@ -706,6 +708,8 @@ pub mod pallet { InvalidMinValidatorStake, /// The maximum allowed validators value is invalid, minimum is 10. InvalidMaxAllowedValidators, + /// Uid is not in general subnet legit whitelist + UidNotWhitelisted, } // --------------------------------- @@ -1047,21 +1051,4 @@ impl Pallet { pub fn get_delegated_stake(staked: &T::AccountId) -> u64 { StakeFrom::::iter_prefix_values(staked).sum() } - - // --- Returns the transaction priority for setting weights. - pub fn get_priority_set_weights(key: &T::AccountId, netuid: u16) -> u64 { - if let Some(uid) = Uids::::get(netuid, key) { - let last_update = Self::get_last_update_for_uid(netuid, uid); - Self::get_current_block_number().saturating_add(last_update) - } else { - 0 - } - } - // --- Returns the transaction priority for setting weights. - pub fn get_priority_stake(key: &T::AccountId, netuid: u16) -> u64 { - if Uids::::contains_key(netuid, key) { - return Self::get_delegated_stake(key); - } - 0 - } } diff --git a/pallets/subspace/src/migrations.rs b/pallets/subspace/src/migrations.rs index e9720766..ea296df0 100644 --- a/pallets/subspace/src/migrations.rs +++ b/pallets/subspace/src/migrations.rs @@ -1,6 +1,7 @@ use super::*; use frame_support::traits::{StorageInstance, StorageVersion}; +use pallet_subnet_emission_api::SubnetConsensus; impl StorageInstance for Pallet { fn pallet_prefix() -> &'static str { @@ -33,6 +34,29 @@ pub mod v14 { log::info!("Storage v14 already updated"); return Weight::zero(); } + + let general_subnet_netuid = 2; + let onchain_netuid = T::get_consensus_netuid(SubnetConsensus::Linear).unwrap_or(2); + + // return early if there is not a match + if general_subnet_netuid != onchain_netuid { + log::info!("General subnet netuid does not match onchain netuid"); + return Weight::zero(); + } + + // Clear all of the current weights on subnet 2 + let _ = Weights::::clear_prefix(general_subnet_netuid, u32::MAX, None); + log::info!("Cleared all weights for subnet 2"); + + // Make sure we allow just one weight for the general subnet + MinAllowedWeights::::set(general_subnet_netuid, 1); + log::info!("Set min allowed weights for subnet 2"); + + // Make sure max allowed weights are same as max allowed uids + let max_allowed_uids = MaxAllowedUids::::get(general_subnet_netuid); + MaxAllowedWeights::::set(general_subnet_netuid, max_allowed_uids); + log::info!("Set max allowed weights for subnet 2"); + log::info!("Migrating storage to v14"); StorageVersion::new(14).put::>(); Weight::zero() diff --git a/pallets/subspace/src/set_weights.rs b/pallets/subspace/src/set_weights.rs index 8a786b83..cb8458b7 100644 --- a/pallets/subspace/src/set_weights.rs +++ b/pallets/subspace/src/set_weights.rs @@ -1,9 +1,10 @@ use super::*; use frame_support::pallet_prelude::DispatchResult; use pallet_subnet_emission_api::SubnetConsensus; +use sp_core::Get; impl Pallet { - /// Sets weights for a node in a specific subnet. + /// Sets weights for a node in a specific subnet. /// # Arguments /// /// * `origin` - The origin of the call, must be a signed account. @@ -60,6 +61,7 @@ impl Pallet { Self::validate_input(uid, &uids, &values, netuid)?; Self::handle_rate_limiting(uid, netuid, &key)?; Self::validate_stake(&key, uids.len())?; + Self::check_whitelisted(netuid, &uids)?; Self::finalize_weights(netuid, uid, &uids, &values)?; Self::remove_rootnet_delegation(netuid, key); Ok(()) @@ -106,6 +108,33 @@ impl Pallet { Ok(()) } + fn check_whitelisted(netuid: u16, uids: &[u16]) -> DispatchResult { + // Only perform the whitelist check if EnforceWhitelist is true + if T::EnforceWhitelist::get() { + let consensus_netuid = T::get_consensus_netuid(SubnetConsensus::Linear); + + // Early return if consensus_netuid is None or doesn't match the given netuid + if consensus_netuid.map_or(true, |cn| cn != netuid) { + return Ok(()); + } + + let whitelisted = T::whitelisted_keys(); + + uids.iter().try_for_each(|&uid| { + let key = Self::get_key_for_uid(netuid, uid).ok_or(Error::::InvalidUid)?; + + if !whitelisted.contains(&key) { + return Err(Error::::UidNotWhitelisted.into()); + } + + Ok(()) + }) + } else { + // If EnforceWhitelist is false, always return Ok + Ok(()) + } + } + fn finalize_weights(netuid: u16, uid: u16, uids: &[u16], values: &[u16]) -> DispatchResult { let normalized_values = Self::normalize_weights(values); let zipped_weights: Vec<(u16, u16)> = uids.iter().copied().zip(normalized_values).collect(); @@ -116,17 +145,15 @@ impl Pallet { Self::deposit_event(Event::WeightsSet(netuid, uid)); Ok(()) } - + // ---------- + // Utils + // ---------- fn remove_rootnet_delegation(netuid: u16, key: T::AccountId) { if Self::is_rootnet(netuid) { RootnetControlDelegation::::remove(key); } } - // ---------- - // Utils - // ---------- - fn contains_duplicates(items: &[u16]) -> bool { let mut seen = sp_std::collections::btree_set::BTreeSet::new(); items.iter().any(|item| !seen.insert(item)) diff --git a/pallets/subspace/src/subnet.rs b/pallets/subspace/src/subnet.rs index b85b3937..d3a85f87 100644 --- a/pallets/subspace/src/subnet.rs +++ b/pallets/subspace/src/subnet.rs @@ -410,11 +410,13 @@ impl Pallet { pub fn get_netuid_for_name(name: &[u8]) -> Option { SubnetNames::::iter().find(|(_, n)| n == name).map(|(id, _)| id) } - // Returs the key under the network uid as a Result. Ok if the uid is taken. + /// Returs the key under the network uid as a Result. Ok if the uid is taken. + #[inline] pub fn get_key_for_uid(netuid: u16, module_uid: u16) -> Option { Keys::::get(netuid, module_uid) } - // Returns the uid of the key in the network as a Result. Ok if the key has a slot. + /// Returns the uid of the key in the network as a Result. Ok if the key has a slot. + #[inline] pub fn get_uid_for_key(netuid: u16, key: &T::AccountId) -> Option { Uids::::get(netuid, key) } diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 658d496b..b4015784 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "node-subspace-runtime" -version = "1.8.4" +version = "1.8.5" description = "A Substrate node for commune-ai" authors = ["Commune Community"] homepage = "https://substrate.io/" diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 7863202b..c70760a3 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -162,7 +162,7 @@ pub mod opaque { } } -pub type Migrations = pallet_governance::migrations::v2::MigrateToV2; +pub type Migrations = pallet_subspace::migrations::v14::MigrateToV14; // To learn more about runtime versioning, see: // https://docs.substrate.io/main-docs/build/upgrade#runtime-versioning @@ -176,7 +176,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 123, + spec_version: 124, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -415,6 +415,7 @@ impl pallet_subspace::Config for Runtime { type DefaultSubnetMinBurn = ConstU64<2_000_000_000_000>; type WeightInfo = pallet_subspace::weights::SubstrateWeight; type DefaultMinValidatorStake = ConstU64<50_000_000_000_000>; + type EnforceWhitelist = ConstBool; } impl pallet_governance::Config for Runtime { diff --git a/tests/src/mock.rs b/tests/src/mock.rs index 118186b8..41d74919 100644 --- a/tests/src/mock.rs +++ b/tests/src/mock.rs @@ -2,7 +2,7 @@ use frame_support::{ ensure, parameter_types, - traits::{Currency, Everything, Get, Hooks}, + traits::{ConstBool, Currency, Everything, Get, Hooks}, PalletId, }; use frame_system as system; @@ -121,6 +121,7 @@ impl pallet_subspace::Config for Test { type DefaultSubnetMinBurn = SubnetMinBurnConfig; type DefaultMinValidatorStake = MinValidatorStake; type PalletId = SubspacePalletId; + type EnforceWhitelist = ConstBool; } impl GovernanceApi<::AccountId> for Test {