Transactional processing for XCM (#1222)

Moved from: https://github.com/paritytech/polkadot/pull/6951

closes https://github.com/paritytech/polkadot-sdk/issues/490

- [x] update cumulus

--- 
This PR introduces transactional processing of certain xcm instructions.
For the list of instructions checkout
https://github.com/paritytech/polkadot-sdk/issues/490. The transactional
processing is implemented as an xcm-executor config item. The two
implementations in this PR are `FrameTransactionalProcessor` and `()`.
The `()` implementation does no transactional processing. Each
implementation of the `ProcessTransaction` trait has an
`IS_TRANSACTIONAL` const that tells the XCVM if transactional processing
is actually implemented. If Transactional processing is implemented,
changes to touched registers should also be rolled back to prevent
inconsistencies.


Note for reviewers:
Check out the following safety assumption:
https://github.com/paritytech/polkadot-sdk/pull/1222/files#diff-4effad7d8c1c9de19fd27e18661cbf2128c8718f3b2420a27d2f816e0749ea53R30

---------

Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>
Co-authored-by: Francisco Aguirre <franciscoaguirreperez@gmail.com>
Co-authored-by: command-bot <>
This commit is contained in:
Just van Stam
2024-01-24 17:30:27 +01:00
committed by GitHub
parent a78ff7d770
commit 50eb12cf2f
54 changed files with 675 additions and 295 deletions
@@ -26,7 +26,7 @@ use frame_support::{
use sp_core::H256;
use sp_runtime::traits::{BlakeTwo256, IdentityLookup};
use xcm::latest::prelude::*;
use xcm_builder::{AllowUnpaidExecutionFrom, MintLocation};
use xcm_builder::{AllowUnpaidExecutionFrom, FrameTransactionalProcessor, MintLocation};
type Block = frame_system::mocking::MockBlock<Test>;
@@ -145,6 +145,7 @@ impl xcm_executor::Config for XcmConfig {
type CallDispatcher = RuntimeCall;
type SafeCallFilter = Everything;
type Aliasers = Nothing;
type TransactionalProcessor = FrameTransactionalProcessor;
}
impl crate::Config for Test {
@@ -125,11 +125,15 @@ benchmarks! {
}
refund_surplus {
let holding = T::worst_case_holding(0).into();
let mut executor = new_executor::<T>(Default::default());
executor.set_holding(holding);
let holding_assets = T::worst_case_holding(1);
// We can already buy execution since we'll load the holding register manually
let asset_for_fees = T::fee_asset().unwrap();
let previous_xcm = Xcm(vec![BuyExecution { fees: asset_for_fees, weight_limit: Limited(Weight::from_parts(1337, 1337)) }]);
executor.set_holding(holding_assets.into());
executor.set_total_surplus(Weight::from_parts(1337, 1337));
executor.set_total_refunded(Weight::zero());
executor.bench_process(previous_xcm).expect("Holding has been loaded, so we can buy execution here");
let instruction = Instruction::<XcmCallOf<T>>::RefundSurplus;
let xcm = Xcm(vec![instruction]);
@@ -30,7 +30,7 @@ use xcm_builder::{
AssetsInHolding, TestAssetExchanger, TestAssetLocker, TestAssetTrap,
TestSubscriptionService, TestUniversalAliases,
},
AliasForeignAccountId32, AllowUnpaidExecutionFrom,
AliasForeignAccountId32, AllowUnpaidExecutionFrom, FrameTransactionalProcessor,
};
use xcm_executor::traits::ConvertOrigin;
@@ -134,6 +134,7 @@ impl xcm_executor::Config for XcmConfig {
type CallDispatcher = RuntimeCall;
type SafeCallFilter = Everything;
type Aliasers = Aliasers;
type TransactionalProcessor = FrameTransactionalProcessor;
}
parameter_types! {
@@ -196,6 +197,10 @@ impl generic::Config for Test {
Ok((Default::default(), ticket, assets))
}
fn fee_asset() -> Result<Asset, BenchmarkError> {
Ok(Asset { id: AssetId(Here.into()), fun: Fungible(1_000_000) })
}
fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> {
let assets: Asset = (AssetId(Here.into()), 100).into();
Ok((Default::default(), account_id_junction::<Test>(1).into(), assets))
@@ -73,6 +73,10 @@ pub mod pallet {
/// Return an origin, ticket, and assets that can be trapped and claimed.
fn claimable_asset() -> Result<(Location, Location, Assets), BenchmarkError>;
/// Asset used to pay for fees. Used to buy weight in benchmarks, for example in
/// `refund_surplus`.
fn fee_asset() -> Result<Asset, BenchmarkError>;
/// Return an unlocker, owner and assets that can be locked and unlocked.
fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError>;