diff --git a/substrate/frame/democracy/src/tests.rs b/substrate/frame/democracy/src/tests.rs index 4dd96d219b..9df594ed07 100644 --- a/substrate/frame/democracy/src/tests.rs +++ b/substrate/frame/democracy/src/tests.rs @@ -22,7 +22,7 @@ use super::*; use codec::Encode; use frame_support::{ assert_noop, assert_ok, parameter_types, ord_parameter_types, - traits::{Contains, OnInitialize, Filter}, + traits::{SortedMembers, OnInitialize, Filter}, weights::Weight, }; use sp_core::H256; @@ -151,7 +151,7 @@ ord_parameter_types! { pub const Six: u64 = 6; } pub struct OneToFive; -impl Contains for OneToFive { +impl SortedMembers for OneToFive { fn sorted_members() -> Vec { vec![1, 2, 3, 4, 5] } diff --git a/substrate/frame/elections-phragmen/src/lib.rs b/substrate/frame/elections-phragmen/src/lib.rs index 6317bcebac..c7fcb4cec8 100644 --- a/substrate/frame/elections-phragmen/src/lib.rs +++ b/substrate/frame/elections-phragmen/src/lib.rs @@ -107,7 +107,7 @@ use frame_support::{ traits::{ ChangeMembers, Contains, ContainsLengthBound, Currency, CurrencyToVote, Get, InitializeMembers, LockIdentifier, LockableCurrency, OnUnbalanced, ReservableCurrency, - WithdrawReasons, + WithdrawReasons, SortedMembers, }, weights::Weight, }; @@ -1015,6 +1015,12 @@ impl Contains for Module { fn contains(who: &T::AccountId) -> bool { Self::is_member(who) } +} + +impl SortedMembers for Module { + fn contains(who: &T::AccountId) -> bool { + Self::is_member(who) + } fn sorted_members() -> Vec { Self::members_ids() diff --git a/substrate/frame/membership/src/lib.rs b/substrate/frame/membership/src/lib.rs index 532a235ad3..7ad7d6a543 100644 --- a/substrate/frame/membership/src/lib.rs +++ b/substrate/frame/membership/src/lib.rs @@ -26,7 +26,7 @@ use sp_std::prelude::*; use frame_support::{ decl_module, decl_storage, decl_event, decl_error, - traits::{ChangeMembers, InitializeMembers, EnsureOrigin, Contains}, + traits::{ChangeMembers, InitializeMembers, EnsureOrigin, Contains, SortedMembers}, }; use frame_system::ensure_signed; @@ -267,6 +267,12 @@ impl, I: Instance> Module { } impl, I: Instance> Contains for Module { + fn contains(t: &T::AccountId) -> bool { + Self::members().binary_search(t).is_ok() + } +} + +impl, I: Instance> SortedMembers for Module { fn sorted_members() -> Vec { Self::members() } diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index 13feab8ed3..92ffe0cb0c 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -459,13 +459,16 @@ macro_rules! ord_parameter_types { ); () => (); (IMPL $name:ident , $type:ty , $value:expr) => { - impl $crate::traits::Contains<$type> for $name { + impl $crate::traits::SortedMembers<$type> for $name { fn contains(t: &$type) -> bool { &$value == t } fn sorted_members() -> $crate::sp_std::prelude::Vec<$type> { vec![$value] } fn count() -> usize { 1 } #[cfg(feature = "runtime-benchmarks")] fn add(_: &$type) {} } + impl $crate::traits::Contains<$type> for $name { + fn contains(t: &$type) -> bool { &$value == t } + } } } diff --git a/substrate/frame/support/src/traits.rs b/substrate/frame/support/src/traits.rs index 6fd40aa9ba..7288f6c0d2 100644 --- a/substrate/frame/support/src/traits.rs +++ b/substrate/frame/support/src/traits.rs @@ -29,7 +29,10 @@ pub use tokens::imbalance::{Imbalance, OnUnbalanced, SignedImbalance}; pub use tokens::{ExistenceRequirement, WithdrawReasons, BalanceStatus}; mod members; -pub use members::{Contains, ContainsLengthBound, InitializeMembers, ChangeMembers}; +pub use members::{ + Contains, ContainsLengthBound, SortedMembers, InitializeMembers, ChangeMembers, All, IsInVec, + AsContains, +}; mod validation; pub use validation::{ diff --git a/substrate/frame/support/src/traits/members.rs b/substrate/frame/support/src/traits/members.rs index d3ce6786af..35748ca9c0 100644 --- a/substrate/frame/support/src/traits/members.rs +++ b/substrate/frame/support/src/traits/members.rs @@ -17,16 +17,28 @@ //! Traits for dealing with the idea of membership. -use sp_std::prelude::*; +use sp_std::{prelude::*, marker::PhantomData}; /// A trait for querying whether a type can be said to "contain" a value. -pub trait Contains { +pub trait Contains { /// Return `true` if this "contains" the given value `t`. - fn contains(t: &T) -> bool { Self::sorted_members().binary_search(t).is_ok() } + fn contains(t: &T) -> bool; +} +/// A `Contains` implementation which always returns `true`. +pub struct All(PhantomData); +impl Contains for All { + fn contains(_: &T) -> bool { true } +} + +/// A trait for a set which can enumerate its members in order. +pub trait SortedMembers { /// Get a vector of all members in the set, ordered. fn sorted_members() -> Vec; + /// Return `true` if this "contains" the given value `t`. + fn contains(t: &T) -> bool { Self::sorted_members().binary_search(t).is_ok() } + /// Get the number of items in the set. fn count() -> usize { Self::sorted_members().len() } @@ -38,6 +50,21 @@ pub trait Contains { fn add(_t: &T) { unimplemented!() } } +/// Adapter struct for turning an `OrderedMembership` impl into a `Contains` impl. +pub struct AsContains(PhantomData<(OM,)>); +impl> Contains for AsContains { + fn contains(t: &T) -> bool { OM::contains(t) } +} + +/// Trivial utility for implementing `Contains`/`OrderedMembership` with a `Vec`. +pub struct IsInVec(PhantomData); +impl>> Contains for IsInVec { + fn contains(t: &X) -> bool { T::get().contains(t) } +} +impl>> SortedMembers for IsInVec { + fn sorted_members() -> Vec { let mut r = T::get(); r.sort(); r } +} + /// A trait for querying bound for the length of an implementation of `Contains` pub trait ContainsLengthBound { /// Minimum number of elements contained diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs index d8a50f9f7a..bd6ef5eb50 100644 --- a/substrate/frame/system/src/lib.rs +++ b/substrate/frame/system/src/lib.rs @@ -87,7 +87,7 @@ use sp_core::{ChangesTrieConfiguration, storage::well_known_keys}; use frame_support::{ Parameter, storage, traits::{ - Contains, Get, PalletInfo, OnNewAccount, OnKilledAccount, HandleLifetime, + SortedMembers, Get, PalletInfo, OnNewAccount, OnKilledAccount, HandleLifetime, StoredMap, EnsureOrigin, OriginTrait, Filter, }, weights::{ @@ -870,7 +870,7 @@ impl< pub struct EnsureSignedBy(sp_std::marker::PhantomData<(Who, AccountId)>); impl< O: Into, O>> + From>, - Who: Contains, + Who: SortedMembers, AccountId: PartialEq + Clone + Ord + Default, > EnsureOrigin for EnsureSignedBy { type Success = AccountId; diff --git a/substrate/frame/tips/src/lib.rs b/substrate/frame/tips/src/lib.rs index 10b2b01683..b31468797c 100644 --- a/substrate/frame/tips/src/lib.rs +++ b/substrate/frame/tips/src/lib.rs @@ -68,7 +68,7 @@ use frame_support::traits::{ use sp_runtime::{ Percent, RuntimeDebug, traits::{ Zero, AccountIdConversion, Hash, BadOrigin }}; -use frame_support::traits::{Contains, ContainsLengthBound, OnUnbalanced, EnsureOrigin}; +use frame_support::traits::{SortedMembers, ContainsLengthBound, OnUnbalanced, EnsureOrigin}; use codec::{Encode, Decode}; use frame_system::{self as system, ensure_signed}; pub use weights::WeightInfo; @@ -86,7 +86,7 @@ pub trait Config: frame_system::Config + pallet_treasury::Config { /// Origin from which tippers must come. /// /// `ContainsLengthBound::max_len` must be cost free (i.e. no storage read or heavy operation). - type Tippers: Contains + ContainsLengthBound; + type Tippers: SortedMembers + ContainsLengthBound; /// The period for which a tip remains open after is has achieved threshold tippers. type TipCountdown: Get; diff --git a/substrate/frame/tips/src/tests.rs b/substrate/frame/tips/src/tests.rs index 9524c136aa..cb0d4e6c47 100644 --- a/substrate/frame/tips/src/tests.rs +++ b/substrate/frame/tips/src/tests.rs @@ -24,7 +24,7 @@ use super::*; use std::cell::RefCell; use frame_support::{ assert_noop, assert_ok, parameter_types, - weights::Weight, traits::Contains, + weights::Weight, traits::SortedMembers, PalletId }; use sp_runtime::Permill; @@ -98,7 +98,7 @@ thread_local! { static TEN_TO_FOURTEEN: RefCell> = RefCell::new(vec![10,11,12,13,14]); } pub struct TenToFourteen; -impl Contains for TenToFourteen { +impl SortedMembers for TenToFourteen { fn sorted_members() -> Vec { TEN_TO_FOURTEEN.with(|v| { v.borrow().clone()