Frame: Give Referendum SubmitOrigin argument (#14326)

* Referedum's SubmitOrigin should have an arg

* Fixes

* Nits and two extra utils

* Fixes

* Fixes
This commit is contained in:
Gavin Wood
2023-06-12 09:10:19 +01:00
committed by GitHub
parent 62f37e105c
commit 9716c8a1cb
14 changed files with 462 additions and 88 deletions
+27 -2
View File
@@ -53,9 +53,10 @@ use frame_support::{
DispatchError, DispatchResult, DispatchResultWithPostInfo, Dispatchable, GetDispatchInfo,
Pays, PostDispatchInfo,
},
ensure,
ensure, impl_ensure_origin_with_arg_ignoring_arg,
traits::{
Backing, ChangeMembers, EnsureOrigin, Get, GetBacking, InitializeMembers, StorageVersion,
Backing, ChangeMembers, EnsureOrigin, EnsureOriginWithArg, Get, GetBacking,
InitializeMembers, StorageVersion,
},
weights::Weight,
};
@@ -1154,6 +1155,12 @@ impl<
}
}
impl_ensure_origin_with_arg_ignoring_arg! {
impl< { O: .., I: 'static, AccountId: Decode, T } >
EnsureOriginWithArg<O, T> for EnsureMember<AccountId, I>
{}
}
pub struct EnsureMembers<AccountId, I: 'static, const N: u32>(PhantomData<(AccountId, I)>);
impl<
O: Into<Result<RawOrigin<AccountId, I>, O>> + From<RawOrigin<AccountId, I>>,
@@ -1176,6 +1183,12 @@ impl<
}
}
impl_ensure_origin_with_arg_ignoring_arg! {
impl< { O: .., I: 'static, const N: u32, AccountId, T } >
EnsureOriginWithArg<O, T> for EnsureMembers<AccountId, I, N>
{}
}
pub struct EnsureProportionMoreThan<AccountId, I: 'static, const N: u32, const D: u32>(
PhantomData<(AccountId, I)>,
);
@@ -1201,6 +1214,12 @@ impl<
}
}
impl_ensure_origin_with_arg_ignoring_arg! {
impl< { O: .., I: 'static, const N: u32, const D: u32, AccountId, T } >
EnsureOriginWithArg<O, T> for EnsureProportionMoreThan<AccountId, I, N, D>
{}
}
pub struct EnsureProportionAtLeast<AccountId, I: 'static, const N: u32, const D: u32>(
PhantomData<(AccountId, I)>,
);
@@ -1225,3 +1244,9 @@ impl<
Ok(O::from(RawOrigin::Members(0u32, 0u32)))
}
}
impl_ensure_origin_with_arg_ignoring_arg! {
impl< { O: .., I: 'static, const N: u32, const D: u32, AccountId, T } >
EnsureOriginWithArg<O, T> for EnsureProportionAtLeast<AccountId, I, N, D>
{}
}
+11 -3
View File
@@ -65,8 +65,10 @@ use sp_std::{marker::PhantomData, prelude::*};
use frame_support::{
dispatch::DispatchResultWithPostInfo,
ensure,
traits::{tokens::Balance as BalanceTrait, EnsureOrigin, Get, RankedMembers},
ensure, impl_ensure_origin_with_arg_ignoring_arg,
traits::{
tokens::Balance as BalanceTrait, EnsureOrigin, EnsureOriginWithArg, Get, RankedMembers,
},
BoundedVec, RuntimeDebug,
};
@@ -570,7 +572,7 @@ impl<T: Config<I>, I: 'static, const MIN_RANK: u16> EnsureOrigin<T::RuntimeOrigi
type Success = T::AccountId;
fn try_origin(o: T::RuntimeOrigin) -> Result<Self::Success, T::RuntimeOrigin> {
let who = frame_system::EnsureSigned::try_origin(o)?;
let who = <frame_system::EnsureSigned<_> as EnsureOrigin<_>>::try_origin(o)?;
match T::Members::rank_of(&who) {
Some(rank) if rank >= MIN_RANK && Member::<T, I>::contains_key(&who) => Ok(who),
_ => Err(frame_system::RawOrigin::Signed(who).into()),
@@ -591,3 +593,9 @@ impl<T: Config<I>, I: 'static, const MIN_RANK: u16> EnsureOrigin<T::RuntimeOrigi
Ok(frame_system::RawOrigin::Signed(who).into())
}
}
impl_ensure_origin_with_arg_ignoring_arg! {
impl< { T: Config<I>, I: 'static, const MIN_RANK: u16, A } >
EnsureOriginWithArg<T::RuntimeOrigin, A> for EnsureInducted<T, I, MIN_RANK>
{}
}
+57 -7
View File
@@ -53,8 +53,8 @@ use sp_std::{marker::PhantomData, prelude::*};
use frame_support::{
codec::{Decode, Encode, MaxEncodedLen},
dispatch::{DispatchError, DispatchResultWithPostInfo, PostDispatchInfo},
ensure,
traits::{EnsureOrigin, PollStatus, Polling, RankedMembers, VoteTally},
ensure, impl_ensure_origin_with_arg_ignoring_arg,
traits::{EnsureOrigin, EnsureOriginWithArg, PollStatus, Polling, RankedMembers, VoteTally},
CloneNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound,
};
@@ -263,7 +263,7 @@ impl<T: Config<I>, I: 'static, const MIN_RANK: u16> EnsureOrigin<T::RuntimeOrigi
type Success = Rank;
fn try_origin(o: T::RuntimeOrigin) -> Result<Self::Success, T::RuntimeOrigin> {
let who = frame_system::EnsureSigned::try_origin(o)?;
let who = <frame_system::EnsureSigned<_> as EnsureOrigin<_>>::try_origin(o)?;
match Members::<T, I>::get(&who) {
Some(MemberRecord { rank, .. }) if rank >= MIN_RANK => Ok(rank),
_ => Err(frame_system::RawOrigin::Signed(who).into()),
@@ -272,7 +272,36 @@ impl<T: Config<I>, I: 'static, const MIN_RANK: u16> EnsureOrigin<T::RuntimeOrigi
#[cfg(feature = "runtime-benchmarks")]
fn try_successful_origin() -> Result<T::RuntimeOrigin, ()> {
EnsureRankedMember::<T, I, MIN_RANK>::try_successful_origin()
<EnsureRankedMember<T, I, MIN_RANK> as EnsureOrigin<_>>::try_successful_origin()
}
}
impl_ensure_origin_with_arg_ignoring_arg! {
impl<{ T: Config<I>, I: 'static, const MIN_RANK: u16, A }>
EnsureOriginWithArg<T::RuntimeOrigin, A> for EnsureRanked<T, I, MIN_RANK>
{}
}
/// Guard to ensure that the given origin is a member of the collective. The rank of the member is
/// the `Success` value.
pub struct EnsureOfRank<T, I>(PhantomData<(T, I)>);
impl<T: Config<I>, I: 'static> EnsureOriginWithArg<T::RuntimeOrigin, Rank> for EnsureOfRank<T, I> {
type Success = (T::AccountId, Rank);
fn try_origin(o: T::RuntimeOrigin, min_rank: &Rank) -> Result<Self::Success, T::RuntimeOrigin> {
let who = <frame_system::EnsureSigned<_> as EnsureOrigin<_>>::try_origin(o)?;
match Members::<T, I>::get(&who) {
Some(MemberRecord { rank, .. }) if rank >= *min_rank => Ok((who, rank)),
_ => Err(frame_system::RawOrigin::Signed(who).into()),
}
}
#[cfg(feature = "runtime-benchmarks")]
fn try_successful_origin(min_rank: &Rank) -> Result<T::RuntimeOrigin, ()> {
let who = frame_benchmarking::account::<T::AccountId>("successful_origin", 0, 0);
crate::Pallet::<T, I>::do_add_member_to_rank(who.clone(), *min_rank)
.expect("Could not add members for benchmarks");
Ok(frame_system::RawOrigin::Signed(who).into())
}
}
@@ -285,7 +314,7 @@ impl<T: Config<I>, I: 'static, const MIN_RANK: u16> EnsureOrigin<T::RuntimeOrigi
type Success = T::AccountId;
fn try_origin(o: T::RuntimeOrigin) -> Result<Self::Success, T::RuntimeOrigin> {
let who = frame_system::EnsureSigned::try_origin(o)?;
let who = <frame_system::EnsureSigned<_> as EnsureOrigin<_>>::try_origin(o)?;
match Members::<T, I>::get(&who) {
Some(MemberRecord { rank, .. }) if rank >= MIN_RANK => Ok(who),
_ => Err(frame_system::RawOrigin::Signed(who).into()),
@@ -294,10 +323,16 @@ impl<T: Config<I>, I: 'static, const MIN_RANK: u16> EnsureOrigin<T::RuntimeOrigi
#[cfg(feature = "runtime-benchmarks")]
fn try_successful_origin() -> Result<T::RuntimeOrigin, ()> {
EnsureRankedMember::<T, I, MIN_RANK>::try_successful_origin()
<EnsureRankedMember<T, I, MIN_RANK> as EnsureOrigin<_>>::try_successful_origin()
}
}
impl_ensure_origin_with_arg_ignoring_arg! {
impl<{ T: Config<I>, I: 'static, const MIN_RANK: u16, A }>
EnsureOriginWithArg<T::RuntimeOrigin, A> for EnsureMember<T, I, MIN_RANK>
{}
}
/// Guard to ensure that the given origin is a member of the collective. The pair of both the
/// account ID and the rank of the member is the `Success` value.
pub struct EnsureRankedMember<T, I, const MIN_RANK: u16>(PhantomData<(T, I)>);
@@ -307,7 +342,7 @@ impl<T: Config<I>, I: 'static, const MIN_RANK: u16> EnsureOrigin<T::RuntimeOrigi
type Success = (T::AccountId, Rank);
fn try_origin(o: T::RuntimeOrigin) -> Result<Self::Success, T::RuntimeOrigin> {
let who = frame_system::EnsureSigned::try_origin(o)?;
let who = <frame_system::EnsureSigned<_> as EnsureOrigin<_>>::try_origin(o)?;
match Members::<T, I>::get(&who) {
Some(MemberRecord { rank, .. }) if rank >= MIN_RANK => Ok((who, rank)),
_ => Err(frame_system::RawOrigin::Signed(who).into()),
@@ -323,6 +358,12 @@ impl<T: Config<I>, I: 'static, const MIN_RANK: u16> EnsureOrigin<T::RuntimeOrigi
}
}
impl_ensure_origin_with_arg_ignoring_arg! {
impl<{ T: Config<I>, I: 'static, const MIN_RANK: u16, A }>
EnsureOriginWithArg<T::RuntimeOrigin, A> for EnsureRankedMember<T, I, MIN_RANK>
{}
}
#[frame_support::pallet]
pub mod pallet {
use super::*;
@@ -708,6 +749,15 @@ pub mod pallet {
}
Ok(())
}
/// Determine the rank of the account behind the `Signed` origin `o`, `None` if the account
/// is unknown to this collective or `o` is not `Signed`.
pub fn as_rank(
o: &<T::RuntimeOrigin as frame_support::traits::OriginTrait>::PalletsOrigin,
) -> Option<u16> {
use frame_support::traits::CallerTrait;
o.as_signed().and_then(Self::rank_of)
}
}
impl<T: Config<I>, I: 'static> RankedMembers for Pallet<T, I> {
+30 -12
View File
@@ -464,34 +464,52 @@ fn ensure_ranked_works() {
type Rank2 = EnsureRanked<Test, (), 2>;
type Rank3 = EnsureRanked<Test, (), 3>;
type Rank4 = EnsureRanked<Test, (), 4>;
assert_eq!(Rank1::try_origin(RuntimeOrigin::signed(1)).unwrap(), 1);
assert_eq!(Rank1::try_origin(RuntimeOrigin::signed(2)).unwrap(), 2);
assert_eq!(Rank1::try_origin(RuntimeOrigin::signed(3)).unwrap(), 3);
assert_eq!(<Rank1 as EnsureOrigin<_>>::try_origin(RuntimeOrigin::signed(1)).unwrap(), 1);
assert_eq!(<Rank1 as EnsureOrigin<_>>::try_origin(RuntimeOrigin::signed(2)).unwrap(), 2);
assert_eq!(<Rank1 as EnsureOrigin<_>>::try_origin(RuntimeOrigin::signed(3)).unwrap(), 3);
assert_eq!(
Rank2::try_origin(RuntimeOrigin::signed(1)).unwrap_err().as_signed().unwrap(),
<Rank2 as EnsureOrigin<_>>::try_origin(RuntimeOrigin::signed(1))
.unwrap_err()
.into_signer()
.unwrap(),
1
);
assert_eq!(Rank2::try_origin(RuntimeOrigin::signed(2)).unwrap(), 2);
assert_eq!(Rank2::try_origin(RuntimeOrigin::signed(3)).unwrap(), 3);
assert_eq!(<Rank2 as EnsureOrigin<_>>::try_origin(RuntimeOrigin::signed(2)).unwrap(), 2);
assert_eq!(<Rank2 as EnsureOrigin<_>>::try_origin(RuntimeOrigin::signed(3)).unwrap(), 3);
assert_eq!(
Rank3::try_origin(RuntimeOrigin::signed(1)).unwrap_err().as_signed().unwrap(),
<Rank3 as EnsureOrigin<_>>::try_origin(RuntimeOrigin::signed(1))
.unwrap_err()
.into_signer()
.unwrap(),
1
);
assert_eq!(
Rank3::try_origin(RuntimeOrigin::signed(2)).unwrap_err().as_signed().unwrap(),
<Rank3 as EnsureOrigin<_>>::try_origin(RuntimeOrigin::signed(2))
.unwrap_err()
.into_signer()
.unwrap(),
2
);
assert_eq!(Rank3::try_origin(RuntimeOrigin::signed(3)).unwrap(), 3);
assert_eq!(<Rank3 as EnsureOrigin<_>>::try_origin(RuntimeOrigin::signed(3)).unwrap(), 3);
assert_eq!(
Rank4::try_origin(RuntimeOrigin::signed(1)).unwrap_err().as_signed().unwrap(),
<Rank4 as EnsureOrigin<_>>::try_origin(RuntimeOrigin::signed(1))
.unwrap_err()
.into_signer()
.unwrap(),
1
);
assert_eq!(
Rank4::try_origin(RuntimeOrigin::signed(2)).unwrap_err().as_signed().unwrap(),
<Rank4 as EnsureOrigin<_>>::try_origin(RuntimeOrigin::signed(2))
.unwrap_err()
.into_signer()
.unwrap(),
2
);
assert_eq!(
Rank4::try_origin(RuntimeOrigin::signed(3)).unwrap_err().as_signed().unwrap(),
<Rank4 as EnsureOrigin<_>>::try_origin(RuntimeOrigin::signed(3))
.unwrap_err()
.into_signer()
.unwrap(),
3
);
});
+31 -31
View File
@@ -26,7 +26,7 @@ use frame_benchmarking::v1::{
use frame_support::{
assert_ok,
dispatch::UnfilteredDispatchable,
traits::{Bounded, Currency, EnsureOrigin},
traits::{Bounded, Currency, EnsureOrigin, EnsureOriginWithArg},
};
use frame_system::RawOrigin;
use sp_runtime::traits::Bounded as ArithBounded;
@@ -196,7 +196,7 @@ fn is_not_confirming<T: Config<I>, I: 'static>(index: ReferendumIndex) -> bool {
benchmarks_instance_pallet! {
submit {
let origin =
T::SubmitOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into()).map_err(|_| BenchmarkError::Weightless)?;
if let Ok(caller) = frame_system::ensure_signed(origin.clone()) {
T::Currency::make_free_balance_be(&caller, BalanceOf::<T, I>::max_value());
whitelist_account!(caller);
@@ -213,7 +213,7 @@ benchmarks_instance_pallet! {
place_decision_deposit_preparing {
let origin =
T::SubmitOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into()).map_err(|_| BenchmarkError::Weightless)?;
let index = create_referendum::<T, I>(origin.clone());
}: place_decision_deposit<T::RuntimeOrigin>(origin, index)
verify {
@@ -222,7 +222,7 @@ benchmarks_instance_pallet! {
place_decision_deposit_queued {
let origin =
T::SubmitOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into()).map_err(|_| BenchmarkError::Weightless)?;
let index = create_referendum::<T, I>(origin.clone());
fill_queue::<T, I>(origin.clone(), index, 1, 90);
}: place_decision_deposit<T::RuntimeOrigin>(origin, index)
@@ -234,7 +234,7 @@ benchmarks_instance_pallet! {
place_decision_deposit_not_queued {
let origin =
T::SubmitOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into()).map_err(|_| BenchmarkError::Weightless)?;
let index = create_referendum::<T, I>(origin.clone());
fill_queue::<T, I>(origin.clone(), index, 0, 90);
let track = Referenda::<T, I>::ensure_ongoing(index).unwrap().track;
@@ -248,7 +248,7 @@ benchmarks_instance_pallet! {
place_decision_deposit_passing {
let origin =
T::SubmitOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into()).map_err(|_| BenchmarkError::Weightless)?;
let index = create_referendum::<T, I>(origin.clone());
skip_prepare_period::<T, I>(index);
make_passing::<T, I>(index);
@@ -259,7 +259,7 @@ benchmarks_instance_pallet! {
place_decision_deposit_failing {
let origin =
T::SubmitOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into()).map_err(|_| BenchmarkError::Weightless)?;
let index = create_referendum::<T, I>(origin.clone());
skip_prepare_period::<T, I>(index);
}: place_decision_deposit<T::RuntimeOrigin>(origin, index)
@@ -269,7 +269,7 @@ benchmarks_instance_pallet! {
refund_decision_deposit {
let origin =
T::SubmitOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into()).map_err(|_| BenchmarkError::Weightless)?;
let index = create_referendum::<T, I>(origin.clone());
place_deposit::<T, I>(index);
assert_ok!(Referenda::<T, I>::cancel(
@@ -284,7 +284,7 @@ benchmarks_instance_pallet! {
refund_submission_deposit {
let origin =
T::SubmitOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into()).map_err(|_| BenchmarkError::Weightless)?;
let index = create_referendum::<T, I>(origin.clone());
let caller = frame_system::ensure_signed(origin.clone()).unwrap();
let balance = T::Currency::free_balance(&caller);
@@ -303,7 +303,7 @@ benchmarks_instance_pallet! {
}
cancel {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin);
place_deposit::<T, I>(index);
@@ -315,7 +315,7 @@ benchmarks_instance_pallet! {
}
kill {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin);
place_deposit::<T, I>(index);
@@ -327,7 +327,7 @@ benchmarks_instance_pallet! {
}
one_fewer_deciding_queue_empty {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin);
place_deposit::<T, I>(index);
@@ -346,7 +346,7 @@ benchmarks_instance_pallet! {
}
one_fewer_deciding_failing {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin.clone());
// No spaces free in the queue.
@@ -371,7 +371,7 @@ benchmarks_instance_pallet! {
}
one_fewer_deciding_passing {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin.clone());
// No spaces free in the queue.
@@ -396,7 +396,7 @@ benchmarks_instance_pallet! {
}
nudge_referendum_requeued_insertion {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
// First create our referendum and place the deposit. It will be failing.
let index = create_referendum::<T, I>(origin.clone());
@@ -419,7 +419,7 @@ benchmarks_instance_pallet! {
}
nudge_referendum_requeued_slide {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
// First create our referendum and place the deposit. It will be failing.
let index = create_referendum::<T, I>(origin.clone());
@@ -447,7 +447,7 @@ benchmarks_instance_pallet! {
// free and this failing. It would result in `QUEUE_SIZE - 1` items being shifted for the
// insertion at the beginning.
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
// First create our referendum and place the deposit. It will be failing.
let index = create_referendum::<T, I>(origin.clone());
@@ -466,7 +466,7 @@ benchmarks_instance_pallet! {
}
nudge_referendum_not_queued {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
// First create our referendum and place the deposit. It will be failing.
let index = create_referendum::<T, I>(origin.clone());
@@ -485,7 +485,7 @@ benchmarks_instance_pallet! {
}
nudge_referendum_no_deposit {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin);
skip_prepare_period::<T, I>(index);
@@ -496,7 +496,7 @@ benchmarks_instance_pallet! {
}
nudge_referendum_preparing {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin);
place_deposit::<T, I>(index);
@@ -507,7 +507,7 @@ benchmarks_instance_pallet! {
}
nudge_referendum_timed_out {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin);
skip_timeout_period::<T, I>(index);
@@ -518,7 +518,7 @@ benchmarks_instance_pallet! {
}
nudge_referendum_begin_deciding_failing {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin);
place_deposit::<T, I>(index);
@@ -529,7 +529,7 @@ benchmarks_instance_pallet! {
}
nudge_referendum_begin_deciding_passing {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin);
place_deposit::<T, I>(index);
@@ -541,7 +541,7 @@ benchmarks_instance_pallet! {
}
nudge_referendum_begin_confirming {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin);
place_deposit::<T, I>(index);
@@ -555,7 +555,7 @@ benchmarks_instance_pallet! {
}
nudge_referendum_end_confirming {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin);
place_deposit::<T, I>(index);
@@ -570,7 +570,7 @@ benchmarks_instance_pallet! {
}
nudge_referendum_continue_not_confirming {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin);
place_deposit::<T, I>(index);
@@ -586,7 +586,7 @@ benchmarks_instance_pallet! {
}
nudge_referendum_continue_confirming {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin);
place_deposit::<T, I>(index);
@@ -601,7 +601,7 @@ benchmarks_instance_pallet! {
}
nudge_referendum_approved {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin);
place_deposit::<T, I>(index);
@@ -616,7 +616,7 @@ benchmarks_instance_pallet! {
}
nudge_referendum_rejected {
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin);
place_deposit::<T, I>(index);
@@ -632,7 +632,7 @@ benchmarks_instance_pallet! {
set_some_metadata {
use sp_std::borrow::Cow;
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin.clone());
let hash = T::Preimages::note(Cow::from(vec![5, 6])).unwrap();
@@ -643,7 +643,7 @@ benchmarks_instance_pallet! {
clear_metadata {
use sp_std::borrow::Cow;
let origin = T::SubmitOrigin::try_successful_origin()
let origin = T::SubmitOrigin::try_successful_origin(&RawOrigin::Root.into())
.expect("SubmitOrigin has no successful origin required for the benchmark");
let index = create_referendum::<T, I>(origin.clone());
let hash = T::Preimages::note(Cow::from(vec![6, 7, 8])).unwrap();
+9 -4
View File
@@ -138,7 +138,7 @@ const ASSEMBLY_ID: LockIdentifier = *b"assembly";
#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_support::pallet_prelude::*;
use frame_support::{pallet_prelude::*, traits::EnsureOriginWithArg};
use frame_system::pallet_prelude::*;
/// The current storage version.
@@ -167,7 +167,11 @@ pub mod pallet {
type Currency: ReservableCurrency<Self::AccountId>;
// Origins and unbalances.
/// Origin from which proposals may be submitted.
type SubmitOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Self::AccountId>;
type SubmitOrigin: EnsureOriginWithArg<
Self::RuntimeOrigin,
PalletsOriginOf<Self>,
Success = Self::AccountId,
>;
/// Origin from which any vote may be cancelled.
type CancelOrigin: EnsureOrigin<Self::RuntimeOrigin>;
/// Origin from which any vote may be killed.
@@ -430,7 +434,8 @@ pub mod pallet {
proposal: BoundedCallOf<T, I>,
enactment_moment: DispatchTime<T::BlockNumber>,
) -> DispatchResult {
let who = T::SubmitOrigin::ensure_origin(origin)?;
let proposal_origin = *proposal_origin;
let who = T::SubmitOrigin::ensure_origin(origin, &proposal_origin)?;
let track =
T::Tracks::track_for(&proposal_origin).map_err(|_| Error::<T, I>::NoTrack)?;
@@ -445,7 +450,7 @@ pub mod pallet {
T::Preimages::bound(CallOf::<T, I>::from(Call::nudge_referendum { index }))?;
let status = ReferendumStatus {
track,
origin: *proposal_origin,
origin: proposal_origin,
proposal: proposal.clone(),
enactment: enactment_moment,
submitted: now,
+9 -2
View File
@@ -252,10 +252,11 @@ mod mock;
mod tests;
use frame_support::{
impl_ensure_origin_with_arg_ignoring_arg,
pallet_prelude::*,
traits::{
BalanceStatus, ChangeMembers, Currency, EnsureOrigin, ExistenceRequirement::AllowDeath,
Imbalance, OnUnbalanced, Randomness, ReservableCurrency,
BalanceStatus, ChangeMembers, Currency, EnsureOrigin, EnsureOriginWithArg,
ExistenceRequirement::AllowDeath, Imbalance, OnUnbalanced, Randomness, ReservableCurrency,
},
PalletId,
};
@@ -1181,6 +1182,12 @@ impl<T: Config> EnsureOrigin<T::RuntimeOrigin> for EnsureFounder<T> {
}
}
impl_ensure_origin_with_arg_ignoring_arg! {
impl<{ T: Config, A }>
EnsureOriginWithArg<T::RuntimeOrigin, A> for EnsureFounder<T>
{}
}
/// Pick an item at pseudo-random from the slice, given the `rng`. `None` iff the slice is empty.
fn pick_item<'a, R: RngCore, T>(rng: &mut R, items: &'a [T]) -> Option<&'a T> {
if items.is_empty() {
@@ -418,6 +418,34 @@ fn expand_origin_pallet_conversions(
}
}
}
#attr
impl<'a> TryFrom<&'a OriginCaller> for &'a #pallet_origin {
type Error = ();
fn try_from(
x: &'a OriginCaller,
) -> #scrate::sp_std::result::Result<&'a #pallet_origin, ()> {
if let OriginCaller::#variant_name(l) = x {
Ok(&l)
} else {
Err(())
}
}
}
#attr
impl<'a> TryFrom<&'a RuntimeOrigin> for &'a #pallet_origin {
type Error = ();
fn try_from(
x: &'a RuntimeOrigin,
) -> #scrate::sp_std::result::Result<&'a #pallet_origin, ()> {
if let OriginCaller::#variant_name(l) = &x.caller {
Ok(&l)
} else {
Err(())
}
}
}
}
}
+20
View File
@@ -89,6 +89,26 @@ impl<AccountId> From<Option<AccountId>> for RawOrigin<AccountId> {
}
}
impl<AccountId> RawOrigin<AccountId> {
/// Returns `Some` with a reference to the `AccountId` if `self` is `Signed`, `None` otherwise.
pub fn as_signed(&self) -> Option<&AccountId> {
match &self {
Self::Signed(x) => Some(x),
_ => None,
}
}
/// Returns `true` if `self` is `Root`, `None` otherwise.
pub fn is_root(&self) -> bool {
matches!(&self, Self::Root)
}
/// Returns `true` if `self` is `None`, `None` otherwise.
pub fn is_none(&self) -> bool {
matches!(&self, Self::None)
}
}
/// A type that can be used as a parameter in a dispatchable function.
///
/// When using `decl_module` all arguments for call functions must implement this trait.
+1 -1
View File
@@ -98,7 +98,7 @@ pub use dispatch::EnsureOneOf;
pub use dispatch::{
AsEnsureOriginWithArg, CallerTrait, EitherOf, EitherOfDiverse, EnsureOrigin,
EnsureOriginEqualOrHigherPrivilege, EnsureOriginWithArg, MapSuccess, NeverEnsureOrigin,
OriginTrait, TryMapSuccess, UnfilteredDispatchable,
OriginTrait, TryMapSuccess, TryWithMorphedArg, UnfilteredDispatchable,
};
mod voting;
+161 -13
View File
@@ -48,19 +48,6 @@ pub trait EnsureOrigin<OuterOrigin> {
fn try_successful_origin() -> Result<OuterOrigin, ()>;
}
/// [`EnsureOrigin`] implementation that always fails.
pub struct NeverEnsureOrigin<Success>(sp_std::marker::PhantomData<Success>);
impl<OO, Success> EnsureOrigin<OO> for NeverEnsureOrigin<Success> {
type Success = Success;
fn try_origin(o: OO) -> Result<Success, OO> {
Err(o)
}
#[cfg(feature = "runtime-benchmarks")]
fn try_successful_origin() -> Result<OO, ()> {
Err(())
}
}
/// [`EnsureOrigin`] implementation that checks that an origin has equal or higher privilege
/// compared to the expected `Origin`.
///
@@ -166,6 +153,62 @@ pub trait EnsureOriginWithArg<OuterOrigin, Argument> {
fn try_successful_origin(a: &Argument) -> Result<OuterOrigin, ()>;
}
/// Simple macro to explicitly implement [EnsureOriginWithArg] to be used on any type which
/// implements [EnsureOrigin]. This is quick and dirty, so you must use the type parameters `O`
/// (the origin type), `T` (the argument type) and `AccountId` (if you are using the `O: ..` form).
///
/// The argument is ignored, much like in [AsEnsureOriginWithArg].
#[macro_export]
macro_rules! impl_ensure_origin_with_arg_ignoring_arg {
( impl < { O: .., I: 'static, $( $bound:tt )* }> EnsureOriginWithArg<O, $t_param:ty> for $name:ty {} ) => {
impl_ensure_origin_with_arg_ignoring_arg! {
impl <{
O: Into<Result<RawOrigin<AccountId, I>, O>> + From<RawOrigin<AccountId, I>>,
I: 'static,
$( $bound )*
}> EnsureOriginWithArg<O, $t_param> for $name {}
}
};
( impl < { O: .. , $( $bound:tt )* }> EnsureOriginWithArg<O, $t_param:ty> for $name:ty {} ) => {
impl_ensure_origin_with_arg_ignoring_arg! {
impl <{
O: Into<Result<RawOrigin<AccountId>, O>> + From<RawOrigin<AccountId>>,
$( $bound )*
}> EnsureOriginWithArg<O, $t_param> for $name {}
}
};
( impl < { $( $bound:tt )* } > EnsureOriginWithArg<$o_param:ty, $t_param:ty> for $name:ty {} ) => {
impl < $( $bound )* > EnsureOriginWithArg<$o_param, $t_param> for $name {
type Success = <Self as EnsureOrigin<$o_param>>::Success;
fn try_origin(o: $o_param, _: &$t_param) -> Result<Self::Success, $o_param> {
<Self as EnsureOrigin<$o_param>>::try_origin(o)
}
#[cfg(feature = "runtime-benchmarks")]
fn try_successful_origin(_: &$t_param) -> Result<$o_param, ()> {
<Self as EnsureOrigin<$o_param>>::try_successful_origin()
}
}
}
}
/// [`EnsureOrigin`] implementation that always fails.
pub struct NeverEnsureOrigin<Success>(sp_std::marker::PhantomData<Success>);
impl<OO, Success> EnsureOrigin<OO> for NeverEnsureOrigin<Success> {
type Success = Success;
fn try_origin(o: OO) -> Result<Success, OO> {
Err(o)
}
#[cfg(feature = "runtime-benchmarks")]
fn try_successful_origin() -> Result<OO, ()> {
Err(())
}
}
impl_ensure_origin_with_arg_ignoring_arg! {
impl<{ OO, Success, A }>
EnsureOriginWithArg<OO, A> for NeverEnsureOrigin<Success>
{}
}
pub struct AsEnsureOriginWithArg<EO>(sp_std::marker::PhantomData<EO>);
impl<OuterOrigin, Argument, EO: EnsureOrigin<OuterOrigin>>
EnsureOriginWithArg<OuterOrigin, Argument> for AsEnsureOriginWithArg<EO>
@@ -207,6 +250,18 @@ impl<O, Original: EnsureOrigin<O>, Mutator: Morph<Original::Success>> EnsureOrig
Original::try_successful_origin()
}
}
impl<O, Original: EnsureOriginWithArg<O, A>, Mutator: Morph<Original::Success>, A>
EnsureOriginWithArg<O, A> for MapSuccess<Original, Mutator>
{
type Success = Mutator::Outcome;
fn try_origin(o: O, a: &A) -> Result<Mutator::Outcome, O> {
Ok(Mutator::morph(Original::try_origin(o, a)?))
}
#[cfg(feature = "runtime-benchmarks")]
fn try_successful_origin(a: &A) -> Result<O, ()> {
Original::try_successful_origin(a)
}
}
/// A derivative `EnsureOrigin` implementation. It mutates the `Success` result of an `Original`
/// implementation with a given `Mutator`, allowing the possibility of an error to be returned
@@ -228,6 +283,43 @@ impl<O: Clone, Original: EnsureOrigin<O>, Mutator: TryMorph<Original::Success>>
Original::try_successful_origin()
}
}
impl<O: Clone, Original: EnsureOriginWithArg<O, A>, Mutator: TryMorph<Original::Success>, A>
EnsureOriginWithArg<O, A> for TryMapSuccess<Original, Mutator>
{
type Success = Mutator::Outcome;
fn try_origin(o: O, a: &A) -> Result<Mutator::Outcome, O> {
let orig = o.clone();
Mutator::try_morph(Original::try_origin(o, a)?).map_err(|()| orig)
}
#[cfg(feature = "runtime-benchmarks")]
fn try_successful_origin(a: &A) -> Result<O, ()> {
Original::try_successful_origin(a)
}
}
pub struct TryWithMorphedArg<O, A, Morph, Inner, Success>(
PhantomData<(O, A, Morph, Inner, Success)>,
);
impl<
O,
A,
Morph: for<'a> TryMorph<&'a A>,
Inner: for<'a> EnsureOriginWithArg<O, <Morph as TryMorph<&'a A>>::Outcome, Success = Success>,
Success,
> EnsureOriginWithArg<O, A> for TryWithMorphedArg<O, A, Morph, Inner, Success>
{
type Success = Success;
fn try_origin(o: O, a: &A) -> Result<Success, O> {
match Morph::try_morph(a) {
Ok(x) => Inner::try_origin(o, &x),
_ => return Err(o),
}
}
#[cfg(feature = "runtime-benchmarks")]
fn try_successful_origin(a: &A) -> Result<O, ()> {
Inner::try_successful_origin(&Morph::try_morph(a).map_err(|_| ())?)
}
}
/// "OR gate" implementation of `EnsureOrigin` allowing for different `Success` types for `L`
/// and `R`, with them combined using an `Either` type.
@@ -250,6 +342,24 @@ impl<OuterOrigin, L: EnsureOrigin<OuterOrigin>, R: EnsureOrigin<OuterOrigin>>
L::try_successful_origin().or_else(|()| R::try_successful_origin())
}
}
impl<
OuterOrigin,
L: EnsureOriginWithArg<OuterOrigin, Argument>,
R: EnsureOriginWithArg<OuterOrigin, Argument>,
Argument,
> EnsureOriginWithArg<OuterOrigin, Argument> for EitherOfDiverse<L, R>
{
type Success = Either<L::Success, R::Success>;
fn try_origin(o: OuterOrigin, a: &Argument) -> Result<Self::Success, OuterOrigin> {
L::try_origin(o, a)
.map_or_else(|o| R::try_origin(o, a).map(Either::Right), |o| Ok(Either::Left(o)))
}
#[cfg(feature = "runtime-benchmarks")]
fn try_successful_origin(a: &Argument) -> Result<OuterOrigin, ()> {
L::try_successful_origin(a).or_else(|()| R::try_successful_origin(a))
}
}
/// "OR gate" implementation of `EnsureOrigin` allowing for different `Success` types for `L`
/// and `R`, with them combined using an `Either` type.
@@ -283,6 +393,23 @@ impl<
L::try_successful_origin().or_else(|()| R::try_successful_origin())
}
}
impl<
OuterOrigin,
L: EnsureOriginWithArg<OuterOrigin, Argument>,
R: EnsureOriginWithArg<OuterOrigin, Argument, Success = L::Success>,
Argument,
> EnsureOriginWithArg<OuterOrigin, Argument> for EitherOf<L, R>
{
type Success = L::Success;
fn try_origin(o: OuterOrigin, a: &Argument) -> Result<Self::Success, OuterOrigin> {
L::try_origin(o, a).or_else(|o| R::try_origin(o, a))
}
#[cfg(feature = "runtime-benchmarks")]
fn try_successful_origin(a: &Argument) -> Result<OuterOrigin, ()> {
L::try_successful_origin(a).or_else(|()| R::try_successful_origin(a))
}
}
/// Type that can be dispatched with an origin but without checking the origin filter.
///
@@ -306,6 +433,21 @@ pub trait CallerTrait<AccountId>: Parameter + Member + From<RawOrigin<AccountId>
/// Extract a reference to the system-level `RawOrigin` if it is that.
fn as_system_ref(&self) -> Option<&RawOrigin<AccountId>>;
/// Extract the signer from it if a system `Signed` origin, `None` otherwise.
fn as_signed(&self) -> Option<&AccountId> {
self.as_system_ref().and_then(RawOrigin::as_signed)
}
/// Returns `true` if `self` is a system `Root` origin, `None` otherwise.
fn is_root(&self) -> bool {
self.as_system_ref().map_or(false, RawOrigin::is_root)
}
/// Returns `true` if `self` is a system `None` origin, `None` otherwise.
fn is_none(&self) -> bool {
self.as_system_ref().map_or(false, RawOrigin::is_none)
}
}
/// Methods available on `frame_system::Config::RuntimeOrigin`.
@@ -356,7 +498,13 @@ pub trait OriginTrait: Sized {
fn signed(by: Self::AccountId) -> Self;
/// Extract the signer from the message if it is a `Signed` origin.
#[deprecated = "Use `into_signer` instead"]
fn as_signed(self) -> Option<Self::AccountId> {
self.into_signer()
}
/// Extract the signer from the message if it is a `Signed` origin.
fn into_signer(self) -> Option<Self::AccountId> {
self.into_caller().into_system().and_then(|s| {
if let RawOrigin::Signed(who) = s {
Some(who)
+43 -6
View File
@@ -89,10 +89,11 @@ use frame_support::{
extract_actual_pays_fee, extract_actual_weight, DispatchClass, DispatchInfo,
DispatchResult, DispatchResultWithPostInfo, PerDispatchClass,
},
impl_ensure_origin_with_arg_ignoring_arg,
storage::{self, StorageStreamIter},
traits::{
ConstU32, Contains, EnsureOrigin, Get, HandleLifetime, OnKilledAccount, OnNewAccount,
OriginTrait, PalletInfo, SortedMembers, StoredMap, TypedGet,
ConstU32, Contains, EnsureOrigin, EnsureOriginWithArg, Get, HandleLifetime,
OnKilledAccount, OnNewAccount, OriginTrait, PalletInfo, SortedMembers, StoredMap, TypedGet,
},
Parameter,
};
@@ -265,7 +266,7 @@ pub mod pallet {
type RuntimeOrigin: Into<Result<RawOrigin<Self::AccountId>, Self::RuntimeOrigin>>
+ From<RawOrigin<Self::AccountId>>
+ Clone
+ OriginTrait<Call = Self::RuntimeCall>;
+ OriginTrait<Call = Self::RuntimeCall, AccountId = Self::AccountId>;
/// The aggregated `RuntimeCall` type.
#[pallet::no_default]
@@ -823,6 +824,12 @@ impl<O: Into<Result<RawOrigin<AccountId>, O>> + From<RawOrigin<AccountId>>, Acco
}
}
impl_ensure_origin_with_arg_ignoring_arg! {
impl< { O: .., AccountId: Decode, T } >
EnsureOriginWithArg<O, T> for EnsureRoot<AccountId>
{}
}
/// Ensure the origin is Root and return the provided `Success` value.
pub struct EnsureRootWithSuccess<AccountId, Success>(
sp_std::marker::PhantomData<(AccountId, Success)>,
@@ -847,6 +854,12 @@ impl<
}
}
impl_ensure_origin_with_arg_ignoring_arg! {
impl< { O: .., AccountId: Decode, Success: TypedGet, T } >
EnsureOriginWithArg<O, T> for EnsureRootWithSuccess<AccountId, Success>
{}
}
/// Ensure the origin is provided `Ensure` origin and return the provided `Success` value.
pub struct EnsureWithSuccess<Ensure, AccountId, Success>(
sp_std::marker::PhantomData<(Ensure, AccountId, Success)>,
@@ -892,6 +905,12 @@ impl<O: Into<Result<RawOrigin<AccountId>, O>> + From<RawOrigin<AccountId>>, Acco
}
}
impl_ensure_origin_with_arg_ignoring_arg! {
impl< { O: .., AccountId: Decode, T } >
EnsureOriginWithArg<O, T> for EnsureSigned<AccountId>
{}
}
/// Ensure the origin is `Signed` origin from the given `AccountId`.
pub struct EnsureSignedBy<Who, AccountId>(sp_std::marker::PhantomData<(Who, AccountId)>);
impl<
@@ -918,6 +937,12 @@ impl<
}
}
impl_ensure_origin_with_arg_ignoring_arg! {
impl< { O: .., Who: SortedMembers<AccountId>, AccountId: PartialEq + Clone + Ord + Decode, T } >
EnsureOriginWithArg<O, T> for EnsureSignedBy<Who, AccountId>
{}
}
/// Ensure the origin is `None`. i.e. unsigned transaction.
pub struct EnsureNone<AccountId>(sp_std::marker::PhantomData<AccountId>);
impl<O: Into<Result<RawOrigin<AccountId>, O>> + From<RawOrigin<AccountId>>, AccountId>
@@ -937,10 +962,16 @@ impl<O: Into<Result<RawOrigin<AccountId>, O>> + From<RawOrigin<AccountId>>, Acco
}
}
impl_ensure_origin_with_arg_ignoring_arg! {
impl< { O: .., AccountId, T } >
EnsureOriginWithArg<O, T> for EnsureNone<AccountId>
{}
}
/// Always fail.
pub struct EnsureNever<T>(sp_std::marker::PhantomData<T>);
impl<O, T> EnsureOrigin<O> for EnsureNever<T> {
type Success = T;
pub struct EnsureNever<Success>(sp_std::marker::PhantomData<Success>);
impl<O, Success> EnsureOrigin<O> for EnsureNever<Success> {
type Success = Success;
fn try_origin(o: O) -> Result<Self::Success, O> {
Err(o)
}
@@ -951,6 +982,12 @@ impl<O, T> EnsureOrigin<O> for EnsureNever<T> {
}
}
impl_ensure_origin_with_arg_ignoring_arg! {
impl< { O, Success, T } >
EnsureOriginWithArg<O, T> for EnsureNever<Success>
{}
}
/// 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>
+8 -7
View File
@@ -746,19 +746,20 @@ fn ensure_signed_stuff_works() {
}
let signed_origin = RuntimeOrigin::signed(0u64);
assert_ok!(EnsureSigned::try_origin(signed_origin.clone()));
assert_ok!(EnsureSignedBy::<Members, _>::try_origin(signed_origin));
assert_ok!(<EnsureSigned<_> as EnsureOrigin<_>>::try_origin(signed_origin.clone()));
assert_ok!(<EnsureSignedBy<Members, _> as EnsureOrigin<_>>::try_origin(signed_origin));
#[cfg(feature = "runtime-benchmarks")]
{
let successful_origin: RuntimeOrigin = EnsureSigned::try_successful_origin()
.expect("EnsureSigned has no successful origin required for the test");
assert_ok!(EnsureSigned::try_origin(successful_origin));
let successful_origin: RuntimeOrigin =
<EnsureSigned<_> as EnsureOrigin<_>>::try_successful_origin()
.expect("EnsureSigned has no successful origin required for the test");
assert_ok!(<EnsureSigned<_> as EnsureOrigin<_>>::try_origin(successful_origin));
let successful_origin: RuntimeOrigin =
EnsureSignedBy::<Members, _>::try_successful_origin()
<EnsureSignedBy<Members, _> as EnsureOrigin<_>>::try_successful_origin()
.expect("EnsureSignedBy has no successful origin required for the test");
assert_ok!(EnsureSignedBy::<Members, _>::try_origin(successful_origin));
assert_ok!(<EnsureSignedBy<Members, _> as EnsureOrigin<_>>::try_origin(successful_origin));
}
}
@@ -339,6 +339,33 @@ impl<T, A: TryInto<T>> TryMorph<A> for TryMorphInto<T> {
}
}
/// Implementation of `Morph` to retrieve just the first element of a tuple.
pub struct TakeFirst;
impl<T1> Morph<(T1,)> for TakeFirst {
type Outcome = T1;
fn morph(a: (T1,)) -> T1 {
a.0
}
}
impl<T1, T2> Morph<(T1, T2)> for TakeFirst {
type Outcome = T1;
fn morph(a: (T1, T2)) -> T1 {
a.0
}
}
impl<T1, T2, T3> Morph<(T1, T2, T3)> for TakeFirst {
type Outcome = T1;
fn morph(a: (T1, T2, T3)) -> T1 {
a.0
}
}
impl<T1, T2, T3, T4> Morph<(T1, T2, T3, T4)> for TakeFirst {
type Outcome = T1;
fn morph(a: (T1, T2, T3, T4)) -> T1 {
a.0
}
}
/// Create a `Morph` and/or `TryMorph` impls with a simple closure-like expression.
///
/// # Examples