Skip to content

Commit

Permalink
XCM paid execution barrier supports more origin altering instructions (
Browse files Browse the repository at this point in the history
…#5917)

The AllowTopLevelPaidExecutionFrom allows ClearOrigin instructions
before the expected BuyExecution instruction, it also allows messages
without any origin altering instructions.

This commit enhances the barrier to also support messages that use
AliasOrigin, or DescendOrigin. This is sometimes desired in asset
transfer XCM programs that need to run the inbound assets instructions
using the origin chain root origin, but then want to drop privileges for
the rest of the program. Currently these programs drop privileges by
clearing the origin completely, but that also unnecessarily limits the
range of actions available to the rest of the program. Using
DescendOrigin or AliasOrigin allows the sending chain to instruct the
receiving chain what the deprivileged real origin is.

See polkadot-fellows/RFCs#109 and
polkadot-fellows/RFCs#122 for more details on
how DescendOrigin and AliasOrigin could be used instead of ClearOrigin.

---------

Signed-off-by: Adrian Catangiu <adrian@parity.io>
  • Loading branch information
acatangiu authored Oct 5, 2024
1 parent f8807d1 commit d968c94
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 4 deletions.
12 changes: 8 additions & 4 deletions polkadot/xcm/xcm-builder/src/barriers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ const MAX_ASSETS_FOR_BUY_EXECUTION: usize = 2;
/// Allows execution from `origin` if it is contained in `T` (i.e. `T::Contains(origin)`) taking
/// payments into account.
///
/// Only allows for `TeleportAsset`, `WithdrawAsset`, `ClaimAsset` and `ReserveAssetDeposit` XCMs
/// because they are the only ones that place assets in the Holding Register to pay for execution.
/// Only allows for `WithdrawAsset`, `ReceiveTeleportedAsset`, `ReserveAssetDeposited` and
/// `ClaimAsset` XCMs because they are the only ones that place assets in the Holding Register to
/// pay for execution.
pub struct AllowTopLevelPaidExecutionFrom<T>(PhantomData<T>);
impl<T: Contains<Location>> ShouldExecute for AllowTopLevelPaidExecutionFrom<T> {
fn should_execute<RuntimeCall>(
Expand All @@ -81,9 +82,9 @@ impl<T: Contains<Location>> ShouldExecute for AllowTopLevelPaidExecutionFrom<T>
instructions[..end]
.matcher()
.match_next_inst(|inst| match inst {
WithdrawAsset(ref assets) |
ReceiveTeleportedAsset(ref assets) |
ReserveAssetDeposited(ref assets) |
WithdrawAsset(ref assets) |
ClaimAsset { ref assets, .. } =>
if assets.len() <= MAX_ASSETS_FOR_BUY_EXECUTION {
Ok(())
Expand All @@ -92,7 +93,10 @@ impl<T: Contains<Location>> ShouldExecute for AllowTopLevelPaidExecutionFrom<T>
},
_ => Err(ProcessMessageError::BadFormat),
})?
.skip_inst_while(|inst| matches!(inst, ClearOrigin))?
.skip_inst_while(|inst| {
matches!(inst, ClearOrigin | AliasOrigin(..)) ||
matches!(inst, DescendOrigin(child) if child != &Here)
})?
.match_next_inst(|inst| match inst {
BuyExecution { weight_limit: Limited(ref mut weight), .. }
if weight.all_gte(max_weight) =>
Expand Down
50 changes: 50 additions & 0 deletions polkadot/xcm/xcm-builder/src/tests/barriers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,56 @@ fn allow_paid_should_work() {
assert_eq!(r, Ok(()))
}

#[test]
fn allow_paid_should_deprivilege_origin() {
AllowPaidFrom::set(vec![Parent.into()]);
let fees = (Parent, 1).into();

let mut paying_message_clears_origin = Xcm::<()>(vec![
ReserveAssetDeposited((Parent, 100).into()),
ClearOrigin,
BuyExecution { fees, weight_limit: Limited(Weight::from_parts(30, 30)) },
DepositAsset { assets: AllCounted(1).into(), beneficiary: Here.into() },
]);
let r = AllowTopLevelPaidExecutionFrom::<IsInVec<AllowPaidFrom>>::should_execute(
&Parent.into(),
paying_message_clears_origin.inner_mut(),
Weight::from_parts(30, 30),
&mut props(Weight::zero()),
);
assert_eq!(r, Ok(()));

let mut paying_message_aliases_origin = paying_message_clears_origin.clone();
paying_message_aliases_origin.0[1] = AliasOrigin(Parachain(1).into());
let r = AllowTopLevelPaidExecutionFrom::<IsInVec<AllowPaidFrom>>::should_execute(
&Parent.into(),
paying_message_aliases_origin.inner_mut(),
Weight::from_parts(30, 30),
&mut props(Weight::zero()),
);
assert_eq!(r, Ok(()));

let mut paying_message_descends_origin = paying_message_clears_origin.clone();
paying_message_descends_origin.0[1] = DescendOrigin(Parachain(1).into());
let r = AllowTopLevelPaidExecutionFrom::<IsInVec<AllowPaidFrom>>::should_execute(
&Parent.into(),
paying_message_descends_origin.inner_mut(),
Weight::from_parts(30, 30),
&mut props(Weight::zero()),
);
assert_eq!(r, Ok(()));

let mut paying_message_fake_descends_origin = paying_message_clears_origin.clone();
paying_message_fake_descends_origin.0[1] = DescendOrigin(Here.into());
let r = AllowTopLevelPaidExecutionFrom::<IsInVec<AllowPaidFrom>>::should_execute(
&Parent.into(),
paying_message_fake_descends_origin.inner_mut(),
Weight::from_parts(30, 30),
&mut props(Weight::zero()),
);
assert_eq!(r, Err(ProcessMessageError::Overweight(Weight::from_parts(30, 30))));
}

#[test]
fn suspension_should_work() {
TestSuspender::set_suspended(true);
Expand Down
14 changes: 14 additions & 0 deletions prdoc/pr_5917.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json

title: "XCM paid execution barrier supports more origin altering instructions"

doc:
- audience: Runtime Dev
description: |
Updates the `AllowTopLevelPaidExecutionFrom` barrier to also support messages that
use `DescendOrigin` or `AliasOrigin` for altering the computed origin during execution.

crates:
- name: staging-xcm-builder
bump: patch

0 comments on commit d968c94

Please sign in to comment.