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

Move EnsureOneOf into the dispatch.rs, make an interface more general #10379

Merged
merged 3 commits into from
Dec 1, 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
11 changes: 3 additions & 8 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, EqualPrivilegeOnly, Everything, Imbalance, InstanceFilter, KeyOwnerProofSystem,
LockIdentifier, Nothing, OnUnbalanced, U128CurrencyToVote,
Currency, EnsureOneOf, EqualPrivilegeOnly, Everything, Imbalance, InstanceFilter,
KeyOwnerProofSystem, LockIdentifier, Nothing, OnUnbalanced, U128CurrencyToVote,
},
weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
Expand All @@ -37,7 +37,7 @@ use frame_support::{
};
use frame_system::{
limits::{BlockLength, BlockWeights},
EnsureOneOf, EnsureRoot,
EnsureRoot,
};
pub use node_primitives::{AccountId, Signature};
use node_primitives::{AccountIndex, Balance, BlockNumber, Hash, Index, Moment};
Expand Down Expand Up @@ -529,7 +529,6 @@ impl pallet_staking::Config for Runtime {
type SlashDeferDuration = SlashDeferDuration;
/// A super-majority of the council can cancel the slash.
type SlashCancelOrigin = EnsureOneOf<
AccountId,
EnsureRoot<AccountId>,
pallet_collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>,
>;
Expand Down Expand Up @@ -719,7 +718,6 @@ impl pallet_democracy::Config for Runtime {
// To cancel a proposal before it has been passed, the technical committee must be unanimous or
// Root must agree.
type CancelProposalOrigin = EnsureOneOf<
AccountId,
EnsureRoot<AccountId>,
pallet_collective::EnsureProportionAtLeast<_1, _1, AccountId, TechnicalCollective>,
>;
Expand Down Expand Up @@ -810,7 +808,6 @@ impl pallet_collective::Config<TechnicalCollective> for Runtime {
}

type EnsureRootOrHalfCouncil = EnsureOneOf<
AccountId,
EnsureRoot<AccountId>,
pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>,
>;
Expand Down Expand Up @@ -850,12 +847,10 @@ impl pallet_treasury::Config for Runtime {
type PalletId = TreasuryPalletId;
type Currency = Balances;
type ApproveOrigin = EnsureOneOf<
AccountId,
EnsureRoot<AccountId>,
pallet_collective::EnsureProportionAtLeast<_3, _5, AccountId, CouncilCollective>,
>;
type RejectOrigin = EnsureOneOf<
AccountId,
EnsureRoot<AccountId>,
pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>,
>;
Expand Down
10 changes: 6 additions & 4 deletions frame/identity/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ use super::*;
use crate as pallet_identity;

use codec::{Decode, Encode};
use frame_support::{assert_noop, assert_ok, ord_parameter_types, parameter_types, BoundedVec};
use frame_system::{EnsureOneOf, EnsureRoot, EnsureSignedBy};
use frame_support::{
assert_noop, assert_ok, ord_parameter_types, parameter_types, traits::EnsureOneOf, BoundedVec,
};
use frame_system::{EnsureRoot, EnsureSignedBy};
use sp_core::H256;
use sp_runtime::{
testing::Header,
Expand Down Expand Up @@ -100,8 +102,8 @@ ord_parameter_types! {
pub const One: u64 = 1;
pub const Two: u64 = 2;
}
type EnsureOneOrRoot = EnsureOneOf<u64, EnsureRoot<u64>, EnsureSignedBy<One, u64>>;
type EnsureTwoOrRoot = EnsureOneOf<u64, EnsureRoot<u64>, EnsureSignedBy<Two, u64>>;
type EnsureOneOrRoot = EnsureOneOf<EnsureRoot<u64>, EnsureSignedBy<One, u64>>;
type EnsureTwoOrRoot = EnsureOneOf<EnsureRoot<u64>, EnsureSignedBy<Two, u64>>;
impl pallet_identity::Config for Test {
type Event = Event;
type Currency = Balances;
Expand Down
6 changes: 3 additions & 3 deletions frame/scheduler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -801,11 +801,11 @@ mod tests {
use crate as scheduler;
use frame_support::{
assert_err, assert_noop, assert_ok, ord_parameter_types, parameter_types,
traits::{Contains, EqualPrivilegeOnly, OnFinalize, OnInitialize},
traits::{Contains, EnsureOneOf, EqualPrivilegeOnly, OnFinalize, OnInitialize},
weights::constants::RocksDbWeight,
Hashable,
};
use frame_system::{EnsureOneOf, EnsureRoot, EnsureSignedBy};
use frame_system::{EnsureRoot, EnsureSignedBy};
use sp_core::H256;
use sp_runtime::{
testing::Header,
Expand Down Expand Up @@ -946,7 +946,7 @@ mod tests {
type PalletsOrigin = OriginCaller;
type Call = Call;
type MaximumWeight = MaximumSchedulerWeight;
type ScheduleOrigin = EnsureOneOf<u64, EnsureRoot<u64>, EnsureSignedBy<One, u64>>;
type ScheduleOrigin = EnsureOneOf<EnsureRoot<u64>, EnsureSignedBy<One, u64>>;
type MaxScheduledPerBlock = MaxScheduledPerBlock;
type WeightInfo = ();
type OriginPrivilegeCmp = EqualPrivilegeOnly;
Expand Down
2 changes: 1 addition & 1 deletion frame/support/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ pub use storage::{
};

mod dispatch;
pub use dispatch::{EnsureOrigin, OriginTrait, UnfilteredDispatchable};
pub use dispatch::{EnsureOneOf, EnsureOrigin, OriginTrait, UnfilteredDispatchable};

mod voting;
pub use voting::{CurrencyToVote, SaturatingCurrencyToVote, U128CurrencyToVote};
60 changes: 59 additions & 1 deletion frame/support/src/traits/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
//! Traits for dealing with dispatching calls and the origin from which they are dispatched.

use crate::dispatch::DispatchResultWithPostInfo;
use sp_runtime::traits::BadOrigin;
use sp_runtime::{traits::BadOrigin, Either};

/// Some sort of check on the origin is performed by this object.
pub trait EnsureOrigin<OuterOrigin> {
Expand Down Expand Up @@ -94,3 +94,61 @@ pub trait OriginTrait: Sized {
/// Create with system signed origin and `frame_system::Config::BaseCallFilter`.
fn signed(by: Self::AccountId) -> Self;
}

/// The "OR gate" implementation of `EnsureOrigin`.
///
/// Origin check will pass if `L` or `R` origin check passes. `L` is tested first.
pub struct EnsureOneOf<L, R>(sp_std::marker::PhantomData<(L, R)>);
Mr-Leshiy marked this conversation as resolved.
Show resolved Hide resolved

impl<OuterOrigin, L: EnsureOrigin<OuterOrigin>, R: EnsureOrigin<OuterOrigin>>
EnsureOrigin<OuterOrigin> for EnsureOneOf<L, R>
{
type Success = Either<L::Success, R::Success>;
fn try_origin(o: OuterOrigin) -> Result<Self::Success, OuterOrigin> {
L::try_origin(o)
.map_or_else(|o| R::try_origin(o).map(|o| Either::Right(o)), |o| Ok(Either::Left(o)))
}

#[cfg(feature = "runtime-benchmarks")]
fn successful_origin() -> OuterOrigin {
L::successful_origin()
}
}

#[cfg(test)]
mod tests {
use super::*;

struct EnsureSuccess;
struct EnsureFail;

impl EnsureOrigin<()> for EnsureSuccess {
type Success = ();
fn try_origin(_: ()) -> Result<Self::Success, ()> {
Ok(())
}
#[cfg(feature = "runtime-benchmarks")]
fn successful_origin() -> () {
()
}
}

impl EnsureOrigin<()> for EnsureFail {
type Success = ();
fn try_origin(_: ()) -> Result<Self::Success, ()> {
Err(())
}
#[cfg(feature = "runtime-benchmarks")]
fn successful_origin() -> () {
()
}
}

#[test]
fn ensure_one_of_test() {
assert!(<EnsureOneOf<EnsureSuccess, EnsureSuccess>>::try_origin(()).is_ok());
assert!(<EnsureOneOf<EnsureSuccess, EnsureFail>>::try_origin(()).is_ok());
assert!(<EnsureOneOf<EnsureFail, EnsureSuccess>>::try_origin(()).is_ok());
assert!(<EnsureOneOf<EnsureFail, EnsureFail>>::try_origin(()).is_err());
}
}
25 changes: 1 addition & 24 deletions frame/system/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ use sp_runtime::{
CheckEqual, Dispatchable, Hash, Lookup, LookupError, MaybeDisplay, MaybeMallocSizeOf,
MaybeSerializeDeserialize, Member, One, Saturating, SimpleBitOps, StaticLookup, Zero,
},
DispatchError, Either, Perbill, RuntimeDebug,
DispatchError, Perbill, RuntimeDebug,
};
#[cfg(any(feature = "std", test))]
use sp_std::map;
Expand Down Expand Up @@ -902,29 +902,6 @@ impl<O, T> EnsureOrigin<O> for EnsureNever<T> {
}
}

/// The "OR gate" implementation of `EnsureOrigin`.
///
/// Origin check will pass if `L` or `R` origin check passes. `L` is tested first.
pub struct EnsureOneOf<AccountId, L, R>(sp_std::marker::PhantomData<(AccountId, L, R)>);
impl<
AccountId,
O: Into<Result<RawOrigin<AccountId>, O>> + From<RawOrigin<AccountId>>,
L: EnsureOrigin<O>,
R: EnsureOrigin<O>,
> EnsureOrigin<O> for EnsureOneOf<AccountId, L, R>
{
type Success = Either<L::Success, R::Success>;
fn try_origin(o: O) -> Result<Self::Success, O> {
L::try_origin(o)
.map_or_else(|o| R::try_origin(o).map(|o| Either::Right(o)), |o| Ok(Either::Left(o)))
}

#[cfg(feature = "runtime-benchmarks")]
fn successful_origin() -> O {
L::successful_origin()
}
}

/// Ensure that the origin `o` represents a signed extrinsic (i.e. transaction).
/// Returns `Ok` with the account that signed the extrinsic or an `Err` otherwise.
pub fn ensure_signed<OuterOrigin, AccountId>(o: OuterOrigin) -> Result<AccountId, BadOrigin>
Expand Down
11 changes: 0 additions & 11 deletions frame/system/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -464,17 +464,6 @@ fn events_not_emitted_during_genesis() {
});
}

#[test]
fn ensure_one_of_works() {
fn ensure_root_or_signed(o: RawOrigin<u64>) -> Result<Either<(), u64>, Origin> {
EnsureOneOf::<u64, EnsureRoot<u64>, EnsureSigned<u64>>::try_origin(o.into())
}

assert_eq!(ensure_root_or_signed(RawOrigin::Root).unwrap(), Either::Left(()));
assert_eq!(ensure_root_or_signed(RawOrigin::Signed(0)).unwrap(), Either::Right(0));
assert!(ensure_root_or_signed(RawOrigin::None).is_err());
}

#[test]
fn extrinsics_root_is_calculated_correctly() {
new_test_ext().execute_with(|| {
Expand Down