use super::unchecked_extrinsic::ExtensionVersion;
use crate::{
traits::{
self, AsTransactionAuthorizedOrigin, DispatchInfoOf, DispatchTransaction, Dispatchable,
ExtensionVariant, InvalidVersion, MaybeDisplay, Member, Pipeline, PostDispatchInfoOf,
TransactionExtension,
},
transaction_validity::{TransactionSource, TransactionValidity},
};
use codec::Encode;
use sp_weights::Weight;
const EXTENSION_V0_VERSION: ExtensionVersion = 0;
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum ExtrinsicFormat<AccountId, ExtensionV0, ExtensionOtherVersions = InvalidVersion> {
Bare,
Signed(AccountId, ExtensionV0),
General(ExtensionVariant<ExtensionV0, ExtensionOtherVersions>),
}
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct CheckedExtrinsic<AccountId, Call, ExtensionV0, ExtensionOtherVersions = InvalidVersion> {
pub format: ExtrinsicFormat<AccountId, ExtensionV0, ExtensionOtherVersions>,
pub function: Call,
}
impl<AccountId, Call, ExtensionV0, ExtensionOtherVersions, RuntimeOrigin> traits::Applyable
for CheckedExtrinsic<AccountId, Call, ExtensionV0, ExtensionOtherVersions>
where
AccountId: Member + MaybeDisplay,
Call: Member + Dispatchable<RuntimeOrigin = RuntimeOrigin> + Encode,
ExtensionV0: TransactionExtension<Call>,
ExtensionOtherVersions: Pipeline<Call>,
RuntimeOrigin: From<Option<AccountId>> + AsTransactionAuthorizedOrigin,
{
type Call = Call;
#[allow(deprecated)]
fn validate<I: crate::traits::ValidateUnsigned<Call = Self::Call>>(
&self,
source: TransactionSource,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> TransactionValidity {
match self.format {
ExtrinsicFormat::Bare => {
let inherent_validation = I::validate_unsigned(source, &self.function)?;
let legacy_validation = ExtensionV0::bare_validate(&self.function, info, len)?;
Ok(legacy_validation.combine_with(inherent_validation))
},
ExtrinsicFormat::Signed(ref signer, ref extension) => {
let origin = Some(signer.clone()).into();
extension
.validate_only(origin, &self.function, info, len, source, EXTENSION_V0_VERSION)
.map(|x| x.0)
},
ExtrinsicFormat::General(ref extension) => {
extension.validate_only(None.into(), &self.function, info, len, source)
},
}
}
#[allow(deprecated)]
fn apply<I: crate::traits::ValidateUnsigned<Call = Self::Call>>(
self,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> crate::ApplyExtrinsicResultWithInfo<PostDispatchInfoOf<Self::Call>> {
match self.format {
ExtrinsicFormat::Bare => {
I::pre_dispatch(&self.function)?;
ExtensionV0::bare_validate_and_prepare(&self.function, info, len)?;
let res = self.function.dispatch(None.into());
let mut post_info = res.unwrap_or_else(|err| err.post_info);
let pd_res = res.map(|_| ()).map_err(|e| e.error);
ExtensionV0::bare_post_dispatch(info, &mut post_info, len, &pd_res)?;
Ok(res)
},
ExtrinsicFormat::Signed(signer, extension) => extension.dispatch_transaction(
Some(signer).into(),
self.function,
info,
len,
EXTENSION_V0_VERSION,
),
ExtrinsicFormat::General(extension) => {
extension.dispatch_transaction(None.into(), self.function, info, len)
},
}
}
}
impl<AccountId, Call, ExtensionV0, ExtensionOtherVersions>
CheckedExtrinsic<AccountId, Call, ExtensionV0, ExtensionOtherVersions>
where
Call: Dispatchable + Encode,
ExtensionV0: TransactionExtension<Call>,
ExtensionOtherVersions: Pipeline<Call>,
<Call as Dispatchable>::RuntimeOrigin: AsTransactionAuthorizedOrigin,
{
pub fn extension_weight(&self) -> Weight {
match &self.format {
ExtrinsicFormat::Bare => Weight::zero(),
ExtrinsicFormat::Signed(_, ext) => ext.weight(&self.function),
ExtrinsicFormat::General(ext) => ext.weight(&self.function),
}
}
}