sp-runtime 46.0.0

Runtime Modules shared primitive types.
Documentation
// This file is part of Substrate.

// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! The [DispatchTransaction] trait.

use crate::{
	generic::ExtensionVersion,
	traits::AsTransactionAuthorizedOrigin,
	transaction_validity::{InvalidTransaction, TransactionSource},
};

use super::*;

/// Single-function utility trait with a blanket impl over [`TransactionExtension`] in order to
/// provide transaction dispatching functionality. We avoid implementing this directly on the trait
/// since we never want it to be overriden by the trait implementation.
pub trait DispatchTransaction<Call: Dispatchable> {
	/// The origin type of the transaction.
	type Origin;
	/// The info type.
	type Info;
	/// The resultant type.
	type Result;
	/// The `Val` of the extension.
	type Val;
	/// The `Pre` of the extension.
	type Pre;
	/// Just validate a transaction.
	///
	/// The is basically the same as [validate](TransactionExtension::validate), except that there
	/// is no need to supply the bond data.
	fn validate_only(
		&self,
		origin: Self::Origin,
		call: &Call,
		info: &Self::Info,
		len: usize,
		source: TransactionSource,
		extension_version: ExtensionVersion,
	) -> Result<(ValidTransaction, Self::Val, Self::Origin), TransactionValidityError>;
	/// Validate and prepare a transaction, ready for dispatch.
	fn validate_and_prepare(
		self,
		origin: Self::Origin,
		call: &Call,
		info: &Self::Info,
		len: usize,
		extension_version: ExtensionVersion,
	) -> Result<(Self::Pre, Self::Origin), TransactionValidityError>;
	/// Dispatch a transaction with the given base origin and call.
	fn dispatch_transaction(
		self,
		origin: Self::Origin,
		call: Call,
		info: &Self::Info,
		len: usize,
		extension_version: ExtensionVersion,
	) -> Self::Result;
	/// Do everything which would be done in a [dispatch_transaction](Self::dispatch_transaction),
	/// but instead of executing the call, execute `substitute` instead. Since this doesn't actually
	/// dispatch the call, it doesn't need to consume it and so `call` can be passed as a reference.
	fn test_run(
		self,
		origin: Self::Origin,
		call: &Call,
		info: &Self::Info,
		len: usize,
		extension_version: ExtensionVersion,
		substitute: impl FnOnce(
			Self::Origin,
		) -> crate::DispatchResultWithInfo<<Call as Dispatchable>::PostInfo>,
	) -> Self::Result;
}

impl<T: TransactionExtension<Call>, Call: Dispatchable + Encode> DispatchTransaction<Call> for T
where
	<Call as Dispatchable>::RuntimeOrigin: AsTransactionAuthorizedOrigin,
{
	type Origin = <Call as Dispatchable>::RuntimeOrigin;
	type Info = DispatchInfoOf<Call>;
	type Result = crate::ApplyExtrinsicResultWithInfo<PostDispatchInfoOf<Call>>;
	type Val = T::Val;
	type Pre = T::Pre;

	fn validate_only(
		&self,
		origin: Self::Origin,
		call: &Call,
		info: &DispatchInfoOf<Call>,
		len: usize,
		source: TransactionSource,
		extension_version: ExtensionVersion,
	) -> Result<(ValidTransaction, T::Val, Self::Origin), TransactionValidityError> {
		match self.validate(
			origin,
			call,
			info,
			len,
			self.implicit()?,
			&TxBaseImplication((extension_version, call)),
			source,
		) {
			// After validation, some origin must have been authorized.
			Ok((_, _, origin)) if !origin.is_transaction_authorized() => {
				Err(InvalidTransaction::UnknownOrigin.into())
			},
			res => res,
		}
	}
	fn validate_and_prepare(
		self,
		origin: Self::Origin,
		call: &Call,
		info: &DispatchInfoOf<Call>,
		len: usize,
		extension_version: ExtensionVersion,
	) -> Result<(T::Pre, Self::Origin), TransactionValidityError> {
		let (_, val, origin) = self.validate_only(
			origin,
			call,
			info,
			len,
			TransactionSource::InBlock,
			extension_version,
		)?;
		let pre = self.prepare(val, &origin, &call, info, len)?;
		Ok((pre, origin))
	}
	fn dispatch_transaction(
		self,
		origin: <Call as Dispatchable>::RuntimeOrigin,
		call: Call,
		info: &DispatchInfoOf<Call>,
		len: usize,
		extension_version: ExtensionVersion,
	) -> Self::Result {
		let (pre, origin) =
			self.validate_and_prepare(origin, &call, info, len, extension_version)?;
		let mut res = call.dispatch(origin);
		let pd_res = res.map(|_| ()).map_err(|e| e.error);
		let post_info = match &mut res {
			Ok(info) => info,
			Err(err) => &mut err.post_info,
		};
		post_info.set_extension_weight(info);
		T::post_dispatch(pre, info, post_info, len, &pd_res)?;
		Ok(res)
	}
	fn test_run(
		self,
		origin: Self::Origin,
		call: &Call,
		info: &Self::Info,
		len: usize,
		extension_version: ExtensionVersion,
		substitute: impl FnOnce(
			Self::Origin,
		) -> crate::DispatchResultWithInfo<<Call as Dispatchable>::PostInfo>,
	) -> Self::Result {
		let (pre, origin) =
			self.validate_and_prepare(origin, &call, info, len, extension_version)?;
		let mut res = substitute(origin);
		let pd_res = res.map(|_| ()).map_err(|e| e.error);
		let post_info = match &mut res {
			Ok(info) => info,
			Err(err) => &mut err.post_info,
		};
		post_info.set_extension_weight(info);
		T::post_dispatch(pre, info, post_info, len, &pd_res)?;
		Ok(res)
	}
}