From 51aec90cbac6a1e8ecabada0a182bb19d731e78e Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Thu, 14 Dec 2023 00:47:48 +0000 Subject: [PATCH] ".git/.scripts/commands/fmt/fmt.sh" --- .../cookbook/relay_token_transactor/mod.rs | 14 +- .../relay_token_transactor/network.rs | 48 ++- .../relay_token_transactor/parachain/mod.rs | 31 +- .../parachain/xcm_config.rs | 195 ++++++------ .../relay_token_transactor/relay_chain/mod.rs | 19 +- .../relay_chain/xcm_config.rs | 179 +++++------ .../cookbook/relay_token_transactor/tests.rs | 124 ++++---- polkadot/xcm/docs/src/fundamentals.rs | 57 ++-- polkadot/xcm/docs/src/glossary.rs | 91 +++--- polkadot/xcm/docs/src/lib.rs | 3 +- polkadot/xcm/docs/src/mock_message_queue.rs | 278 +++++++++--------- 11 files changed, 522 insertions(+), 517 deletions(-) diff --git a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/mod.rs b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/mod.rs index 687142dc4eb3..773700381c84 100644 --- a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/mod.rs +++ b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/mod.rs @@ -2,23 +2,21 @@ //! //! This example shows how to configure a parachain to only deal with the relay chain token. //! -//! The first step is using the [`xcm_builder::CurrencyAdapter`] to create an `AssetTransactor` that can -//! handle the relay chain token. -//! +//! The first step is using the [`xcm_builder::CurrencyAdapter`] to create an `AssetTransactor` that +//! can handle the relay chain token. #![doc = docify::embed!("src/cookbook/relay_token_transactor/parachain/xcm_config.rs", asset_transactor)] //! //! The second step is to configure `IsReserve` to recognize the relay chain as a reserve for its //! own asset. -//! With this, you'll be able to easily get derivatives from the relay chain by using the xcm pallet's -//! `transfer_assets` extrinsic. +//! With this, you'll be able to easily get derivatives from the relay chain by using the xcm +//! pallet's `transfer_assets` extrinsic. //! //! The `IsReserve` type takes a type that implements `ContainsPair`. //! In this case, we want a type that contains the pair `(relay_chain_native_token, relay_chain)`. -//! #![doc = docify::embed!("src/cookbook/relay_token_transactor/parachain/xcm_config.rs", is_reserve)] //! -//! With this setup, we are able to do a reserve asset transfer to and from the parachain and relay chain. -//! +//! With this setup, we are able to do a reserve asset transfer to and from the parachain and relay +//! chain. #![doc = docify::embed!("src/cookbook/relay_token_transactor/tests.rs", reserve_asset_transfers_work)] //! //! For the rest of the code, be sure to check the contents of this module. diff --git a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/network.rs b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/network.rs index 6da87576b4a7..5eb0b8160f62 100644 --- a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/network.rs +++ b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/network.rs @@ -1,8 +1,10 @@ //! Mock network -use frame::deps::frame_system; -use frame::deps::sp_runtime::{BuildStorage, AccountId32}; -use frame::deps::sp_io::TestExternalities; +use frame::deps::{ + frame_system, + sp_io::TestExternalities, + sp_runtime::{AccountId32, BuildStorage}, +}; use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain, TestExt}; use super::{parachain, relay_chain}; @@ -44,33 +46,29 @@ decl_test_network! { } pub fn para_ext() -> TestExternalities { - use parachain::{MessageQueue, Runtime, System}; + use parachain::{MessageQueue, Runtime, System}; - let t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - let mut ext = frame::deps::sp_io::TestExternalities::new(t); - ext.execute_with(|| { - System::set_block_number(1); - MessageQueue::set_para_id(2222.into()); - }); - ext + let t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + let mut ext = frame::deps::sp_io::TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + MessageQueue::set_para_id(2222.into()); + }); + ext } pub fn relay_ext() -> TestExternalities { - use relay_chain::{Runtime, System}; + use relay_chain::{Runtime, System}; - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - pallet_balances::GenesisConfig:: { - balances: vec![ - (ALICE, INITIAL_BALANCE), - ], - } - .assimilate_storage(&mut t) - .unwrap(); + pallet_balances::GenesisConfig:: { balances: vec![(ALICE, INITIAL_BALANCE)] } + .assimilate_storage(&mut t) + .unwrap(); - let mut ext = TestExternalities::new(t); - ext.execute_with(|| { - System::set_block_number(1); - }); - ext + let mut ext = TestExternalities::new(t); + ext.execute_with(|| { + System::set_block_number(1); + }); + ext } diff --git a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/mod.rs b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/mod.rs index 7fdcfaabf7b4..2a487588c758 100644 --- a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/mod.rs +++ b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/mod.rs @@ -1,34 +1,31 @@ //! # Runtime -use frame::prelude::*; -use frame::runtime::prelude::*; -use frame::deps::frame_system; -use frame::traits::IdentityLookup; +use frame::{deps::frame_system, prelude::*, runtime::prelude::*, traits::IdentityLookup}; use xcm_executor::XcmExecutor; mod xcm_config; -use xcm_config::XcmConfig; use crate::mock_message_queue; +use xcm_config::XcmConfig; pub type Block = frame_system::mocking::MockBlock; pub type AccountId = frame::deps::sp_runtime::AccountId32; pub type Balance = u64; construct_runtime! { - pub struct Runtime { - System: frame_system, - MessageQueue: mock_message_queue, - Balances: pallet_balances, - XcmPallet: pallet_xcm, - } + pub struct Runtime { + System: frame_system, + MessageQueue: mock_message_queue, + Balances: pallet_balances, + XcmPallet: pallet_xcm, + } } #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Runtime { - type Block = Block; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type AccountData = pallet_balances::AccountData; + type Block = Block; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type AccountData = pallet_balances::AccountData; } impl mock_message_queue::Config for Runtime { @@ -38,6 +35,6 @@ impl mock_message_queue::Config for Runtime { #[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] impl pallet_balances::Config for Runtime { - type Balance = Balance; - type AccountStore = System; + type Balance = Balance; + type AccountStore = System; } diff --git a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/xcm_config.rs b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/xcm_config.rs index ef5b543f8731..ccaad78199dc 100644 --- a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/xcm_config.rs +++ b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/parachain/xcm_config.rs @@ -1,147 +1,148 @@ //! # XCM Configuration -use frame::runtime::prelude::*; -use frame::traits::{Nothing, Everything}; -use frame::deps::frame_system; -use xcm_builder::{ - IsConcrete, CurrencyAdapter, HashedDescription, DescribeFamily, DescribeAllTerminal, - EnsureXcmOrigin, SignedToAccountId32, AccountId32Aliases, +use frame::{ + deps::frame_system, + runtime::prelude::*, + traits::{Everything, Nothing}, }; use xcm::v3::prelude::*; +use xcm_builder::{ + AccountId32Aliases, CurrencyAdapter, DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, + HashedDescription, IsConcrete, SignedToAccountId32, +}; use xcm_executor::XcmExecutor; -use super::{ - Runtime, Balances, AccountId, RuntimeCall, RuntimeOrigin, RuntimeEvent, MessageQueue, -}; +use super::{AccountId, Balances, MessageQueue, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin}; parameter_types! { - pub RelayLocation: MultiLocation = MultiLocation::parent(); - pub ThisNetwork: NetworkId = NetworkId::Polkadot; + pub RelayLocation: MultiLocation = MultiLocation::parent(); + pub ThisNetwork: NetworkId = NetworkId::Polkadot; } pub type LocationToAccountId = ( - HashedDescription>, - AccountId32Aliases, + HashedDescription>, + AccountId32Aliases, ); #[docify::export] mod asset_transactor { - use super::*; - - /// AssetTransactor for handling the relay chain token - pub type CurrencyTransactor = CurrencyAdapter< - // Use this Currency implementation - Balances, - // Use this transactor for dealing with the relay chain token - IsConcrete, - // How to convert an XCM MultiLocation into a local account id - LocationToAccountId, - // The account id type, needed because Currency is generic over it - AccountId, - // Not tracking teleports - (), - >; - - /// All asset transactors, in this case only one - pub type AssetTransactor = CurrencyTransactor; + use super::*; + + /// AssetTransactor for handling the relay chain token + pub type CurrencyTransactor = CurrencyAdapter< + // Use this Currency implementation + Balances, + // Use this transactor for dealing with the relay chain token + IsConcrete, + // How to convert an XCM MultiLocation into a local account id + LocationToAccountId, + // The account id type, needed because Currency is generic over it + AccountId, + // Not tracking teleports + (), + >; + + /// All asset transactors, in this case only one + pub type AssetTransactor = CurrencyTransactor; } #[docify::export] mod is_reserve { - use super::*; + use super::*; - parameter_types! { - pub RelayTokenForRelay: (MultiAssetFilter, MultiLocation) = - (Wild(AllOf { id: Concrete(Parent.into()), fun: WildFungible }), Parent.into()); - } + parameter_types! { + pub RelayTokenForRelay: (MultiAssetFilter, MultiLocation) = + (Wild(AllOf { id: Concrete(Parent.into()), fun: WildFungible }), Parent.into()); + } - /// Put it all together - pub type IsReserve = xcm_builder::Case; + /// Put it all together + pub type IsReserve = xcm_builder::Case; } mod weigher { - use super::*; - use xcm_builder::FixedWeightBounds; + use super::*; + use xcm_builder::FixedWeightBounds; - parameter_types! { - pub const WeightPerInstruction: Weight = Weight::from_parts(1, 1); - pub const MaxInstructions: u32 = 100; - } + parameter_types! { + pub const WeightPerInstruction: Weight = Weight::from_parts(1, 1); + pub const MaxInstructions: u32 = 100; + } - pub type Weigher = FixedWeightBounds; + pub type Weigher = FixedWeightBounds; } parameter_types! { - pub UniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(NetworkId::Polkadot), Parachain(2222)); + pub UniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(NetworkId::Polkadot), Parachain(2222)); } pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { - type RuntimeCall = RuntimeCall; - type XcmSender = (); - type AssetTransactor = asset_transactor::AssetTransactor; - type OriginConverter = (); - type IsReserve = is_reserve::IsReserve; - type IsTeleporter = (); - type UniversalLocation = UniversalLocation; - // This is not safe, you should use `xcm_builder::AllowTopLevelPaidExecutionFrom` in a production chain - type Barrier = xcm_builder::AllowUnpaidExecutionFrom; - type Weigher = weigher::Weigher; - type Trader = (); - type ResponseHandler = (); - type AssetTrap = (); - type AssetLocker = (); - type AssetExchanger = (); - type AssetClaims = (); - type SubscriptionService = (); - type PalletInstancesInfo = (); - type FeeManager = (); - type MaxAssetsIntoHolding = frame::traits::ConstU32<1>; - type MessageExporter = (); - type UniversalAliases = Nothing; - type CallDispatcher = RuntimeCall; - type SafeCallFilter = Everything; - type Aliasers = Nothing; + type RuntimeCall = RuntimeCall; + type XcmSender = (); + type AssetTransactor = asset_transactor::AssetTransactor; + type OriginConverter = (); + type IsReserve = is_reserve::IsReserve; + type IsTeleporter = (); + type UniversalLocation = UniversalLocation; + // This is not safe, you should use `xcm_builder::AllowTopLevelPaidExecutionFrom` in a + // production chain + type Barrier = xcm_builder::AllowUnpaidExecutionFrom; + type Weigher = weigher::Weigher; + type Trader = (); + type ResponseHandler = (); + type AssetTrap = (); + type AssetLocker = (); + type AssetExchanger = (); + type AssetClaims = (); + type SubscriptionService = (); + type PalletInstancesInfo = (); + type FeeManager = (); + type MaxAssetsIntoHolding = frame::traits::ConstU32<1>; + type MessageExporter = (); + type UniversalAliases = Nothing; + type CallDispatcher = RuntimeCall; + type SafeCallFilter = Everything; + type Aliasers = Nothing; } pub type LocalOriginToLocation = SignedToAccountId32; impl pallet_xcm::Config for Runtime { - // We turn off sending for these tests - type SendXcmOrigin = EnsureXcmOrigin; - type XcmRouter = super::super::network::ParachainXcmRouter; // Provided by xcm-simulator - // Anyone can execute XCM programs - type ExecuteXcmOrigin = EnsureXcmOrigin; - // We execute any type of program - type XcmExecuteFilter = Everything; - // How we execute programs - type XcmExecutor = XcmExecutor; - // We don't allow teleports - type XcmTeleportFilter = Nothing; - // We allow all reserve transfers - type XcmReserveTransferFilter = Everything; - // Same weigher executor uses to weigh XCM programs - type Weigher = weigher::Weigher; - // Same universal location - type UniversalLocation = UniversalLocation; - // No version discovery needed + // We turn off sending for these tests + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = super::super::network::ParachainXcmRouter; // Provided by xcm-simulator + // Anyone can execute XCM programs + type ExecuteXcmOrigin = EnsureXcmOrigin; + // We execute any type of program + type XcmExecuteFilter = Everything; + // How we execute programs + type XcmExecutor = XcmExecutor; + // We don't allow teleports + type XcmTeleportFilter = Nothing; + // We allow all reserve transfers + type XcmReserveTransferFilter = Everything; + // Same weigher executor uses to weigh XCM programs + type Weigher = weigher::Weigher; + // Same universal location + type UniversalLocation = UniversalLocation; + // No version discovery needed const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 0; type AdvertisedXcmVersion = frame::traits::ConstU32<3>; type AdminOrigin = frame_system::EnsureRoot; - // No locking + // No locking type TrustedLockers = (); type MaxLockers = frame::traits::ConstU32<0>; type MaxRemoteLockConsumers = frame::traits::ConstU32<0>; type RemoteLockConsumerIdentifier = (); - // How to turn locations into accounts + // How to turn locations into accounts type SovereignAccountOf = LocationToAccountId; - // A currency to pay for things and its matcher, we are using the relay token + // A currency to pay for things and its matcher, we are using the relay token type Currency = Balances; type CurrencyMatcher = IsConcrete; - // Pallet benchmarks, no need for this example + // Pallet benchmarks, no need for this example type WeightInfo = pallet_xcm::TestWeightInfo; - // Runtime types - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type RuntimeEvent = RuntimeEvent; + // Runtime types + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; } diff --git a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/mod.rs b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/mod.rs index f64c9dfca6eb..fbc1a3fdcb39 100644 --- a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/mod.rs +++ b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/mod.rs @@ -1,15 +1,12 @@ //! Relay chain runtime mock. -use frame::prelude::*; -use frame::runtime::prelude::*; -use frame::deps::{ - sp_runtime::AccountId32, - frame_support::weights::WeightMeter, -}; -use frame::traits::{IdentityLookup, ProcessMessage, ProcessMessageError}; -use polkadot_runtime_parachains::{ - inclusion::{AggregateMessageOrigin, UmpQueueId}, +use frame::{ + deps::{frame_support::weights::WeightMeter, sp_runtime::AccountId32}, + prelude::*, + runtime::prelude::*, + traits::{IdentityLookup, ProcessMessage, ProcessMessageError}, }; +use polkadot_runtime_parachains::inclusion::{AggregateMessageOrigin, UmpQueueId}; use xcm::v3::prelude::*; mod xcm_config; @@ -32,7 +29,7 @@ impl frame_system::Config for Runtime { #[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] impl pallet_balances::Config for Runtime { - type AccountStore = System; + type AccountStore = System; } type Block = frame_system::mocking::MockBlock; @@ -83,6 +80,6 @@ construct_runtime! { System: frame_system, Balances: pallet_balances, MessageQueue: pallet_message_queue, - XcmPallet: pallet_xcm, + XcmPallet: pallet_xcm, } } diff --git a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/xcm_config.rs b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/xcm_config.rs index 7d93450abff6..9184fbdba140 100644 --- a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/xcm_config.rs +++ b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/relay_chain/xcm_config.rs @@ -1,134 +1,135 @@ //! Relay chain XCM configuration -use frame::runtime::prelude::*; -use frame::traits::{Nothing, Everything}; -use frame::deps::frame_system; -use xcm_builder::{ - IsConcrete, CurrencyAdapter, HashedDescription, DescribeFamily, DescribeAllTerminal, - EnsureXcmOrigin, SignedToAccountId32, AccountId32Aliases, +use frame::{ + deps::frame_system, + runtime::prelude::*, + traits::{Everything, Nothing}, }; use xcm::v3::prelude::*; +use xcm_builder::{ + AccountId32Aliases, CurrencyAdapter, DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, + HashedDescription, IsConcrete, SignedToAccountId32, +}; use xcm_executor::XcmExecutor; -use super::{ - Runtime, Balances, AccountId, RuntimeCall, RuntimeOrigin, RuntimeEvent, -}; +use super::{AccountId, Balances, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin}; parameter_types! { - pub HereLocation: MultiLocation = MultiLocation::here(); - pub ThisNetwork: NetworkId = NetworkId::Polkadot; + pub HereLocation: MultiLocation = MultiLocation::here(); + pub ThisNetwork: NetworkId = NetworkId::Polkadot; } pub type LocationToAccountId = ( - HashedDescription>, - AccountId32Aliases, + HashedDescription>, + AccountId32Aliases, ); mod asset_transactor { - use super::*; + use super::*; - /// AssetTransactor for handling the relay chain token - pub type CurrencyTransactor = CurrencyAdapter< - // Use this Currency implementation - Balances, - // Use this transactor for dealing with the native token - IsConcrete, - // How to convert an XCM MultiLocation into a local account id - LocationToAccountId, - // The account id type, needed because Currency is generic over it - AccountId, - // Not tracking teleports - (), - >; + /// AssetTransactor for handling the relay chain token + pub type CurrencyTransactor = CurrencyAdapter< + // Use this Currency implementation + Balances, + // Use this transactor for dealing with the native token + IsConcrete, + // How to convert an XCM MultiLocation into a local account id + LocationToAccountId, + // The account id type, needed because Currency is generic over it + AccountId, + // Not tracking teleports + (), + >; - /// All asset transactors, in this case only one - pub type AssetTransactor = CurrencyTransactor; + /// All asset transactors, in this case only one + pub type AssetTransactor = CurrencyTransactor; } mod weigher { - use super::*; - use xcm_builder::FixedWeightBounds; + use super::*; + use xcm_builder::FixedWeightBounds; - parameter_types! { - pub const WeightPerInstruction: Weight = Weight::from_parts(1, 1); - pub const MaxInstructions: u32 = 100; - } + parameter_types! { + pub const WeightPerInstruction: Weight = Weight::from_parts(1, 1); + pub const MaxInstructions: u32 = 100; + } - pub type Weigher = FixedWeightBounds; + pub type Weigher = FixedWeightBounds; } parameter_types! { - pub UniversalLocation: InteriorMultiLocation = X1(GlobalConsensus(NetworkId::Polkadot)); + pub UniversalLocation: InteriorMultiLocation = X1(GlobalConsensus(NetworkId::Polkadot)); } pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { - type RuntimeCall = RuntimeCall; - type XcmSender = (); - type AssetTransactor = asset_transactor::AssetTransactor; - type OriginConverter = (); - // We don't need to recognize anyone as a reserve - type IsReserve = (); - type IsTeleporter = (); - type UniversalLocation = UniversalLocation; - // This is not safe, you should use `xcm_builder::AllowTopLevelPaidExecutionFrom` in a production chain - type Barrier = xcm_builder::AllowUnpaidExecutionFrom; - type Weigher = weigher::Weigher; - type Trader = (); - type ResponseHandler = (); - type AssetTrap = (); - type AssetLocker = (); - type AssetExchanger = (); - type AssetClaims = (); - type SubscriptionService = (); - type PalletInstancesInfo = (); - type FeeManager = (); - type MaxAssetsIntoHolding = frame::traits::ConstU32<1>; - type MessageExporter = (); - type UniversalAliases = Nothing; - type CallDispatcher = RuntimeCall; - type SafeCallFilter = Everything; - type Aliasers = Nothing; + type RuntimeCall = RuntimeCall; + type XcmSender = (); + type AssetTransactor = asset_transactor::AssetTransactor; + type OriginConverter = (); + // We don't need to recognize anyone as a reserve + type IsReserve = (); + type IsTeleporter = (); + type UniversalLocation = UniversalLocation; + // This is not safe, you should use `xcm_builder::AllowTopLevelPaidExecutionFrom` in a + // production chain + type Barrier = xcm_builder::AllowUnpaidExecutionFrom; + type Weigher = weigher::Weigher; + type Trader = (); + type ResponseHandler = (); + type AssetTrap = (); + type AssetLocker = (); + type AssetExchanger = (); + type AssetClaims = (); + type SubscriptionService = (); + type PalletInstancesInfo = (); + type FeeManager = (); + type MaxAssetsIntoHolding = frame::traits::ConstU32<1>; + type MessageExporter = (); + type UniversalAliases = Nothing; + type CallDispatcher = RuntimeCall; + type SafeCallFilter = Everything; + type Aliasers = Nothing; } pub type LocalOriginToLocation = SignedToAccountId32; impl pallet_xcm::Config for Runtime { - // No one can call `send` - type SendXcmOrigin = EnsureXcmOrigin; - type XcmRouter = super::super::network::RelayChainXcmRouter; // Provided by xcm-simulator - // Anyone can execute XCM programs - type ExecuteXcmOrigin = EnsureXcmOrigin; - // We execute any type of program - type XcmExecuteFilter = Everything; - // How we execute programs - type XcmExecutor = XcmExecutor; - // We don't allow teleports - type XcmTeleportFilter = Nothing; - // We allow all reserve transfers - type XcmReserveTransferFilter = Everything; - // Same weigher executor uses to weigh XCM programs - type Weigher = weigher::Weigher; - // Same universal location - type UniversalLocation = UniversalLocation; - // No version discovery needed + // No one can call `send` + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = super::super::network::RelayChainXcmRouter; // Provided by xcm-simulator + // Anyone can execute XCM programs + type ExecuteXcmOrigin = EnsureXcmOrigin; + // We execute any type of program + type XcmExecuteFilter = Everything; + // How we execute programs + type XcmExecutor = XcmExecutor; + // We don't allow teleports + type XcmTeleportFilter = Nothing; + // We allow all reserve transfers + type XcmReserveTransferFilter = Everything; + // Same weigher executor uses to weigh XCM programs + type Weigher = weigher::Weigher; + // Same universal location + type UniversalLocation = UniversalLocation; + // No version discovery needed const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 0; type AdvertisedXcmVersion = frame::traits::ConstU32<3>; type AdminOrigin = frame_system::EnsureRoot; - // No locking + // No locking type TrustedLockers = (); type MaxLockers = frame::traits::ConstU32<0>; type MaxRemoteLockConsumers = frame::traits::ConstU32<0>; type RemoteLockConsumerIdentifier = (); - // How to turn locations into accounts + // How to turn locations into accounts type SovereignAccountOf = LocationToAccountId; - // A currency to pay for things and its matcher, we are using the relay token + // A currency to pay for things and its matcher, we are using the relay token type Currency = Balances; type CurrencyMatcher = IsConcrete; - // Pallet benchmarks, no need for this example + // Pallet benchmarks, no need for this example type WeightInfo = pallet_xcm::TestWeightInfo; - // Runtime types - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type RuntimeEvent = RuntimeEvent; + // Runtime types + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; } diff --git a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/tests.rs b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/tests.rs index 241a74ade41f..8fa9939f40fa 100644 --- a/polkadot/xcm/docs/src/cookbook/relay_token_transactor/tests.rs +++ b/polkadot/xcm/docs/src/cookbook/relay_token_transactor/tests.rs @@ -1,12 +1,11 @@ -use test_log::test; use frame::testing_prelude::*; +use test_log::test; use xcm::prelude::*; use xcm_simulator::TestExt; use super::{ - network::{MockNet, Relay, ParaA, ALICE, BOB, CENTS, INITIAL_BALANCE}, - relay_chain, - parachain, + network::{MockNet, ParaA, Relay, ALICE, BOB, CENTS, INITIAL_BALANCE}, + parachain, relay_chain, }; // Scenario: @@ -19,68 +18,73 @@ use super::{ #[docify::export] #[test] fn reserve_asset_transfers_work() { - MockNet::reset(); + MockNet::reset(); - // ALICE starts with INITIAL_BALANCE on the relay chain - Relay::execute_with(|| { - assert_eq!(relay_chain::Balances::free_balance(&ALICE), INITIAL_BALANCE); - }); + // ALICE starts with INITIAL_BALANCE on the relay chain + Relay::execute_with(|| { + assert_eq!(relay_chain::Balances::free_balance(&ALICE), INITIAL_BALANCE); + }); - // BOB starts with 0 on the parachain - ParaA::execute_with(|| { - assert_eq!(parachain::Balances::free_balance(&BOB), 0); - }); + // BOB starts with 0 on the parachain + ParaA::execute_with(|| { + assert_eq!(parachain::Balances::free_balance(&BOB), 0); + }); - // ALICE on the relay chain sends some relay token to BOB on the parachain - // Because of how the network is set up, us sending the native token and - // the parachain recognizing the relay as the reserve for its token, `transfer_assets` - // determines a reserve transfer should be done with the local chain as the reserve. - Relay::execute_with(|| { - let destination: MultiLocation = Parachain(2222).into(); - let beneficiary: MultiLocation = AccountId32 { id: BOB.clone().into(), network: Some(NetworkId::Polkadot) }.into(); - // We need to use `u128` here for the conversion to work properly. - // If we don't specify anything, it will be a `u64`, which the conversion - // will turn into a non fungible token instead of a fungible one. - let assets: MultiAssets = (Here, 50u128 * CENTS as u128).into(); - assert_ok!(relay_chain::XcmPallet::transfer_assets( - relay_chain::RuntimeOrigin::signed(ALICE), - Box::new(VersionedMultiLocation::V3(destination)), - Box::new(VersionedMultiLocation::V3(beneficiary)), - Box::new(VersionedMultiAssets::V3(assets)), - 0, - WeightLimit::Unlimited, - )); + // ALICE on the relay chain sends some relay token to BOB on the parachain + // Because of how the network is set up, us sending the native token and + // the parachain recognizing the relay as the reserve for its token, `transfer_assets` + // determines a reserve transfer should be done with the local chain as the reserve. + Relay::execute_with(|| { + let destination: MultiLocation = Parachain(2222).into(); + let beneficiary: MultiLocation = + AccountId32 { id: BOB.clone().into(), network: Some(NetworkId::Polkadot) }.into(); + // We need to use `u128` here for the conversion to work properly. + // If we don't specify anything, it will be a `u64`, which the conversion + // will turn into a non fungible token instead of a fungible one. + let assets: MultiAssets = (Here, 50u128 * CENTS as u128).into(); + assert_ok!(relay_chain::XcmPallet::transfer_assets( + relay_chain::RuntimeOrigin::signed(ALICE), + Box::new(VersionedMultiLocation::V3(destination)), + Box::new(VersionedMultiLocation::V3(beneficiary)), + Box::new(VersionedMultiAssets::V3(assets)), + 0, + WeightLimit::Unlimited, + )); - // ALICE now has less relay chain token - assert_eq!(relay_chain::Balances::free_balance(&ALICE), INITIAL_BALANCE - 50 * CENTS); - }); + // ALICE now has less relay chain token + assert_eq!(relay_chain::Balances::free_balance(&ALICE), INITIAL_BALANCE - 50 * CENTS); + }); - // On the parachain, BOB has received the derivative tokens - ParaA::execute_with(|| { - assert_eq!(parachain::Balances::free_balance(&BOB), 50 * CENTS); + // On the parachain, BOB has received the derivative tokens + ParaA::execute_with(|| { + assert_eq!(parachain::Balances::free_balance(&BOB), 50 * CENTS); - // BOB gives back half to ALICE in the relay chain - let destination: MultiLocation = Parent.into(); - let beneficiary: MultiLocation = AccountId32 { id: ALICE.clone().into(), network: Some(NetworkId::Polkadot) }.into(); - // We specify `Parent` because we are referencing the relay chain token. - // This chain doesn't have a token of its own, so we always refer to this token, - // and we do so by the location of the relay chain. - let assets: MultiAssets = (Parent, 25u128 * CENTS as u128).into(); - assert_ok!(parachain::XcmPallet::transfer_assets( - parachain::RuntimeOrigin::signed(BOB), - Box::new(VersionedMultiLocation::V3(destination)), - Box::new(VersionedMultiLocation::V3(beneficiary)), - Box::new(VersionedMultiAssets::V3(assets)), - 0, - WeightLimit::Unlimited, - )); + // BOB gives back half to ALICE in the relay chain + let destination: MultiLocation = Parent.into(); + let beneficiary: MultiLocation = + AccountId32 { id: ALICE.clone().into(), network: Some(NetworkId::Polkadot) }.into(); + // We specify `Parent` because we are referencing the relay chain token. + // This chain doesn't have a token of its own, so we always refer to this token, + // and we do so by the location of the relay chain. + let assets: MultiAssets = (Parent, 25u128 * CENTS as u128).into(); + assert_ok!(parachain::XcmPallet::transfer_assets( + parachain::RuntimeOrigin::signed(BOB), + Box::new(VersionedMultiLocation::V3(destination)), + Box::new(VersionedMultiLocation::V3(beneficiary)), + Box::new(VersionedMultiAssets::V3(assets)), + 0, + WeightLimit::Unlimited, + )); - // BOB's balance decreased - assert_eq!(parachain::Balances::free_balance(&BOB), 25 * CENTS); - }); + // BOB's balance decreased + assert_eq!(parachain::Balances::free_balance(&BOB), 25 * CENTS); + }); - // ALICE's balance increases - Relay::execute_with(|| { - assert_eq!(relay_chain::Balances::free_balance(&ALICE), INITIAL_BALANCE - 50 * CENTS + 25 * CENTS); - }); + // ALICE's balance increases + Relay::execute_with(|| { + assert_eq!( + relay_chain::Balances::free_balance(&ALICE), + INITIAL_BALANCE - 50 * CENTS + 25 * CENTS + ); + }); } diff --git a/polkadot/xcm/docs/src/fundamentals.rs b/polkadot/xcm/docs/src/fundamentals.rs index 5e836b803505..99528e856a9a 100644 --- a/polkadot/xcm/docs/src/fundamentals.rs +++ b/polkadot/xcm/docs/src/fundamentals.rs @@ -7,7 +7,8 @@ //! //! The goal of XCM is to allow multi-chain ecosystems to thrive via specialization. //! Very specific functionalities can be abstracted away and standardized in this common language. -//! Then, every member of the ecosystem can implement the subset of the language that makes sense for them. +//! Then, every member of the ecosystem can implement the subset of the language that makes sense +//! for them. //! //! The language evolves over time to accomodate the needs of the community //! via the [RFC process](https://github.com/paritytech/xcm-format/blob/master/proposals/0001-process.md). @@ -22,7 +23,8 @@ //! It's the virtual machine that executes XCM programs. //! It is a specification that comes with the language. //! -//! For this docs, we'll use a Rust implementation of XCM and the XCVM, consisting of the following parts: +//! For this docs, we'll use a Rust implementation of XCM and the XCVM, consisting of the following +//! parts: //! - XCM: Holds the definition of an XCM program, the instructions and main concepts. //! - Executor: Implements the XCVM, capable of executing XCMs. Highly configurable. //! - Builder: A collection of types used to configure the executor. @@ -34,19 +36,21 @@ //! ## Locations //! //! Locations are XCM's vocabulary of places we want to talk about in our XCM programs. -//! They are used to reference things like 32-byte accounts, governance bodies, smart contracts, blockchains and more. +//! They are used to reference things like 32-byte accounts, governance bodies, smart contracts, +//! blockchains and more. //! //! Locations are hierarchical. //! This means some places in consensus are wholly encapsulated in other places. //! Say we have two systems A and B. //! If any change in A's state implies a change in B's state, then we say A is interior to B. -//! #![doc = simple_mermaid::mermaid!("../mermaid/location_hierarchy.mmd")] //! -//! Parachains are interior to their relaychain, since a change in their state implies a change in the relaychain's state. +//! Parachains are interior to their relaychain, since a change in their state implies a change in +//! the relaychain's state. //! -//! Because of this hierarchy, the way we represent locations is with both a number of **parents**, times we move __up__ the hierarchy, -//! and a sequence of **junctions**, the steps we take __down__ the hierarchy after going up the specified amount of parents. +//! Because of this hierarchy, the way we represent locations is with both a number of **parents**, +//! times we move __up__ the hierarchy, and a sequence of **junctions**, the steps we take __down__ +//! the hierarchy after going up the specified amount of parents. //! //! In Rust, this is specified with the following datatype: //! ```ignore @@ -56,8 +60,8 @@ //! } //! ``` //! -//! Many junctions are available, parachains, pallets, 32 and 20 byte accounts, governance bodies, and arbitrary indices -//! are the most common. +//! Many junctions are available, parachains, pallets, 32 and 20 byte accounts, governance bodies, +//! and arbitrary indices are the most common. //! A full list of available junctions can be found in the [format](https://github.com/paritytech/xcm-format#interior-locations--junctions) //! and [Junction enum](xcm::v3::prelude::Junction). //! @@ -67,20 +71,20 @@ //! - From parachain 1000 itself: `Here` //! - From parachain 2000: `../Parachain(1000)` //! -//! Relative locations are interpreted by the system that is executing an XCM program, which is the receiver of a message -//! in the case where it's sent. +//! Relative locations are interpreted by the system that is executing an XCM program, which is the +//! receiver of a message in the case where it's sent. //! //! Locations can also be absolute. //! Keeping in line with our filesystem analogy, we can imagine the root of our filesystem to exist. -//! This would be a location with no parents, that is also the parent of all systems that derive their own consensus, say -//! Polkadot or Ethereum or Bitcoin. +//! This would be a location with no parents, that is also the parent of all systems that derive +//! their own consensus, say Polkadot or Ethereum or Bitcoin. //! Such a location does not exist concretely, but we can still use this definition for it. //! This is the **universal location**. //! We need the universal location to be able to describe locations in an absolute way. -//! #![doc = simple_mermaid::mermaid!("../mermaid/universal_location.mmd")] //! -//! Here, the absolute location of parachain 1000 would be `GlobalConsensus(Polkadot)/Parachain(1000)`. +//! Here, the absolute location of parachain 1000 would be +//! `GlobalConsensus(Polkadot)/Parachain(1000)`. //! //! ## Assets //! @@ -97,7 +101,6 @@ //! assets pallet instance it uses. //! USDT, an example asset that lives on asset hub, is identified by the location //! `Parachain(1000)/PalletInstance(53)/GeneralIndex(1984)`, when seen from the Polkadot relaychain. -//! #![doc = simple_mermaid::mermaid!("../mermaid/usdt_location.mmd")] //! //! The whole type can be seen in the [format](https://github.com/paritytech/xcm-format#6-universal-asset-identifiers) @@ -105,8 +108,8 @@ //! //! ## Instructions //! -//! Given the vocabulary to talk about both locations, chains and accounts, and assets, we now need a way to -//! express what we want the consensus system to do when executing our programs. +//! Given the vocabulary to talk about both locations, chains and accounts, and assets, we now need +//! a way to express what we want the consensus system to do when executing our programs. //! We need a way of writing our programs. //! //! XCM programs are composed of a sequence of instructions. @@ -122,9 +125,9 @@ //! ]); //! ``` //! -//! This instruction is enough to transfer `assets` from the account of the **origin** of a message to the `beneficiary` account. -//! However, because of XCM's generality, fees need to be paid explicitly. -//! This next example sheds more light on this: +//! This instruction is enough to transfer `assets` from the account of the **origin** of a message +//! to the `beneficiary` account. However, because of XCM's generality, fees need to be paid +//! explicitly. This next example sheds more light on this: //! //! ```ignore //! let message = Xcm(vec![ @@ -134,8 +137,10 @@ //! ]); //! ``` //! -//! Here we see the process of transferring assets was broken down into smaller instructions, and we add the explicit fee payment -//! step in the middle. -//! `WithdrawAsset` withdraws assets from the account of the **origin** of the message for usage inside this message's execution. -//! `BuyExecution` explicitly buys execution for this program using the assets specified in `fees`, with a sanity check of `weight_limit`. -//! `DepositAsset` has the same operands as the original `TransferAsset` instruction, specifying `assets` and a `beneficiary` account. +//! Here we see the process of transferring assets was broken down into smaller instructions, and we +//! add the explicit fee payment step in the middle. +//! `WithdrawAsset` withdraws assets from the account of the **origin** of the message for usage +//! inside this message's execution. `BuyExecution` explicitly buys execution for this program using +//! the assets specified in `fees`, with a sanity check of `weight_limit`. `DepositAsset` has the +//! same operands as the original `TransferAsset` instruction, specifying `assets` and a +//! `beneficiary` account. diff --git a/polkadot/xcm/docs/src/glossary.rs b/polkadot/xcm/docs/src/glossary.rs index e748960366c2..90e8e9d74e13 100644 --- a/polkadot/xcm/docs/src/glossary.rs +++ b/polkadot/xcm/docs/src/glossary.rs @@ -1,81 +1,88 @@ //! # Glossary -//! +//! //! ## XCM (Cross-Consensus Messaging) -//! +//! //! A messaging format meant to communicate intentions between consensus systems. //! XCM could also refer to a single message. -//! +//! //! ## Instructions -//! +//! //! XCMs are composed of a sequence of instructions. //! Each instruction aims to convey a particular intention. -//! There are instructions for transferring and locking assets, handling fees, calling arbitrary blobs, and more. -//! +//! There are instructions for transferring and locking assets, handling fees, calling arbitrary +//! blobs, and more. +//! //! ## Consensus system -//! +//! //! A system that can reach any kind of consensus. //! For example, relay chains, parachains, smart contracts. -//! +//! //! ## MultiLocation -//! +//! //! A way of addressing consensus systems. //! These could be relative or absolute. -//! +//! //! ## Junction -//! +//! //! The different ways of descending down a `MultiLocation` hierarchy. //! A junction can be a Parachain, an Account, or more. -//! +//! //! ## MultiAsset -//! +//! //! A way of identifying assets in the same or another consensus system, by using a `MultiLocation`. -//! +//! //! ## Sovereign account -//! +//! //! An account on a consensus system that is controlled by an account in another consensus system. -//! +//! //! ## Teleport -//! +//! //! A way of transferring assets between two consensus systems without the need of a third party. -//! It consists of the sender system burning the asset that wants to be sent over and the recipient minting an equivalent amount of that asset. -//! It requires a lot of trust between the two systems, since failure to mint or burn will reduce the total issuance of the token. -//! +//! It consists of the sender system burning the asset that wants to be sent over and the recipient +//! minting an equivalent amount of that asset. It requires a lot of trust between the two systems, +//! since failure to mint or burn will reduce the total issuance of the token. +//! //! ## Reserve asset transfer -//! -//! A way of transferring assets between two consensus systems that don't trust each other, by using a third system they both trust, called the reserve. -//! The real asset only exists on the reserve, both sender and recipient only deal with derivatives. -//! It consists of the sender burning a certain amount of derivatives, telling the reserve to move real assets from its sovereign account to the destination's sovereign account, and then telling the recipient to mint the right amount of derivatives. -//! +//! +//! A way of transferring assets between two consensus systems that don't trust each other, by using +//! a third system they both trust, called the reserve. The real asset only exists on the reserve, +//! both sender and recipient only deal with derivatives. It consists of the sender burning a +//! certain amount of derivatives, telling the reserve to move real assets from its sovereign +//! account to the destination's sovereign account, and then telling the recipient to mint the right +//! amount of derivatives. +//! //! ## XCVM -//! +//! //! The virtual machine behind XCM. //! Every XCM is an XCVM programme. //! Holds state in registers. -//! +//! //! ## Holding register -//! +//! //! An XCVM register used to hold arbitrary `Asset`s during the execution of an XCVM programme. -//! +//! //! ## Barrier -//! +//! //! An XCM executor configuration item that works as a firewall for incoming XCMs. //! All XCMs have to pass the barrier to be executed, else they are dropped. //! It can be used for whitelisting only certain types or messages or messages from certain senders. -//! +//! //! ## UMP (Upward Message Passing) -//! +//! //! Transport-layer protocol that allows parachains to send messages upwards to their relay chain. -//! +//! //! ## DMP (Downward Message Passing) -//! -//! Transport-layer protocol that allows the relay chain to send messages downwards to one of their parachains. -//! +//! +//! Transport-layer protocol that allows the relay chain to send messages downwards to one of their +//! parachains. +//! //! ## XCMP (Cross-Consensus Message Passing) -//! -//! Transport-layer protocol that allows parachains to send messages between themselves, without going through the relay chain. -//! +//! +//! Transport-layer protocol that allows parachains to send messages between themselves, without +//! going through the relay chain. +//! //! ## HRMP (Horizontal Message Passing) -//! -//! Transport-layer protocol that allows a parachain to send messages to a sibling parachain going through the relay chain. -//! It's a precursor to XCMP, also known as XCMP-lite. +//! +//! Transport-layer protocol that allows a parachain to send messages to a sibling parachain going +//! through the relay chain. It's a precursor to XCMP, also known as XCMP-lite. //! It uses a mixture of UMP and VMP. diff --git a/polkadot/xcm/docs/src/lib.rs b/polkadot/xcm/docs/src/lib.rs index e8ad961d7056..6ed5a5243761 100644 --- a/polkadot/xcm/docs/src/lib.rs +++ b/polkadot/xcm/docs/src/lib.rs @@ -5,7 +5,8 @@ //! Welcome to the Cross-Consensus Messaging documentation! //! //! XCM is a **language** for communicating **intentions** between **consensus systems**. -//! Whether you're a developer, a blockchain enthusiast, or just interested in Polkadot, this guide aims to provide you with an easy-to-understand and comprehensive introduction to XCM. +//! Whether you're a developer, a blockchain enthusiast, or just interested in Polkadot, this guide +//! aims to provide you with an easy-to-understand and comprehensive introduction to XCM. //! //! ## Getting started //! diff --git a/polkadot/xcm/docs/src/mock_message_queue.rs b/polkadot/xcm/docs/src/mock_message_queue.rs index 7713852928ce..bd1bb5904aac 100644 --- a/polkadot/xcm/docs/src/mock_message_queue.rs +++ b/polkadot/xcm/docs/src/mock_message_queue.rs @@ -19,7 +19,7 @@ use codec::{Decode, Encode}; use polkadot_parachain_primitives::primitives::{ - DmpMessageHandler, Id as ParaId, XcmpMessageFormat, XcmpMessageHandler, + DmpMessageHandler, Id as ParaId, XcmpMessageFormat, XcmpMessageHandler, }; use polkadot_primitives::BlockNumber as RelayBlockNumber; use sp_runtime::traits::{Get, Hash}; @@ -31,144 +31,140 @@ pub use pallet::*; #[frame::pallet] pub mod pallet { - use super::*; - use frame::prelude::*; - use frame::deps::frame_system; - - #[pallet::config] - pub trait Config: frame_system::Config { - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - type XcmExecutor: ExecuteXcm; - } - - #[pallet::call] - impl Pallet {} - - #[pallet::pallet] - #[pallet::without_storage_info] - pub struct Pallet(_); - - #[pallet::storage] - #[pallet::getter(fn parachain_id)] - pub(super) type ParachainId = StorageValue<_, ParaId, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn received_dmp)] - /// A queue of received DMP messages - pub(super) type ReceivedDmp = StorageValue<_, Vec>, ValueQuery>; - - impl Get for Pallet { - fn get() -> ParaId { - Self::parachain_id() - } - } - - pub type MessageId = [u8; 32]; - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - // XCMP - /// Some XCM was executed OK. - Success(Option), - /// Some XCM failed. - Fail(Option, XcmError), - /// Bad XCM version used. - BadVersion(Option), - /// Bad XCM format used. - BadFormat(Option), - - // DMP - /// Downward message is invalid XCM. - InvalidFormat(MessageId), - /// Downward message is unsupported version of XCM. - UnsupportedVersion(MessageId), - /// Downward message executed with the given outcome. - ExecutedDownward(MessageId, Outcome), - } - - impl Pallet { - pub fn set_para_id(para_id: ParaId) { - ParachainId::::put(para_id); - } - - fn handle_xcmp_message( - sender: ParaId, - _sent_at: RelayBlockNumber, - xcm: VersionedXcm, - max_weight: xcm::latest::Weight, - ) -> Result { - let hash = Encode::using_encoded(&xcm, T::Hashing::hash); - let message_hash = Encode::using_encoded(&xcm, sp_io::hashing::blake2_256); - let (result, event) = match Xcm::::try_from(xcm) { - Ok(xcm) => { - let location = (Parent, Parachain(sender.into())); - match T::XcmExecutor::execute_xcm(location, xcm, message_hash, max_weight) { - Outcome::Error(e) => (Err(e.clone()), Event::Fail(Some(hash), e)), - Outcome::Complete(w) => (Ok(w), Event::Success(Some(hash))), - // As far as the caller is concerned, this was dispatched without error, so - // we just report the weight used. - Outcome::Incomplete(w, e) => (Ok(w), Event::Fail(Some(hash), e)), - } - } - Err(()) => ( - Err(XcmError::UnhandledXcmVersion), - Event::BadVersion(Some(hash)), - ), - }; - Self::deposit_event(event); - result - } - } - - impl XcmpMessageHandler for Pallet { - fn handle_xcmp_messages<'a, I: Iterator>( - iter: I, - max_weight: xcm::latest::Weight, - ) -> xcm::latest::Weight { - for (sender, sent_at, data) in iter { - let mut data_ref = data; - let _ = XcmpMessageFormat::decode(&mut data_ref) - .expect("Simulator encodes with versioned xcm format; qed"); - - let mut remaining_fragments = &data_ref[..]; - while !remaining_fragments.is_empty() { - if let Ok(xcm) = - VersionedXcm::::decode(&mut remaining_fragments) - { - let _ = Self::handle_xcmp_message(sender, sent_at, xcm, max_weight); - } else { - debug_assert!(false, "Invalid incoming XCMP message data"); - } - } - } - max_weight - } - } - - impl DmpMessageHandler for Pallet { - fn handle_dmp_messages( - iter: impl Iterator)>, - limit: frame::prelude::Weight, - ) -> frame::prelude::Weight { - for (_i, (_sent_at, data)) in iter.enumerate() { - let id = sp_io::hashing::blake2_256(&data[..]); - let maybe_versioned = VersionedXcm::::decode(&mut &data[..]); - match maybe_versioned { - Err(_) => { - Self::deposit_event(Event::InvalidFormat(id)); - } - Ok(versioned) => match Xcm::try_from(versioned) { - Err(()) => Self::deposit_event(Event::UnsupportedVersion(id)), - Ok(x) => { - let outcome = T::XcmExecutor::execute_xcm(Parent, x.clone(), id, limit); - >::append(x); - Self::deposit_event(Event::ExecutedDownward(id, outcome)); - } - }, - } - } - limit - } - } + use super::*; + use frame::{deps::frame_system, prelude::*}; + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + type XcmExecutor: ExecuteXcm; + } + + #[pallet::call] + impl Pallet {} + + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn parachain_id)] + pub(super) type ParachainId = StorageValue<_, ParaId, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn received_dmp)] + /// A queue of received DMP messages + pub(super) type ReceivedDmp = StorageValue<_, Vec>, ValueQuery>; + + impl Get for Pallet { + fn get() -> ParaId { + Self::parachain_id() + } + } + + pub type MessageId = [u8; 32]; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + // XCMP + /// Some XCM was executed OK. + Success(Option), + /// Some XCM failed. + Fail(Option, XcmError), + /// Bad XCM version used. + BadVersion(Option), + /// Bad XCM format used. + BadFormat(Option), + + // DMP + /// Downward message is invalid XCM. + InvalidFormat(MessageId), + /// Downward message is unsupported version of XCM. + UnsupportedVersion(MessageId), + /// Downward message executed with the given outcome. + ExecutedDownward(MessageId, Outcome), + } + + impl Pallet { + pub fn set_para_id(para_id: ParaId) { + ParachainId::::put(para_id); + } + + fn handle_xcmp_message( + sender: ParaId, + _sent_at: RelayBlockNumber, + xcm: VersionedXcm, + max_weight: xcm::latest::Weight, + ) -> Result { + let hash = Encode::using_encoded(&xcm, T::Hashing::hash); + let message_hash = Encode::using_encoded(&xcm, sp_io::hashing::blake2_256); + let (result, event) = match Xcm::::try_from(xcm) { + Ok(xcm) => { + let location = (Parent, Parachain(sender.into())); + match T::XcmExecutor::execute_xcm(location, xcm, message_hash, max_weight) { + Outcome::Error(e) => (Err(e.clone()), Event::Fail(Some(hash), e)), + Outcome::Complete(w) => (Ok(w), Event::Success(Some(hash))), + // As far as the caller is concerned, this was dispatched without error, so + // we just report the weight used. + Outcome::Incomplete(w, e) => (Ok(w), Event::Fail(Some(hash), e)), + } + }, + Err(()) => (Err(XcmError::UnhandledXcmVersion), Event::BadVersion(Some(hash))), + }; + Self::deposit_event(event); + result + } + } + + impl XcmpMessageHandler for Pallet { + fn handle_xcmp_messages<'a, I: Iterator>( + iter: I, + max_weight: xcm::latest::Weight, + ) -> xcm::latest::Weight { + for (sender, sent_at, data) in iter { + let mut data_ref = data; + let _ = XcmpMessageFormat::decode(&mut data_ref) + .expect("Simulator encodes with versioned xcm format; qed"); + + let mut remaining_fragments = &data_ref[..]; + while !remaining_fragments.is_empty() { + if let Ok(xcm) = + VersionedXcm::::decode(&mut remaining_fragments) + { + let _ = Self::handle_xcmp_message(sender, sent_at, xcm, max_weight); + } else { + debug_assert!(false, "Invalid incoming XCMP message data"); + } + } + } + max_weight + } + } + + impl DmpMessageHandler for Pallet { + fn handle_dmp_messages( + iter: impl Iterator)>, + limit: frame::prelude::Weight, + ) -> frame::prelude::Weight { + for (_i, (_sent_at, data)) in iter.enumerate() { + let id = sp_io::hashing::blake2_256(&data[..]); + let maybe_versioned = VersionedXcm::::decode(&mut &data[..]); + match maybe_versioned { + Err(_) => { + Self::deposit_event(Event::InvalidFormat(id)); + }, + Ok(versioned) => match Xcm::try_from(versioned) { + Err(()) => Self::deposit_event(Event::UnsupportedVersion(id)), + Ok(x) => { + let outcome = T::XcmExecutor::execute_xcm(Parent, x.clone(), id, limit); + >::append(x); + Self::deposit_event(Event::ExecutedDownward(id, outcome)); + }, + }, + } + } + limit + } + } }