fp_self_contained/
unchecked_extrinsic.rs

1// SPDX-License-Identifier: Apache-2.0
2// This file is part of Frontier.
3//
4// Copyright (c) 2017-2020 Parity Technologies (UK) Ltd.
5//
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use 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/// A extrinsic right from the external world. This is unchecked and so
37/// can contain a signature.
38#[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	/// New instance of a signed extrinsic aka "transaction".
54	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	/// New instance of an unsigned extrinsic aka "inherent".
66	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}