Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

pallet-scheduler: Introduce OriginPrivilegeCmp #10078

Merged
merged 5 commits into from
Oct 29, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ use codec::{Decode, Encode, MaxEncodedLen};
use frame_support::{
construct_runtime, parameter_types,
traits::{
Currency, Everything, Imbalance, InstanceFilter, KeyOwnerProofSystem, LockIdentifier,
Nothing, OnUnbalanced, U128CurrencyToVote,
Currency, EqualPrivilegeOnly, Everything, Imbalance, InstanceFilter, KeyOwnerProofSystem,
LockIdentifier, Nothing, OnUnbalanced, U128CurrencyToVote,
},
weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
Expand Down Expand Up @@ -345,6 +345,7 @@ impl pallet_scheduler::Config for Runtime {
type ScheduleOrigin = EnsureRoot<AccountId>;
type MaxScheduledPerBlock = MaxScheduledPerBlock;
type WeightInfo = pallet_scheduler::weights::SubstrateWeight<Runtime>;
type OriginPrivilegeCmp = EqualPrivilegeOnly;
}

parameter_types! {
Expand Down
3 changes: 2 additions & 1 deletion frame/democracy/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate as pallet_democracy;
use codec::Encode;
use frame_support::{
assert_noop, assert_ok, ord_parameter_types, parameter_types,
traits::{Contains, GenesisBuild, OnInitialize, SortedMembers},
traits::{Contains, EqualPrivilegeOnly, GenesisBuild, OnInitialize, SortedMembers},
weights::Weight,
};
use frame_system::{EnsureRoot, EnsureSignedBy};
Expand Down Expand Up @@ -118,6 +118,7 @@ impl pallet_scheduler::Config for Test {
type ScheduleOrigin = EnsureRoot<u64>;
type MaxScheduledPerBlock = ();
type WeightInfo = ();
type OriginPrivilegeCmp = EqualPrivilegeOnly;
}
parameter_types! {
pub const ExistentialDeposit: u64 = 1;
Expand Down
26 changes: 21 additions & 5 deletions frame/scheduler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ use frame_support::{
dispatch::{DispatchError, DispatchResult, Dispatchable, Parameter},
traits::{
schedule::{self, DispatchTime},
EnsureOrigin, Get, IsType, OriginTrait,
EnsureOrigin, Get, IsType, OriginTrait, PrivilegeCmp,
},
weights::{GetDispatchInfo, Weight},
};
Expand All @@ -69,7 +69,7 @@ use sp_runtime::{
traits::{BadOrigin, One, Saturating, Zero},
RuntimeDebug,
};
use sp_std::{borrow::Borrow, marker::PhantomData, prelude::*};
use sp_std::{borrow::Borrow, cmp::Ordering, marker::PhantomData, prelude::*};
pub use weights::WeightInfo;

/// Just a simple index for naming period tasks.
Expand Down Expand Up @@ -160,6 +160,15 @@ pub mod pallet {
/// Required origin to schedule or cancel calls.
type ScheduleOrigin: EnsureOrigin<<Self as system::Config>::Origin>;

/// Compare the privileges of origins.
///
/// This will be used when canceling a task, to ensure that the origin that tries
/// to cancel has greater or equal privileges as the origin that created the scheduled task.
///
/// For simplicity the [`EqualPrivilegeOnly`](frame_support::traits::EqualPrivilegeOnly) can
/// be used. This will only check if two given origins are equal.
type OriginPrivilegeCmp: PrivilegeCmp<Self::PalletsOrigin>;

/// The maximum number of scheduled calls in the queue for a single block.
/// Not strictly enforced, but used for weight estimation.
#[pallet::constant]
Expand Down Expand Up @@ -614,7 +623,10 @@ impl<T: Config> Pallet<T> {
Ok(None),
|s| -> Result<Option<Scheduled<_, _, _, _>>, DispatchError> {
if let (Some(ref o), Some(ref s)) = (origin, s.borrow()) {
if *o != s.origin {
if matches!(
T::OriginPrivilegeCmp::cmp_privilege(o, &s.origin),
Some(Ordering::Less) | None
) {
return Err(BadOrigin.into())
}
};
Expand Down Expand Up @@ -709,7 +721,10 @@ impl<T: Config> Pallet<T> {
Agenda::<T>::try_mutate(when, |agenda| -> DispatchResult {
if let Some(s) = agenda.get_mut(i) {
if let (Some(ref o), Some(ref s)) = (origin, s.borrow()) {
if *o != s.origin {
if matches!(
T::OriginPrivilegeCmp::cmp_privilege(o, &s.origin),
Some(Ordering::Less) | None
) {
return Err(BadOrigin.into())
}
}
Expand Down Expand Up @@ -832,7 +847,7 @@ mod tests {
use crate as scheduler;
use frame_support::{
assert_err, assert_noop, assert_ok, ord_parameter_types, parameter_types,
traits::{Contains, OnFinalize, OnInitialize},
traits::{Contains, EqualPrivilegeOnly, OnFinalize, OnInitialize},
weights::constants::RocksDbWeight,
Hashable,
};
Expand Down Expand Up @@ -980,6 +995,7 @@ mod tests {
type ScheduleOrigin = EnsureOneOf<u64, EnsureRoot<u64>, EnsureSignedBy<One, u64>>;
type MaxScheduledPerBlock = MaxScheduledPerBlock;
type WeightInfo = ();
type OriginPrivilegeCmp = EqualPrivilegeOnly;
}

pub type LoggerCall = logger::Call<Test>;
Expand Down
7 changes: 4 additions & 3 deletions frame/support/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ pub use filter::{ClearFilterGuard, FilterStack, FilterStackGuard, InstanceFilter

mod misc;
pub use misc::{
Backing, ConstU32, EnsureInherentsAreFirst, EstimateCallFee, ExecuteBlock, ExtrinsicCall, Get,
GetBacking, GetDefault, HandleLifetime, IsSubType, IsType, Len, OffchainWorker,
OnKilledAccount, OnNewAccount, SameOrOther, Time, TryDrop, UnixTime, WrapperOpaque,
Backing, ConstU32, EnsureInherentsAreFirst, EqualPrivilegeOnly, EstimateCallFee, ExecuteBlock,
ExtrinsicCall, Get, GetBacking, GetDefault, HandleLifetime, IsSubType, IsType, Len,
OffchainWorker, OnKilledAccount, OnNewAccount, PrivilegeCmp, SameOrOther, Time, TryDrop,
UnixTime, WrapperOpaque,
};

mod stored_map;
Expand Down
26 changes: 25 additions & 1 deletion frame/support/src/traits/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::dispatch::Parameter;
use codec::{Decode, Encode, EncodeLike, Input, MaxEncodedLen};
use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter};
use sp_runtime::{traits::Block as BlockT, DispatchError};
use sp_std::prelude::*;
use sp_std::{cmp::Ordering, prelude::*};

/// Anything that can have a `::len()` method.
pub trait Len {
Expand Down Expand Up @@ -289,6 +289,30 @@ pub trait ExecuteBlock<Block: BlockT> {
fn execute_block(block: Block);
}

/// Something that can compare privileges of two origins.
pub trait PrivilegeCmp<Origin> {
/// Compare the `left` to the `right` origin.
///
/// The returned ordering should be from the pov of the `left` origin.
///
/// Should return `None` when it can not compare the given origins.
fn cmp_privilege(left: &Origin, right: &Origin) -> Option<Ordering>;
}

/// Implementation of [`PrivilegeCmp`] that only checks for equal origins.
///
/// This means it will either return [`Origin::Equal`] or `None`.
pub struct EqualPrivilegeOnly;
impl<Origin: PartialEq> PrivilegeCmp<Origin> for EqualPrivilegeOnly {
fn cmp_privilege(left: &Origin, right: &Origin) -> Option<Ordering> {
if left == right {
Some(Ordering::Equal)
} else {
None
}
}
}

/// Off-chain computation trait.
///
/// Implementing this trait on a module allows you to perform long-running tasks
Expand Down