1use frame_support::{
19 dispatch::{DispatchInfo, GetDispatchInfo},
20 traits::{InherentBuilder, SignedTransactionBuilder},
21};
22use scale_codec::{Decode, DecodeWithMemTracking, Encode};
23use scale_info::TypeInfo;
24use sp_runtime::{
25 generic::{self, Preamble},
26 traits::{
27 self, Checkable, Dispatchable, ExtrinsicCall, ExtrinsicLike, ExtrinsicMetadata,
28 IdentifyAccount, MaybeDisplay, Member, TransactionExtension,
29 },
30 transaction_validity::{InvalidTransaction, TransactionValidityError},
31 OpaqueExtrinsic, RuntimeDebug,
32};
33
34use crate::{CheckedExtrinsic, CheckedSignature, SelfContainedCall};
35
36#[derive(
39 PartialEq,
40 Eq,
41 Clone,
42 Encode,
43 Decode,
44 DecodeWithMemTracking,
45 RuntimeDebug,
46 TypeInfo
47)]
48pub struct UncheckedExtrinsic<Address, Call, Signature, Extension>(
49 pub generic::UncheckedExtrinsic<Address, Call, Signature, Extension>,
50);
51
52impl<Address, Call, Signature, Extension> UncheckedExtrinsic<Address, Call, Signature, Extension> {
53 pub fn new_signed(
55 function: Call,
56 signed: Address,
57 signature: Signature,
58 tx_ext: Extension,
59 ) -> Self {
60 Self(generic::UncheckedExtrinsic::new_signed(
61 function, signed, signature, tx_ext,
62 ))
63 }
64
65 pub fn new_bare(function: Call) -> Self {
67 Self(generic::UncheckedExtrinsic::new_bare(function))
68 }
69}
70
71impl<Address: TypeInfo, Call: TypeInfo, Signature: TypeInfo, Extension: TypeInfo> ExtrinsicLike
72 for UncheckedExtrinsic<Address, Call, Signature, Extension>
73{
74 fn is_bare(&self) -> bool {
75 ExtrinsicLike::is_bare(&self.0)
76 }
77}
78
79impl<Address, AccountId, Call, Signature, Extension, Lookup> Checkable<Lookup>
80 for UncheckedExtrinsic<Address, Call, Signature, Extension>
81where
82 Address: Member + MaybeDisplay,
83 Call: Encode + Member + SelfContainedCall,
84 Signature: Member + traits::Verify,
85 <Signature as traits::Verify>::Signer: IdentifyAccount<AccountId = AccountId>,
86 Extension: Encode + TransactionExtension<Call>,
87 AccountId: Member + MaybeDisplay,
88 Lookup: traits::Lookup<Source = Address, Target = AccountId>,
89{
90 type Checked =
91 CheckedExtrinsic<AccountId, Call, Extension, <Call as SelfContainedCall>::SignedInfo>;
92
93 fn check(self, lookup: &Lookup) -> Result<Self::Checked, TransactionValidityError> {
94 if self.0.function.is_self_contained() {
95 if matches!(self.0.preamble, Preamble::Signed(_, _, _)) {
96 return Err(TransactionValidityError::Invalid(
97 InvalidTransaction::BadProof,
98 ));
99 }
100
101 let signed_info = self.0.function.check_self_contained().ok_or(
102 TransactionValidityError::Invalid(InvalidTransaction::BadProof),
103 )??;
104 Ok(CheckedExtrinsic {
105 signed: CheckedSignature::SelfContained(signed_info),
106 function: self.0.function,
107 })
108 } else {
109 let checked = Checkable::<Lookup>::check(self.0, lookup)?;
110 Ok(CheckedExtrinsic {
111 signed: CheckedSignature::GenericDelegated(checked.format),
112 function: checked.function,
113 })
114 }
115 }
116
117 #[cfg(feature = "try-runtime")]
118 fn unchecked_into_checked_i_know_what_i_am_doing(
119 self,
120 lookup: &Lookup,
121 ) -> Result<Self::Checked, TransactionValidityError> {
122 use generic::ExtrinsicFormat;
123 if self.0.function.is_self_contained() {
124 match self.0.function.check_self_contained() {
125 Some(signed_info) => Ok(CheckedExtrinsic {
126 signed: match signed_info {
127 Ok(info) => CheckedSignature::SelfContained(info),
128 _ => CheckedSignature::GenericDelegated(ExtrinsicFormat::Bare),
129 },
130 function: self.0.function,
131 }),
132 None => Ok(CheckedExtrinsic {
133 signed: CheckedSignature::GenericDelegated(ExtrinsicFormat::Bare),
134 function: self.0.function,
135 }),
136 }
137 } else {
138 let checked =
139 Checkable::<Lookup>::unchecked_into_checked_i_know_what_i_am_doing(self.0, lookup)?;
140 Ok(CheckedExtrinsic {
141 signed: CheckedSignature::GenericDelegated(checked.format),
142 function: checked.function,
143 })
144 }
145 }
146}
147
148impl<Address, Call, Signature, Extension> ExtrinsicMetadata
149 for UncheckedExtrinsic<Address, Call, Signature, Extension>
150where
151 Call: Dispatchable,
152 Extension: TransactionExtension<Call>,
153{
154 const VERSIONS: &'static [u8] =
155 generic::UncheckedExtrinsic::<Address, Call, Signature, Extension>::VERSIONS;
156 type TransactionExtensions = Extension;
157}
158
159impl<Address, Call, Signature, Extension> ExtrinsicCall
160 for UncheckedExtrinsic<Address, Call, Signature, Extension>
161where
162 Address: TypeInfo,
163 Call: TypeInfo,
164 Signature: TypeInfo,
165 Extension: TypeInfo,
166{
167 type Call = Call;
168
169 fn call(&self) -> &Self::Call {
170 &self.0.function
171 }
172}
173
174impl<Address, Call, Signature, Extension> GetDispatchInfo
175 for UncheckedExtrinsic<Address, Call, Signature, Extension>
176where
177 Call: GetDispatchInfo + Dispatchable,
178 Extension: TransactionExtension<Call>,
179{
180 fn get_dispatch_info(&self) -> DispatchInfo {
181 self.0.function.get_dispatch_info()
182 }
183}
184
185#[cfg(feature = "serde")]
186impl<Address: Encode, Signature: Encode, Call, Extension> serde::Serialize
187 for UncheckedExtrinsic<Address, Call, Signature, Extension>
188where
189 Call: Encode + Dispatchable,
190 Extension: Encode + TransactionExtension<Call>,
191{
192 fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
193 where
194 S: ::serde::Serializer,
195 {
196 self.0.serialize(seq)
197 }
198}
199
200#[cfg(feature = "serde")]
201impl<'a, Address: Decode, Signature: Decode, Call, Extension> serde::Deserialize<'a>
202 for UncheckedExtrinsic<Address, Call, Signature, Extension>
203where
204 Call: Decode + Dispatchable + DecodeWithMemTracking,
205 Extension: Decode + TransactionExtension<Call>,
206{
207 fn deserialize<D>(de: D) -> Result<Self, D::Error>
208 where
209 D: serde::Deserializer<'a>,
210 {
211 <generic::UncheckedExtrinsic<Address, Call, Signature, Extension>>::deserialize(de)
212 .map(Self)
213 }
214}
215
216impl<Address, Signature, Call, Extension> SignedTransactionBuilder
217 for UncheckedExtrinsic<Address, Call, Signature, Extension>
218where
219 Address: TypeInfo,
220 Signature: TypeInfo,
221 Call: TypeInfo,
222 Extension: TypeInfo,
223{
224 type Address = Address;
225 type Signature = Signature;
226 type Extension = Extension;
227
228 fn new_signed_transaction(
229 call: Self::Call,
230 signed: Address,
231 signature: Signature,
232 tx_ext: Extension,
233 ) -> Self {
234 generic::UncheckedExtrinsic::new_signed(call, signed, signature, tx_ext).into()
235 }
236}
237
238impl<Address, Signature, Call, Extension> InherentBuilder
239 for UncheckedExtrinsic<Address, Call, Signature, Extension>
240where
241 Address: TypeInfo,
242 Signature: TypeInfo,
243 Call: TypeInfo,
244 Extension: TypeInfo,
245{
246 fn new_inherent(call: Self::Call) -> Self {
247 generic::UncheckedExtrinsic::new_bare(call).into()
248 }
249}
250
251impl<Address, Call, Signature, Extension>
252 From<UncheckedExtrinsic<Address, Call, Signature, Extension>> for OpaqueExtrinsic
253where
254 Address: Encode,
255 Signature: Encode,
256 Call: Encode,
257 Extension: Encode,
258{
259 fn from(extrinsic: UncheckedExtrinsic<Address, Call, Signature, Extension>) -> Self {
260 extrinsic.0.into()
261 }
262}
263
264impl<Address, Call, Signature, Extension>
265 From<generic::UncheckedExtrinsic<Address, Call, Signature, Extension>>
266 for UncheckedExtrinsic<Address, Call, Signature, Extension>
267{
268 fn from(utx: generic::UncheckedExtrinsic<Address, Call, Signature, Extension>) -> Self {
269 Self(utx)
270 }
271}