Skip to content

Commit

Permalink
feat: making s0 applications more robust (#62)
Browse files Browse the repository at this point in the history
* feat: making s0 applications more robust

* fix: correct balance fix

* fix: safer migration

* fixed migration

* fix: `paying_for` appication
  • Loading branch information
functor-flow authored May 1, 2024
1 parent a51636b commit 1c08703
Show file tree
Hide file tree
Showing 8 changed files with 304 additions and 64 deletions.
12 changes: 6 additions & 6 deletions pallets/subspace/src/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ impl<T: Config> Pallet<T> {
max_allowed_subnets: Self::get_global_max_allowed_subnets(),
max_allowed_modules: Self::get_max_allowed_modules(),
unit_emission: Self::get_unit_emission(),
nominator: Self::get_nominator(),
curator: Self::get_curator(),
floor_delegation_fee: Self::get_floor_delegation_fee(),
// burn & registrations
max_registrations_per_block: Self::get_max_registrations_per_block(),
Expand Down Expand Up @@ -150,7 +150,7 @@ impl<T: Config> Pallet<T> {
Self::set_adjustment_alpha(params.adjustment_alpha);
Self::set_min_stake_global(params.min_stake);
Self::set_floor_delegation_fee(params.floor_delegation_fee);
Self::set_nominator(params.nominator);
Self::set_curator(params.curator);

// weights
Self::set_max_allowed_weights_global(params.max_allowed_weights);
Expand All @@ -162,12 +162,12 @@ impl<T: Config> Pallet<T> {
Self::set_proposal_participation_threshold(params.proposal_participation_threshold);
}

pub fn get_nominator() -> T::AccountId {
Nominator::<T>::get()
pub fn get_curator() -> T::AccountId {
Curator::<T>::get()
}

pub fn set_nominator(nominator: T::AccountId) {
Nominator::<T>::put(nominator)
pub fn set_curator(curator: T::AccountId) {
Curator::<T>::put(curator)
}

pub fn get_target_registrations_per_interval() -> u16 {
Expand Down
48 changes: 37 additions & 11 deletions pallets/subspace/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,17 @@ pub mod pallet {
clippy::type_complexity
)]

use self::voting::{Proposal, VoteMode};
use self::voting::{CuratorApplication, Proposal, VoteMode};

use super::*;
use frame_support::{pallet_prelude::*, traits::Currency};
use frame_support::{pallet_prelude::*, traits::Currency, Identity};
use frame_system::pallet_prelude::*;

use module::ModuleChangeset;
use sp_arithmetic::per_things::Percent;
pub use sp_std::{vec, vec::Vec};

const STORAGE_VERSION: StorageVersion = StorageVersion::new(4);
const STORAGE_VERSION: StorageVersion = StorageVersion::new(5);

#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
Expand Down Expand Up @@ -312,7 +312,7 @@ pub mod pallet {
* registration interval */
pub adjustment_alpha: u64, // adjustment alpha
pub unit_emission: u64, // emission per block
pub nominator: T::AccountId,
pub curator: T::AccountId,

pub subnet_stake_threshold: Percent,

Expand Down Expand Up @@ -353,7 +353,7 @@ pub mod pallet {
)
.field("adjustment_alpha", &self.adjustment_alpha)
.field("unit_emission", &self.unit_emission)
.field("nominator", &self.nominator)
.field("curator", &self.curator)
.finish()
}
}
Expand Down Expand Up @@ -500,12 +500,12 @@ pub mod pallet {
// =======================================

#[pallet::type_value]
pub fn DefaultNominator<T: Config>() -> T::AccountId {
pub fn DefaultCurator<T: Config>() -> T::AccountId {
T::AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()).unwrap()
}

#[pallet::storage]
pub type Nominator<T: Config> = StorageValue<_, T::AccountId, ValueQuery, DefaultNominator<T>>;
pub type Curator<T: Config> = StorageValue<_, T::AccountId, ValueQuery, DefaultCurator<T>>;

// VOTING MODE
#[pallet::type_value]
Expand Down Expand Up @@ -710,6 +710,7 @@ pub mod pallet {

//voting
ProposalCreated(u64), // id of the proposal
ApplicationCreated(u64), // id of the application
ProposalVoted(u64, T::AccountId, bool), // (id, voter, vote)
ProposalVoteUnregistered(u64, T::AccountId), // (id, voter)
GlobalParamsUpdated(GlobalParams<T>), /* --- Event created when global
Expand Down Expand Up @@ -782,8 +783,9 @@ pub mod pallet {
KeyAlreadyRegistered,
EmptyKeys,
TooManyKeys,
NotNominator, /* --- Thrown when the user tries to set the nominator and is not the
* nominator */
NotCurator, /* --- Thrown when the user tries to set the curator and is not the
* curator */
ApplicationNotFound,
AlreadyWhitelisted, /* --- Thrown when the user tries to whitelist an account that is
* already whitelisted. */
NotWhitelisted, /* --- Thrown when the user tries to remove an account from the
Expand Down Expand Up @@ -862,7 +864,13 @@ pub mod pallet {
InvalidProposalCustomData,
ProposalCustomDataTooSmall,
ProposalCustomDataTooLarge,
// DAO / Governance
ApplicationTooSmall,
ApplicationTooLarge,
ApplicationNotPending,
InvalidApplication,
NotEnoughBalanceToPropose,
NotEnoughtBalnceToApply,

// Other
InvalidMaxWeightAge,
Expand Down Expand Up @@ -973,6 +981,9 @@ pub mod pallet {
#[pallet::storage]
pub type Proposals<T: Config> = StorageMap<_, Identity, u64, Proposal<T>>;

#[pallet::storage]
pub type CuratorApplications<T: Config> = StorageMap<_, Identity, u64, CuratorApplication<T>>;

// ================
// ==== Hooks =====
// ================
Expand Down Expand Up @@ -1190,7 +1201,7 @@ pub mod pallet {
* registration interval */
adjustment_alpha: u64, // adjustment alpha
unit_emission: u64, // emission per block
nominator: T::AccountId, // subnet 0 dao multisig
curator: T::AccountId, // subnet 0 dao multisig
subnet_stake_threshold: Percent, // stake needed to start subnet emission
proposal_cost: u64, /*amount of $COMAI to create a proposal
* returned if proposal gets accepted */
Expand All @@ -1216,7 +1227,7 @@ pub mod pallet {
params.target_registrations_interval = target_registrations_interval;
params.adjustment_alpha = adjustment_alpha;
params.unit_emission = unit_emission;
params.nominator = nominator;
params.curator = curator;
params.subnet_stake_threshold = subnet_stake_threshold;
params.proposal_cost = proposal_cost;
params.proposal_expiration = proposal_expiration;
Expand Down Expand Up @@ -1269,6 +1280,21 @@ pub mod pallet {
Self::do_add_custom_proposal(origin, data)
}

// Subnet 0 DAO
#[pallet::weight((Weight::zero(), DispatchClass::Normal, Pays::No))]
pub fn add_dao_application(
origin: OriginFor<T>,
application_key: T::AccountId,
data: Vec<u8>,
) -> DispatchResult {
Self::do_add_dao_application(origin, application_key, data)
}

#[pallet::weight((Weight::zero(), DispatchClass::Normal, Pays::No))]
pub fn refuse_dao_application(origin: OriginFor<T>, id: u64) -> DispatchResult {
Self::do_refuse_dao_application(origin, id)
}

#[pallet::weight((Weight::zero(), DispatchClass::Normal, Pays::No))]
pub fn add_custom_subnet_proposal(
origin: OriginFor<T>,
Expand Down
62 changes: 50 additions & 12 deletions pallets/subspace/src/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ impl<T: Config> StorageInstance for Pallet<T> {
const STORAGE_PREFIX: &'static str = "Subspace";
}

use sp_core::crypto::Ss58Codec;
use sp_runtime::AccountId32;

pub fn ss58_to_account_id<T: Config>(
ss58_address: &str,
) -> Result<T::AccountId, sp_core::crypto::PublicError> {
let account_id = AccountId32::from_ss58check(ss58_address)?;
let account_id_vec = account_id.encode();
Ok(T::AccountId::decode(&mut &account_id_vec[..]).unwrap())
}

// Delegation update, migrations.
pub mod v1 {
use super::*;
Expand Down Expand Up @@ -141,19 +152,9 @@ pub mod v3 {
use super::*;

use crate::voting::{ProposalStatus, VoteMode};
use sp_core::crypto::Ss58Codec;
use sp_runtime::AccountId32;

const SUBNET_CEILING: u16 = 42;

fn ss58_to_account_id<T: Config>(
ss58_address: &str,
) -> Result<T::AccountId, sp_core::crypto::PublicError> {
let account_id = AccountId32::from_ss58check(ss58_address)?;
let account_id_vec = account_id.encode();
Ok(T::AccountId::decode(&mut &account_id_vec[..]).unwrap())
}

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

impl<T: Config> OnRuntimeUpgrade for MigrateToV3<T> {
Expand Down Expand Up @@ -321,8 +322,8 @@ pub mod v3 {
let dao_bot = "5GnXkyoCGVHD7PL3ZRGM2oELpUhDG6HFqAHZT3hHTmFD8CZF";
let dao_bot_account_id = ss58_to_account_id::<T>(dao_bot).unwrap();

Nominator::<T>::put(dao_bot_account_id); // Old empty
log::info!("Nominator migrated");
Curator::<T>::put(dao_bot_account_id); // Old empty
log::info!("Curator migrated");

// Finally update
MaxAllowedSubnets::<T>::put(SUBNET_CEILING); // Old 256
Expand Down Expand Up @@ -387,3 +388,40 @@ pub mod v4 {
}
}
}

pub mod v5 {
use super::*;

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

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

if on_chain_version == 4 {
let dao_bot = "5GnXkyoCGVHD7PL3ZRGM2oELpUhDG6HFqAHZT3hHTmFD8CZF";
let dao_bot_account_id = match ss58_to_account_id::<T>(dao_bot) {
Ok(account_id) => Some(account_id),
Err(_) => {
log::warn!("Failed to convert SS58 to account ID");
None
}
};

if let Some(account_id) = dao_bot_account_id {
Curator::<T>::put(account_id);
} else {
log::warn!("Skipping storage update due to missing account ID");
}

StorageVersion::new(5).put::<Pallet<T>>();
log::info!("Migrated v5");

T::DbWeight::get().writes(1)
} else {
log::info!("Storage v4 already updated");
Weight::zero()
}
}
}
}
17 changes: 13 additions & 4 deletions pallets/subspace/src/registration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@ impl<T: Config> Pallet<T> {
// --- 1. Check that the caller has signed the transaction.
let key = ensure_signed(origin)?;

// --- 2. Ensure that the key is the nominator multisig.
ensure!(Self::get_nominator() == key, Error::<T>::NotNominator);
// --- 2. Ensure that the key is the curator multisig.
ensure!(Self::get_curator() == key, Error::<T>::NotCurator);

// --- 2.1 Make sure the key application was submitted
let application_exists = CuratorApplications::<T>::iter()
.any(|(_, application)| application.user_id == module_key);

ensure!(application_exists, Error::<T>::ApplicationNotFound);

// --- 3. Ensure that the module_key is not already in the whitelist.
ensure!(
Expand All @@ -34,6 +40,9 @@ impl<T: Config> Pallet<T> {
// --- 4. Insert the module_key into the whitelist.
Self::insert_to_whitelist(module_key.clone(), recommended_weight);

// execute the application
Self::execute_application(&module_key).unwrap();

// -- deposit event
Self::deposit_event(Event::WhitelistModuleAdded(module_key));

Expand All @@ -48,8 +57,8 @@ impl<T: Config> Pallet<T> {
// --- 1. Check that the caller has signed the transaction.
let key = ensure_signed(origin)?;

// --- 2. Ensure that the key is the nominator multisig.
ensure!(Self::get_nominator() == key, Error::<T>::NotNominator);
// --- 2. Ensure that the key is the curator multisig.
ensure!(Self::get_curator() == key, Error::<T>::NotCurator);

// --- 3. Ensure that the module_key is in the whitelist.
ensure!(
Expand Down
Loading

0 comments on commit 1c08703

Please sign in to comment.