From 8e3d929623d43398ed3ab8c9ca813aff32588011 Mon Sep 17 00:00:00 2001
From: Guillaume Thiolliere <gui.thiolliere@gmail.com>
Date: Wed, 13 Nov 2024 18:20:25 +0900
Subject: [PATCH] [Tx ext stage 2: 1/4] Add `TransactionSource` as argument in
 `TransactionExtension::validate` (#6323)

## Meta

This PR is part of 4 PR:
* https://github.com/paritytech/polkadot-sdk/pull/6323
* https://github.com/paritytech/polkadot-sdk/pull/6324
* https://github.com/paritytech/polkadot-sdk/pull/6325
* https://github.com/paritytech/polkadot-sdk/pull/6326

## Description

One goal of transaction extension is to get rid or unsigned
transactions.
But unsigned transaction validation has access to the
`TransactionSource`.

The source is used for unsigned transactions that the node trust and
don't want to pay upfront.
Instead of using transaction source we could do: the transaction is
valid if it is signed by the block author, conceptually it should work,
but it doesn't look so easy.

This PR add `TransactionSource` to the validate function for transaction
extensions
---
 bridges/bin/runtime-common/src/extensions.rs  | 13 ++++--
 bridges/modules/relayers/src/extension/mod.rs |  9 +++-
 polkadot/runtime/common/src/claims.rs         | 11 +++--
 prdoc/pr_6323.prdoc                           | 32 ++++++++++++++
 .../src/extensions.rs                         |  3 +-
 substrate/frame/examples/basic/src/lib.rs     |  2 +
 substrate/frame/examples/basic/src/tests.rs   |  5 ++-
 substrate/frame/sudo/src/extension.rs         |  3 +-
 .../system/src/extensions/check_mortality.rs  | 11 ++++-
 .../src/extensions/check_non_zero_sender.rs   | 12 +++---
 .../system/src/extensions/check_nonce.rs      | 30 ++++++++-----
 .../system/src/extensions/check_weight.rs     |  2 +
 .../asset-conversion-tx-payment/src/lib.rs    |  2 +
 .../asset-tx-payment/src/lib.rs               |  3 +-
 .../skip-feeless-payment/src/lib.rs           | 13 +++++-
 .../skip-feeless-payment/src/mock.rs          |  1 +
 .../skip-feeless-payment/src/tests.rs         | 18 ++++++--
 .../frame/transaction-payment/src/lib.rs      |  2 +
 .../frame/transaction-payment/src/tests.rs    | 43 ++++++++++++++-----
 .../verify-signature/src/benchmarking.rs      | 17 +++++++-
 .../frame/verify-signature/src/extension.rs   |  3 +-
 substrate/frame/verify-signature/src/tests.rs | 10 ++---
 .../runtime/src/generic/checked_extrinsic.rs  |  7 +--
 .../as_transaction_extension.rs               |  3 +-
 .../dispatch_transaction.rs                   | 12 ++++--
 .../src/traits/transaction_extension/mod.rs   | 10 ++++-
 substrate/test-utils/runtime/src/lib.rs       |  5 ++-
 27 files changed, 217 insertions(+), 65 deletions(-)
 create mode 100644 prdoc/pr_6323.prdoc

diff --git a/bridges/bin/runtime-common/src/extensions.rs b/bridges/bin/runtime-common/src/extensions.rs
index 19d1554c668..256e975f44c 100644
--- a/bridges/bin/runtime-common/src/extensions.rs
+++ b/bridges/bin/runtime-common/src/extensions.rs
@@ -299,6 +299,7 @@ macro_rules! generate_bridge_reject_obsolete_headers_and_messages {
 				_len: usize,
 				_self_implicit: Self::Implicit,
 				_inherited_implication: &impl codec::Encode,
+				_source: sp_runtime::transaction_validity::TransactionSource,
 			) -> Result<
 				(
 					sp_runtime::transaction_validity::ValidTransaction,
@@ -390,7 +391,9 @@ mod tests {
 			parameter_types, AsSystemOriginSigner, AsTransactionAuthorizedOrigin, ConstU64,
 			DispatchTransaction, Header as _, TransactionExtension,
 		},
-		transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction},
+		transaction_validity::{
+			InvalidTransaction, TransactionSource::External, TransactionValidity, ValidTransaction,
+		},
 		DispatchError,
 	};
 
@@ -610,7 +613,8 @@ mod tests {
 					42u64.into(),
 					&MockCall { data: 1 },
 					&(),
-					0
+					0,
+					External,
 				),
 				InvalidTransaction::Custom(1)
 			);
@@ -629,7 +633,8 @@ mod tests {
 					42u64.into(),
 					&MockCall { data: 2 },
 					&(),
-					0
+					0,
+					External,
 				),
 				InvalidTransaction::Custom(2)
 			);
@@ -645,7 +650,7 @@ mod tests {
 
 			assert_eq!(
 				BridgeRejectObsoleteHeadersAndMessages
-					.validate_only(42u64.into(), &MockCall { data: 3 }, &(), 0)
+					.validate_only(42u64.into(), &MockCall { data: 3 }, &(), 0, External)
 					.unwrap()
 					.0,
 				ValidTransaction { priority: 3, ..Default::default() },
diff --git a/bridges/modules/relayers/src/extension/mod.rs b/bridges/modules/relayers/src/extension/mod.rs
index 710533c223a..a400aeaee07 100644
--- a/bridges/modules/relayers/src/extension/mod.rs
+++ b/bridges/modules/relayers/src/extension/mod.rs
@@ -33,6 +33,7 @@ use bp_runtime::{Chain, RangeInclusiveExt, StaticStrProvider};
 use codec::{Decode, Encode};
 use frame_support::{
 	dispatch::{DispatchInfo, PostDispatchInfo},
+	pallet_prelude::TransactionSource,
 	weights::Weight,
 	CloneNoBound, DefaultNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound,
 };
@@ -304,6 +305,7 @@ where
 		_len: usize,
 		_self_implicit: Self::Implicit,
 		_inherited_implication: &impl Encode,
+		_source: TransactionSource,
 	) -> ValidateResult<Self::Val, R::RuntimeCall> {
 		// Prepare relevant data for `prepare`
 		let parsed_call = match C::parse_and_check_for_obsolete_call(call)? {
@@ -463,7 +465,9 @@ mod tests {
 	use pallet_utility::Call as UtilityCall;
 	use sp_runtime::{
 		traits::{ConstU64, DispatchTransaction, Header as HeaderT},
-		transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction},
+		transaction_validity::{
+			InvalidTransaction, TransactionSource::External, TransactionValidity, ValidTransaction,
+		},
 		DispatchError,
 	};
 
@@ -1076,6 +1080,7 @@ mod tests {
 				&call,
 				&DispatchInfo::default(),
 				0,
+				External,
 			)
 			.map(|t| t.0)
 	}
@@ -1088,6 +1093,7 @@ mod tests {
 				&call,
 				&DispatchInfo::default(),
 				0,
+				External,
 			)
 			.map(|t| t.0)
 	}
@@ -1100,6 +1106,7 @@ mod tests {
 				&call,
 				&DispatchInfo::default(),
 				0,
+				External,
 			)
 			.map(|t| t.0)
 	}
diff --git a/polkadot/runtime/common/src/claims.rs b/polkadot/runtime/common/src/claims.rs
index b77cbfeff77..5383fe41d48 100644
--- a/polkadot/runtime/common/src/claims.rs
+++ b/polkadot/runtime/common/src/claims.rs
@@ -39,7 +39,8 @@ use sp_runtime::{
 		Dispatchable, TransactionExtension, Zero,
 	},
 	transaction_validity::{
-		InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction,
+		InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError,
+		ValidTransaction,
 	},
 	RuntimeDebug,
 };
@@ -663,6 +664,7 @@ where
 		_len: usize,
 		_self_implicit: Self::Implicit,
 		_inherited_implication: &impl Encode,
+		_source: TransactionSource,
 	) -> Result<
 		(ValidTransaction, Self::Val, <T::RuntimeCall as Dispatchable>::RuntimeOrigin),
 		TransactionValidityError,
@@ -716,6 +718,7 @@ mod tests {
 	use super::*;
 	use hex_literal::hex;
 	use secp_utils::*;
+	use sp_runtime::transaction_validity::TransactionSource::External;
 
 	use codec::Encode;
 	// The testing primitives are very useful for avoiding having to work with signatures
@@ -1075,7 +1078,7 @@ mod tests {
 			});
 			let di = c.get_dispatch_info();
 			assert_eq!(di.pays_fee, Pays::No);
-			let r = p.validate_only(Some(42).into(), &c, &di, 20);
+			let r = p.validate_only(Some(42).into(), &c, &di, 20, External);
 			assert_eq!(r.unwrap().0, ValidTransaction::default());
 		});
 	}
@@ -1088,13 +1091,13 @@ mod tests {
 				statement: StatementKind::Regular.to_text().to_vec(),
 			});
 			let di = c.get_dispatch_info();
-			let r = p.validate_only(Some(42).into(), &c, &di, 20);
+			let r = p.validate_only(Some(42).into(), &c, &di, 20, External);
 			assert!(r.is_err());
 			let c = RuntimeCall::Claims(ClaimsCall::attest {
 				statement: StatementKind::Saft.to_text().to_vec(),
 			});
 			let di = c.get_dispatch_info();
-			let r = p.validate_only(Some(69).into(), &c, &di, 20);
+			let r = p.validate_only(Some(69).into(), &c, &di, 20, External);
 			assert!(r.is_err());
 		});
 	}
diff --git a/prdoc/pr_6323.prdoc b/prdoc/pr_6323.prdoc
new file mode 100644
index 00000000000..ec632a14f94
--- /dev/null
+++ b/prdoc/pr_6323.prdoc
@@ -0,0 +1,32 @@
+title: add `TransactionSource` to `TransactionExtension::validate`
+doc:
+- audience: Runtime Dev
+  description: |
+    Add a the source of the extrinsic as an argument in `TransactionExtension::validate`.
+    The transaction source can be useful for transactions that should only be valid if it comes from the node. For example from offchain worker.
+    To update the current code. The transaction source can simply be ignored: `_source: TransactionSource`
+
+
+crates:
+- name: sp-runtime
+  bump: major
+- name: bridge-runtime-common
+  bump: patch
+- name: frame-system
+  bump: patch
+- name: pallet-transaction-payment
+  bump: patch
+- name: polkadot-runtime-common
+  bump: patch
+- name: pallet-sudo
+  bump: patch
+- name: pallet-verify-signature
+  bump: patch
+- name: pallet-asset-tx-payment
+  bump: patch
+- name: pallet-bridge-relayers
+  bump: patch
+- name: pallet-asset-conversion-tx-payment
+  bump: patch
+- name: pallet-skip-feeless-payment
+  bump: patch
diff --git a/substrate/frame/examples/authorization-tx-extension/src/extensions.rs b/substrate/frame/examples/authorization-tx-extension/src/extensions.rs
index d1e56916d3a..dcbe171c183 100644
--- a/substrate/frame/examples/authorization-tx-extension/src/extensions.rs
+++ b/substrate/frame/examples/authorization-tx-extension/src/extensions.rs
@@ -18,7 +18,7 @@
 use core::{fmt, marker::PhantomData};
 
 use codec::{Decode, Encode};
-use frame_support::{traits::OriginTrait, Parameter};
+use frame_support::{pallet_prelude::TransactionSource, traits::OriginTrait, Parameter};
 use scale_info::TypeInfo;
 use sp_runtime::{
 	impl_tx_ext_default,
@@ -94,6 +94,7 @@ where
 		_len: usize,
 		_self_implicit: Self::Implicit,
 		inherited_implication: &impl codec::Encode,
+		_source: TransactionSource,
 	) -> ValidateResult<Self::Val, T::RuntimeCall> {
 		// If the extension is inactive, just move on in the pipeline.
 		let Some(auth) = &self.inner else {
diff --git a/substrate/frame/examples/basic/src/lib.rs b/substrate/frame/examples/basic/src/lib.rs
index 2f1b32d964e..efdf4332e32 100644
--- a/substrate/frame/examples/basic/src/lib.rs
+++ b/substrate/frame/examples/basic/src/lib.rs
@@ -61,6 +61,7 @@ use codec::{Decode, Encode};
 use core::marker::PhantomData;
 use frame_support::{
 	dispatch::{ClassifyDispatch, DispatchClass, DispatchResult, Pays, PaysFee, WeighData},
+	pallet_prelude::TransactionSource,
 	traits::IsSubType,
 	weights::Weight,
 };
@@ -508,6 +509,7 @@ where
 		len: usize,
 		_self_implicit: Self::Implicit,
 		_inherited_implication: &impl Encode,
+		_source: TransactionSource,
 	) -> ValidateResult<Self::Val, <T as frame_system::Config>::RuntimeCall> {
 		// if the transaction is too big, just drop it.
 		if len > 200 {
diff --git a/substrate/frame/examples/basic/src/tests.rs b/substrate/frame/examples/basic/src/tests.rs
index 8e33d3d0a34..8008f9264c7 100644
--- a/substrate/frame/examples/basic/src/tests.rs
+++ b/substrate/frame/examples/basic/src/tests.rs
@@ -28,6 +28,7 @@ use sp_core::H256;
 // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required.
 use sp_runtime::{
 	traits::{BlakeTwo256, DispatchTransaction, IdentityLookup},
+	transaction_validity::TransactionSource::External,
 	BuildStorage,
 };
 // Reexport crate as its pallet name for construct_runtime.
@@ -146,7 +147,7 @@ fn signed_ext_watch_dummy_works() {
 
 		assert_eq!(
 			WatchDummy::<Test>(PhantomData)
-				.validate_only(Some(1).into(), &call, &info, 150)
+				.validate_only(Some(1).into(), &call, &info, 150, External)
 				.unwrap()
 				.0
 				.priority,
@@ -154,7 +155,7 @@ fn signed_ext_watch_dummy_works() {
 		);
 		assert_eq!(
 			WatchDummy::<Test>(PhantomData)
-				.validate_only(Some(1).into(), &call, &info, 250)
+				.validate_only(Some(1).into(), &call, &info, 250, External)
 				.unwrap_err(),
 			InvalidTransaction::ExhaustsResources.into(),
 		);
diff --git a/substrate/frame/sudo/src/extension.rs b/substrate/frame/sudo/src/extension.rs
index 573de45ba32..d2669de79e5 100644
--- a/substrate/frame/sudo/src/extension.rs
+++ b/substrate/frame/sudo/src/extension.rs
@@ -18,7 +18,7 @@
 use crate::{Config, Key};
 use codec::{Decode, Encode};
 use core::{fmt, marker::PhantomData};
-use frame_support::{dispatch::DispatchInfo, ensure};
+use frame_support::{dispatch::DispatchInfo, ensure, pallet_prelude::TransactionSource};
 use scale_info::TypeInfo;
 use sp_runtime::{
 	impl_tx_ext_default,
@@ -94,6 +94,7 @@ where
 		_len: usize,
 		_self_implicit: Self::Implicit,
 		_inherited_implication: &impl Encode,
+		_source: TransactionSource,
 	) -> Result<
 		(
 			ValidTransaction,
diff --git a/substrate/frame/system/src/extensions/check_mortality.rs b/substrate/frame/system/src/extensions/check_mortality.rs
index 7da5521f353..75e1fc2fc11 100644
--- a/substrate/frame/system/src/extensions/check_mortality.rs
+++ b/substrate/frame/system/src/extensions/check_mortality.rs
@@ -17,6 +17,7 @@
 
 use crate::{pallet_prelude::BlockNumberFor, BlockHash, Config, Pallet};
 use codec::{Decode, Encode};
+use frame_support::pallet_prelude::TransactionSource;
 use scale_info::TypeInfo;
 use sp_runtime::{
 	generic::Era,
@@ -91,6 +92,7 @@ impl<T: Config + Send + Sync> TransactionExtension<T::RuntimeCall> for CheckMort
 		_len: usize,
 		_self_implicit: Self::Implicit,
 		_inherited_implication: &impl Encode,
+		_source: TransactionSource,
 	) -> ValidateResult<Self::Val, T::RuntimeCall> {
 		let current_u64 = <Pallet<T>>::block_number().saturated_into::<u64>();
 		let valid_till = self.0.death(current_u64);
@@ -115,7 +117,9 @@ mod tests {
 		weights::Weight,
 	};
 	use sp_core::H256;
-	use sp_runtime::traits::DispatchTransaction;
+	use sp_runtime::{
+		traits::DispatchTransaction, transaction_validity::TransactionSource::External,
+	};
 
 	#[test]
 	fn signed_ext_check_era_should_work() {
@@ -151,7 +155,10 @@ mod tests {
 			<BlockHash<Test>>::insert(16, H256::repeat_byte(1));
 
 			assert_eq!(
-				ext.validate_only(Some(1).into(), CALL, &normal, len).unwrap().0.longevity,
+				ext.validate_only(Some(1).into(), CALL, &normal, len, External)
+					.unwrap()
+					.0
+					.longevity,
 				15
 			);
 		})
diff --git a/substrate/frame/system/src/extensions/check_non_zero_sender.rs b/substrate/frame/system/src/extensions/check_non_zero_sender.rs
index ec8c12b790d..a4e54954dc2 100644
--- a/substrate/frame/system/src/extensions/check_non_zero_sender.rs
+++ b/substrate/frame/system/src/extensions/check_non_zero_sender.rs
@@ -18,7 +18,7 @@
 use crate::Config;
 use codec::{Decode, Encode};
 use core::marker::PhantomData;
-use frame_support::{traits::OriginTrait, DefaultNoBound};
+use frame_support::{pallet_prelude::TransactionSource, traits::OriginTrait, DefaultNoBound};
 use scale_info::TypeInfo;
 use sp_runtime::{
 	impl_tx_ext_default,
@@ -68,6 +68,7 @@ impl<T: Config + Send + Sync> TransactionExtension<T::RuntimeCall> for CheckNonZ
 		_len: usize,
 		_self_implicit: Self::Implicit,
 		_inherited_implication: &impl Encode,
+		_source: TransactionSource,
 	) -> sp_runtime::traits::ValidateResult<Self::Val, T::RuntimeCall> {
 		if let Some(who) = origin.as_signer() {
 			if who.using_encoded(|d| d.iter().all(|x| *x == 0)) {
@@ -86,7 +87,7 @@ mod tests {
 	use frame_support::{assert_ok, dispatch::DispatchInfo};
 	use sp_runtime::{
 		traits::{AsTransactionAuthorizedOrigin, DispatchTransaction},
-		transaction_validity::TransactionValidityError,
+		transaction_validity::{TransactionSource::External, TransactionValidityError},
 	};
 
 	#[test]
@@ -96,7 +97,7 @@ mod tests {
 			let len = 0_usize;
 			assert_eq!(
 				CheckNonZeroSender::<Test>::new()
-					.validate_only(Some(0).into(), CALL, &info, len)
+					.validate_only(Some(0).into(), CALL, &info, len, External)
 					.unwrap_err(),
 				TransactionValidityError::from(InvalidTransaction::BadSigner)
 			);
@@ -104,7 +105,8 @@ mod tests {
 				Some(1).into(),
 				CALL,
 				&info,
-				len
+				len,
+				External,
 			));
 		})
 	}
@@ -115,7 +117,7 @@ mod tests {
 			let info = DispatchInfo::default();
 			let len = 0_usize;
 			let (_, _, origin) = CheckNonZeroSender::<Test>::new()
-				.validate(None.into(), CALL, &info, len, (), CALL)
+				.validate(None.into(), CALL, &info, len, (), CALL, External)
 				.unwrap();
 			assert!(!origin.is_transaction_authorized());
 		})
diff --git a/substrate/frame/system/src/extensions/check_nonce.rs b/substrate/frame/system/src/extensions/check_nonce.rs
index d96d2c2c066..eed08050338 100644
--- a/substrate/frame/system/src/extensions/check_nonce.rs
+++ b/substrate/frame/system/src/extensions/check_nonce.rs
@@ -18,7 +18,9 @@
 use crate::Config;
 use alloc::vec;
 use codec::{Decode, Encode};
-use frame_support::{dispatch::DispatchInfo, RuntimeDebugNoBound};
+use frame_support::{
+	dispatch::DispatchInfo, pallet_prelude::TransactionSource, RuntimeDebugNoBound,
+};
 use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{
@@ -108,6 +110,7 @@ where
 		_len: usize,
 		_self_implicit: Self::Implicit,
 		_inherited_implication: &impl Encode,
+		_source: TransactionSource,
 	) -> ValidateResult<Self::Val, T::RuntimeCall> {
 		let Some(who) = origin.as_system_origin_signer() else {
 			return Ok((Default::default(), Val::Refund(self.weight(call)), origin))
@@ -182,7 +185,10 @@ mod tests {
 	use frame_support::{
 		assert_ok, assert_storage_noop, dispatch::GetDispatchInfo, traits::OriginTrait,
 	};
-	use sp_runtime::traits::{AsTransactionAuthorizedOrigin, DispatchTransaction};
+	use sp_runtime::{
+		traits::{AsTransactionAuthorizedOrigin, DispatchTransaction},
+		transaction_validity::TransactionSource::External,
+	};
 
 	#[test]
 	fn signed_ext_check_nonce_works() {
@@ -203,7 +209,7 @@ mod tests {
 			assert_storage_noop!({
 				assert_eq!(
 					CheckNonce::<Test>(0u64.into())
-						.validate_only(Some(1).into(), CALL, &info, len)
+						.validate_only(Some(1).into(), CALL, &info, len, External)
 						.unwrap_err(),
 					TransactionValidityError::Invalid(InvalidTransaction::Stale)
 				);
@@ -219,7 +225,8 @@ mod tests {
 				Some(1).into(),
 				CALL,
 				&info,
-				len
+				len,
+				External,
 			));
 			assert_ok!(CheckNonce::<Test>(1u64.into()).validate_and_prepare(
 				Some(1).into(),
@@ -232,7 +239,8 @@ mod tests {
 				Some(1).into(),
 				CALL,
 				&info,
-				len
+				len,
+				External,
 			));
 			assert_eq!(
 				CheckNonce::<Test>(5u64.into())
@@ -272,7 +280,7 @@ mod tests {
 			assert_storage_noop!({
 				assert_eq!(
 					CheckNonce::<Test>(1u64.into())
-						.validate_only(Some(1).into(), CALL, &info, len)
+						.validate_only(Some(1).into(), CALL, &info, len, External)
 						.unwrap_err(),
 					TransactionValidityError::Invalid(InvalidTransaction::Payment)
 				);
@@ -288,7 +296,8 @@ mod tests {
 				Some(2).into(),
 				CALL,
 				&info,
-				len
+				len,
+				External,
 			));
 			assert_ok!(CheckNonce::<Test>(1u64.into()).validate_and_prepare(
 				Some(2).into(),
@@ -301,7 +310,8 @@ mod tests {
 				Some(3).into(),
 				CALL,
 				&info,
-				len
+				len,
+				External,
 			));
 			assert_ok!(CheckNonce::<Test>(1u64.into()).validate_and_prepare(
 				Some(3).into(),
@@ -318,7 +328,7 @@ mod tests {
 			let info = DispatchInfo::default();
 			let len = 0_usize;
 			let (_, val, origin) = CheckNonce::<Test>(1u64.into())
-				.validate(None.into(), CALL, &info, len, (), CALL)
+				.validate(None.into(), CALL, &info, len, (), CALL, External)
 				.unwrap();
 			assert!(!origin.is_transaction_authorized());
 			assert_ok!(CheckNonce::<Test>(1u64.into()).prepare(val, &origin, CALL, &info, len));
@@ -342,7 +352,7 @@ mod tests {
 			let len = 0_usize;
 			// run the validation step
 			let (_, val, origin) = CheckNonce::<Test>(1u64.into())
-				.validate(Some(1).into(), CALL, &info, len, (), CALL)
+				.validate(Some(1).into(), CALL, &info, len, (), CALL, External)
 				.unwrap();
 			// mutate `AccountData` for the caller
 			crate::Account::<Test>::mutate(1, |info| {
diff --git a/substrate/frame/system/src/extensions/check_weight.rs b/substrate/frame/system/src/extensions/check_weight.rs
index 131057f54a7..435c96c8741 100644
--- a/substrate/frame/system/src/extensions/check_weight.rs
+++ b/substrate/frame/system/src/extensions/check_weight.rs
@@ -19,6 +19,7 @@ use crate::{limits::BlockWeights, Config, Pallet, LOG_TARGET};
 use codec::{Decode, Encode};
 use frame_support::{
 	dispatch::{DispatchInfo, PostDispatchInfo},
+	pallet_prelude::TransactionSource,
 	traits::Get,
 };
 use scale_info::TypeInfo;
@@ -254,6 +255,7 @@ where
 		len: usize,
 		_self_implicit: Self::Implicit,
 		_inherited_implication: &impl Encode,
+		_source: TransactionSource,
 	) -> ValidateResult<Self::Val, T::RuntimeCall> {
 		let (validity, next_len) = Self::do_validate(info, len)?;
 		Ok((validity, next_len, origin))
diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/lib.rs b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/lib.rs
index 787f6b122e8..d6721c46422 100644
--- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/lib.rs
+++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/lib.rs
@@ -47,6 +47,7 @@ extern crate alloc;
 use codec::{Decode, Encode};
 use frame_support::{
 	dispatch::{DispatchInfo, DispatchResult, PostDispatchInfo},
+	pallet_prelude::TransactionSource,
 	traits::IsType,
 	DefaultNoBound,
 };
@@ -308,6 +309,7 @@ where
 		len: usize,
 		_self_implicit: Self::Implicit,
 		_inherited_implication: &impl Encode,
+		_source: TransactionSource,
 	) -> ValidateResult<Self::Val, T::RuntimeCall> {
 		let Some(who) = origin.as_system_origin_signer() else {
 			return Ok((ValidTransaction::default(), Val::NoCharge, origin))
diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/lib.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/lib.rs
index 25aa272ba01..dd752989c36 100644
--- a/substrate/frame/transaction-payment/asset-tx-payment/src/lib.rs
+++ b/substrate/frame/transaction-payment/asset-tx-payment/src/lib.rs
@@ -38,7 +38,7 @@
 use codec::{Decode, Encode};
 use frame_support::{
 	dispatch::{DispatchInfo, DispatchResult, PostDispatchInfo},
-	pallet_prelude::Weight,
+	pallet_prelude::{TransactionSource, Weight},
 	traits::{
 		tokens::{
 			fungibles::{Balanced, Credit, Inspect},
@@ -324,6 +324,7 @@ where
 		len: usize,
 		_self_implicit: Self::Implicit,
 		_inherited_implication: &impl Encode,
+		_source: TransactionSource,
 	) -> Result<
 		(ValidTransaction, Self::Val, <T::RuntimeCall as Dispatchable>::RuntimeOrigin),
 		TransactionValidityError,
diff --git a/substrate/frame/transaction-payment/skip-feeless-payment/src/lib.rs b/substrate/frame/transaction-payment/skip-feeless-payment/src/lib.rs
index d6ac648cefd..dd907f6fcbb 100644
--- a/substrate/frame/transaction-payment/skip-feeless-payment/src/lib.rs
+++ b/substrate/frame/transaction-payment/skip-feeless-payment/src/lib.rs
@@ -39,6 +39,7 @@
 use codec::{Decode, Encode};
 use frame_support::{
 	dispatch::{CheckIfFeeless, DispatchResult},
+	pallet_prelude::TransactionSource,
 	traits::{IsType, OriginTrait},
 	weights::Weight,
 };
@@ -147,12 +148,20 @@ where
 		len: usize,
 		self_implicit: S::Implicit,
 		inherited_implication: &impl Encode,
+		source: TransactionSource,
 	) -> ValidateResult<Self::Val, T::RuntimeCall> {
 		if call.is_feeless(&origin) {
 			Ok((Default::default(), Skip(origin.caller().clone()), origin))
 		} else {
-			let (x, y, z) =
-				self.0.validate(origin, call, info, len, self_implicit, inherited_implication)?;
+			let (x, y, z) = self.0.validate(
+				origin,
+				call,
+				info,
+				len,
+				self_implicit,
+				inherited_implication,
+				source,
+			)?;
 			Ok((x, Apply(y), z))
 		}
 	}
diff --git a/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs b/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs
index 83f7b7dfe2b..cff232a0cae 100644
--- a/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs
+++ b/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs
@@ -60,6 +60,7 @@ impl TransactionExtension<RuntimeCall> for DummyExtension {
 		_len: usize,
 		_self_implicit: Self::Implicit,
 		_inherited_implication: &impl Encode,
+		_source: TransactionSource,
 	) -> ValidateResult<Self::Val, RuntimeCall> {
 		ValidateCount::mutate(|c| *c += 1);
 		Ok((ValidTransaction::default(), (), origin))
diff --git a/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs b/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs
index 666844c883b..1940110a1f1 100644
--- a/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs
+++ b/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs
@@ -18,7 +18,7 @@ use crate::mock::{
 	pallet_dummy::Call, DummyExtension, PrepareCount, Runtime, RuntimeCall, ValidateCount,
 };
 use frame_support::dispatch::DispatchInfo;
-use sp_runtime::traits::DispatchTransaction;
+use sp_runtime::{traits::DispatchTransaction, transaction_validity::TransactionSource};
 
 #[test]
 fn skip_feeless_payment_works() {
@@ -41,14 +41,26 @@ fn validate_works() {
 
 	let call = RuntimeCall::DummyPallet(Call::<Runtime>::aux { data: 1 });
 	SkipCheckIfFeeless::<Runtime, DummyExtension>::from(DummyExtension)
-		.validate_only(Some(0).into(), &call, &DispatchInfo::default(), 0)
+		.validate_only(
+			Some(0).into(),
+			&call,
+			&DispatchInfo::default(),
+			0,
+			TransactionSource::External,
+		)
 		.unwrap();
 	assert_eq!(ValidateCount::get(), 1);
 	assert_eq!(PrepareCount::get(), 0);
 
 	let call = RuntimeCall::DummyPallet(Call::<Runtime>::aux { data: 0 });
 	SkipCheckIfFeeless::<Runtime, DummyExtension>::from(DummyExtension)
-		.validate_only(Some(0).into(), &call, &DispatchInfo::default(), 0)
+		.validate_only(
+			Some(0).into(),
+			&call,
+			&DispatchInfo::default(),
+			0,
+			TransactionSource::External,
+		)
 		.unwrap();
 	assert_eq!(ValidateCount::get(), 1);
 	assert_eq!(PrepareCount::get(), 0);
diff --git a/substrate/frame/transaction-payment/src/lib.rs b/substrate/frame/transaction-payment/src/lib.rs
index 711189be8d0..018c2f6b591 100644
--- a/substrate/frame/transaction-payment/src/lib.rs
+++ b/substrate/frame/transaction-payment/src/lib.rs
@@ -54,6 +54,7 @@ use frame_support::{
 	dispatch::{
 		DispatchClass, DispatchInfo, DispatchResult, GetDispatchInfo, Pays, PostDispatchInfo,
 	},
+	pallet_prelude::TransactionSource,
 	traits::{Defensive, EstimateCallFee, Get},
 	weights::{Weight, WeightToFee},
 	RuntimeDebugNoBound,
@@ -916,6 +917,7 @@ where
 		len: usize,
 		_: (),
 		_implication: &impl Encode,
+		_source: TransactionSource,
 	) -> Result<
 		(ValidTransaction, Self::Val, <T::RuntimeCall as Dispatchable>::RuntimeOrigin),
 		TransactionValidityError,
diff --git a/substrate/frame/transaction-payment/src/tests.rs b/substrate/frame/transaction-payment/src/tests.rs
index e8f5ab99529..dde696f09c2 100644
--- a/substrate/frame/transaction-payment/src/tests.rs
+++ b/substrate/frame/transaction-payment/src/tests.rs
@@ -23,7 +23,7 @@ use codec::Encode;
 use sp_runtime::{
 	generic::UncheckedExtrinsic,
 	traits::{DispatchTransaction, One},
-	transaction_validity::InvalidTransaction,
+	transaction_validity::{InvalidTransaction, TransactionSource::External},
 	BuildStorage,
 };
 
@@ -235,7 +235,7 @@ fn transaction_extension_allows_free_transactions() {
 				class: DispatchClass::Operational,
 				pays_fee: Pays::No,
 			};
-			assert_ok!(Ext::from(0).validate_only(Some(1).into(), CALL, &op_tx, len));
+			assert_ok!(Ext::from(0).validate_only(Some(1).into(), CALL, &op_tx, len, External));
 
 			// like a InsecureFreeNormal
 			let free_tx = DispatchInfo {
@@ -245,7 +245,9 @@ fn transaction_extension_allows_free_transactions() {
 				pays_fee: Pays::Yes,
 			};
 			assert_eq!(
-				Ext::from(0).validate_only(Some(1).into(), CALL, &free_tx, len).unwrap_err(),
+				Ext::from(0)
+					.validate_only(Some(1).into(), CALL, &free_tx, len, External)
+					.unwrap_err(),
 				TransactionValidityError::Invalid(InvalidTransaction::Payment),
 			);
 		});
@@ -659,11 +661,19 @@ fn should_alter_operational_priority() {
 		};
 
 		let ext = Ext::from(tip);
-		let priority = ext.validate_only(Some(2).into(), CALL, &normal, len).unwrap().0.priority;
+		let priority = ext
+			.validate_only(Some(2).into(), CALL, &normal, len, External)
+			.unwrap()
+			.0
+			.priority;
 		assert_eq!(priority, 60);
 
 		let ext = Ext::from(2 * tip);
-		let priority = ext.validate_only(Some(2).into(), CALL, &normal, len).unwrap().0.priority;
+		let priority = ext
+			.validate_only(Some(2).into(), CALL, &normal, len, External)
+			.unwrap()
+			.0
+			.priority;
 		assert_eq!(priority, 110);
 	});
 
@@ -676,11 +686,13 @@ fn should_alter_operational_priority() {
 		};
 
 		let ext = Ext::from(tip);
-		let priority = ext.validate_only(Some(2).into(), CALL, &op, len).unwrap().0.priority;
+		let priority =
+			ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority;
 		assert_eq!(priority, 5810);
 
 		let ext = Ext::from(2 * tip);
-		let priority = ext.validate_only(Some(2).into(), CALL, &op, len).unwrap().0.priority;
+		let priority =
+			ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority;
 		assert_eq!(priority, 6110);
 	});
 }
@@ -698,7 +710,11 @@ fn no_tip_has_some_priority() {
 			pays_fee: Pays::Yes,
 		};
 		let ext = Ext::from(tip);
-		let priority = ext.validate_only(Some(2).into(), CALL, &normal, len).unwrap().0.priority;
+		let priority = ext
+			.validate_only(Some(2).into(), CALL, &normal, len, External)
+			.unwrap()
+			.0
+			.priority;
 		assert_eq!(priority, 10);
 	});
 
@@ -710,7 +726,8 @@ fn no_tip_has_some_priority() {
 			pays_fee: Pays::Yes,
 		};
 		let ext = Ext::from(tip);
-		let priority = ext.validate_only(Some(2).into(), CALL, &op, len).unwrap().0.priority;
+		let priority =
+			ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority;
 		assert_eq!(priority, 5510);
 	});
 }
@@ -729,7 +746,11 @@ fn higher_tip_have_higher_priority() {
 				pays_fee: Pays::Yes,
 			};
 			let ext = Ext::from(tip);
-			pri1 = ext.validate_only(Some(2).into(), CALL, &normal, len).unwrap().0.priority;
+			pri1 = ext
+				.validate_only(Some(2).into(), CALL, &normal, len, External)
+				.unwrap()
+				.0
+				.priority;
 		});
 
 		ExtBuilder::default().balance_factor(100).build().execute_with(|| {
@@ -740,7 +761,7 @@ fn higher_tip_have_higher_priority() {
 				pays_fee: Pays::Yes,
 			};
 			let ext = Ext::from(tip);
-			pri2 = ext.validate_only(Some(2).into(), CALL, &op, len).unwrap().0.priority;
+			pri2 = ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority;
 		});
 
 		(pri1, pri2)
diff --git a/substrate/frame/verify-signature/src/benchmarking.rs b/substrate/frame/verify-signature/src/benchmarking.rs
index 2b592a4023e..475cf4cec59 100644
--- a/substrate/frame/verify-signature/src/benchmarking.rs
+++ b/substrate/frame/verify-signature/src/benchmarking.rs
@@ -27,7 +27,10 @@ use super::*;
 use crate::{extension::VerifySignature, Config, Pallet as VerifySignaturePallet};
 use alloc::vec;
 use frame_benchmarking::{v2::*, BenchmarkError};
-use frame_support::dispatch::{DispatchInfo, GetDispatchInfo};
+use frame_support::{
+	dispatch::{DispatchInfo, GetDispatchInfo},
+	pallet_prelude::TransactionSource,
+};
 use frame_system::{Call as SystemCall, RawOrigin};
 use sp_io::hashing::blake2_256;
 use sp_runtime::traits::{AsTransactionAuthorizedOrigin, Dispatchable, TransactionExtension};
@@ -55,7 +58,17 @@ mod benchmarks {
 
 		#[block]
 		{
-			assert!(ext.validate(RawOrigin::None.into(), &call, &info, 0, (), &call).is_ok());
+			assert!(ext
+				.validate(
+					RawOrigin::None.into(),
+					&call,
+					&info,
+					0,
+					(),
+					&call,
+					TransactionSource::External
+				)
+				.is_ok());
 		}
 
 		Ok(())
diff --git a/substrate/frame/verify-signature/src/extension.rs b/substrate/frame/verify-signature/src/extension.rs
index 4490a0a600b..d48991e7a1d 100644
--- a/substrate/frame/verify-signature/src/extension.rs
+++ b/substrate/frame/verify-signature/src/extension.rs
@@ -20,7 +20,7 @@
 
 use crate::{Config, WeightInfo};
 use codec::{Decode, Encode};
-use frame_support::traits::OriginTrait;
+use frame_support::{pallet_prelude::TransactionSource, traits::OriginTrait};
 use scale_info::TypeInfo;
 use sp_io::hashing::blake2_256;
 use sp_runtime::{
@@ -113,6 +113,7 @@ where
 		_len: usize,
 		_: (),
 		inherited_implication: &impl Encode,
+		_source: TransactionSource,
 	) -> Result<
 		(ValidTransaction, Self::Val, <T::RuntimeCall as Dispatchable>::RuntimeOrigin),
 		TransactionValidityError,
diff --git a/substrate/frame/verify-signature/src/tests.rs b/substrate/frame/verify-signature/src/tests.rs
index 3e4c8db12fe..505a33a883c 100644
--- a/substrate/frame/verify-signature/src/tests.rs
+++ b/substrate/frame/verify-signature/src/tests.rs
@@ -25,7 +25,7 @@ use extension::VerifySignature;
 use frame_support::{
 	derive_impl,
 	dispatch::GetDispatchInfo,
-	pallet_prelude::{InvalidTransaction, TransactionValidityError},
+	pallet_prelude::{InvalidTransaction, TransactionSource, TransactionValidityError},
 	traits::OriginTrait,
 };
 use frame_system::Call as SystemCall;
@@ -84,7 +84,7 @@ fn verification_works() {
 	let info = call.get_dispatch_info();
 
 	let (_, _, origin) = VerifySignature::<Test>::new_with_signature(sig, who)
-		.validate_only(None.into(), &call, &info, 0)
+		.validate_only(None.into(), &call, &info, 0, TransactionSource::External)
 		.unwrap();
 	assert_eq!(origin.as_signer().unwrap(), &who)
 }
@@ -98,7 +98,7 @@ fn bad_signature() {
 
 	assert_eq!(
 		VerifySignature::<Test>::new_with_signature(sig, who)
-			.validate_only(None.into(), &call, &info, 0)
+			.validate_only(None.into(), &call, &info, 0, TransactionSource::External)
 			.unwrap_err(),
 		TransactionValidityError::Invalid(InvalidTransaction::BadProof)
 	);
@@ -113,7 +113,7 @@ fn bad_starting_origin() {
 
 	assert_eq!(
 		VerifySignature::<Test>::new_with_signature(sig, who)
-			.validate_only(Some(42).into(), &call, &info, 0)
+			.validate_only(Some(42).into(), &call, &info, 0, TransactionSource::External)
 			.unwrap_err(),
 		TransactionValidityError::Invalid(InvalidTransaction::BadSigner)
 	);
@@ -126,7 +126,7 @@ fn disabled_extension_works() {
 	let info = call.get_dispatch_info();
 
 	let (_, _, origin) = VerifySignature::<Test>::new_disabled()
-		.validate_only(Some(who).into(), &call, &info, 0)
+		.validate_only(Some(who).into(), &call, &info, 0, TransactionSource::External)
 		.unwrap();
 	assert_eq!(origin.as_signer().unwrap(), &who)
 }
diff --git a/substrate/primitives/runtime/src/generic/checked_extrinsic.rs b/substrate/primitives/runtime/src/generic/checked_extrinsic.rs
index e2ecd5ed6da..521f54bf4af 100644
--- a/substrate/primitives/runtime/src/generic/checked_extrinsic.rs
+++ b/substrate/primitives/runtime/src/generic/checked_extrinsic.rs
@@ -85,10 +85,11 @@ where
 			},
 			ExtrinsicFormat::Signed(ref signer, ref extension) => {
 				let origin = Some(signer.clone()).into();
-				extension.validate_only(origin, &self.function, info, len).map(|x| x.0)
+				extension.validate_only(origin, &self.function, info, len, source).map(|x| x.0)
 			},
-			ExtrinsicFormat::General(ref extension) =>
-				extension.validate_only(None.into(), &self.function, info, len).map(|x| x.0),
+			ExtrinsicFormat::General(ref extension) => extension
+				.validate_only(None.into(), &self.function, info, len, source)
+				.map(|x| x.0),
 		}
 	}
 
diff --git a/substrate/primitives/runtime/src/traits/transaction_extension/as_transaction_extension.rs b/substrate/primitives/runtime/src/traits/transaction_extension/as_transaction_extension.rs
index a5179748673..282064078fe 100644
--- a/substrate/primitives/runtime/src/traits/transaction_extension/as_transaction_extension.rs
+++ b/substrate/primitives/runtime/src/traits/transaction_extension/as_transaction_extension.rs
@@ -25,7 +25,7 @@ use sp_core::RuntimeDebug;
 
 use crate::{
 	traits::{AsSystemOriginSigner, SignedExtension, ValidateResult},
-	transaction_validity::InvalidTransaction,
+	transaction_validity::{InvalidTransaction, TransactionSource},
 };
 
 use super::*;
@@ -74,6 +74,7 @@ where
 		len: usize,
 		_self_implicit: Self::Implicit,
 		_inherited_implication: &impl Encode,
+		_source: TransactionSource,
 	) -> ValidateResult<Self::Val, SE::Call> {
 		let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?;
 		let r = self.0.validate(who, call, info, len)?;
diff --git a/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs b/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs
index e2fb556bf9d..19c8a2b2d49 100644
--- a/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs
+++ b/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs
@@ -17,7 +17,10 @@
 
 //! The [DispatchTransaction] trait.
 
-use crate::{traits::AsTransactionAuthorizedOrigin, transaction_validity::InvalidTransaction};
+use crate::{
+	traits::AsTransactionAuthorizedOrigin,
+	transaction_validity::{InvalidTransaction, TransactionSource},
+};
 
 use super::*;
 
@@ -45,6 +48,7 @@ pub trait DispatchTransaction<Call: Dispatchable> {
 		call: &Call,
 		info: &Self::Info,
 		len: usize,
+		source: TransactionSource,
 	) -> Result<(ValidTransaction, Self::Val, Self::Origin), TransactionValidityError>;
 	/// Validate and prepare a transaction, ready for dispatch.
 	fn validate_and_prepare(
@@ -93,8 +97,9 @@ where
 		call: &Call,
 		info: &DispatchInfoOf<Call>,
 		len: usize,
+		source: TransactionSource,
 	) -> Result<(ValidTransaction, T::Val, Self::Origin), TransactionValidityError> {
-		match self.validate(origin, call, info, len, self.implicit()?, call) {
+		match self.validate(origin, call, info, len, self.implicit()?, call, source) {
 			// After validation, some origin must have been authorized.
 			Ok((_, _, origin)) if !origin.is_transaction_authorized() =>
 				Err(InvalidTransaction::UnknownOrigin.into()),
@@ -108,7 +113,8 @@ where
 		info: &DispatchInfoOf<Call>,
 		len: usize,
 	) -> Result<(T::Pre, Self::Origin), TransactionValidityError> {
-		let (_, val, origin) = self.validate_only(origin, call, info, len)?;
+		let (_, val, origin) =
+			self.validate_only(origin, call, info, len, TransactionSource::InBlock)?;
 		let pre = self.prepare(val, &origin, &call, info, len)?;
 		Ok((pre, origin))
 	}
diff --git a/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs b/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs
index 58cd0974661..f8c5dc6a724 100644
--- a/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs
+++ b/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs
@@ -19,7 +19,9 @@
 
 use crate::{
 	scale_info::{MetaType, StaticTypeInfo},
-	transaction_validity::{TransactionValidity, TransactionValidityError, ValidTransaction},
+	transaction_validity::{
+		TransactionSource, TransactionValidity, TransactionValidityError, ValidTransaction,
+	},
 	DispatchResult,
 };
 use codec::{Codec, Decode, Encode};
@@ -243,6 +245,7 @@ pub trait TransactionExtension<Call: Dispatchable>:
 		len: usize,
 		self_implicit: Self::Implicit,
 		inherited_implication: &impl Encode,
+		source: TransactionSource,
 	) -> ValidateResult<Self::Val, Call>;
 
 	/// Do any pre-flight stuff for a transaction after validation.
@@ -429,6 +432,7 @@ macro_rules! impl_tx_ext_default {
 			_len: usize,
 			_self_implicit: Self::Implicit,
 			_inherited_implication: &impl $crate::codec::Encode,
+			_source: $crate::transaction_validity::TransactionSource,
 		) -> $crate::traits::ValidateResult<Self::Val, $call> {
 			Ok((Default::default(), Default::default(), origin))
 		}
@@ -496,6 +500,7 @@ impl<Call: Dispatchable> TransactionExtension<Call> for Tuple {
 		len: usize,
 		self_implicit: Self::Implicit,
 		inherited_implication: &impl Encode,
+		source: TransactionSource,
 	) -> Result<
 		(ValidTransaction, Self::Val, <Call as Dispatchable>::RuntimeOrigin),
 		TransactionValidityError,
@@ -521,7 +526,7 @@ impl<Call: Dispatchable> TransactionExtension<Call> for Tuple {
 					// passed into the next items in this pipeline-tuple.
 					&following_implicit_implications,
 				);
-				Tuple.validate(origin, call, info, len, item_implicit, &implications)?
+				Tuple.validate(origin, call, info, len, item_implicit, &implications, source)?
 			};
 			let valid = valid.combine_with(item_valid);
 			let val = val.push_back(item_val);
@@ -616,6 +621,7 @@ impl<Call: Dispatchable> TransactionExtension<Call> for () {
 		_len: usize,
 		_self_implicit: Self::Implicit,
 		_inherited_implication: &impl Encode,
+		_source: TransactionSource,
 	) -> Result<
 		(ValidTransaction, (), <Call as Dispatchable>::RuntimeOrigin),
 		TransactionValidityError,
diff --git a/substrate/test-utils/runtime/src/lib.rs b/substrate/test-utils/runtime/src/lib.rs
index 1314d9d6dd4..d565f65e8d3 100644
--- a/substrate/test-utils/runtime/src/lib.rs
+++ b/substrate/test-utils/runtime/src/lib.rs
@@ -292,6 +292,7 @@ impl sp_runtime::traits::TransactionExtension<RuntimeCall> for CheckSubstrateCal
 		_len: usize,
 		_self_implicit: Self::Implicit,
 		_inherited_implication: &impl Encode,
+		_source: TransactionSource,
 	) -> Result<
 		(ValidTransaction, Self::Val, <RuntimeCall as Dispatchable>::RuntimeOrigin),
 		TransactionValidityError,
@@ -1053,7 +1054,7 @@ mod tests {
 	use sp_core::{storage::well_known_keys::HEAP_PAGES, traits::CallContext};
 	use sp_runtime::{
 		traits::{DispatchTransaction, Hash as _},
-		transaction_validity::{InvalidTransaction, ValidTransaction},
+		transaction_validity::{InvalidTransaction, TransactionSource::External, ValidTransaction},
 	};
 	use substrate_test_runtime_client::{
 		prelude::*, runtime::TestAPI, DefaultTestClientBuilderExt, TestClientBuilder,
@@ -1211,6 +1212,7 @@ mod tests {
 						&ExtrinsicBuilder::new_call_with_priority(16).build().function,
 						&info,
 						len,
+						External,
 					)
 					.unwrap()
 					.0
@@ -1225,6 +1227,7 @@ mod tests {
 						&ExtrinsicBuilder::new_call_do_not_propagate().build().function,
 						&info,
 						len,
+						External,
 					)
 					.unwrap()
 					.0
-- 
GitLab