1use frame_support::dispatch::{DispatchInfo, GetDispatchInfo};
19use scale_codec::Encode;
20use sp_runtime::{
21 generic::ExtrinsicFormat,
22 traits::{
23 transaction_extension::TransactionExtension, Applyable, AsTransactionAuthorizedOrigin,
24 DispatchInfoOf, DispatchTransaction, Dispatchable, MaybeDisplay, Member,
25 PostDispatchInfoOf, ValidateUnsigned,
26 },
27 transaction_validity::{
28 InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError,
29 },
30 RuntimeDebug,
31};
32
33use crate::SelfContainedCall;
34
35#[derive(Clone, Eq, PartialEq, RuntimeDebug)]
36pub enum CheckedSignature<AccountId, Extension, SelfContainedSignedInfo> {
37 GenericDelegated(ExtrinsicFormat<AccountId, Extension>),
38 SelfContained(SelfContainedSignedInfo),
39}
40
41#[derive(Clone, Eq, PartialEq, RuntimeDebug)]
45pub struct CheckedExtrinsic<AccountId, Call, Extension, SelfContainedSignedInfo> {
46 pub signed: CheckedSignature<AccountId, Extension, SelfContainedSignedInfo>,
49
50 pub function: Call,
52}
53
54impl<AccountId, Call: GetDispatchInfo, Extension, SelfContainedSignedInfo> GetDispatchInfo
55 for CheckedExtrinsic<AccountId, Call, Extension, SelfContainedSignedInfo>
56{
57 fn get_dispatch_info(&self) -> DispatchInfo {
58 self.function.get_dispatch_info()
59 }
60}
61
62impl<AccountId, Call, Extension, SelfContainedSignedInfo, Origin> Applyable
63 for CheckedExtrinsic<AccountId, Call, Extension, SelfContainedSignedInfo>
64where
65 AccountId: Member + MaybeDisplay,
66 Call: Member
67 + Dispatchable<RuntimeOrigin = Origin>
68 + Encode
69 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,
70 Extension: TransactionExtension<Call>,
71 Origin: From<Option<AccountId>> + AsTransactionAuthorizedOrigin,
72 SelfContainedSignedInfo: Send + Sync + 'static,
73{
74 type Call = Call;
75
76 fn validate<U: ValidateUnsigned<Call = Self::Call>>(
77 &self,
78 source: TransactionSource,
79 info: &DispatchInfoOf<Self::Call>,
80 len: usize,
81 ) -> TransactionValidity {
82 use CheckedSignature::*;
83 match &self.signed {
84 GenericDelegated(format) => match format {
85 ExtrinsicFormat::Bare => {
86 let inherent_validation = U::validate_unsigned(source, &self.function)?;
87 #[allow(deprecated)]
88 let legacy_validation = Extension::bare_validate(&self.function, info, len)?;
89 Ok(legacy_validation.combine_with(inherent_validation))
90 }
91 ExtrinsicFormat::Signed(ref signer, ref extension) => {
92 let origin = Some(signer.clone()).into();
93 extension
94 .validate_only(origin, &self.function, info, len, source, 0)
95 .map(|x| x.0)
96 }
97 ExtrinsicFormat::General(extension_version, ref extension) => extension
98 .validate_only(
99 None.into(),
100 &self.function,
101 info,
102 len,
103 source,
104 *extension_version,
105 )
106 .map(|x| x.0),
107 },
108 SelfContained(signed_info) => self
109 .function
110 .validate_self_contained(signed_info, info, len)
111 .ok_or(TransactionValidityError::Invalid(
112 InvalidTransaction::BadProof,
113 ))?,
114 }
115 }
116
117 fn apply<U: ValidateUnsigned<Call = Self::Call>>(
118 self,
119 info: &DispatchInfoOf<Self::Call>,
120 len: usize,
121 ) -> sp_runtime::ApplyExtrinsicResultWithInfo<PostDispatchInfoOf<Self::Call>> {
122 match self.signed {
123 CheckedSignature::GenericDelegated(format) => match format {
124 ExtrinsicFormat::Bare => {
125 U::pre_dispatch(&self.function)?;
126 Extension::bare_validate_and_prepare(&self.function, info, len)?;
129 let res = self.function.dispatch(None.into());
130 let mut post_info = res.unwrap_or_else(|err| err.post_info);
131 let pd_res = res.map(|_| ()).map_err(|e| e.error);
132 Extension::bare_post_dispatch(info, &mut post_info, len, &pd_res)?;
135 Ok(res)
136 }
137 ExtrinsicFormat::Signed(signer, extension) => {
138 extension.dispatch_transaction(Some(signer).into(), self.function, info, len, 0)
139 }
140 ExtrinsicFormat::General(extension_version, extension) => extension
141 .dispatch_transaction(None.into(), self.function, info, len, extension_version),
142 },
143 CheckedSignature::SelfContained(signed_info) => {
144 self.function
146 .pre_dispatch_self_contained(&signed_info, info, len)
147 .ok_or(TransactionValidityError::Invalid(
148 InvalidTransaction::BadProof,
149 ))??;
150 let res = self.function.apply_self_contained(signed_info).ok_or(
151 TransactionValidityError::Invalid(InvalidTransaction::BadProof),
152 )?;
153 let mut post_info = match res {
154 Ok(info) => info,
155 Err(err) => err.post_info,
156 };
157 Extension::bare_post_dispatch(
158 info,
159 &mut post_info,
160 len,
161 &res.map(|_| ()).map_err(|e| e.error),
162 )?;
163 Ok(res)
164 }
165 }
166 }
167}