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