Skip to content
Snippets Groups Projects
Commit fb0d1572 authored by Éloïs's avatar Éloïs
Browse files

fix(authority-members): MaxAuthorities constraint must be applied

parent 50b33e45
No related branches found
No related tags found
No related merge requests found
...@@ -66,6 +66,9 @@ pub mod pallet { ...@@ -66,6 +66,9 @@ pub mod pallet {
type KeysWrapper: Parameter + Into<Self::Keys>; type KeysWrapper: Parameter + Into<Self::Keys>;
type IsMember: IsMember<Self::MemberId>; type IsMember: IsMember<Self::MemberId>;
type OnRemovedMember: OnRemovedMember<Self::MemberId>; type OnRemovedMember: OnRemovedMember<Self::MemberId>;
/// Max number of authorities allowed
#[pallet::constant]
type MaxAuthorities: Get<u32>;
#[pallet::constant] #[pallet::constant]
type MaxKeysLife: Get<SessionIndex>; type MaxKeysLife: Get<SessionIndex>;
#[pallet::constant] #[pallet::constant]
...@@ -113,6 +116,7 @@ pub mod pallet { ...@@ -113,6 +116,7 @@ pub mod pallet {
.collect::<Vec<T::MemberId>>(); .collect::<Vec<T::MemberId>>();
members_ids.sort(); members_ids.sort();
AuthoritiesCounter::<T>::put(members_ids.len() as u32);
OnlineAuthorities::<T>::put(members_ids.clone()); OnlineAuthorities::<T>::put(members_ids.clone());
MustRotateKeysBefore::<T>::insert(T::MaxKeysLife::get(), members_ids); MustRotateKeysBefore::<T>::insert(T::MaxKeysLife::get(), members_ids);
} }
...@@ -125,6 +129,10 @@ pub mod pallet { ...@@ -125,6 +129,10 @@ pub mod pallet {
pub type AccountIdOf<T: Config> = pub type AccountIdOf<T: Config> =
StorageMap<_, Twox64Concat, T::MemberId, T::AccountId, OptionQuery>; StorageMap<_, Twox64Concat, T::MemberId, T::AccountId, OptionQuery>;
#[pallet::storage]
#[pallet::getter(fn authorities_counter)]
pub type AuthoritiesCounter<T: Config> = StorageValue<_, u32, ValueQuery>;
#[pallet::storage] #[pallet::storage]
#[pallet::getter(fn incoming)] #[pallet::getter(fn incoming)]
pub type IncomingAuthorities<T: Config> = StorageValue<_, Vec<T::MemberId>, ValueQuery>; pub type IncomingAuthorities<T: Config> = StorageValue<_, Vec<T::MemberId>, ValueQuery>;
...@@ -198,6 +206,8 @@ pub mod pallet { ...@@ -198,6 +206,8 @@ pub mod pallet {
NotMember, NotMember,
/// Session keys not provided /// Session keys not provided
SessionKeysNotProvided, SessionKeysNotProvided,
/// Too man aAuthorities
TooManyAuthorities,
} }
// CALLS // // CALLS //
...@@ -258,6 +268,9 @@ pub mod pallet { ...@@ -258,6 +268,9 @@ pub mod pallet {
if Self::is_online(member_id) && !is_outgoing { if Self::is_online(member_id) && !is_outgoing {
return Err(Error::<T>::AlreadyOnline.into()); return Err(Error::<T>::AlreadyOnline.into());
} }
if AuthoritiesCounter::<T>::get() >= T::MaxAuthorities::get() {
return Err(Error::<T>::TooManyAuthorities.into());
}
// Apply phase // // Apply phase //
if is_outgoing { if is_outgoing {
...@@ -398,6 +411,7 @@ pub mod pallet { ...@@ -398,6 +411,7 @@ pub mod pallet {
} }
}); });
if not_already_inserted { if not_already_inserted {
AuthoritiesCounter::<T>::mutate(|counter| *counter += 1);
AccountIdOf::<T>::insert(member_id, account_id); AccountIdOf::<T>::insert(member_id, account_id);
Self::deposit_event(Event::MemberGoOnline(member_id)); Self::deposit_event(Event::MemberGoOnline(member_id));
} }
...@@ -413,6 +427,11 @@ pub mod pallet { ...@@ -413,6 +427,11 @@ pub mod pallet {
} }
}); });
if not_already_inserted { if not_already_inserted {
AuthoritiesCounter::<T>::mutate(|counter| {
if *counter > 0 {
*counter -= 1
}
});
Self::deposit_event(Event::MemberGoOffline(member_id)); Self::deposit_event(Event::MemberGoOffline(member_id));
} }
not_already_inserted not_already_inserted
...@@ -433,6 +452,7 @@ pub mod pallet { ...@@ -433,6 +452,7 @@ pub mod pallet {
.is_ok() .is_ok()
} }
fn remove_in(member_id: T::MemberId) { fn remove_in(member_id: T::MemberId) {
AuthoritiesCounter::<T>::mutate(|counter| counter.saturating_sub(1));
IncomingAuthorities::<T>::mutate(|members_ids| { IncomingAuthorities::<T>::mutate(|members_ids| {
if let Ok(index) = members_ids.binary_search(&member_id) { if let Ok(index) = members_ids.binary_search(&member_id) {
members_ids.remove(index); members_ids.remove(index);
...@@ -440,6 +460,7 @@ pub mod pallet { ...@@ -440,6 +460,7 @@ pub mod pallet {
}) })
} }
fn remove_online(member_id: T::MemberId) { fn remove_online(member_id: T::MemberId) {
AuthoritiesCounter::<T>::mutate(|counter| counter.saturating_add(1));
OnlineAuthorities::<T>::mutate(|members_ids| { OnlineAuthorities::<T>::mutate(|members_ids| {
if let Ok(index) = members_ids.binary_search(&member_id) { if let Ok(index) = members_ids.binary_search(&member_id) {
members_ids.remove(index); members_ids.remove(index);
......
...@@ -151,6 +151,7 @@ impl pallet_authority_members::Config for Test { ...@@ -151,6 +151,7 @@ impl pallet_authority_members::Config for Test {
type Event = Event; type Event = Event;
type KeysWrapper = MockSessionKeys; type KeysWrapper = MockSessionKeys;
type IsMember = TestIsSmithMember; type IsMember = TestIsSmithMember;
type MaxAuthorities = ConstU32<4>;
type MaxKeysLife = ConstU32<5>; type MaxKeysLife = ConstU32<5>;
type MaxOfflineSessions = ConstU32<2>; type MaxOfflineSessions = ConstU32<2>;
type MemberId = u64; type MemberId = u64;
...@@ -175,8 +176,9 @@ pub fn new_test_ext(initial_authorities_len: u64) -> sp_io::TestExternalities { ...@@ -175,8 +176,9 @@ pub fn new_test_ext(initial_authorities_len: u64) -> sp_io::TestExternalities {
for (ref k, ..) in &keys { for (ref k, ..) in &keys {
frame_system::Pallet::<Test>::inc_providers(k); frame_system::Pallet::<Test>::inc_providers(k);
} }
// A dedicated test account // Some dedicated test account
frame_system::Pallet::<Test>::inc_providers(&12); frame_system::Pallet::<Test>::inc_providers(&12);
frame_system::Pallet::<Test>::inc_providers(&15);
}); });
pallet_authority_members::GenesisConfig::<Test> { pallet_authority_members::GenesisConfig::<Test> {
initial_authorities, initial_authorities,
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
use super::*; use super::*;
use crate::mock::*; use crate::mock::*;
use crate::MemberData; use crate::MemberData;
use frame_support::assert_ok; use frame_support::{assert_err, assert_ok};
use sp_runtime::testing::UintAuthorityId; use sp_runtime::testing::UintAuthorityId;
const EMPTY: Vec<u64> = Vec::new(); const EMPTY: Vec<u64> = Vec::new();
...@@ -224,6 +224,40 @@ fn test_go_online() { ...@@ -224,6 +224,40 @@ fn test_go_online() {
}); });
} }
#[test]
fn test_too_many_authorities() {
new_test_ext(3).execute_with(|| {
run_to_block(1);
// Member 12 set his session keys then go online
assert_ok!(AuthorityMembers::set_session_keys(
Origin::signed(12),
12,
UintAuthorityId(12).into(),
));
assert_eq!(AuthorityMembers::authorities_counter(), 3);
assert_ok!(AuthorityMembers::go_online(Origin::signed(12), 12),);
// Member 15 can't go online because there is already 4 authorities "planned"
assert_ok!(AuthorityMembers::set_session_keys(
Origin::signed(15),
15,
UintAuthorityId(15).into(),
));
assert_eq!(AuthorityMembers::authorities_counter(), 4);
assert_err!(
AuthorityMembers::go_online(Origin::signed(15), 15),
Error::<Test>::TooManyAuthorities,
);
// If member 3 go_offline, member 15 can go_online
assert_ok!(AuthorityMembers::go_offline(Origin::signed(3), 3),);
assert_eq!(AuthorityMembers::authorities_counter(), 3);
assert_ok!(AuthorityMembers::go_online(Origin::signed(15), 15),);
assert_eq!(AuthorityMembers::authorities_counter(), 4);
});
}
#[test] #[test]
fn test_go_online_then_go_offline_in_same_session() { fn test_go_online_then_go_offline_in_same_session() {
new_test_ext(3).execute_with(|| { new_test_ext(3).execute_with(|| {
......
...@@ -183,6 +183,7 @@ macro_rules! pallets_config { ...@@ -183,6 +183,7 @@ macro_rules! pallets_config {
type OnRemovedMember = OnRemovedAuthorityMemberHandler<Runtime>; type OnRemovedMember = OnRemovedAuthorityMemberHandler<Runtime>;
type MemberId = IdtyIndex; type MemberId = IdtyIndex;
type MemberIdOf = Identity; type MemberIdOf = Identity;
type MaxAuthorities = MaxAuthorities;
type MaxKeysLife = frame_support::pallet_prelude::ConstU32<1_000>; type MaxKeysLife = frame_support::pallet_prelude::ConstU32<1_000>;
type MaxOfflineSessions = frame_support::pallet_prelude::ConstU32<100>; type MaxOfflineSessions = frame_support::pallet_prelude::ConstU32<100>;
type RemoveMemberOrigin = EnsureRoot<Self::AccountId>; type RemoveMemberOrigin = EnsureRoot<Self::AccountId>;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment