Skip to content

Commit

Permalink
Add fellowship pallet (#247)
Browse files Browse the repository at this point in the history
* add to runtime with dummy weights

* add genesis config

* add fellowship migration, add migration to runtime

* fix migration

* fix accountid trait bounds

* fix dependancy issue: #252

* add fellowship to runtime benchmarks

* generate fellowship weights

* remove test test

* fmt

* run gcp on all pushes

* restore

* remove genesis, add permissions, FellowshipPermissions trait

* permissions impl, mock impl

* fix tests

* organise tests, add permissions tests

* add new config to runtime

* fmt

* post upgrade test fix version err

* sanity

* sanity v2

* add context

* fmt
  • Loading branch information
f-gate authored Oct 31, 2023
1 parent c99d337 commit 9353c93
Show file tree
Hide file tree
Showing 20 changed files with 661 additions and 166 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pallets/deposits/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ std = [
"pallet-xcm/std",
"common-runtime/std"
]
runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks", "pallet-xcm/runtime-benchmarks"]
runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "common-runtime/runtime-benchmarks"]
try-runtime = [
"frame-support/try-runtime",
"frame-system/try-runtime",
Expand Down
1 change: 1 addition & 0 deletions pallets/fellowship/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false, features = [
"derive",
] }
hex-literal = {version = "0.3.4", default-features = false}
serde = { version = "1.0.101", features = ["derive"] }
scale-info = { version = "2.1.1", default-features = false, features = ["derive"] }
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.43", default-features = false, optional = true }
Expand Down
1 change: 0 additions & 1 deletion pallets/fellowship/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use orml_traits::MultiCurrency;
use sp_runtime::SaturatedConversion;

#[benchmarks( where <T as frame_system::Config>::AccountId: AsRef<[u8]>, crate::Event::<T>: Into<<T as frame_system::Config>::RuntimeEvent>)]
#[benchmarks]
mod benchmarks {
use super::*;
#[benchmark]
Expand Down
32 changes: 18 additions & 14 deletions pallets/fellowship/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ use sp_runtime::{
traits::{BadOrigin, Convert},
DispatchError, Percent,
};
use sp_std::vec::Vec;

use sp_std::{vec, vec::Vec};
/// Ensure that a account is of a given role.
/// Used in other pallets like an ensure origin.
pub struct EnsureFellowshipRole<T>(T);
Expand Down Expand Up @@ -47,18 +46,6 @@ impl<T: Config> MaybeConvert<&AccountIdOf<T>, VetterIdOf<T>> for Pallet<T> {
}
}

pub struct RoleToPercentFee;
impl Convert<crate::Role, Percent> for RoleToPercentFee {
fn convert(role: Role) -> Percent {
match role {
Role::Vetter => Percent::from_percent(50u8),
Role::Freelancer => Percent::from_percent(50u8),
Role::BusinessDev => Percent::from_percent(50u8),
Role::Approver => Percent::from_percent(50u8),
}
}
}

impl<T: Config> Pallet<T> {
/// Try take the membership deposit from who
/// If the deposit was taken, this will return true, else false.
Expand All @@ -77,3 +64,20 @@ impl<T: Config> Pallet<T> {
false
}
}

pub struct VetterAndFreelancerAllPermissions;
impl crate::traits::FellowshipPermissions<crate::Role, crate::Permission>
for VetterAndFreelancerAllPermissions
{
fn has_permission(role: Role, permission: Permission) -> bool {
Self::get_permissions(role).contains(&permission)
}

// Force match on all so we dont forget to add permissions when we add new roles.
fn get_permissions(role: Role) -> Vec<Permission> {
match role {
Role::Freelancer => vec![Permission::AddToShortlist, Permission::RemoveFromShortlist],
Role::Vetter => vec![Permission::AddToShortlist, Permission::RemoveFromShortlist],
}
}
}
43 changes: 24 additions & 19 deletions pallets/fellowship/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ mod mock;
#[cfg(test)]
mod tests;

pub mod migration;

#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;

Expand All @@ -33,7 +35,7 @@ pub mod pallet {

use crate::impls::EnsureFellowshipRole;
use crate::traits::WeightInfoT;
use crate::traits::{EnsureRole, FellowshipHandle};
use crate::traits::{EnsureRole, FellowshipHandle, FellowshipPermissions};

pub(crate) type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
pub(crate) type VetterIdOf<T> = AccountIdOf<T>;
Expand All @@ -48,9 +50,13 @@ pub mod pallet {
<T as Config>::MaxCandidatesPerShortlist,
>;

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

#[pallet::pallet]
#[pallet::storage_version(STORAGE_VERSION)]
pub struct Pallet<T>(_);

// TODO: Use permissions instead of ensure role, leave ensure role in place
#[pallet::config]
pub trait Config: frame_system::Config {
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
Expand All @@ -68,6 +74,8 @@ pub mod pallet {
type DepositCurrencyId: Get<CurrencyId>;
/// Currently just send all slash deposits to a single account.
type SlashAccount: Get<AccountIdOf<Self>>;
/// The permissions of a given role.
type Permissions: FellowshipPermissions<Role, Permission>;
/// The weights generated by the benchmarks.
type WeightInfo: WeightInfoT;
}
Expand Down Expand Up @@ -126,8 +134,6 @@ pub mod pallet {
RoleNotFound,
/// This account is not a fellow.
NotAFellow,
/// This account is not a Vetter.
NotAVetter,
/// Already a fellow.
AlreadyAFellow,
/// The candidate must have the deposit amount to be put on the shortlst.
Expand All @@ -138,6 +144,8 @@ pub mod pallet {
TooManyCandidates,
/// The fellowship deposit has could not be found, contact development.
FellowshipReserveDisapeared,
/// The role of the caller lacks the necessary permissions to run this.
RoleLacksPermission,
}

#[pallet::hooks]
Expand Down Expand Up @@ -225,14 +233,10 @@ pub mod pallet {
rank: Rank,
) -> DispatchResult {
let who = ensure_signed(origin)?;
let (caller_role, _) = Roles::<T>::get(&who).ok_or(Error::<T>::NotAFellow)?;
ensure!(
EnsureFellowshipRole::<T>::ensure_role_in(
&who,
vec![Role::Freelancer, Role::Vetter],
None
)
.is_ok(),
Error::<T>::NotAVetter
T::Permissions::has_permission(caller_role, Permission::AddToShortlist),
Error::<T>::RoleLacksPermission
);
ensure!(
Roles::<T>::get(&candidate).is_none(),
Expand Down Expand Up @@ -270,14 +274,10 @@ pub mod pallet {
candidate: AccountIdOf<T>,
) -> DispatchResult {
let who = ensure_signed(origin)?;
let (caller_role, _) = Roles::<T>::get(&who).ok_or(Error::<T>::NotAFellow)?;
ensure!(
EnsureFellowshipRole::<T>::ensure_role_in(
&who,
vec![Role::Freelancer, Role::Vetter],
None
)
.is_ok(),
Error::<T>::NotAVetter
T::Permissions::has_permission(caller_role, Permission::RemoveFromShortlist),
Error::<T>::RoleLacksPermission
);
CandidateShortlist::<T>::try_mutate(ShortlistRound::<T>::get(), |m_shortlist| {
m_shortlist.remove(&candidate);
Expand Down Expand Up @@ -396,7 +396,12 @@ pub mod pallet {
pub enum Role {
Vetter,
Freelancer,
BusinessDev,
Approver,
}

#[derive(Encode, Decode, PartialEq, Eq, Copy, Clone, Debug, MaxEncodedLen, TypeInfo)]
pub enum Permission {
AddToShortlist,
RemoveFromShortlist,
None,
}
}
158 changes: 158 additions & 0 deletions pallets/fellowship/src/migration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
use frame_support::traits::OnRuntimeUpgrade;
use frame_support::{dispatch::EncodeLike, pallet_prelude::*, *};
use hex_literal::hex;
use sp_runtime::AccountId32;
use sp_std::{fmt::Debug, vec, vec::Vec};

use crate::{traits::*, *};

pub mod v0 {
use super::*;

pub struct MigrateInitial<T: crate::Config>(T);
impl<T: Config> MigrateInitial<T>
where
T: frame_system::Config<AccountId = AccountId32>,
{
pub fn insert_initial_fellows(
weight: &mut Weight,
initial_fellows: Vec<(
<T as frame_system::Config>::AccountId,
crate::Role,
crate::Rank,
)>,
) {
for (acc, role, rank) in initial_fellows.into_iter() {
<Pallet<T> as FellowshipHandle<AccountIdOf<T>>>::add_to_fellowship(
&acc, role, rank, None, false,
);
*weight = weight.saturating_add(T::WeightInfo::add_to_fellowship())
}
}
pub fn get_initial_fellows() -> Vec<(
<T as frame_system::Config>::AccountId,
crate::Role,
crate::Rank,
)> {
vec![
// EARNEST
//"5Da1Fna8wvgQNmCFPhcRGR9oxmhyPd7MNhPZADq2X6GiKkkr",
(
AccountId32::new(hex![
"4294eb45758b4b92b01ceffe209bbcfeb26c973d5c0e21ac6c9cfbb99201b334"
]),
Role::Freelancer,
1,
),
// FELIX
// 5DCzKK5EZvY77vxxWXeip7sp17TqB7sk7Fj1hXes7Bo6B5Eq
(
AccountId32::new(hex![
"328d9a97c6f7f0fbbc60be2faba4c36cd4e5d3cfcb316393b384ee1a45433034"
]),
Role::Freelancer,
1,
),
// BEA
// "5DU2hcQnEmrSXCDUnjiwNX3A1uTf26ACpgs4KUFpsLJqAnjd",
(
AccountId32::new(hex![
"3e064fcfd9f02b99dda26226d3d6b2d68032b1c990e7a350cd01747271356f4c"
]),
Role::Freelancer,
1,
),
// SAM
// "5F28xL42VWThNonDft4TAQ6rw6a82E2jMsQXS5uMyKiA4ccv",
(
AccountId32::new(hex![
"82bf733f44a840f0a5c1935a002d4e541d81298fad6d1da8124073485983860e"
]),
Role::Freelancer,
1,
),
// SHANKAR
// "5E6pjCAGAtpV4nDoTWfMyQ474ku9DNScYeU3PK3e8Jd94Z1n",
(
AccountId32::new(hex![
"5a1616831e4508abf2eced2670199ab7a00e9e2bbcfc04655ba7ed138af8787d"
]),
Role::Freelancer,
1,
),
]
}
}

impl<T: Config> OnRuntimeUpgrade for MigrateInitial<T>
where
T: frame_system::Config<AccountId = AccountId32>,
{
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
log::warn!( target: "pallet-fellowship", "Running pre_upgrade()");
Ok(Vec::new())
}

fn on_runtime_upgrade() -> Weight {
let mut weight = T::DbWeight::get().reads_writes(1, 1);
log::warn!("****** STARTING MIGRATION *****");

let current = <Pallet<T> as GetStorageVersion>::current_storage_version();
let onchain = <Pallet<T> as GetStorageVersion>::on_chain_storage_version();

if current == 1 && onchain == 0 {
let initial_fellows = Self::get_initial_fellows();
Self::insert_initial_fellows(&mut weight, initial_fellows);

current.put::<Pallet<T>>();
log::warn!("v1 has been successfully applied");
weight = weight.saturating_add(T::DbWeight::get().reads_writes(2, 1));
} else {
log::warn!("Skipping v1, should be removed from Executive");
weight = weight.saturating_add(T::DbWeight::get().reads(1));
}

log::warn!("****** ENDING MIGRATION *****");
weight
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(_state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
log::warn!( target: "pallet-fellowship", "Running post_upgrade()");

let accounts = vec![
AccountId32::new(hex![
"4294eb45758b4b92b01ceffe209bbcfeb26c973d5c0e21ac6c9cfbb99201b334"
]),
AccountId32::new(hex![
"328d9a97c6f7f0fbbc60be2faba4c36cd4e5d3cfcb316393b384ee1a45433034"
]),
AccountId32::new(hex![
"3e064fcfd9f02b99dda26226d3d6b2d68032b1c990e7a350cd01747271356f4c"
]),
AccountId32::new(hex![
"82bf733f44a840f0a5c1935a002d4e541d81298fad6d1da8124073485983860e"
]),
AccountId32::new(hex![
"5a1616831e4508abf2eced2670199ab7a00e9e2bbcfc04655ba7ed138af8787d"
]),
];

accounts.iter().for_each(|acc| {
let role = Roles::<T>::get(acc).unwrap();
assert!(
role == (Role::Freelancer, 1),
"Roles have not been inserted correctly."
);
});

ensure!(
Pallet::<T>::current_storage_version() == 1,
"Storage version should be v1 after the migration"
);

Ok(())
}
}
}
2 changes: 2 additions & 0 deletions pallets/fellowship/src/mock.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate as pallet_fellowship;
use crate::{Permission, Role};
use common_types::CurrencyId;
use frame_support::once_cell::sync::Lazy;
use frame_support::traits::{ConstU16, Nothing};
Expand Down Expand Up @@ -76,6 +77,7 @@ impl pallet_fellowship::Config for Test {
type MembershipDeposit = MembershipDeposit;
type DepositCurrencyId = DepositCurrencyId;
type SlashAccount = SlashAccount;
type Permissions = crate::impls::VetterAndFreelancerAllPermissions;
type WeightInfo = ();
}

Expand Down
Loading

0 comments on commit 9353c93

Please sign in to comment.