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

* move EnsureOneOf into the dispatch.rs, make an interface more general

* Update frame/support/src/traits/dispatch.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
Alex Pozhylenkov
2021-12-01 23:31:57 +02:00
committed by GitHub
parent a18749d315
commit 1d19c7dc7f
7 changed files with 72 additions and 51 deletions
+1 -1
View File
@@ -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};
+59 -1
View File
@@ -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> {
@@ -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)>);
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());
}
}