1use super::unchecked_extrinsic::ExtensionVersion;
22use crate::{
23 traits::{
24 self, AsTransactionAuthorizedOrigin, DispatchInfoOf, DispatchTransaction, Dispatchable,
25 ExtensionVariant, InvalidVersion, MaybeDisplay, Member, Pipeline, PostDispatchInfoOf,
26 TransactionExtension,
27 },
28 transaction_validity::{TransactionSource, TransactionValidity},
29};
30use codec::Encode;
31use sp_weights::Weight;
32
33const EXTENSION_V0_VERSION: ExtensionVersion = 0;
35
36#[derive(PartialEq, Eq, Clone, Debug)]
47pub enum ExtrinsicFormat<AccountId, ExtensionV0, ExtensionOtherVersions = InvalidVersion> {
48 Bare,
51 Signed(AccountId, ExtensionV0),
54 General(ExtensionVariant<ExtensionV0, ExtensionOtherVersions>),
57}
58
59#[derive(PartialEq, Eq, Clone, Debug)]
73pub struct CheckedExtrinsic<AccountId, Call, ExtensionV0, ExtensionOtherVersions = InvalidVersion> {
74 pub format: ExtrinsicFormat<AccountId, ExtensionV0, ExtensionOtherVersions>,
77
78 pub function: Call,
80}
81
82impl<AccountId, Call, ExtensionV0, ExtensionOtherVersions, RuntimeOrigin> traits::Applyable
83 for CheckedExtrinsic<AccountId, Call, ExtensionV0, ExtensionOtherVersions>
84where
85 AccountId: Member + MaybeDisplay,
86 Call: Member + Dispatchable<RuntimeOrigin = RuntimeOrigin> + Encode,
87 ExtensionV0: TransactionExtension<Call>,
88 ExtensionOtherVersions: Pipeline<Call>,
89 RuntimeOrigin: From<Option<AccountId>> + AsTransactionAuthorizedOrigin,
90{
91 type Call = Call;
92
93 #[allow(deprecated)]
94 fn validate<I: crate::traits::ValidateUnsigned<Call = Self::Call>>(
95 &self,
96 source: TransactionSource,
97 info: &DispatchInfoOf<Self::Call>,
98 len: usize,
99 ) -> TransactionValidity {
100 match self.format {
101 ExtrinsicFormat::Bare => {
102 let inherent_validation = I::validate_unsigned(source, &self.function)?;
103 let legacy_validation = ExtensionV0::bare_validate(&self.function, info, len)?;
104 Ok(legacy_validation.combine_with(inherent_validation))
105 },
106 ExtrinsicFormat::Signed(ref signer, ref extension) => {
107 let origin = Some(signer.clone()).into();
108 extension
109 .validate_only(origin, &self.function, info, len, source, EXTENSION_V0_VERSION)
110 .map(|x| x.0)
111 },
112 ExtrinsicFormat::General(ref extension) => {
113 extension.validate_only(None.into(), &self.function, info, len, source)
114 },
115 }
116 }
117
118 #[allow(deprecated)]
119 fn apply<I: crate::traits::ValidateUnsigned<Call = Self::Call>>(
120 self,
121 info: &DispatchInfoOf<Self::Call>,
122 len: usize,
123 ) -> crate::ApplyExtrinsicResultWithInfo<PostDispatchInfoOf<Self::Call>> {
124 match self.format {
125 ExtrinsicFormat::Bare => {
126 I::pre_dispatch(&self.function)?;
127 ExtensionV0::bare_validate_and_prepare(&self.function, info, len)?;
130 let res = self.function.dispatch(None.into());
131 let mut post_info = res.unwrap_or_else(|err| err.post_info);
132 let pd_res = res.map(|_| ()).map_err(|e| e.error);
133 ExtensionV0::bare_post_dispatch(info, &mut post_info, len, &pd_res)?;
136 Ok(res)
137 },
138 ExtrinsicFormat::Signed(signer, extension) => extension.dispatch_transaction(
139 Some(signer).into(),
140 self.function,
141 info,
142 len,
143 EXTENSION_V0_VERSION,
144 ),
145 ExtrinsicFormat::General(extension) => {
146 extension.dispatch_transaction(None.into(), self.function, info, len)
147 },
148 }
149 }
150}
151
152impl<AccountId, Call, ExtensionV0, ExtensionOtherVersions>
153 CheckedExtrinsic<AccountId, Call, ExtensionV0, ExtensionOtherVersions>
154where
155 Call: Dispatchable + Encode,
156 ExtensionV0: TransactionExtension<Call>,
157 ExtensionOtherVersions: Pipeline<Call>,
158 <Call as Dispatchable>::RuntimeOrigin: AsTransactionAuthorizedOrigin,
159{
160 pub fn extension_weight(&self) -> Weight {
163 match &self.format {
164 ExtrinsicFormat::Bare => Weight::zero(),
165 ExtrinsicFormat::Signed(_, ext) => ext.weight(&self.function),
166 ExtrinsicFormat::General(ext) => ext.weight(&self.function),
167 }
168 }
169}