Skip to main content

sp_runtime/generic/
unchecked_extrinsic.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
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
18//! Generic implementation of an unchecked (pre-verification) extrinsic.
19
20use crate::{
21	generic::{CheckedExtrinsic, ExtrinsicFormat},
22	traits::{
23		self, transaction_extension::TransactionExtension, Checkable, Dispatchable, ExtrinsicCall,
24		ExtrinsicLike, ExtrinsicMetadata, IdentifyAccount, LazyExtrinsic, MaybeDisplay, Member,
25		SignaturePayload,
26	},
27	transaction_validity::{InvalidTransaction, TransactionValidityError},
28	OpaqueExtrinsic,
29};
30#[cfg(all(not(feature = "std"), feature = "serde"))]
31use alloc::format;
32use alloc::{vec, vec::Vec};
33use codec::{
34	Compact, CountedInput, Decode, DecodeWithMemLimit, DecodeWithMemTracking, Encode, EncodeLike,
35	Input,
36};
37use core::fmt::{
38	Debug, {self},
39};
40use scale_info::{build::Fields, meta_type, Path, StaticTypeInfo, Type, TypeInfo, TypeParameter};
41use sp_io::hashing::blake2_256;
42use sp_weights::Weight;
43
44/// Type to represent the version of the [Extension](TransactionExtension) used in this extrinsic.
45pub type ExtensionVersion = u8;
46/// Type to represent the extrinsic format version which defines an [UncheckedExtrinsic].
47pub type ExtrinsicVersion = u8;
48
49/// Current version of the [`UncheckedExtrinsic`] encoded format.
50///
51/// This version needs to be bumped if the encoded representation changes.
52/// It ensures that if the representation is changed and the format is not known,
53/// the decoding fails.
54pub const EXTRINSIC_FORMAT_VERSION: ExtrinsicVersion = 5;
55/// Legacy version of the [`UncheckedExtrinsic`] encoded format.
56///
57/// This version was used in the signed/unsigned transaction model and is still supported for
58/// compatibility reasons. It will be deprecated in favor of v5 extrinsics and an inherent/general
59/// transaction model.
60pub const LEGACY_EXTRINSIC_FORMAT_VERSION: ExtrinsicVersion = 4;
61/// Current version of the [Extension](TransactionExtension) used in this
62/// [extrinsic](UncheckedExtrinsic).
63///
64/// This version needs to be bumped if there are breaking changes to the extension used in the
65/// [UncheckedExtrinsic] implementation.
66const EXTENSION_VERSION: ExtensionVersion = 0;
67
68/// Maximum decoded heap size for a runtime call (in bytes).
69pub const DEFAULT_MAX_CALL_SIZE: usize = 16 * 1024 * 1024; // 16 MiB
70
71/// The `SignaturePayload` of `UncheckedExtrinsic`.
72pub type UncheckedSignaturePayload<Address, Signature, Extension> = (Address, Signature, Extension);
73
74impl<Address: TypeInfo, Signature: TypeInfo, Extension: TypeInfo> SignaturePayload
75	for UncheckedSignaturePayload<Address, Signature, Extension>
76{
77	type SignatureAddress = Address;
78	type Signature = Signature;
79	type SignatureExtra = Extension;
80}
81
82/// A "header" for extrinsics leading up to the call itself. Determines the type of extrinsic and
83/// holds any necessary specialized data.
84#[derive(DecodeWithMemTracking, Eq, PartialEq, Clone)]
85pub enum Preamble<Address, Signature, Extension> {
86	/// An extrinsic without a signature or any extension. This means it's either an inherent or
87	/// an old-school "Unsigned" (we don't use that terminology any more since it's confusable with
88	/// the general transaction which is without a signature but does have an extension).
89	///
90	/// NOTE: In the future, once we remove `ValidateUnsigned`, this will only serve Inherent
91	/// extrinsics and thus can be renamed to `Inherent`.
92	Bare(ExtrinsicVersion),
93	/// An old-school transaction extrinsic which includes a signature of some hard-coded crypto.
94	/// Available only on extrinsic version 4.
95	Signed(Address, Signature, Extension),
96	/// A new-school transaction extrinsic which does not include a signature by default. The
97	/// origin authorization, through signatures or other means, is performed by the transaction
98	/// extension in this extrinsic. Available starting with extrinsic version 5.
99	General(ExtensionVersion, Extension),
100}
101
102const VERSION_MASK: u8 = 0b0011_1111;
103const TYPE_MASK: u8 = 0b1100_0000;
104const BARE_EXTRINSIC: u8 = 0b0000_0000;
105const SIGNED_EXTRINSIC: u8 = 0b1000_0000;
106const GENERAL_EXTRINSIC: u8 = 0b0100_0000;
107
108impl<Address, Signature, Extension> Decode for Preamble<Address, Signature, Extension>
109where
110	Address: Decode,
111	Signature: Decode,
112	Extension: Decode,
113{
114	fn decode<I: Input>(input: &mut I) -> Result<Self, codec::Error> {
115		let version_and_type = input.read_byte()?;
116
117		let version = version_and_type & VERSION_MASK;
118		let xt_type = version_and_type & TYPE_MASK;
119
120		let preamble = match (version, xt_type) {
121			(
122				extrinsic_version @ LEGACY_EXTRINSIC_FORMAT_VERSION..=EXTRINSIC_FORMAT_VERSION,
123				BARE_EXTRINSIC,
124			) => Self::Bare(extrinsic_version),
125			(LEGACY_EXTRINSIC_FORMAT_VERSION, SIGNED_EXTRINSIC) => {
126				let address = Address::decode(input)?;
127				let signature = Signature::decode(input)?;
128				let ext = Extension::decode(input)?;
129				Self::Signed(address, signature, ext)
130			},
131			(EXTRINSIC_FORMAT_VERSION, GENERAL_EXTRINSIC) => {
132				let ext_version = ExtensionVersion::decode(input)?;
133				let ext = Extension::decode(input)?;
134				Self::General(ext_version, ext)
135			},
136			(_, _) => return Err("Invalid transaction version".into()),
137		};
138
139		Ok(preamble)
140	}
141}
142
143impl<Address, Signature, Extension> Encode for Preamble<Address, Signature, Extension>
144where
145	Address: Encode,
146	Signature: Encode,
147	Extension: Encode,
148{
149	fn size_hint(&self) -> usize {
150		match &self {
151			Preamble::Bare(_) => EXTRINSIC_FORMAT_VERSION.size_hint(),
152			Preamble::Signed(address, signature, ext) => LEGACY_EXTRINSIC_FORMAT_VERSION
153				.size_hint()
154				.saturating_add(address.size_hint())
155				.saturating_add(signature.size_hint())
156				.saturating_add(ext.size_hint()),
157			Preamble::General(ext_version, ext) => EXTRINSIC_FORMAT_VERSION
158				.size_hint()
159				.saturating_add(ext_version.size_hint())
160				.saturating_add(ext.size_hint()),
161		}
162	}
163
164	fn encode_to<T: codec::Output + ?Sized>(&self, dest: &mut T) {
165		match &self {
166			Preamble::Bare(extrinsic_version) => {
167				(extrinsic_version | BARE_EXTRINSIC).encode_to(dest);
168			},
169			Preamble::Signed(address, signature, ext) => {
170				(LEGACY_EXTRINSIC_FORMAT_VERSION | SIGNED_EXTRINSIC).encode_to(dest);
171				address.encode_to(dest);
172				signature.encode_to(dest);
173				ext.encode_to(dest);
174			},
175			Preamble::General(ext_version, ext) => {
176				(EXTRINSIC_FORMAT_VERSION | GENERAL_EXTRINSIC).encode_to(dest);
177				ext_version.encode_to(dest);
178				ext.encode_to(dest);
179			},
180		}
181	}
182}
183
184impl<Address, Signature, Extension> Preamble<Address, Signature, Extension> {
185	/// Returns `Some` if this is a signed extrinsic, together with the relevant inner fields.
186	pub fn to_signed(self) -> Option<(Address, Signature, Extension)> {
187		match self {
188			Self::Signed(a, s, e) => Some((a, s, e)),
189			_ => None,
190		}
191	}
192}
193
194impl<Address, Signature, Extension> fmt::Debug for Preamble<Address, Signature, Extension>
195where
196	Address: fmt::Debug,
197	Extension: fmt::Debug,
198{
199	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
200		match self {
201			Self::Bare(_) => write!(f, "Bare"),
202			Self::Signed(address, _, tx_ext) => write!(f, "Signed({:?}, {:?})", address, tx_ext),
203			Self::General(ext_version, tx_ext) => {
204				write!(f, "General({:?}, {:?})", ext_version, tx_ext)
205			},
206		}
207	}
208}
209
210/// An extrinsic right from the external world. This is unchecked and so can contain a signature.
211///
212/// An extrinsic is formally described as any external data that is originating from the outside of
213/// the runtime and fed into the runtime as a part of the block-body.
214///
215/// Inherents are special types of extrinsics that are placed into the block by the block-builder.
216/// They are unsigned because the assertion is that they are "inherently true" by virtue of getting
217/// past all validators.
218///
219/// Transactions are all other statements provided by external entities that the chain deems values
220/// and decided to include in the block. This value is typically in the form of fee payment, but it
221/// could in principle be any other interaction. Transactions are either signed or unsigned. A
222/// sensible transaction pool should ensure that only transactions that are worthwhile are
223/// considered for block-building.
224#[cfg_attr(all(feature = "std", not(windows)), doc = simple_mermaid::mermaid!("../../docs/mermaid/extrinsics.mmd"))]
225/// This type is by no means enforced within Substrate, but given its genericness, it is highly
226/// likely that for most use-cases it will suffice. Thus, the encoding of this type will dictate
227/// exactly what bytes should be sent to a runtime to transact with it.
228///
229/// This can be checked using [`Checkable`], yielding a [`CheckedExtrinsic`], which is the
230/// counterpart of this type after its signature (and other non-negotiable validity checks) have
231/// passed.
232#[derive(DecodeWithMemTracking, Eq, Clone)]
233#[codec(decode_with_mem_tracking_bound(
234	Address: DecodeWithMemTracking,
235	Call: DecodeWithMemTracking,
236	Signature: DecodeWithMemTracking,
237	Extension: DecodeWithMemTracking)
238)]
239pub struct UncheckedExtrinsic<
240	Address,
241	Call,
242	Signature,
243	Extension,
244	const MAX_CALL_SIZE: usize = DEFAULT_MAX_CALL_SIZE,
245> {
246	/// Information regarding the type of extrinsic this is (inherent or transaction) as well as
247	/// associated extension (`Extension`) data if it's a transaction and a possible signature.
248	pub preamble: Preamble<Address, Signature, Extension>,
249	/// The function that should be called.
250	pub function: Call,
251	/// Stores the raw encoded call.
252	///
253	/// This is mainly interesting if this extrinsic was created by decoding it from bytes. In this
254	/// case this field should be set to `Some` holding the original bytes used to decode the
255	/// [`Self::function`]. This is done to protect against decode implementations of `Call` that
256	/// are not bijective (encodes to the exact same bytes it was encoded from). If this `field`
257	/// is set, it is being used when re-encoding this transaction.
258	pub encoded_call: Option<Vec<u8>>,
259}
260
261impl<
262		Address: Debug,
263		Call: Debug,
264		Signature: Debug,
265		Extension: Debug,
266		const MAX_CALL_SIZE: usize,
267	> Debug for UncheckedExtrinsic<Address, Call, Signature, Extension, MAX_CALL_SIZE>
268{
269	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
270		f.debug_struct("UncheckedExtrinsic")
271			.field("preamble", &self.preamble)
272			.field("function", &self.function)
273			.finish()
274	}
275}
276
277impl<
278		Address: PartialEq,
279		Call: PartialEq,
280		Signature: PartialEq,
281		Extension: PartialEq,
282		const MAX_CALL_SIZE: usize,
283	> PartialEq for UncheckedExtrinsic<Address, Call, Signature, Extension, MAX_CALL_SIZE>
284{
285	fn eq(&self, other: &Self) -> bool {
286		self.preamble == other.preamble && self.function == other.function
287	}
288}
289
290/// Manual [`TypeInfo`] implementation because of custom encoding. The data is a valid encoded
291/// `Vec<u8>`, but requires some logic to extract the signature and payload.
292///
293/// See [`UncheckedExtrinsic::encode`] and [`UncheckedExtrinsic::decode`].
294impl<Address, Call, Signature, Extension> TypeInfo
295	for UncheckedExtrinsic<Address, Call, Signature, Extension>
296where
297	Address: StaticTypeInfo,
298	Call: StaticTypeInfo,
299	Signature: StaticTypeInfo,
300	Extension: StaticTypeInfo,
301{
302	type Identity = UncheckedExtrinsic<Address, Call, Signature, Extension>;
303
304	fn type_info() -> Type {
305		Type::builder()
306			.path(Path::new("UncheckedExtrinsic", module_path!()))
307			// Include the type parameter types, even though they are not used directly in any of
308			// the described fields. These type definitions can be used by downstream consumers
309			// to help construct the custom decoding from the opaque bytes (see below).
310			.type_params(vec![
311				TypeParameter::new("Address", Some(meta_type::<Address>())),
312				TypeParameter::new("Call", Some(meta_type::<Call>())),
313				TypeParameter::new("Signature", Some(meta_type::<Signature>())),
314				TypeParameter::new("Extra", Some(meta_type::<Extension>())),
315			])
316			.docs(&["UncheckedExtrinsic raw bytes, requires custom decoding routine"])
317			// Because of the custom encoding, we can only accurately describe the encoding as an
318			// opaque `Vec<u8>`. Downstream consumers will need to manually implement the codec to
319			// encode/decode the `signature` and `function` fields.
320			.composite(Fields::unnamed().field(|f| f.ty::<Vec<u8>>()))
321	}
322}
323
324impl<Address, Call, Signature, Extension, const MAX_CALL_SIZE: usize>
325	UncheckedExtrinsic<Address, Call, Signature, Extension, MAX_CALL_SIZE>
326{
327	/// New instance of a bare (ne unsigned) extrinsic. This could be used for an inherent or an
328	/// old-school "unsigned transaction" (which are new being deprecated in favour of general
329	/// transactions).
330	#[deprecated = "Use new_bare instead"]
331	pub fn new_unsigned(function: Call) -> Self {
332		Self::new_bare(function)
333	}
334
335	/// Returns `true` if this extrinsic instance is an inherent, `false`` otherwise.
336	pub fn is_inherent(&self) -> bool {
337		matches!(self.preamble, Preamble::Bare(_))
338	}
339
340	/// Returns `true` if this extrinsic instance is an old-school signed transaction, `false`
341	/// otherwise.
342	pub fn is_signed(&self) -> bool {
343		matches!(self.preamble, Preamble::Signed(..))
344	}
345
346	/// Create an `UncheckedExtrinsic` from a `Preamble` and the actual `Call`.
347	pub fn from_parts(function: Call, preamble: Preamble<Address, Signature, Extension>) -> Self {
348		Self { preamble, function, encoded_call: None }
349	}
350
351	/// New instance of a bare (ne unsigned) extrinsic.
352	pub fn new_bare(function: Call) -> Self {
353		Self::from_parts(function, Preamble::Bare(EXTRINSIC_FORMAT_VERSION))
354	}
355
356	/// New instance of a bare (ne unsigned) extrinsic on extrinsic format version 4.
357	pub fn new_bare_legacy(function: Call) -> Self {
358		Self::from_parts(function, Preamble::Bare(LEGACY_EXTRINSIC_FORMAT_VERSION))
359	}
360
361	/// New instance of an old-school signed transaction on extrinsic format version 4.
362	pub fn new_signed(
363		function: Call,
364		signed: Address,
365		signature: Signature,
366		tx_ext: Extension,
367	) -> Self {
368		Self::from_parts(function, Preamble::Signed(signed, signature, tx_ext))
369	}
370
371	/// New instance of a new-school unsigned transaction.
372	pub fn new_transaction(function: Call, tx_ext: Extension) -> Self {
373		Self::from_parts(function, Preamble::General(EXTENSION_VERSION, tx_ext))
374	}
375
376	fn decode_with_len<I: Input>(input: &mut I, len: usize) -> Result<Self, codec::Error>
377	where
378		Preamble<Address, Signature, Extension>: Decode,
379		Call: DecodeWithMemTracking,
380	{
381		let mut input = CountedInput::new(input);
382
383		let preamble = Decode::decode(&mut input)?;
384
385		struct CloneBytes<'a, I>(&'a mut I, Vec<u8>);
386		impl<I: Input> Input for CloneBytes<'_, I> {
387			fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
388				self.0.remaining_len()
389			}
390
391			fn read(&mut self, into: &mut [u8]) -> Result<(), codec::Error> {
392				self.0.read(into)?;
393
394				self.1.extend_from_slice(into);
395				Ok(())
396			}
397
398			fn descend_ref(&mut self) -> Result<(), codec::Error> {
399				self.0.descend_ref()
400			}
401
402			fn ascend_ref(&mut self) {
403				self.0.ascend_ref();
404			}
405
406			fn on_before_alloc_mem(&mut self, size: usize) -> Result<(), codec::Error> {
407				self.0.on_before_alloc_mem(size)
408			}
409		}
410
411		let mut clone_bytes = CloneBytes(&mut input, Vec::new());
412
413		// Adds 1 byte to the `MAX_CALL_SIZE` as the decoding fails exactly at the given value and
414		// the maximum should be allowed to fit in.
415		let function =
416			Call::decode_with_mem_limit(&mut clone_bytes, MAX_CALL_SIZE.saturating_add(1))?;
417
418		let encoded_call = Some(clone_bytes.1);
419
420		if input.count() != len as u64 {
421			return Err("Invalid length prefix".into());
422		}
423
424		Ok(Self { preamble, function, encoded_call })
425	}
426
427	fn encode_without_prefix(&self) -> Vec<u8>
428	where
429		Preamble<Address, Signature, Extension>: Encode,
430		Call: Encode,
431	{
432		let mut encoded = self.preamble.encode();
433
434		match &self.encoded_call {
435			Some(call) => {
436				encoded.extend(call);
437			},
438			None => {
439				self.function.encode_to(&mut encoded);
440			},
441		}
442
443		encoded
444	}
445}
446
447impl<Address, Call, Signature, Extension> ExtrinsicLike
448	for UncheckedExtrinsic<Address, Call, Signature, Extension>
449{
450	fn is_signed(&self) -> Option<bool> {
451		Some(matches!(self.preamble, Preamble::Signed(..)))
452	}
453
454	fn is_bare(&self) -> bool {
455		matches!(self.preamble, Preamble::Bare(_))
456	}
457}
458
459impl<Address, Call, Signature, Extra> ExtrinsicCall
460	for UncheckedExtrinsic<Address, Call, Signature, Extra>
461{
462	type Call = Call;
463
464	fn call(&self) -> &Call {
465		&self.function
466	}
467
468	fn into_call(self) -> Self::Call {
469		self.function
470	}
471}
472
473// TODO: Migrate existing extension pipelines to support current `Signed` transactions as `General`
474// transactions by adding an extension to validate signatures, as they are currently validated in
475// the `Checkable` implementation for `Signed` transactions.
476
477impl<LookupSource, AccountId, Call, Signature, Extension, Lookup> Checkable<Lookup>
478	for UncheckedExtrinsic<LookupSource, Call, Signature, Extension>
479where
480	LookupSource: Member + MaybeDisplay,
481	Call: Encode + Member + Dispatchable,
482	Signature: Member + traits::Verify,
483	<Signature as traits::Verify>::Signer: IdentifyAccount<AccountId = AccountId>,
484	Extension: Encode + TransactionExtension<Call>,
485	AccountId: Member + MaybeDisplay,
486	Lookup: traits::Lookup<Source = LookupSource, Target = AccountId>,
487{
488	type Checked = CheckedExtrinsic<AccountId, Call, Extension>;
489
490	fn check(self, lookup: &Lookup) -> Result<Self::Checked, TransactionValidityError> {
491		Ok(match self.preamble {
492			Preamble::Signed(signed, signature, tx_ext) => {
493				let signed = lookup.lookup(signed)?;
494				// The `Implicit` is "implicitly" included in the payload.
495				let raw_payload = SignedPayload::new(
496					CallAndMaybeEncoded { encoded: self.encoded_call, call: self.function },
497					tx_ext,
498				)?;
499				if !raw_payload.using_encoded(|payload| signature.verify(payload, &signed)) {
500					return Err(InvalidTransaction::BadProof.into());
501				}
502				let (function, tx_ext, _) = raw_payload.deconstruct();
503				CheckedExtrinsic { format: ExtrinsicFormat::Signed(signed, tx_ext), function }
504			},
505			Preamble::General(extension_version, tx_ext) => CheckedExtrinsic {
506				format: ExtrinsicFormat::General(extension_version, tx_ext),
507				function: self.function,
508			},
509			Preamble::Bare(_) => {
510				CheckedExtrinsic { format: ExtrinsicFormat::Bare, function: self.function }
511			},
512		})
513	}
514
515	#[cfg(feature = "try-runtime")]
516	fn unchecked_into_checked_i_know_what_i_am_doing(
517		self,
518		lookup: &Lookup,
519	) -> Result<Self::Checked, TransactionValidityError> {
520		Ok(match self.preamble {
521			Preamble::Signed(signed, _, tx_ext) => {
522				let signed = lookup.lookup(signed)?;
523				CheckedExtrinsic {
524					format: ExtrinsicFormat::Signed(signed, tx_ext),
525					function: self.function,
526				}
527			},
528			Preamble::General(extension_version, tx_ext) => CheckedExtrinsic {
529				format: ExtrinsicFormat::General(extension_version, tx_ext),
530				function: self.function,
531			},
532			Preamble::Bare(_) => {
533				CheckedExtrinsic { format: ExtrinsicFormat::Bare, function: self.function }
534			},
535		})
536	}
537}
538
539impl<Address, Call: Dispatchable, Signature, Extension: TransactionExtension<Call>>
540	ExtrinsicMetadata for UncheckedExtrinsic<Address, Call, Signature, Extension>
541{
542	const VERSIONS: &'static [u8] = &[LEGACY_EXTRINSIC_FORMAT_VERSION, EXTRINSIC_FORMAT_VERSION];
543	type TransactionExtensions = Extension;
544}
545
546impl<Address, Call: Dispatchable, Signature, Extension: TransactionExtension<Call>>
547	UncheckedExtrinsic<Address, Call, Signature, Extension>
548{
549	/// Returns the weight of the extension of this transaction, if present. If the transaction
550	/// doesn't use any extension, the weight returned is equal to zero.
551	pub fn extension_weight(&self) -> Weight {
552		match &self.preamble {
553			Preamble::Bare(_) => Weight::zero(),
554			Preamble::Signed(_, _, ext) | Preamble::General(_, ext) => ext.weight(&self.function),
555		}
556	}
557}
558
559impl<Address, Call, Signature, Extension, const MAX_CALL_SIZE: usize> Decode
560	for UncheckedExtrinsic<Address, Call, Signature, Extension, MAX_CALL_SIZE>
561where
562	Address: Decode,
563	Signature: Decode,
564	Call: DecodeWithMemTracking,
565	Extension: Decode,
566{
567	fn decode<I: Input>(input: &mut I) -> Result<Self, codec::Error> {
568		// This is a little more complicated than usual since the binary format must be compatible
569		// with SCALE's generic `Vec<u8>` type. Basically this just means accepting that there
570		// will be a prefix of vector length.
571		let expected_length: Compact<u32> = Decode::decode(input)?;
572
573		Self::decode_with_len(input, expected_length.0 as usize)
574	}
575}
576
577#[docify::export(unchecked_extrinsic_encode_impl)]
578impl<Address, Call, Signature, Extension> Encode
579	for UncheckedExtrinsic<Address, Call, Signature, Extension>
580where
581	Preamble<Address, Signature, Extension>: Encode,
582	Call: Encode,
583	Extension: Encode,
584{
585	fn encode(&self) -> Vec<u8> {
586		let tmp = self.encode_without_prefix();
587
588		let compact_len = codec::Compact::<u32>(tmp.len() as u32);
589
590		// Allocate the output buffer with the correct length
591		let mut output = Vec::with_capacity(compact_len.size_hint() + tmp.len());
592
593		compact_len.encode_to(&mut output);
594		output.extend(tmp);
595
596		output
597	}
598}
599
600impl<Address, Call, Signature, Extension> EncodeLike
601	for UncheckedExtrinsic<Address, Call, Signature, Extension>
602where
603	Address: Encode,
604	Signature: Encode,
605	Call: Encode + Dispatchable,
606	Extension: TransactionExtension<Call>,
607{
608}
609
610#[cfg(feature = "serde")]
611impl<Address: Encode, Signature: Encode, Call: Encode, Extension: Encode> serde::Serialize
612	for UncheckedExtrinsic<Address, Call, Signature, Extension>
613{
614	fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
615	where
616		S: ::serde::Serializer,
617	{
618		self.using_encoded(|bytes| seq.serialize_bytes(bytes))
619	}
620}
621
622#[cfg(feature = "serde")]
623impl<'a, Address: Decode, Signature: Decode, Call: DecodeWithMemTracking, Extension: Decode>
624	serde::Deserialize<'a> for UncheckedExtrinsic<Address, Call, Signature, Extension>
625{
626	fn deserialize<D>(de: D) -> Result<Self, D::Error>
627	where
628		D: serde::Deserializer<'a>,
629	{
630		let r = sp_core::bytes::deserialize(de)?;
631		Self::decode(&mut &r[..])
632			.map_err(|e| serde::de::Error::custom(format!("Decode error: {}", e)))
633	}
634}
635
636/// Something which holds the actual call and maybe its encoded form.
637pub struct CallAndMaybeEncoded<T> {
638	encoded: Option<Vec<u8>>,
639	call: T,
640}
641
642impl<T> CallAndMaybeEncoded<T> {
643	/// Converts `self` into the underlying call.
644	pub fn into_call(self) -> T {
645		self.call
646	}
647}
648
649impl<T> From<T> for CallAndMaybeEncoded<T> {
650	fn from(value: T) -> Self {
651		Self { call: value, encoded: None }
652	}
653}
654
655impl<T: Encode> Encode for CallAndMaybeEncoded<T> {
656	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
657		match &self.encoded {
658			Some(enc) => f(&enc),
659			None => self.call.using_encoded(f),
660		}
661	}
662}
663
664/// A payload that has been signed for an unchecked extrinsics.
665///
666/// Note that the payload that we sign to produce unchecked extrinsic signature
667/// is going to be different than the `SignaturePayload` - so the thing the extrinsic
668/// actually contains.
669pub struct SignedPayload<Call: Dispatchable, Extension: TransactionExtension<Call>>(
670	(CallAndMaybeEncoded<Call>, Extension, Extension::Implicit),
671);
672
673impl<Call, Extension> SignedPayload<Call, Extension>
674where
675	Call: Encode + Dispatchable,
676	Extension: TransactionExtension<Call>,
677{
678	/// Create new `SignedPayload` for extrinsic format version 4.
679	///
680	/// This function may fail if `implicit` of `Extension` is not available.
681	pub fn new(
682		call: impl Into<CallAndMaybeEncoded<Call>>,
683		tx_ext: Extension,
684	) -> Result<Self, TransactionValidityError> {
685		let implicit = Extension::implicit(&tx_ext)?;
686		Ok(Self((call.into(), tx_ext, implicit)))
687	}
688
689	/// Create new `SignedPayload` from raw components.
690	pub fn from_raw(
691		call: impl Into<CallAndMaybeEncoded<Call>>,
692		tx_ext: Extension,
693		implicit: Extension::Implicit,
694	) -> Self {
695		Self((call.into(), tx_ext, implicit))
696	}
697
698	/// Deconstruct the payload into it's components.
699	pub fn deconstruct(self) -> (Call, Extension, Extension::Implicit) {
700		let (call, ext, implicit) = self.0;
701		(call.call, ext, implicit)
702	}
703}
704
705impl<Call, Extension> Encode for SignedPayload<Call, Extension>
706where
707	Call: Encode + Dispatchable,
708	Extension: TransactionExtension<Call>,
709{
710	/// Get an encoded version of this `blake2_256`-hashed payload.
711	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
712		self.0.using_encoded(|payload| {
713			if payload.len() > 256 {
714				f(&blake2_256(payload)[..])
715			} else {
716				f(payload)
717			}
718		})
719	}
720}
721
722impl<Call, Extension> EncodeLike for SignedPayload<Call, Extension>
723where
724	Call: Encode + Dispatchable,
725	Extension: TransactionExtension<Call>,
726{
727}
728
729impl<Address, Call, Signature, Extension>
730	From<UncheckedExtrinsic<Address, Call, Signature, Extension>> for OpaqueExtrinsic
731where
732	Preamble<Address, Signature, Extension>: Encode,
733	Call: Encode,
734{
735	fn from(extrinsic: UncheckedExtrinsic<Address, Call, Signature, Extension>) -> Self {
736		Self::from_blob(extrinsic.encode_without_prefix())
737	}
738}
739
740impl<Address, Call, Signature, Extension, const MAX_CALL_SIZE: usize> LazyExtrinsic
741	for UncheckedExtrinsic<Address, Call, Signature, Extension, MAX_CALL_SIZE>
742where
743	Preamble<Address, Signature, Extension>: Decode,
744	Call: DecodeWithMemTracking,
745{
746	fn decode_unprefixed(data: &[u8]) -> Result<Self, codec::Error> {
747		Self::decode_with_len(&mut &data[..], data.len())
748	}
749}
750
751#[cfg(test)]
752mod legacy {
753	use codec::{Compact, Decode, Encode, EncodeLike, Error, Input};
754	use scale_info::{
755		build::Fields, meta_type, Path, StaticTypeInfo, Type, TypeInfo, TypeParameter,
756	};
757
758	pub type UncheckedSignaturePayloadV4<Address, Signature, Extra> = (Address, Signature, Extra);
759
760	#[derive(PartialEq, Eq, Clone, Debug)]
761	pub struct UncheckedExtrinsicV4<Address, Call, Signature, Extra> {
762		pub signature: Option<UncheckedSignaturePayloadV4<Address, Signature, Extra>>,
763		pub function: Call,
764	}
765
766	impl<Address, Call, Signature, Extra> TypeInfo
767		for UncheckedExtrinsicV4<Address, Call, Signature, Extra>
768	where
769		Address: StaticTypeInfo,
770		Call: StaticTypeInfo,
771		Signature: StaticTypeInfo,
772		Extra: StaticTypeInfo,
773	{
774		type Identity = UncheckedExtrinsicV4<Address, Call, Signature, Extra>;
775
776		fn type_info() -> Type {
777			Type::builder()
778				.path(Path::new("UncheckedExtrinsic", module_path!()))
779				// Include the type parameter types, even though they are not used directly in any
780				// of the described fields. These type definitions can be used by downstream
781				// consumers to help construct the custom decoding from the opaque bytes (see
782				// below).
783				.type_params(vec![
784					TypeParameter::new("Address", Some(meta_type::<Address>())),
785					TypeParameter::new("Call", Some(meta_type::<Call>())),
786					TypeParameter::new("Signature", Some(meta_type::<Signature>())),
787					TypeParameter::new("Extra", Some(meta_type::<Extra>())),
788				])
789				.docs(&["OldUncheckedExtrinsic raw bytes, requires custom decoding routine"])
790				// Because of the custom encoding, we can only accurately describe the encoding as
791				// an opaque `Vec<u8>`. Downstream consumers will need to manually implement the
792				// codec to encode/decode the `signature` and `function` fields.
793				.composite(Fields::unnamed().field(|f| f.ty::<Vec<u8>>()))
794		}
795	}
796
797	impl<Address, Call, Signature, Extra> UncheckedExtrinsicV4<Address, Call, Signature, Extra> {
798		pub fn new_signed(
799			function: Call,
800			signed: Address,
801			signature: Signature,
802			extra: Extra,
803		) -> Self {
804			Self { signature: Some((signed, signature, extra)), function }
805		}
806
807		pub fn new_unsigned(function: Call) -> Self {
808			Self { signature: None, function }
809		}
810	}
811
812	impl<Address, Call, Signature, Extra> Decode
813		for UncheckedExtrinsicV4<Address, Call, Signature, Extra>
814	where
815		Address: Decode,
816		Signature: Decode,
817		Call: Decode,
818		Extra: Decode,
819	{
820		fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
821			// This is a little more complicated than usual since the binary format must be
822			// compatible with SCALE's generic `Vec<u8>` type. Basically this just means accepting
823			// that there will be a prefix of vector length.
824			let expected_length: Compact<u32> = Decode::decode(input)?;
825			let before_length = input.remaining_len()?;
826
827			let version = input.read_byte()?;
828
829			let is_signed = version & 0b1000_0000 != 0;
830			let version = version & 0b0111_1111;
831			if version != 4u8 {
832				return Err("Invalid transaction version".into());
833			}
834
835			let signature = is_signed.then(|| Decode::decode(input)).transpose()?;
836			let function = Decode::decode(input)?;
837
838			if let Some((before_length, after_length)) =
839				input.remaining_len()?.and_then(|a| before_length.map(|b| (b, a)))
840			{
841				let length = before_length.saturating_sub(after_length);
842
843				if length != expected_length.0 as usize {
844					return Err("Invalid length prefix".into());
845				}
846			}
847
848			Ok(Self { signature, function })
849		}
850	}
851
852	#[docify::export(unchecked_extrinsic_encode_impl)]
853	impl<Address, Call, Signature, Extra> Encode
854		for UncheckedExtrinsicV4<Address, Call, Signature, Extra>
855	where
856		Address: Encode,
857		Signature: Encode,
858		Call: Encode,
859		Extra: Encode,
860	{
861		fn encode(&self) -> Vec<u8> {
862			let mut tmp = Vec::with_capacity(core::mem::size_of::<Self>());
863
864			// 1 byte version id.
865			match self.signature.as_ref() {
866				Some(s) => {
867					tmp.push(4u8 | 0b1000_0000);
868					s.encode_to(&mut tmp);
869				},
870				None => {
871					tmp.push(4u8 & 0b0111_1111);
872				},
873			}
874			self.function.encode_to(&mut tmp);
875
876			let compact_len = codec::Compact::<u32>(tmp.len() as u32);
877
878			// Allocate the output buffer with the correct length
879			let mut output = Vec::with_capacity(compact_len.size_hint() + tmp.len());
880
881			compact_len.encode_to(&mut output);
882			output.extend(tmp);
883
884			output
885		}
886	}
887
888	impl<Address, Call, Signature, Extra> EncodeLike
889		for UncheckedExtrinsicV4<Address, Call, Signature, Extra>
890	where
891		Address: Encode,
892		Signature: Encode,
893		Call: Encode,
894		Extra: Encode,
895	{
896	}
897}
898
899#[cfg(test)]
900mod tests {
901	use super::{legacy::UncheckedExtrinsicV4, *};
902	use crate::{
903		codec::{Decode, Encode},
904		impl_tx_ext_default,
905		testing::TestSignature as TestSig,
906		traits::{FakeDispatchable, IdentityLookup, TransactionExtension},
907	};
908	use sp_io::hashing::blake2_256;
909
910	type TestContext = IdentityLookup<u64>;
911	type TestAccountId = u64;
912
913	// Custom Call enum that supports sorting on decode
914	#[derive(Debug, Clone, Eq, PartialEq, Encode, TypeInfo)]
915	enum Call {
916		Raw(Vec<u8>),
917		Sort(Vec<u8>),
918	}
919
920	impl Decode for Call {
921		fn decode<I: Input>(input: &mut I) -> Result<Self, codec::Error> {
922			let variant = input.read_byte()?;
923			match variant {
924				0 => {
925					let data = Vec::<u8>::decode(input)?;
926					Ok(Call::Raw(data))
927				},
928				1 => {
929					let mut data = Vec::<u8>::decode(input)?;
930					// Sort the data on decode
931					data.sort();
932					Ok(Call::Sort(data))
933				},
934				_ => Err("Invalid Call variant".into()),
935			}
936		}
937	}
938
939	impl DecodeWithMemTracking for Call {}
940
941	impl From<Call> for Vec<u8> {
942		fn from(call: Call) -> Vec<u8> {
943			match call {
944				Call::Sort(data) | Call::Raw(data) => data,
945			}
946		}
947	}
948
949	impl From<Vec<u8>> for FakeDispatchable<Call> {
950		fn from(value: Vec<u8>) -> Self {
951			Self(Call::Raw(value))
952		}
953	}
954
955	type TestCall = FakeDispatchable<Call>;
956
957	const TEST_ACCOUNT: TestAccountId = 0;
958
959	// NOTE: this is demonstration. One can simply use `()` for testing.
960	#[derive(
961		Debug,
962		Encode,
963		Decode,
964		DecodeWithMemTracking,
965		Clone,
966		Eq,
967		PartialEq,
968		Ord,
969		PartialOrd,
970		TypeInfo,
971	)]
972	struct DummyExtension;
973	impl TransactionExtension<TestCall> for DummyExtension {
974		const IDENTIFIER: &'static str = "DummyExtension";
975		type Implicit = ();
976		type Val = ();
977		type Pre = ();
978		impl_tx_ext_default!(TestCall; weight validate prepare);
979	}
980
981	type Ex = UncheckedExtrinsic<TestAccountId, TestCall, TestSig, DummyExtension>;
982	type CEx = CheckedExtrinsic<TestAccountId, TestCall, DummyExtension>;
983
984	#[test]
985	fn unsigned_codec_should_work() {
986		let call: TestCall = Call::Raw(vec![0u8; 0]).into();
987		let ux = Ex::new_bare(call);
988		let encoded = ux.encode();
989		assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux));
990	}
991
992	#[test]
993	fn invalid_length_prefix_is_detected() {
994		let ux = Ex::new_bare(Call::Raw(vec![0u8; 0]).into());
995		let mut encoded = ux.encode();
996
997		let length = Compact::<u32>::decode(&mut &encoded[..]).unwrap();
998		Compact(length.0 + 10).encode_to(&mut &mut encoded[..1]);
999
1000		assert_eq!(Ex::decode(&mut &encoded[..]), Err("Invalid length prefix".into()));
1001	}
1002
1003	#[test]
1004	fn transaction_codec_should_work() {
1005		let ux = Ex::new_transaction(vec![0u8; 0].into(), DummyExtension);
1006		let encoded = ux.encode();
1007		assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux));
1008	}
1009
1010	#[test]
1011	fn signed_codec_should_work() {
1012		let ux = Ex::new_signed(
1013			vec![0u8; 0].into(),
1014			TEST_ACCOUNT,
1015			TestSig(TEST_ACCOUNT, (vec![0u8; 0], DummyExtension).encode()),
1016			DummyExtension,
1017		);
1018		let encoded = ux.encode();
1019		assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux));
1020	}
1021
1022	#[test]
1023	fn large_signed_codec_should_work() {
1024		let ux = Ex::new_signed(
1025			vec![0u8; 0].into(),
1026			TEST_ACCOUNT,
1027			TestSig(
1028				TEST_ACCOUNT,
1029				(vec![0u8; 257], DummyExtension).using_encoded(blake2_256)[..].to_owned(),
1030			),
1031			DummyExtension,
1032		);
1033		let encoded = ux.encode();
1034		assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux));
1035	}
1036
1037	#[test]
1038	fn unsigned_check_should_work() {
1039		let ux = Ex::new_bare(vec![0u8; 0].into());
1040		assert!(ux.is_inherent());
1041		assert_eq!(
1042			<Ex as Checkable<TestContext>>::check(ux, &Default::default()),
1043			Ok(CEx { format: ExtrinsicFormat::Bare, function: vec![0u8; 0].into() }),
1044		);
1045	}
1046
1047	#[test]
1048	fn badly_signed_check_should_fail() {
1049		let ux = Ex::new_signed(
1050			vec![0u8; 0].into(),
1051			TEST_ACCOUNT,
1052			TestSig(TEST_ACCOUNT, vec![0u8; 0].into()),
1053			DummyExtension,
1054		);
1055		assert!(!ux.is_inherent());
1056		assert_eq!(
1057			<Ex as Checkable<TestContext>>::check(ux, &Default::default()),
1058			Err(InvalidTransaction::BadProof.into()),
1059		);
1060	}
1061
1062	#[test]
1063	fn transaction_check_should_work() {
1064		let ux = Ex::new_transaction(vec![0u8; 0].into(), DummyExtension);
1065		assert!(!ux.is_inherent());
1066		assert_eq!(
1067			<Ex as Checkable<TestContext>>::check(ux, &Default::default()),
1068			Ok(CEx {
1069				format: ExtrinsicFormat::General(0, DummyExtension),
1070				function: vec![0u8; 0].into()
1071			}),
1072		);
1073	}
1074
1075	#[test]
1076	fn signed_check_should_work() {
1077		let sig_payload = SignedPayload::from_raw(
1078			FakeDispatchable::from(vec![0u8; 0]),
1079			DummyExtension,
1080			DummyExtension.implicit().unwrap(),
1081		);
1082		let ux = Ex::new_signed(
1083			vec![0u8; 0].into(),
1084			TEST_ACCOUNT,
1085			TestSig(TEST_ACCOUNT, sig_payload.encode()),
1086			DummyExtension,
1087		);
1088		assert!(!ux.is_inherent());
1089		assert_eq!(
1090			<Ex as Checkable<TestContext>>::check(ux, &Default::default()),
1091			Ok(CEx {
1092				format: ExtrinsicFormat::Signed(TEST_ACCOUNT, DummyExtension),
1093				function: Call::Raw(vec![0u8; 0]).into()
1094			}),
1095		);
1096	}
1097
1098	#[test]
1099	fn encoding_matches_vec() {
1100		let ex = Ex::new_bare(Call::Raw(vec![0u8; 0]).into());
1101		let encoded = ex.encode();
1102		let decoded = Ex::decode(&mut encoded.as_slice()).unwrap();
1103		assert_eq!(decoded, ex);
1104		let as_vec: Vec<u8> = Decode::decode(&mut encoded.as_slice()).unwrap();
1105		assert_eq!(as_vec.encode(), encoded);
1106	}
1107
1108	#[test]
1109	fn conversion_to_opaque() {
1110		let ux = Ex::new_bare(Call::Raw(vec![0u8; 0]).into());
1111		let encoded = ux.encode();
1112		let opaque: OpaqueExtrinsic = ux.into();
1113		let opaque_encoded = opaque.encode();
1114		assert_eq!(opaque_encoded, encoded);
1115	}
1116
1117	#[test]
1118	fn large_bad_prefix_should_work() {
1119		let encoded = (Compact::<u32>::from(u32::MAX), Preamble::<(), (), ()>::Bare(0)).encode();
1120		assert!(Ex::decode(&mut &encoded[..]).is_err());
1121	}
1122
1123	#[test]
1124	fn legacy_short_signed_encode_decode() {
1125		let call: TestCall = Call::Raw(vec![0u8; 4]).into();
1126		let signed = TEST_ACCOUNT;
1127		let extension = DummyExtension;
1128		let implicit = extension.implicit().unwrap();
1129		let legacy_signature = TestSig(TEST_ACCOUNT, (&call, &extension, &implicit).encode());
1130
1131		let old_ux =
1132			UncheckedExtrinsicV4::<TestAccountId, TestCall, TestSig, DummyExtension>::new_signed(
1133				call.clone(),
1134				signed,
1135				legacy_signature.clone(),
1136				extension.clone(),
1137			);
1138
1139		let encoded_old_ux = old_ux.encode();
1140		let decoded_old_ux = Ex::decode(&mut &encoded_old_ux[..]).unwrap();
1141
1142		assert_eq!(decoded_old_ux.function, call);
1143		assert_eq!(
1144			decoded_old_ux.preamble,
1145			Preamble::Signed(signed, legacy_signature.clone(), extension.clone())
1146		);
1147
1148		let new_ux =
1149			Ex::new_signed(call.clone(), signed, legacy_signature.clone(), extension.clone());
1150
1151		let new_checked = new_ux.check(&IdentityLookup::<TestAccountId>::default()).unwrap();
1152		let old_checked =
1153			decoded_old_ux.check(&IdentityLookup::<TestAccountId>::default()).unwrap();
1154		assert_eq!(new_checked, old_checked);
1155	}
1156
1157	#[test]
1158	fn legacy_long_signed_encode_decode() {
1159		let call: TestCall = Call::Raw(vec![0u8; 257]).into();
1160		let signed = TEST_ACCOUNT;
1161		let extension = DummyExtension;
1162		let implicit = extension.implicit().unwrap();
1163		let signature = TestSig(
1164			TEST_ACCOUNT,
1165			blake2_256(&(&call, DummyExtension, &implicit).encode()[..]).to_vec(),
1166		);
1167
1168		let old_ux =
1169			UncheckedExtrinsicV4::<TestAccountId, TestCall, TestSig, DummyExtension>::new_signed(
1170				call.clone(),
1171				signed,
1172				signature.clone(),
1173				extension.clone(),
1174			);
1175
1176		let encoded_old_ux = old_ux.encode();
1177		let decoded_old_ux = Ex::decode(&mut &encoded_old_ux[..]).unwrap();
1178
1179		assert_eq!(decoded_old_ux.function, call);
1180		assert_eq!(
1181			decoded_old_ux.preamble,
1182			Preamble::Signed(signed, signature.clone(), extension.clone())
1183		);
1184
1185		let new_ux = Ex::new_signed(call.clone(), signed, signature.clone(), extension.clone());
1186
1187		let new_checked = new_ux.check(&IdentityLookup::<TestAccountId>::default()).unwrap();
1188		let old_checked =
1189			decoded_old_ux.check(&IdentityLookup::<TestAccountId>::default()).unwrap();
1190		assert_eq!(new_checked, old_checked);
1191	}
1192
1193	#[test]
1194	fn legacy_unsigned_encode_decode() {
1195		let call: TestCall = Call::Raw(vec![0u8; 0]).into();
1196
1197		let old_ux =
1198			UncheckedExtrinsicV4::<TestAccountId, TestCall, TestSig, DummyExtension>::new_unsigned(
1199				call.clone(),
1200			);
1201
1202		let encoded_old_ux = old_ux.encode();
1203		let decoded_old_ux = Ex::decode(&mut &encoded_old_ux[..]).unwrap();
1204
1205		assert_eq!(decoded_old_ux.function, call);
1206		assert_eq!(decoded_old_ux.preamble, Preamble::Bare(LEGACY_EXTRINSIC_FORMAT_VERSION));
1207
1208		let new_legacy_ux = Ex::new_bare_legacy(call.clone());
1209		assert_eq!(encoded_old_ux, new_legacy_ux.encode());
1210
1211		let new_ux = Ex::new_bare(call.clone());
1212		let encoded_new_ux = new_ux.encode();
1213		let decoded_new_ux = Ex::decode(&mut &encoded_new_ux[..]).unwrap();
1214		assert_eq!(new_ux, decoded_new_ux);
1215
1216		let new_checked = new_ux.check(&IdentityLookup::<TestAccountId>::default()).unwrap();
1217		let old_checked =
1218			decoded_old_ux.check(&IdentityLookup::<TestAccountId>::default()).unwrap();
1219		assert_eq!(new_checked, old_checked);
1220	}
1221
1222	#[test]
1223	fn max_call_heap_size_should_be_checked() {
1224		// Should be able to decode an `UncheckedExtrinsic` that contains a call with
1225		// heap size < `MAX_CALL_HEAP_SIZE`
1226		let ux = Ex::new_bare(Call::Raw(vec![0u8; DEFAULT_MAX_CALL_SIZE]).into());
1227		let encoded = ux.encode();
1228		assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux));
1229
1230		// Otherwise should fail
1231		let ux = Ex::new_bare(Call::Raw(vec![0u8; DEFAULT_MAX_CALL_SIZE + 1]).into());
1232		let encoded = ux.encode();
1233		assert_eq!(
1234			Ex::decode(&mut &encoded[..]).unwrap_err().to_string(),
1235			"Could not decode `FakeDispatchable.0`:\n\tHeap memory limit exceeded while decoding\n"
1236		);
1237	}
1238
1239	/// Ensures that a decoded extrinsic encodes to the exact same encoded bytes from what it was
1240	/// decoded from.
1241	#[test]
1242	fn encoding_is_stable() {
1243		// Create a call with unsorted data
1244		let unsorted_data = vec![5u8, 3, 7, 1, 9, 2, 8, 4, 6, 0];
1245		let call = Call::Sort(unsorted_data.clone());
1246
1247		let unsorted_encoded = call.encode();
1248
1249		let sig_payload = SignedPayload::from_raw(
1250			FakeDispatchable::from(call.clone()),
1251			DummyExtension,
1252			DummyExtension.implicit().unwrap(),
1253		);
1254		let sig_payload_encoded = sig_payload.encode();
1255
1256		let ux = Ex::new_signed(
1257			call.into(),
1258			TEST_ACCOUNT,
1259			TestSig(TEST_ACCOUNT, sig_payload_encoded.clone()),
1260			DummyExtension,
1261		);
1262
1263		// Encode and decode the extrinsic
1264		// During decode, the Sort variant will sort the data
1265		let encoded = ux.encode();
1266		let decoded_ux = Ex::decode(&mut &encoded[..]).unwrap();
1267
1268		// The decoded call should have sorted data
1269		let mut expected_sorted_data = unsorted_data;
1270		expected_sorted_data.sort();
1271
1272		let expected_decoded_call =
1273			FakeDispatchable::from(Call::Sort(expected_sorted_data.clone()));
1274		assert_eq!(decoded_ux.function, expected_decoded_call);
1275
1276		// Verify that the decoded call encodes differently than the original
1277		let sorted_encoded = Call::Sort(expected_sorted_data).encode();
1278		assert_ne!(
1279			unsorted_encoded, sorted_encoded,
1280			"Sorted and unsorted should encode differently"
1281		);
1282
1283		// Ensure that we can verify the signature successfully.
1284		assert_eq!(
1285			<Ex as Checkable<TestContext>>::check(decoded_ux, &Default::default())
1286				.unwrap()
1287				.function,
1288			expected_decoded_call,
1289		)
1290	}
1291}