From 21927dd4a5384c7cbb09c8ad0ceac483be787dd1 Mon Sep 17 00:00:00 2001
From: Raymond Cheung <178801527+raymondkfcheung@users.noreply.github.com>
Date: Wed, 19 Mar 2025 10:46:06 +0000
Subject: [PATCH] Fix XCM Barrier Rejection Handling to Return Incomplete with
 Weight (#7843)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This PR addresses an issue with the handling of message execution when
blocked by the barrier. Instead of returning an `Outcome::Error`, we
modify the behaviour to return `Outcome::Incomplete`, which includes the
weight consumed up to the point of rejection and the error that caused
the blockage.

This change ensures more accurate weight tracking during message
execution, even when interrupted. It improves resource management and
aligns the XCM executor’s behaviour with better error handling
practices.

---------

Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
 .../people-westend/src/tests/governance.rs    |  3 +--
 polkadot/xcm/xcm-builder/src/tests/origins.rs |  5 ++++-
 .../xcm/xcm-builder/src/tests/querying.rs     |  5 ++++-
 .../src/tests/version_subscriptions.rs        | 19 ++++++++++++++-----
 polkadot/xcm/xcm-builder/tests/scenarios.rs   |  8 +++++++-
 polkadot/xcm/xcm-executor/src/lib.rs          |  6 +++++-
 prdoc/pr_7843.prdoc                           | 15 +++++++++++++++
 7 files changed, 50 insertions(+), 11 deletions(-)
 create mode 100644 prdoc/pr_7843.prdoc

diff --git a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/governance.rs b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/governance.rs
index 3b1779e40b6..56ed029d2ab 100644
--- a/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/governance.rs
+++ b/cumulus/parachains/integration-tests/emulated/tests/people/people-westend/src/tests/governance.rs
@@ -14,7 +14,6 @@
 // limitations under the License.
 
 use crate::imports::*;
-use frame_support::traits::ProcessMessageError;
 
 use codec::Encode;
 use frame_support::sp_runtime::traits::Dispatchable;
@@ -141,7 +140,7 @@ fn relay_commands_add_registrar_wrong_origin() {
 				assert_expected_events!(
 					PeopleWestend,
 					vec![
-						RuntimeEvent::MessageQueue(pallet_message_queue::Event::ProcessingFailed { error: ProcessMessageError::Unsupported, .. }) => {},
+						RuntimeEvent::MessageQueue(pallet_message_queue::Event::Processed { success: false, .. }) => {},
 					]
 				);
 			} else {
diff --git a/polkadot/xcm/xcm-builder/src/tests/origins.rs b/polkadot/xcm/xcm-builder/src/tests/origins.rs
index b6a1a9f1052..3cdc0a8eb36 100644
--- a/polkadot/xcm/xcm-builder/src/tests/origins.rs
+++ b/polkadot/xcm/xcm-builder/src/tests/origins.rs
@@ -139,7 +139,10 @@ fn unpaid_execution_should_work() {
 		Weight::from_parts(50, 50),
 		Weight::zero(),
 	);
-	assert_eq!(r, Outcome::Error { error: XcmError::Barrier });
+	assert_eq!(
+		r,
+		Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::Barrier }
+	);
 
 	let message = Xcm(vec![UnpaidExecution {
 		weight_limit: Limited(Weight::from_parts(10, 10)),
diff --git a/polkadot/xcm/xcm-builder/src/tests/querying.rs b/polkadot/xcm/xcm-builder/src/tests/querying.rs
index 3b47073d53d..062b508368f 100644
--- a/polkadot/xcm/xcm-builder/src/tests/querying.rs
+++ b/polkadot/xcm/xcm-builder/src/tests/querying.rs
@@ -130,5 +130,8 @@ fn prepaid_result_of_query_should_get_free_execution() {
 		weight_limit,
 		Weight::zero(),
 	);
-	assert_eq!(r, Outcome::Error { error: XcmError::Barrier });
+	assert_eq!(
+		r,
+		Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::Barrier }
+	);
 }
diff --git a/polkadot/xcm/xcm-builder/src/tests/version_subscriptions.rs b/polkadot/xcm/xcm-builder/src/tests/version_subscriptions.rs
index 01047fde989..df36b3c5731 100644
--- a/polkadot/xcm/xcm-builder/src/tests/version_subscriptions.rs
+++ b/polkadot/xcm/xcm-builder/src/tests/version_subscriptions.rs
@@ -37,7 +37,7 @@ fn simple_version_subscriptions_should_work() {
 			weight_limit,
 			Weight::zero(),
 		),
-		Outcome::Error { error: XcmError::Barrier }
+		Outcome::Incomplete { used: Weight::from_parts(20, 20), error: XcmError::Barrier }
 	);
 
 	// this case fails because the additional `SetAppendix` instruction is not allowed in the
@@ -50,7 +50,7 @@ fn simple_version_subscriptions_should_work() {
 			weight_limit,
 			Weight::zero(),
 		),
-		Outcome::Error { error: XcmError::Barrier }
+		Outcome::Incomplete { used: Weight::from_parts(20, 20), error: XcmError::Barrier }
 	);
 
 	let message = Xcm::<TestCall>(vec![SubscribeVersion {
@@ -66,7 +66,10 @@ fn simple_version_subscriptions_should_work() {
 		weight_limit,
 		Weight::zero(),
 	);
-	assert_eq!(r, Outcome::Error { error: XcmError::Barrier });
+	assert_eq!(
+		r,
+		Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::Barrier }
+	);
 
 	let r = XcmExecutor::<TestConfig>::prepare_and_execute(
 		Parent,
@@ -139,7 +142,10 @@ fn simple_version_unsubscriptions_should_work() {
 		weight_limit,
 		Weight::zero(),
 	);
-	assert_eq!(r, Outcome::Error { error: XcmError::Barrier });
+	assert_eq!(
+		r,
+		Outcome::Incomplete { used: Weight::from_parts(20, 20), error: XcmError::Barrier }
+	);
 
 	let origin = Parachain(1000);
 	let message = Xcm::<TestCall>(vec![UnsubscribeVersion]);
@@ -152,7 +158,10 @@ fn simple_version_unsubscriptions_should_work() {
 		weight_limit,
 		Weight::zero(),
 	);
-	assert_eq!(r, Outcome::Error { error: XcmError::Barrier });
+	assert_eq!(
+		r,
+		Outcome::Incomplete { used: Weight::from_parts(10, 10), error: XcmError::Barrier }
+	);
 
 	let r = XcmExecutor::<TestConfig>::prepare_and_execute(
 		Parent,
diff --git a/polkadot/xcm/xcm-builder/tests/scenarios.rs b/polkadot/xcm/xcm-builder/tests/scenarios.rs
index 793d4f8b49b..e3a1924a19d 100644
--- a/polkadot/xcm/xcm-builder/tests/scenarios.rs
+++ b/polkadot/xcm/xcm-builder/tests/scenarios.rs
@@ -418,6 +418,12 @@ fn recursive_xcm_execution_fail() {
 			Weight::zero(),
 		);
 
-		assert_eq!(outcome, Outcome::Error { error: XcmError::Barrier });
+		assert_eq!(
+			outcome,
+			Outcome::Incomplete {
+				used: Weight::from_parts(3000000000, 3072),
+				error: XcmError::Barrier
+			}
+		);
 	});
 }
diff --git a/polkadot/xcm/xcm-executor/src/lib.rs b/polkadot/xcm/xcm-executor/src/lib.rs
index 4e1c3a5cf97..ffaafcce282 100644
--- a/polkadot/xcm/xcm-executor/src/lib.rs
+++ b/polkadot/xcm/xcm-executor/src/lib.rs
@@ -272,7 +272,11 @@ impl<Config: config::Config> ExecuteXcm<Config::RuntimeCall> for XcmExecutor<Con
 				error = ?e,
 				"Barrier blocked execution",
 			);
-			return Outcome::Error { error: XcmError::Barrier }
+
+			return Outcome::Incomplete {
+				used: xcm_weight,         // Weight consumed before the error
+				error: XcmError::Barrier, // The error that occurred
+			};
 		}
 
 		*id = properties.message_id.unwrap_or(*id);
diff --git a/prdoc/pr_7843.prdoc b/prdoc/pr_7843.prdoc
new file mode 100644
index 00000000000..ef77a64f51b
--- /dev/null
+++ b/prdoc/pr_7843.prdoc
@@ -0,0 +1,15 @@
+title: Fix XCM Barrier Rejection Handling to Return Incomplete with Weight
+doc:
+- audience: Runtime Dev
+  description: "This PR addresses an issue with the handling of message execution\
+    \ when blocked by the barrier. Instead of returning an `Outcome::Error`, we modify\
+    \ the behaviour to return `Outcome::Incomplete`, which includes the weight consumed\
+    \ up to the point of rejection and the error that caused the blockage.\n\nThis\
+    \ change ensures more accurate weight tracking during message execution, even\
+    \ when interrupted. It improves resource management and aligns the XCM executor\u2019\
+    s behaviour with better error handling practices."
+crates:
+- name: staging-xcm-executor
+  bump: patch
+- name: staging-xcm-builder
+  bump: patch
-- 
GitLab