frame_support/traits/
dispatch.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Traits for dealing with dispatching calls and the origin from which they are dispatched.
19
20use crate::dispatch::{DispatchResultWithPostInfo, Parameter, RawOrigin};
21use codec::MaxEncodedLen;
22use core::{cmp::Ordering, marker::PhantomData};
23use sp_runtime::{
24	traits::{BadOrigin, Get, Member, Morph, TryMorph},
25	transaction_validity::{TransactionSource, TransactionValidityError, ValidTransaction},
26	Either,
27};
28use sp_weights::Weight;
29
30use super::misc;
31
32/// Some sort of check on the origin is performed by this object.
33pub trait EnsureOrigin<OuterOrigin> {
34	/// A return type.
35	type Success;
36
37	/// Perform the origin check.
38	fn ensure_origin(o: OuterOrigin) -> Result<Self::Success, BadOrigin> {
39		Self::try_origin(o).map_err(|_| BadOrigin)
40	}
41
42	/// The same as `ensure_origin` except that Root origin will always pass. This can only be
43	/// used if `Success` has a sensible impl of `Default` since that will be used in the result.
44	fn ensure_origin_or_root(o: OuterOrigin) -> Result<Option<Self::Success>, BadOrigin>
45	where
46		OuterOrigin: OriginTrait,
47	{
48		if o.caller().is_root() {
49			return Ok(None)
50		} else {
51			Self::ensure_origin(o).map(Some)
52		}
53	}
54
55	/// Perform the origin check.
56	fn try_origin(o: OuterOrigin) -> Result<Self::Success, OuterOrigin>;
57
58	/// The same as `try_origin` except that Root origin will always pass. This can only be
59	/// used if `Success` has a sensible impl of `Default` since that will be used in the result.
60	fn try_origin_or_root(o: OuterOrigin) -> Result<Option<Self::Success>, OuterOrigin>
61	where
62		OuterOrigin: OriginTrait,
63	{
64		if o.caller().is_root() {
65			return Ok(None)
66		} else {
67			Self::try_origin(o).map(Some)
68		}
69	}
70
71	/// Attempt to get an outer origin capable of passing `try_origin` check. May return `Err` if it
72	/// is impossible.
73	///
74	/// ** Should be used for benchmarking only!!! **
75	#[cfg(feature = "runtime-benchmarks")]
76	fn try_successful_origin() -> Result<OuterOrigin, ()>;
77}
78
79/// [`EnsureOrigin`] implementation that checks that an origin has equal or higher privilege
80/// compared to the expected `Origin`.
81///
82/// It will take the shortcut of comparing the incoming origin with the expected `Origin` and if
83/// both are the same the origin is accepted.
84///
85/// # Example
86///
87/// ```rust
88/// # use frame_support::traits::{EnsureOriginEqualOrHigherPrivilege, PrivilegeCmp, EnsureOrigin as _};
89/// # use sp_runtime::traits::{parameter_types, Get};
90/// # use core::cmp::Ordering;
91///
92/// #[derive(Eq, PartialEq, Debug)]
93/// pub enum Origin {
94///     Root,
95///     SomethingBelowRoot,
96///     NormalUser,
97/// }
98///
99/// struct OriginPrivilegeCmp;
100///
101/// impl PrivilegeCmp<Origin> for OriginPrivilegeCmp {
102///     fn cmp_privilege(left: &Origin, right: &Origin) -> Option<Ordering> {
103///         match (left, right) {
104///             (Origin::Root, Origin::Root) => Some(Ordering::Equal),
105///             (Origin::Root, _) => Some(Ordering::Greater),
106///             (Origin::SomethingBelowRoot, Origin::SomethingBelowRoot) => Some(Ordering::Equal),
107///             (Origin::SomethingBelowRoot, Origin::Root) => Some(Ordering::Less),
108///             (Origin::SomethingBelowRoot, Origin::NormalUser) => Some(Ordering::Greater),
109///             (Origin::NormalUser, Origin::NormalUser) => Some(Ordering::Equal),
110///             (Origin::NormalUser, _) => Some(Ordering::Less),
111///         }
112///     }
113/// }
114///
115/// parameter_types! {
116///     pub const ExpectedOrigin: Origin = Origin::SomethingBelowRoot;
117/// }
118///
119/// type EnsureOrigin = EnsureOriginEqualOrHigherPrivilege<ExpectedOrigin, OriginPrivilegeCmp>;
120///
121/// // `Root` has an higher privilege as our expected origin.
122/// assert!(EnsureOrigin::ensure_origin(Origin::Root).is_ok());
123/// // `SomethingBelowRoot` is exactly the expected origin.
124/// assert!(EnsureOrigin::ensure_origin(Origin::SomethingBelowRoot).is_ok());
125/// // The `NormalUser` origin is not allowed.
126/// assert!(EnsureOrigin::ensure_origin(Origin::NormalUser).is_err());
127/// ```
128pub struct EnsureOriginEqualOrHigherPrivilege<Origin, PrivilegeCmp>(
129	core::marker::PhantomData<(Origin, PrivilegeCmp)>,
130);
131
132impl<OuterOrigin, Origin, PrivilegeCmp> EnsureOrigin<OuterOrigin>
133	for EnsureOriginEqualOrHigherPrivilege<Origin, PrivilegeCmp>
134where
135	Origin: Get<OuterOrigin>,
136	OuterOrigin: Eq,
137	PrivilegeCmp: misc::PrivilegeCmp<OuterOrigin>,
138{
139	type Success = ();
140
141	fn try_origin(o: OuterOrigin) -> Result<Self::Success, OuterOrigin> {
142		let expected_origin = Origin::get();
143
144		// If this is the expected origin, it has the same privilege.
145		if o == expected_origin {
146			return Ok(())
147		}
148
149		let cmp = PrivilegeCmp::cmp_privilege(&o, &expected_origin);
150
151		match cmp {
152			Some(Ordering::Equal) | Some(Ordering::Greater) => Ok(()),
153			None | Some(Ordering::Less) => Err(o),
154		}
155	}
156
157	#[cfg(feature = "runtime-benchmarks")]
158	fn try_successful_origin() -> Result<OuterOrigin, ()> {
159		Ok(Origin::get())
160	}
161}
162
163/// Some sort of check on the origin is performed by this object.
164pub trait EnsureOriginWithArg<OuterOrigin, Argument> {
165	/// A return type.
166	type Success;
167
168	/// Perform the origin check.
169	fn ensure_origin(o: OuterOrigin, a: &Argument) -> Result<Self::Success, BadOrigin> {
170		Self::try_origin(o, a).map_err(|_| BadOrigin)
171	}
172
173	/// Perform the origin check, returning the origin value if unsuccessful. This allows chaining.
174	fn try_origin(o: OuterOrigin, a: &Argument) -> Result<Self::Success, OuterOrigin>;
175
176	/// Attempt to get an outer origin capable of passing `try_origin` check. May return `Err` if it
177	/// is impossible.
178	///
179	/// ** Should be used for benchmarking only!!! **
180	#[cfg(feature = "runtime-benchmarks")]
181	fn try_successful_origin(a: &Argument) -> Result<OuterOrigin, ()>;
182}
183
184/// Simple macro to explicitly implement [EnsureOriginWithArg] to be used on any type which
185/// implements [EnsureOrigin]. This is quick and dirty, so you must use the type parameters `O`
186/// (the origin type), `T` (the argument type) and `AccountId` (if you are using the `O: ..` form).
187///
188/// The argument is ignored, much like in [AsEnsureOriginWithArg].
189#[macro_export]
190macro_rules! impl_ensure_origin_with_arg_ignoring_arg {
191	( impl < { O: .., I: 'static, $( $bound:tt )* }> EnsureOriginWithArg<O, $t_param:ty> for $name:ty {} ) => {
192		impl_ensure_origin_with_arg_ignoring_arg! {
193			impl <{
194				O: $crate::traits::OriginTrait,
195				I: 'static,
196				$( $bound )*
197			}> EnsureOriginWithArg<O, $t_param> for $name {}
198		}
199	};
200	( impl < { O: .. , $( $bound:tt )* }> EnsureOriginWithArg<O, $t_param:ty> for $name:ty {} ) => {
201		impl_ensure_origin_with_arg_ignoring_arg! {
202			impl <{
203				O: $crate::traits::OriginTrait,
204				$( $bound )*
205			}> EnsureOriginWithArg<O, $t_param> for $name {}
206		}
207	};
208	( impl < { $( $bound:tt )* } > EnsureOriginWithArg<$o_param:ty, $t_param:ty> for $name:ty {} ) => {
209		impl < $( $bound )* > EnsureOriginWithArg<$o_param, $t_param> for $name {
210			type Success = <Self as EnsureOrigin<$o_param>>::Success;
211			fn try_origin(o: $o_param, _: &$t_param) -> Result<Self::Success, $o_param> {
212				<Self as EnsureOrigin<$o_param>>::try_origin(o)
213			}
214			#[cfg(feature = "runtime-benchmarks")]
215			fn try_successful_origin(_: &$t_param) -> Result<$o_param, ()> {
216				<Self as EnsureOrigin<$o_param>>::try_successful_origin()
217			}
218		}
219	}
220}
221
222/// [`EnsureOrigin`] implementation that always fails.
223pub struct NeverEnsureOrigin<Success>(core::marker::PhantomData<Success>);
224impl<OO, Success> EnsureOrigin<OO> for NeverEnsureOrigin<Success> {
225	type Success = Success;
226	fn try_origin(o: OO) -> Result<Success, OO> {
227		Err(o)
228	}
229	#[cfg(feature = "runtime-benchmarks")]
230	fn try_successful_origin() -> Result<OO, ()> {
231		Err(())
232	}
233}
234impl_ensure_origin_with_arg_ignoring_arg! {
235	impl<{ OO, Success, A }>
236		EnsureOriginWithArg<OO, A> for NeverEnsureOrigin<Success>
237	{}
238}
239
240pub struct AsEnsureOriginWithArg<EO>(core::marker::PhantomData<EO>);
241impl<OuterOrigin, Argument, EO: EnsureOrigin<OuterOrigin>>
242	EnsureOriginWithArg<OuterOrigin, Argument> for AsEnsureOriginWithArg<EO>
243{
244	/// A return type.
245	type Success = EO::Success;
246
247	/// Perform the origin check.
248	fn ensure_origin(o: OuterOrigin, _: &Argument) -> Result<Self::Success, BadOrigin> {
249		EO::ensure_origin(o)
250	}
251
252	/// Perform the origin check, returning the origin value if unsuccessful. This allows chaining.
253	fn try_origin(o: OuterOrigin, _: &Argument) -> Result<Self::Success, OuterOrigin> {
254		EO::try_origin(o)
255	}
256
257	/// Returns an outer origin capable of passing `try_origin` check.
258	///
259	/// ** Should be used for benchmarking only!!! **
260	#[cfg(feature = "runtime-benchmarks")]
261	fn try_successful_origin(_: &Argument) -> Result<OuterOrigin, ()> {
262		EO::try_successful_origin()
263	}
264}
265
266/// A derivative `EnsureOrigin` implementation. It mutates the `Success` result of an `Original`
267/// implementation with a given `Mutator`.
268pub struct MapSuccess<Original, Mutator>(PhantomData<(Original, Mutator)>);
269impl<O, Original: EnsureOrigin<O>, Mutator: Morph<Original::Success>> EnsureOrigin<O>
270	for MapSuccess<Original, Mutator>
271{
272	type Success = Mutator::Outcome;
273	fn try_origin(o: O) -> Result<Mutator::Outcome, O> {
274		Ok(Mutator::morph(Original::try_origin(o)?))
275	}
276	#[cfg(feature = "runtime-benchmarks")]
277	fn try_successful_origin() -> Result<O, ()> {
278		Original::try_successful_origin()
279	}
280}
281impl<O, Original: EnsureOriginWithArg<O, A>, Mutator: Morph<Original::Success>, A>
282	EnsureOriginWithArg<O, A> for MapSuccess<Original, Mutator>
283{
284	type Success = Mutator::Outcome;
285	fn try_origin(o: O, a: &A) -> Result<Mutator::Outcome, O> {
286		Ok(Mutator::morph(Original::try_origin(o, a)?))
287	}
288	#[cfg(feature = "runtime-benchmarks")]
289	fn try_successful_origin(a: &A) -> Result<O, ()> {
290		Original::try_successful_origin(a)
291	}
292}
293
294/// A derivative `EnsureOrigin` implementation. It mutates the `Success` result of an `Original`
295/// implementation with a given `Mutator`, allowing the possibility of an error to be returned
296/// from the mutator.
297///
298/// NOTE: This is strictly worse performance than `MapSuccess` since it clones the original origin
299/// value. If possible, use `MapSuccess` instead.
300pub struct TryMapSuccess<Orig, Mutator>(PhantomData<(Orig, Mutator)>);
301impl<O: Clone, Original: EnsureOrigin<O>, Mutator: TryMorph<Original::Success>> EnsureOrigin<O>
302	for TryMapSuccess<Original, Mutator>
303{
304	type Success = Mutator::Outcome;
305	fn try_origin(o: O) -> Result<Mutator::Outcome, O> {
306		let orig = o.clone();
307		Mutator::try_morph(Original::try_origin(o)?).map_err(|()| orig)
308	}
309	#[cfg(feature = "runtime-benchmarks")]
310	fn try_successful_origin() -> Result<O, ()> {
311		Original::try_successful_origin()
312	}
313}
314impl<O: Clone, Original: EnsureOriginWithArg<O, A>, Mutator: TryMorph<Original::Success>, A>
315	EnsureOriginWithArg<O, A> for TryMapSuccess<Original, Mutator>
316{
317	type Success = Mutator::Outcome;
318	fn try_origin(o: O, a: &A) -> Result<Mutator::Outcome, O> {
319		let orig = o.clone();
320		Mutator::try_morph(Original::try_origin(o, a)?).map_err(|()| orig)
321	}
322	#[cfg(feature = "runtime-benchmarks")]
323	fn try_successful_origin(a: &A) -> Result<O, ()> {
324		Original::try_successful_origin(a)
325	}
326}
327
328pub struct TryWithMorphedArg<O, A, Morph, Inner, Success>(
329	PhantomData<(O, A, Morph, Inner, Success)>,
330);
331impl<
332		O,
333		A,
334		Morph: for<'a> TryMorph<&'a A>,
335		Inner: for<'a> EnsureOriginWithArg<O, <Morph as TryMorph<&'a A>>::Outcome, Success = Success>,
336		Success,
337	> EnsureOriginWithArg<O, A> for TryWithMorphedArg<O, A, Morph, Inner, Success>
338{
339	type Success = Success;
340	fn try_origin(o: O, a: &A) -> Result<Success, O> {
341		match Morph::try_morph(a) {
342			Ok(x) => Inner::try_origin(o, &x),
343			_ => return Err(o),
344		}
345	}
346	#[cfg(feature = "runtime-benchmarks")]
347	fn try_successful_origin(a: &A) -> Result<O, ()> {
348		Inner::try_successful_origin(&Morph::try_morph(a).map_err(|_| ())?)
349	}
350}
351
352/// "OR gate" implementation of `EnsureOrigin` allowing for different `Success` types for `L`
353/// and `R`, with them combined using an `Either` type.
354///
355/// Origin check will pass if `L` or `R` origin check passes. `L` is tested first.
356///
357/// Successful origin is derived from the left side.
358pub struct EitherOfDiverse<L, R>(core::marker::PhantomData<(L, R)>);
359impl<OuterOrigin, L: EnsureOrigin<OuterOrigin>, R: EnsureOrigin<OuterOrigin>>
360	EnsureOrigin<OuterOrigin> for EitherOfDiverse<L, R>
361{
362	type Success = Either<L::Success, R::Success>;
363	fn try_origin(o: OuterOrigin) -> Result<Self::Success, OuterOrigin> {
364		L::try_origin(o)
365			.map_or_else(|o| R::try_origin(o).map(Either::Right), |o| Ok(Either::Left(o)))
366	}
367
368	#[cfg(feature = "runtime-benchmarks")]
369	fn try_successful_origin() -> Result<OuterOrigin, ()> {
370		L::try_successful_origin().or_else(|()| R::try_successful_origin())
371	}
372}
373impl<
374		OuterOrigin,
375		L: EnsureOriginWithArg<OuterOrigin, Argument>,
376		R: EnsureOriginWithArg<OuterOrigin, Argument>,
377		Argument,
378	> EnsureOriginWithArg<OuterOrigin, Argument> for EitherOfDiverse<L, R>
379{
380	type Success = Either<L::Success, R::Success>;
381	fn try_origin(o: OuterOrigin, a: &Argument) -> Result<Self::Success, OuterOrigin> {
382		L::try_origin(o, a)
383			.map_or_else(|o| R::try_origin(o, a).map(Either::Right), |o| Ok(Either::Left(o)))
384	}
385
386	#[cfg(feature = "runtime-benchmarks")]
387	fn try_successful_origin(a: &Argument) -> Result<OuterOrigin, ()> {
388		L::try_successful_origin(a).or_else(|()| R::try_successful_origin(a))
389	}
390}
391
392/// "OR gate" implementation of `EnsureOrigin` allowing for different `Success` types for `L`
393/// and `R`, with them combined using an `Either` type.
394///
395/// Origin check will pass if `L` or `R` origin check passes. `L` is tested first.
396///
397/// Successful origin is derived from the left side.
398#[deprecated = "Use `EitherOfDiverse` instead"]
399pub type EnsureOneOf<L, R> = EitherOfDiverse<L, R>;
400
401/// "OR gate" implementation of `EnsureOrigin`, `Success` type for both `L` and `R` must
402/// be equal.
403///
404/// Origin check will pass if `L` or `R` origin check passes. `L` is tested first.
405///
406/// Successful origin is derived from the left side.
407pub struct EitherOf<L, R>(core::marker::PhantomData<(L, R)>);
408impl<
409		OuterOrigin,
410		L: EnsureOrigin<OuterOrigin>,
411		R: EnsureOrigin<OuterOrigin, Success = L::Success>,
412	> EnsureOrigin<OuterOrigin> for EitherOf<L, R>
413{
414	type Success = L::Success;
415	fn try_origin(o: OuterOrigin) -> Result<Self::Success, OuterOrigin> {
416		L::try_origin(o).or_else(|o| R::try_origin(o))
417	}
418
419	#[cfg(feature = "runtime-benchmarks")]
420	fn try_successful_origin() -> Result<OuterOrigin, ()> {
421		L::try_successful_origin().or_else(|()| R::try_successful_origin())
422	}
423}
424impl<
425		OuterOrigin,
426		L: EnsureOriginWithArg<OuterOrigin, Argument>,
427		R: EnsureOriginWithArg<OuterOrigin, Argument, Success = L::Success>,
428		Argument,
429	> EnsureOriginWithArg<OuterOrigin, Argument> for EitherOf<L, R>
430{
431	type Success = L::Success;
432	fn try_origin(o: OuterOrigin, a: &Argument) -> Result<Self::Success, OuterOrigin> {
433		L::try_origin(o, a).or_else(|o| R::try_origin(o, a))
434	}
435
436	#[cfg(feature = "runtime-benchmarks")]
437	fn try_successful_origin(a: &Argument) -> Result<OuterOrigin, ()> {
438		L::try_successful_origin(a).or_else(|()| R::try_successful_origin(a))
439	}
440}
441
442/// Type that can be dispatched with an origin but without checking the origin filter.
443///
444/// Implemented for pallet dispatchable type by `decl_module` and for runtime dispatchable by
445/// `construct_runtime`.
446pub trait UnfilteredDispatchable {
447	/// The origin type of the runtime, (i.e. `frame_system::Config::RuntimeOrigin`).
448	type RuntimeOrigin;
449
450	/// Dispatch this call but do not check the filter in origin.
451	fn dispatch_bypass_filter(self, origin: Self::RuntimeOrigin) -> DispatchResultWithPostInfo;
452}
453
454/// The trait implemented by the overarching enumeration of the different pallets' origins.
455/// Unlike `OriginTrait` impls, this does not include any kind of dispatch/call filter. Also, this
456/// trait is more flexible in terms of how it can be used: it is a `Parameter` and `Member`, so it
457/// can be used as dispatchable parameters as well as in storage items.
458pub trait CallerTrait<AccountId>: Parameter + Member + From<RawOrigin<AccountId>> {
459	/// Extract the signer from the message if it is a `Signed` origin.
460	fn into_system(self) -> Option<RawOrigin<AccountId>>;
461
462	/// Extract a reference to the system-level `RawOrigin` if it is that.
463	fn as_system_ref(&self) -> Option<&RawOrigin<AccountId>>;
464
465	/// Extract the signer from it if a system `Signed` origin, `None` otherwise.
466	fn as_signed(&self) -> Option<&AccountId> {
467		self.as_system_ref().and_then(RawOrigin::as_signed)
468	}
469
470	/// Returns `true` if `self` is a system `Root` origin, `None` otherwise.
471	fn is_root(&self) -> bool {
472		self.as_system_ref().map_or(false, RawOrigin::is_root)
473	}
474
475	/// Returns `true` if `self` is a system `None` origin, `None` otherwise.
476	fn is_none(&self) -> bool {
477		self.as_system_ref().map_or(false, RawOrigin::is_none)
478	}
479}
480
481/// Methods available on `frame_system::Config::RuntimeOrigin`.
482pub trait OriginTrait: Sized {
483	/// Runtime call type, as in `frame_system::Config::Call`
484	type Call;
485
486	/// The caller origin, overarching type of all pallets origins.
487	type PalletsOrigin: Send + Sync + Into<Self> + CallerTrait<Self::AccountId> + MaxEncodedLen;
488
489	/// The AccountId used across the system.
490	type AccountId;
491
492	/// Add a filter to the origin.
493	fn add_filter(&mut self, filter: impl Fn(&Self::Call) -> bool + 'static);
494
495	/// Reset origin filters to default one, i.e `frame_system::1fig::BaseCallFilter`.
496	fn reset_filter(&mut self);
497
498	/// Replace the caller with caller from the other origin
499	fn set_caller_from(&mut self, other: impl Into<Self>);
500
501	/// Replace the caller with caller from the other origin
502	fn set_caller(&mut self, caller: Self::PalletsOrigin);
503
504	/// Replace the caller with caller from the other origin
505	fn set_caller_from_signed(&mut self, caller_account: Self::AccountId) {
506		self.set_caller(Self::PalletsOrigin::from(RawOrigin::Signed(caller_account)))
507	}
508
509	/// Filter the call if caller is not root, if false is returned then the call must be filtered
510	/// out.
511	///
512	/// For root origin caller, the filters are bypassed and true is returned.
513	fn filter_call(&self, call: &Self::Call) -> bool;
514
515	/// Get a reference to the caller (`CallerTrait` impl).
516	fn caller(&self) -> &Self::PalletsOrigin;
517
518	/// Consume `self` and return the caller.
519	fn into_caller(self) -> Self::PalletsOrigin;
520
521	/// Do something with the caller, consuming self but returning it if the caller was unused.
522	fn try_with_caller<R>(
523		self,
524		f: impl FnOnce(Self::PalletsOrigin) -> Result<R, Self::PalletsOrigin>,
525	) -> Result<R, Self>;
526
527	/// Create with system none origin and `frame_system::Config::BaseCallFilter`.
528	fn none() -> Self;
529
530	/// Create with system root origin and `frame_system::Config::BaseCallFilter`.
531	fn root() -> Self;
532
533	/// Create with system signed origin and `frame_system::Config::BaseCallFilter`.
534	fn signed(by: Self::AccountId) -> Self;
535
536	/// Extract the signer from the message if it is a `Signed` origin.
537	#[deprecated = "Use `into_signer` instead"]
538	fn as_signed(self) -> Option<Self::AccountId> {
539		self.into_signer()
540	}
541
542	/// Extract the signer from the message if it is a `Signed` origin.
543	fn into_signer(self) -> Option<Self::AccountId> {
544		self.into_caller().into_system().and_then(|s| {
545			if let RawOrigin::Signed(who) = s {
546				Some(who)
547			} else {
548				None
549			}
550		})
551	}
552
553	/// Extract a reference to the system origin, if that's what the caller is.
554	fn as_system_ref(&self) -> Option<&RawOrigin<Self::AccountId>> {
555		self.caller().as_system_ref()
556	}
557
558	/// Extract a reference to the signer, if that's what the caller is.
559	fn as_signer(&self) -> Option<&Self::AccountId> {
560		self.caller().as_system_ref().and_then(|s| {
561			if let RawOrigin::Signed(ref who) = s {
562				Some(who)
563			} else {
564				None
565			}
566		})
567	}
568}
569
570/// A trait to allow calls to authorize themselves from the origin `None`.
571///
572/// It is implemented by the [`crate::pallet`] macro and used by the
573/// `frame_system::AuthorizeCall` transaction extension.
574///
575/// Pallet writers can declare the authorization logic for a call using the call attribute:
576/// [`crate::pallet_macros::authorize`].
577pub trait Authorize {
578	/// The authorize function.
579	///
580	/// Returns
581	/// * `Some(Ok((valid_transaction, unspent weight)))` if the call is successfully authorized,
582	/// * `Some(Err(error))` if the call authorization is invalid,
583	/// * `None` if the call doesn't provide any authorization.
584	fn authorize(
585		&self,
586		source: TransactionSource,
587	) -> Option<Result<(ValidTransaction, Weight), TransactionValidityError>>;
588
589	/// The weight of the authorization function.
590	fn weight_of_authorize(&self) -> Weight;
591}
592
593#[cfg(test)]
594mod tests {
595	use super::*;
596	use crate::traits::{ConstBool, ConstU8, TypedGet};
597	use std::marker::PhantomData;
598
599	struct EnsureSuccess<V>(PhantomData<V>);
600	struct EnsureFail<T>(PhantomData<T>);
601
602	impl<V: TypedGet> EnsureOrigin<()> for EnsureSuccess<V> {
603		type Success = V::Type;
604		fn try_origin(_: ()) -> Result<Self::Success, ()> {
605			Ok(V::get())
606		}
607		#[cfg(feature = "runtime-benchmarks")]
608		fn try_successful_origin() -> Result<(), ()> {
609			Ok(())
610		}
611	}
612
613	impl<T> EnsureOrigin<()> for EnsureFail<T> {
614		type Success = T;
615		fn try_origin(_: ()) -> Result<Self::Success, ()> {
616			Err(())
617		}
618		#[cfg(feature = "runtime-benchmarks")]
619		fn try_successful_origin() -> Result<(), ()> {
620			Err(())
621		}
622	}
623
624	#[test]
625	fn either_of_diverse_works() {
626		assert_eq!(
627			EitherOfDiverse::<
628				EnsureSuccess<ConstBool<true>>,
629				EnsureSuccess<ConstU8<0>>,
630			>::try_origin(()).unwrap().left(),
631			Some(true)
632		);
633		assert_eq!(
634			EitherOfDiverse::<EnsureSuccess<ConstBool<true>>, EnsureFail<u8>>::try_origin(())
635				.unwrap()
636				.left(),
637			Some(true)
638		);
639		assert_eq!(
640			EitherOfDiverse::<EnsureFail<bool>, EnsureSuccess<ConstU8<0>>>::try_origin(())
641				.unwrap()
642				.right(),
643			Some(0u8)
644		);
645		assert!(EitherOfDiverse::<EnsureFail<bool>, EnsureFail<u8>>::try_origin(()).is_err());
646	}
647
648	#[test]
649	fn either_of_works() {
650		assert_eq!(
651			EitherOf::<
652				EnsureSuccess<ConstBool<true>>,
653				EnsureSuccess<ConstBool<false>>,
654			>::try_origin(()).unwrap(),
655			true
656		);
657		assert_eq!(
658			EitherOf::<EnsureSuccess<ConstBool<true>>, EnsureFail<bool>>::try_origin(()).unwrap(),
659			true
660		);
661		assert_eq!(
662			EitherOf::<EnsureFail<bool>, EnsureSuccess<ConstBool<false>>>::try_origin(()).unwrap(),
663			false
664		);
665		assert!(EitherOf::<EnsureFail<bool>, EnsureFail<bool>>::try_origin(()).is_err());
666	}
667}