Skip to content

Commit

Permalink
feat: making code more robust, fixing incentives (#44)
Browse files Browse the repository at this point in the history
* feat: local subnet burn ! missing migrations

* fixing potential problems after reaching global module limit

* fix: ensuring subnet naming safety

* feat: adding migrations + fixing subnet burn

* applying PR suggestions

* fix: clippy errors
  • Loading branch information
functor-flow authored Apr 2, 2024
1 parent 20b7220 commit 6393e23
Show file tree
Hide file tree
Showing 16 changed files with 408 additions and 139 deletions.
28 changes: 14 additions & 14 deletions pallets/subspace/src/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ impl<T: Config> Pallet<T> {
pub fn global_params() -> GlobalParams<T> {
GlobalParams {
max_name_length: Self::get_global_max_name_length(),
min_name_length: Self::get_global_min_name_length(),
max_allowed_subnets: Self::get_global_max_allowed_subnets(),
max_allowed_modules: Self::get_max_allowed_modules(),
max_registrations_per_block: Self::get_max_registrations_per_block(),
Expand Down Expand Up @@ -39,6 +40,11 @@ impl<T: Config> Pallet<T> {
// check if the name already exists
ensure!(params.max_name_length > 0, Error::<T>::InvalidMaxNameLength);

ensure!(
params.min_name_length < params.max_name_length,
Error::<T>::InvalidMinNameLenght
);

// we need to ensure that the delegation fee floor is only moven up, moving it down would
// require a storage migration
ensure!(
Expand Down Expand Up @@ -141,10 +147,6 @@ impl<T: Config> Pallet<T> {
Nominator::<T>::put(nominator)
}

pub fn get_registrations_this_interval() -> u16 {
RegistrationsThisInterval::<T>::get()
}

pub fn get_target_registrations_per_interval() -> u16 {
TargetRegistrationsPerInterval::<T>::get()
}
Expand Down Expand Up @@ -193,16 +195,6 @@ impl<T: Config> Pallet<T> {
BurnRate::<T>::put(burn_rate.min(100));
}

pub fn get_burn() -> u64 {
Burn::<T>::get()
}

pub fn set_burn(burn: u64) {
Burn::<T>::set(burn);
// announce a burn change
Self::deposit_event(Event::RegistrationBurnChanged(burn));
}

pub fn get_max_proposals() -> u64 {
MaxProposals::<T>::get()
}
Expand Down Expand Up @@ -242,6 +234,14 @@ impl<T: Config> Pallet<T> {
MaxNameLength::<T>::put(max_name_length)
}

pub fn get_global_min_name_length() -> u16 {
MinNameLength::<T>::get()
}

pub fn set_global_min_name_length(min_name_length: u16) {
MinNameLength::<T>::put(min_name_length)
}

pub fn do_update_global(origin: T::RuntimeOrigin, params: GlobalParams<T>) -> DispatchResult {
ensure_root(origin)?;

Expand Down
52 changes: 33 additions & 19 deletions pallets/subspace/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![recursion_limit = "512"]

use crate::subnet::SubnetChangeset;
use frame_system::{self as system, ensure_signed};
pub use pallet::*;

Expand Down Expand Up @@ -63,7 +64,7 @@ pub mod pallet {
use sp_arithmetic::per_things::Percent;
pub use sp_std::{vec, vec::Vec};

const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
const STORAGE_VERSION: StorageVersion = StorageVersion::new(2);

#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
Expand Down Expand Up @@ -167,6 +168,15 @@ pub mod pallet {
pub(super) type MaxNameLength<T: Config> =
StorageValue<_, u16, ValueQuery, DefaultMaxNameLength<T>>;

#[pallet::type_value]
pub fn DefaultMinNameLength<T: Config>() -> u16 {
2
}

#[pallet::storage]
pub(super) type MinNameLength<T: Config> =
StorageValue<_, u16, ValueQuery, DefaultMinNameLength<T>>;

#[pallet::type_value]
pub fn DefaultMaxAllowedSubnets<T: Config>() -> u16 {
256
Expand All @@ -175,22 +185,14 @@ pub mod pallet {
pub(super) type MaxAllowedSubnets<T: Config> =
StorageValue<_, u16, ValueQuery, DefaultMaxAllowedSubnets<T>>;

#[pallet::type_value]
pub fn DefaultRegistrationsThisInterval<T: Config>() -> u16 {
0
}

#[pallet::storage] // --- ITEM ( registrations_this_interval )
#[pallet::storage]
// --- MAP (netuid) --> registrations_this_interval
pub(super) type RegistrationsThisInterval<T: Config> =
StorageValue<_, u16, ValueQuery, DefaultRegistrationsThisInterval<T>>;
StorageMap<_, Identity, u16, u16, ValueQuery>;

#[pallet::type_value]
pub fn DefaultBurn<T: Config>() -> u64 {
0
}

#[pallet::storage] // --- ITEM ( burn )
pub(super) type Burn<T: Config> = StorageValue<_, u64, ValueQuery, DefaultBurn<T>>;
#[pallet::storage]
// --- MAP (netuid) --> burn
pub(super) type Burn<T: Config> = StorageMap<_, Identity, u16, u64, ValueQuery>;

#[pallet::type_value]
pub fn DefaultMaxAllowedModules<T: Config>() -> u16 {
Expand Down Expand Up @@ -278,6 +280,7 @@ pub mod pallet {
pub burn_rate: u16,
// max
pub max_name_length: u16, // max length of a network name
pub min_name_length: u16, // min length of a network name
pub max_allowed_subnets: u16, // max number of subnets allowed
pub max_allowed_modules: u16, // max number of modules allowed per subnet
pub max_registrations_per_block: u16, // max number of registrations per block
Expand Down Expand Up @@ -353,6 +356,7 @@ pub mod pallet {
target_registrations_per_interval: DefaultTargetRegistrationsPerInterval::<T>::get(),
target_registrations_interval: DefaultTargetRegistrationsInterval::<T>::get(),
max_name_length: DefaultMaxNameLength::<T>::get(),
min_name_length: DefaultMinNameLength::<T>::get(),
max_proposals: DefaultMaxProposals::<T>::get(),
min_burn: DefaultMinBurn::<T>::get(),
max_burn: DefaultMaxBurn::<T>::get(),
Expand Down Expand Up @@ -879,6 +883,7 @@ pub mod pallet {
TxRateLimitSet(u64), // --- Event created when setting the transaction rate limit.
UnitEmissionSet(u64), // --- Event created when setting the unit emission
MaxNameLengthSet(u16), // --- Event created when setting the maximum network name length
MinNameLenghtSet(u16), // --- Event created when setting the minimum network name length
MaxAllowedSubnetsSet(u16), // --- Event created when setting the maximum allowed subnets
MaxAllowedModulesSet(u16), // --- Event created when setting the maximum allowed modules
MaxRegistrationsPerBlockSet(u16), // --- Event created when we set max registrations
Expand Down Expand Up @@ -947,10 +952,13 @@ pub mod pallet {
* transactions. */
InvalidMaxAllowedUids, /* --- Thrown when the user tries to set max allowed uids to a
* value less than the current number of registered uids. */
NetuidDoesNotExist,
SubnetNameAlreadyExists,
SubnetNameTooShort,
SubnetNameTooLong,
InvalidSubnetName,
BalanceNotAdded,
StakeNotRemoved,
SubnetNameNotExists,
KeyAlreadyRegistered, //
EmptyKeys,
NotNominator, /* --- Thrown when the user tries to set the nominator and is not the
Expand Down Expand Up @@ -984,6 +992,7 @@ pub mod pallet {
InvalidMinDelegationFee,

InvalidMaxNameLength,
InvalidMinNameLenght,
InvalidMaxAllowedSubnets,
InvalidMaxAllowedModules,
InvalidMaxRegistrationsPerBlock,
Expand All @@ -1000,6 +1009,7 @@ pub mod pallet {
// Modules
/// The module name is too long.
ModuleNameTooLong,
ModuleNameTooShort,
/// The module name is invalid. It has to be a UTF-8 encoded string.
InvalidModuleName,
/// The address is too long.
Expand Down Expand Up @@ -1061,7 +1071,7 @@ pub mod pallet {

let default_params = self::Pallet::<T>::default_subnet_params();

let params = SubnetParams {
let params: SubnetParams<T> = SubnetParams {
name: subnet.0.clone(),
tempo: subnet.1,
immunity_period: subnet.2,
Expand All @@ -1080,7 +1090,9 @@ pub mod pallet {
max_weight_age: default_params.max_weight_age,
};

self::Pallet::<T>::add_subnet(params, None);
let changeset: SubnetChangeset<T> =
SubnetChangeset::new(&params.name, &params.founder, params.clone());
self::Pallet::<T>::add_subnet(changeset, Some(netuid));

for (uid_usize, (key, name, address, weights)) in
self.modules[subnet_idx].iter().enumerate()
Expand Down Expand Up @@ -1378,8 +1390,10 @@ pub mod pallet {
// Check if subnet parameters are valid
Self::check_subnet_params(&params)?;

let subnet_set =
SubnetChangeset::update(&params.name, &params.founder, netuid, params.clone());
// if so update them
Self::do_update_subnet(origin, netuid, params)
Self::do_update_subnet(origin, netuid, subnet_set)
}

#[pallet::weight((Weight::zero(), DispatchClass::Normal, Pays::No))]
Expand Down
34 changes: 34 additions & 0 deletions pallets/subspace/src/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,37 @@ pub mod v1 {
}
}
}

pub mod v2 {
use super::*;

pub struct MigrateToV2<T>(sp_std::marker::PhantomData<T>);

impl<T: Config> OnRuntimeUpgrade for MigrateToV2<T> {
fn on_runtime_upgrade() -> Weight {
let on_chain_version = StorageVersion::get::<Pallet<T>>();

// Migrate Burn to v2
if on_chain_version == 1 {
// Here we will just use the lower bound of the burn
let old_burn = Pallet::<T>::global_params().min_burn;

// Find the highest netuid from the subnetnames
let largest_netuid = SubnetNames::<T>::iter_keys().max().unwrap_or(0);
// Iterate through all netuids and insert the old burn (minimum) value for each
// this is important as we don't want free registrations right after the runtime
// udpate
for netuid in 0..=largest_netuid {
Burn::<T>::insert(netuid, old_burn);
}

StorageVersion::new(2).put::<Pallet<T>>();
log::info!("Migrated Burn to v2");
T::DbWeight::get().writes(largest_netuid as u64)
} else {
log::info!("Burn already updated");
Weight::zero()
}
}
}
}
12 changes: 11 additions & 1 deletion pallets/subspace/src/module.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use super::*;
use frame_support::pallet_prelude::{Decode, DispatchResult, Encode};
use frame_support::{
pallet_prelude::{Decode, DispatchResult, Encode},
IterableStorageDoubleMap,
};

extern crate alloc;
use alloc::vec::Vec;
Expand Down Expand Up @@ -58,10 +61,12 @@ impl ModuleChangeset {
uid: u16,
) -> Result<(), sp_runtime::DispatchError> {
let max = MaxNameLength::<T>::get() as usize;
let min = MinNameLength::<T>::get() as usize;

if let Some(name) = self.name {
ensure!(!name.is_empty(), Error::<T>::InvalidModuleName);
ensure!(name.len() <= max, Error::<T>::ModuleNameTooLong);
ensure!(name.len() >= min, Error::<T>::ModuleNameTooShort);
core::str::from_utf8(&name).map_err(|_| Error::<T>::InvalidModuleName)?;
ensure!(
!Pallet::<T>::does_module_name_exist(netuid, &name),
Expand Down Expand Up @@ -106,6 +111,11 @@ impl<T: Config> Pallet<T> {
Ok(())
}

pub fn does_module_name_exist(netuid: u16, name: &[u8]) -> bool {
<Name<T> as IterableStorageDoubleMap<u16, u16, Vec<u8>>>::iter_prefix(netuid)
.any(|(_, existing)| existing == name)
}

pub fn module_params(netuid: u16, key: &T::AccountId) -> ModuleParams<T> {
let uid = Uids::<T>::try_get(netuid, key).expect("module key does not exist");

Expand Down
Loading

0 comments on commit 6393e23

Please sign in to comment.