diff --git a/Cargo.lock b/Cargo.lock index c7e7e4b568..295849a364 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3661,15 +3661,18 @@ dependencies = [ name = "kilt-support" version = "1.7.1" dependencies = [ + "cumulus-primitives-core", "frame-support", "frame-system", "parity-scale-codec", + "polkadot-core-primitives", "scale-info", "serde", "serde_json", "sp-core", "sp-runtime", "sp-std", + "xcm", ] [[package]] @@ -5869,6 +5872,29 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-relay-migration" +version = "1.7.1" +dependencies = [ + "cumulus-pallet-parachain-system", + "cumulus-primitives-core", + "frame-benchmarking", + "frame-support", + "frame-system", + "kilt-support", + "log", + "pallet-xcm", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-runtime-common", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "xcm", +] + [[package]] name = "pallet-scheduler" version = "4.0.0-dev" @@ -6434,6 +6460,7 @@ dependencies = [ "pallet-preimage", "pallet-proxy", "pallet-randomness-collective-flip", + "pallet-relay-migration", "pallet-scheduler", "pallet-session", "pallet-sudo", @@ -10760,6 +10787,7 @@ dependencies = [ "pallet-preimage", "pallet-proxy", "pallet-randomness-collective-flip", + "pallet-relay-migration", "pallet-scheduler", "pallet-session", "pallet-timestamp", diff --git a/pallets/relay-migration/Cargo.toml b/pallets/relay-migration/Cargo.toml new file mode 100644 index 0000000000..d85c075aca --- /dev/null +++ b/pallets/relay-migration/Cargo.toml @@ -0,0 +1,61 @@ +[package] +authors = ["KILT "] +description = "Initiate migration to another relay chain" +edition = "2021" +name = "pallet-relay-migration" +repository = "https://github.com/KILTprotocol/kilt-node" +version = "1.7.1" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = {package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"]} +cumulus-pallet-parachain-system = {git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.27"} +cumulus-primitives-core = {git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.27"} +log = "0.4.17" +pallet-xcm = {git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.27"} +polkadot-core-primitives = {git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.27"} +polkadot-runtime-common = {git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.27"} +scale-info = {version = "2.1.1", default-features = false, features = ["derive"]} +xcm = {git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.27"} + +# KILT +kilt-support = {default-features = false, path = "../../support"} + +# Substrate dependencies +frame-support = {branch = "polkadot-v0.9.27", default-features = false, git = "https://github.com/paritytech/substrate"} +frame-system = {branch = "polkadot-v0.9.27", default-features = false, git = "https://github.com/paritytech/substrate"} +sp-core = {branch = "polkadot-v0.9.27", default-features = false, git = "https://github.com/paritytech/substrate"} +sp-io = {branch = "polkadot-v0.9.27", default-features = false, git = "https://github.com/paritytech/substrate"} +sp-runtime = {branch = "polkadot-v0.9.27", default-features = false, git = "https://github.com/paritytech/substrate"} +sp-std = {branch = "polkadot-v0.9.27", default-features = false, git = "https://github.com/paritytech/substrate"} + +# benchmarking +frame-benchmarking = {branch = "polkadot-v0.9.27", optional = true, default-features = false, git = "https://github.com/paritytech/substrate"} + +[features] +default = ["std"] +std = [ + "codec/std", + "cumulus-pallet-parachain-system/std", + "cumulus-primitives-core/std", + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "kilt-support/std", + "log/std", + "pallet-xcm/std", + "polkadot-core-primitives/std", + "polkadot-runtime-common/std", + "scale-info/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", + "xcm/std", +] +try-runtime = [ + "frame-support/try-runtime", + "kilt-support/try-runtime", +] diff --git a/pallets/relay-migration/src/lib.rs b/pallets/relay-migration/src/lib.rs new file mode 100644 index 0000000000..8c458c2718 --- /dev/null +++ b/pallets/relay-migration/src/lib.rs @@ -0,0 +1,144 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2022 BOTLabs GmbH + +// The KILT Blockchain is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The KILT Blockchain is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// If you feel like getting in touch with us, you can do so at info@botlabs.org + +//! # Relay migration initialization pallet +//! +//! This pallet provides means of sending an XCM messages to the relay chain by +//! a configurable origin and switching the associated relay number block checks +//! between strictly and any. +//! +//! - [`Pallet`] + +#![cfg_attr(not(feature = "std"), no_std)] + +pub use pallet::*; + +#[frame_support::pallet] +pub mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + use kilt_support::traits::RelayCallBuilder; + use sp_std::vec::Vec; + use xcm::v2::{Junctions::Here, Parent}; + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config + pallet_xcm::Config { + type Event: From> + IsType<::Event>; + + /// Origin from which calls of this pallet can be made. + type ApproveOrigin: EnsureOrigin<::Origin>; + + /// The Call builder for communicating with RelayChain via XCM + /// messaging. + type RelayChainCallBuilder: RelayCallBuilder< + AccountId = Self::AccountId, + Balance = polkadot_core_primitives::Balance, + >; + } + + /// Switch between RelayNumberStrictlyIncreases and AnyRelayNumber. + #[pallet::storage] + #[pallet::getter(fn relay_block_number_strictly_increases)] + pub(crate) type RelayNumberStrictlyIncreases = StorageValue<_, bool, ValueQuery>; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// The parachain lease swap was initiated. + LeaseSwapInitiated, + /// The requirement for associated relay block numbers was set + RelayNumberCheckSet { + /// Reflects setting to RelayNumberStrictlyIncreases + strict: bool, + }, + } + + #[pallet::error] + pub enum Error {} + + #[pallet::call] + impl Pallet { + /// Set an XCM call to the relay chain. + /// + /// Has to be done pre migration. + #[pallet::weight(1_000_000 + T::DbWeight::get().reads_writes(10, 10))] + pub fn send_swap_call_bytes( + origin: OriginFor, + relay_call: Vec, + relay_balance: u128, + max_weight: u64, + ) -> DispatchResult { + T::ApproveOrigin::ensure_origin(origin)?; + let xcm_message = + T::RelayChainCallBuilder::finalize_call_into_xcm_message(relay_call, relay_balance, max_weight); + + let result = pallet_xcm::Pallet::::send_xcm(Here, Parent, xcm_message); + log::debug!("Sending XCM with result: {:?}", result); + + Self::deposit_event(Event::LeaseSwapInitiated); + + Ok(()) + } + + /// Set the associated relay block number to be + /// RelayNumberStrictlyIncreases. + /// + /// Has to be done post migration. + #[pallet::weight(100_000 + T::DbWeight::get().reads_writes(1, 1))] + pub fn enable_strict_relay_number_check(origin: OriginFor) -> DispatchResult { + T::ApproveOrigin::ensure_origin(origin)?; + RelayNumberStrictlyIncreases::::put(true); + + Self::deposit_event(Event::RelayNumberCheckSet { strict: true }); + + Ok(()) + } + + /// Set the associated relay block number to be AnyRelayNumber. + /// + /// Has to be done pre migration. + #[pallet::weight(100_000 + T::DbWeight::get().reads_writes(1, 1))] + pub fn disable_strict_relay_number_check(origin: OriginFor) -> DispatchResult { + T::ApproveOrigin::ensure_origin(origin)?; + RelayNumberStrictlyIncreases::::put(false); + + Self::deposit_event(Event::RelayNumberCheckSet { strict: false }); + + Ok(()) + } + } + + impl cumulus_pallet_parachain_system::CheckAssociatedRelayNumber for Pallet { + fn check_associated_relay_number( + current: polkadot_core_primitives::BlockNumber, + previous: polkadot_core_primitives::BlockNumber, + ) { + if RelayNumberStrictlyIncreases::::get() { + cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases::check_associated_relay_number( + current, previous, + ) + } else { + cumulus_pallet_parachain_system::AnyRelayNumber::check_associated_relay_number(current, previous) + } + } + } +} diff --git a/runtimes/peregrine/Cargo.toml b/runtimes/peregrine/Cargo.toml index 1ae901e4a9..a88079e65d 100644 --- a/runtimes/peregrine/Cargo.toml +++ b/runtimes/peregrine/Cargo.toml @@ -27,9 +27,10 @@ attestation = {path = "../../pallets/attestation", default-features = false} ctype = {path = "../../pallets/ctype", default-features = false} delegation = {path = "../../pallets/delegation", default-features = false} did = {path = "../../pallets/did", default-features = false} -kilt-support = {path = "../../support", default-features = false, optional = true} +kilt-support = {path = "../../support", default-features = false} pallet-did-lookup = {path = "../../pallets/pallet-did-lookup", default-features = false} pallet-inflation = {path = "../../pallets/pallet-inflation", default-features = false} +pallet-relay-migration = {path = "../../pallets/relay-migration", default-features = false} pallet-web3-names = {path = "../../pallets/pallet-web3-names", default-features = false} parachain-staking = {path = "../../pallets/parachain-staking", default-features = false} runtime-common = {path = "../../runtimes/common", default-features = false} @@ -113,7 +114,6 @@ runtime-benchmarks = [ "frame-system-benchmarking", "frame-system/runtime-benchmarks", "hex-literal", - "kilt-support", "kilt-support/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-collective/runtime-benchmarks", @@ -166,6 +166,7 @@ std = [ "pallet-indices/std", "pallet-inflation/std", "pallet-membership/std", + "pallet-relay-migration/std", "pallet-preimage/std", "pallet-proxy/std", "pallet-randomness-collective-flip/std", diff --git a/runtimes/peregrine/src/lib.rs b/runtimes/peregrine/src/lib.rs index 4038289362..61acd0a3d6 100644 --- a/runtimes/peregrine/src/lib.rs +++ b/runtimes/peregrine/src/lib.rs @@ -48,6 +48,7 @@ use delegation::DelegationAc; use pallet_did_lookup::{linkable_account::LinkableAccountId, migrations::EthereumMigration}; pub use parachain_staking::InflationInfo; +use kilt_support::relay::RelayChainCallBuilder; use runtime_common::{ authorization::{AuthorizationId, PalletAuthorize}, constants::{self, EXISTENTIAL_DEPOSIT, KILT}, @@ -218,7 +219,9 @@ impl cumulus_pallet_parachain_system::Config for Runtime { type ReservedDmpWeight = ReservedDmpWeight; type XcmpMessageHandler = XcmpQueue; type ReservedXcmpWeight = ReservedXcmpWeight; - type CheckAssociatedRelayNumber = cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; + // We temporarily control this via the RelayMigration pallet which can toggle + // between strict and any. + type CheckAssociatedRelayNumber = RelayMigration; } impl parachain_info::Config for Runtime {} @@ -662,6 +665,12 @@ impl parachain_staking::Config for Runtime { const BLOCKS_PER_YEAR: Self::BlockNumber = constants::BLOCKS_PER_YEAR; } +impl pallet_relay_migration::Config for Runtime { + type Event = Event; + type ApproveOrigin = ApproveOrigin; + type RelayChainCallBuilder = RelayChainCallBuilder; +} + impl pallet_utility::Config for Runtime { type Event = Event; type Call = Call; @@ -881,6 +890,7 @@ construct_runtime! { // placeholder: parachain council election = 33, TechnicalMembership: pallet_membership:: = 34, Treasury: pallet_treasury = 35, + RelayMigration: pallet_relay_migration::{Pallet, Call, Storage, Event} = 36, // Utility module. Utility: pallet_utility = 40, diff --git a/runtimes/spiritnet/Cargo.toml b/runtimes/spiritnet/Cargo.toml index 2cc39c760f..e60d7049c2 100644 --- a/runtimes/spiritnet/Cargo.toml +++ b/runtimes/spiritnet/Cargo.toml @@ -27,9 +27,10 @@ attestation = {path = "../../pallets/attestation", default-features = false} ctype = {path = "../../pallets/ctype", default-features = false} delegation = {path = "../../pallets/delegation", default-features = false} did = {path = "../../pallets/did", default-features = false} -kilt-support = {path = "../../support", default-features = false, optional = true} +kilt-support = {path = "../../support", default-features = false} pallet-did-lookup = {path = "../../pallets/pallet-did-lookup", default-features = false} pallet-inflation = {path = "../../pallets/pallet-inflation", default-features = false} +pallet-relay-migration = {path = "../../pallets/relay-migration", default-features = false} pallet-web3-names = {path = "../../pallets/pallet-web3-names", default-features = false} parachain-staking = {path = "../../pallets/parachain-staking", default-features = false} runtime-common = {path = "../../runtimes/common", default-features = false} @@ -112,7 +113,6 @@ runtime-benchmarks = [ "frame-system-benchmarking", "frame-system/runtime-benchmarks", "hex-literal", - "kilt-support", "kilt-support/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-collective/runtime-benchmarks", @@ -155,6 +155,7 @@ std = [ "frame-system-rpc-runtime-api/std", "frame-system/std", "frame-try-runtime/std", + "kilt-support/std", "log/std", "pallet-aura/std", "pallet-authorship/std", @@ -165,6 +166,7 @@ std = [ "pallet-indices/std", "pallet-inflation/std", "pallet-membership/std", + "pallet-relay-migration/std", "pallet-preimage/std", "pallet-proxy/std", "pallet-randomness-collective-flip/std", diff --git a/runtimes/spiritnet/src/lib.rs b/runtimes/spiritnet/src/lib.rs index 79c85fd895..5207d15553 100644 --- a/runtimes/spiritnet/src/lib.rs +++ b/runtimes/spiritnet/src/lib.rs @@ -48,6 +48,7 @@ use delegation::DelegationAc; use pallet_did_lookup::{linkable_account::LinkableAccountId, migrations::EthereumMigration}; pub use parachain_staking::InflationInfo; +use kilt_support::relay::RelayChainCallBuilder; use runtime_common::{ authorization::{AuthorizationId, PalletAuthorize}, constants::{self, EXISTENTIAL_DEPOSIT, KILT}, @@ -213,7 +214,9 @@ impl cumulus_pallet_parachain_system::Config for Runtime { type ReservedDmpWeight = ReservedDmpWeight; type XcmpMessageHandler = XcmpQueue; type ReservedXcmpWeight = ReservedXcmpWeight; - type CheckAssociatedRelayNumber = cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; + // We temporarily control this via the RelayMigration pallet which can toggle + // between strict and any. + type CheckAssociatedRelayNumber = RelayMigration; } impl parachain_info::Config for Runtime {} @@ -657,6 +660,12 @@ impl parachain_staking::Config for Runtime { const BLOCKS_PER_YEAR: Self::BlockNumber = constants::BLOCKS_PER_YEAR; } +impl pallet_relay_migration::Config for Runtime { + type Event = Event; + type ApproveOrigin = ApproveOrigin; + type RelayChainCallBuilder = RelayChainCallBuilder; +} + impl pallet_utility::Config for Runtime { type Event = Event; type Call = Call; @@ -874,6 +883,7 @@ construct_runtime! { // placeholder: parachain council election = 33, TechnicalMembership: pallet_membership:: = 34, Treasury: pallet_treasury = 35, + RelayMigration: pallet_relay_migration::{Pallet, Call, Storage, Event} = 36, // Utility module. Utility: pallet_utility = 40, @@ -907,16 +917,16 @@ construct_runtime! { // Parachains pallets. Start indices at 80 to leave room. - // Many other things but also: Send and receive DMP and XCMP messages + // Among others: Send and receive DMP and XCMP messages. ParachainSystem: cumulus_pallet_parachain_system = 80, ParachainInfo: parachain_info::{Pallet, Storage, Config} = 81, // Wrap and unwrap XCMP messages to send and receive them. Queue them for later processing. XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event} = 82, - // Build XCM scripts + // Build XCM scripts. PolkadotXcm: pallet_xcm::{Pallet, Call, Event, Origin, Config} = 83, - // Does nothing cool. Provides an origin... + // Does nothing cool, just provides an origin. CumulusXcm: cumulus_pallet_xcm::{Pallet, Event, Origin} = 84, - // Queue and DMP messages and pass them on to be executed + // Queue and pass DMP messages on to be executed. DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event} = 85, } } @@ -1002,7 +1012,7 @@ pub type Executive = frame_executive::Executive< // Executes pallet hooks in reverse order of definition in construct_runtime // If we want to switch to AllPalletsWithSystem, we need to reorder the staking pallets AllPalletsReversedWithSystemFirst, - (EthereumMigration,), + EthereumMigration, >; impl_runtime_apis! { @@ -1133,7 +1143,7 @@ impl_runtime_apis! { did::Did::::get(&owner_info.owner).map(|details| (owner_info, details)) }) .map(|(owner_info, details)| { - let accounts: Vec = pallet_did_lookup::ConnectedAccounts::::iter_key_prefix(&owner_info.owner).collect(); + let accounts = pallet_did_lookup::ConnectedAccounts::::iter_key_prefix(&owner_info.owner).collect(); let service_endpoints = did::ServiceEndpoints::::iter_prefix(&owner_info.owner).map(|e| From::from(e.1)).collect(); did_rpc_runtime_api::RawDidLinkedInfo { diff --git a/support/Cargo.toml b/support/Cargo.toml index a5f21fd402..487c61d6f9 100644 --- a/support/Cargo.toml +++ b/support/Cargo.toml @@ -11,11 +11,14 @@ codec = {package = "parity-scale-codec", version = "3.1.5", default-features = f scale-info = {version = "2.1.1", default-features = false, features = ["derive"]} serde = {version = "1.0.136", optional = true, features = ["derive"]} +cumulus-primitives-core = {branch = "polkadot-v0.9.27", default-features = false, git = "https://github.com/paritytech/cumulus"} frame-support = {branch = "polkadot-v0.9.27", default-features = false, git = "https://github.com/paritytech/substrate"} frame-system = {branch = "polkadot-v0.9.27", default-features = false, git = "https://github.com/paritytech/substrate"} +polkadot-core-primitives = {branch = "release-v0.9.27", default-features = false, git = "https://github.com/paritytech/polkadot"} sp-core = {branch = "polkadot-v0.9.27", default-features = false, git = "https://github.com/paritytech/substrate"} sp-runtime = {branch = "polkadot-v0.9.27", default-features = false, git = "https://github.com/paritytech/substrate"} sp-std = {branch = "polkadot-v0.9.27", default-features = false, git = "https://github.com/paritytech/substrate"} +xcm = {branch = "release-v0.9.27", default-features = false, git = "https://github.com/paritytech/polkadot"} [dev-dependencies] serde_json = "1.0.83" @@ -34,12 +37,15 @@ runtime-benchmarks = [ std = [ "serde", "codec/std", + "cumulus-primitives-core/std", "frame-support/std", "frame-system/std", + "polkadot-core-primitives/std", "scale-info/std", "sp-core/std", "sp-runtime/std", "sp-std/std", + "xcm/std", ] try-runtime = [ "frame-support/try-runtime", diff --git a/support/src/lib.rs b/support/src/lib.rs index 7a58831778..1cb723b63c 100644 --- a/support/src/lib.rs +++ b/support/src/lib.rs @@ -24,6 +24,7 @@ use sp_runtime::traits::Zero; pub mod deposit; #[cfg(any(feature = "runtime-benchmarks", feature = "mock"))] pub mod mock; +pub mod relay; pub mod signature; pub mod traits; diff --git a/support/src/relay.rs b/support/src/relay.rs new file mode 100644 index 0000000000..7bd0187ba0 --- /dev/null +++ b/support/src/relay.rs @@ -0,0 +1,113 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2022 BOTLabs GmbH + +// The KILT Blockchain is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The KILT Blockchain is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// If you feel like getting in touch with us, you can do so at info@botlabs.org + +//! # RelayChain Support Module +//! +//! Provides means of of handling relaychain related utilities and +//! business logic such as finalizing XCM calls. + +#![cfg_attr(not(feature = "std"), no_std)] +#![allow(clippy::unused_unit)] + +use codec::{Decode, Encode, FullCodec}; +use frame_support::{traits::Get, weights::Weight}; +use frame_system::Config; +use scale_info::TypeInfo; +use sp_std::{boxed::Box, marker::PhantomData, prelude::*}; +use xcm::latest::prelude::*; + +pub use cumulus_primitives_core::ParaId; + +use crate::traits::RelayCallBuilder; + +#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo)] +pub enum UtilityCall { + #[codec(index = 1)] + AsDerivative(u16, RelayChainCall), + #[codec(index = 2)] + BatchAll(Vec), +} + +#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo)] +pub enum RegistrarCall { + #[codec(index = 4)] + Swap(ParaId, ParaId), +} + +/// The encoded index correspondes to Kusama's Runtime module configuration. +/// https://github.com/paritytech/polkadot/blob/444e96ae34bcec8362f0f947a07bd912b32ca48f/runtime/kusama/src/lib.rs#L1379 +#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo)] +pub enum RelayChainCall { + #[codec(index = 24)] + Utility(Box>), + #[codec(index = 70)] + Registrar(RegistrarCall), +} + +#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo)] +pub struct RelayChainCallBuilder>(PhantomData<(T, ParachainId)>); + +impl> RelayCallBuilder for RelayChainCallBuilder +where + T::AccountId: FullCodec, + RelayChainCall: FullCodec, +{ + type AccountId = T::AccountId; + type Balance = polkadot_core_primitives::Balance; + type RelayChainCall = RelayChainCall; + + fn utility_batch_call(calls: Vec) -> Self::RelayChainCall { + RelayChainCall::Utility(Box::new(UtilityCall::BatchAll(calls))) + } + + fn utility_as_derivative_call(call: Self::RelayChainCall, index: u16) -> Self::RelayChainCall { + RelayChainCall::Utility(Box::new(UtilityCall::AsDerivative(index, call))) + } + + fn swap_call(id: ParaId, other: ParaId) -> Self::RelayChainCall { + RelayChainCall::Registrar(RegistrarCall::Swap(id, other)) + } + + fn finalize_call_into_xcm_message(call: Vec, extra_fee: Self::Balance, weight: Weight) -> Xcm<()> { + let asset = MultiAsset { + id: Concrete(MultiLocation::here()), + fun: Fungibility::Fungible(extra_fee), + }; + Xcm(vec![ + WithdrawAsset(asset.clone().into()), + BuyExecution { + fees: asset, + weight_limit: Unlimited, + }, + Transact { + origin_type: OriginKind::Native, + require_weight_at_most: weight, + call: call.into(), + }, + RefundSurplus, + DepositAsset { + assets: All.into(), + max_assets: 1, + beneficiary: MultiLocation { + parents: 0, + interior: X1(Parachain(ParachainId::get().into())), + }, + }, + ]) + } +} diff --git a/support/src/traits.rs b/support/src/traits.rs index 07448b8a99..99ae91ce31 100644 --- a/support/src/traits.rs +++ b/support/src/traits.rs @@ -16,6 +16,13 @@ // If you feel like getting in touch with us, you can do so at info@botlabs.org +use codec::{EncodeLike, FullCodec}; +use cumulus_primitives_core::ParaId; +use frame_support::weights::Weight; +use scale_info::TypeInfo; +use sp_std::vec::Vec; +use xcm::latest::Xcm; + /// The sources of a call struct. /// /// This trait allows to differentiate between the sender of a call and the @@ -68,3 +75,40 @@ pub trait VersionMigratorTrait: Sized { pub trait GenerateBenchmarkOrigin { fn generate_origin(sender: AccountId, subject: SubjectId) -> OuterOrigin; } + +/// Trait to reflect calls to the relaychain which we support on the pallet +/// level. +pub trait RelayCallBuilder { + type AccountId: FullCodec; + type Balance: FullCodec; + type RelayChainCall: FullCodec + EncodeLike + sp_std::fmt::Debug + Clone + PartialEq + Eq + TypeInfo; + + /// Execute multiple calls in a batch. + /// + /// * calls: The list of calls to be executed. + fn utility_batch_call(calls: Vec) -> Self::RelayChainCall; + + /// Execute a call, replacing the `Origin` with a sub-account. + /// + /// * call: The call to be executed. Can be nested with + /// `utility_batch_call`. + /// * index: The index of the sub-account to be used as the new origin. + fn utility_as_derivative_call(call: Self::RelayChainCall, index: u16) -> Self::RelayChainCall; + + /// Execute a parachain lease swap call. + /// + /// * id: One of the two para ids. Typically, this should be the one of the + /// parachain that executes this XCM call, e.g. the source. + /// * other: The target para id with which the lease swap should be + /// executed. + fn swap_call(id: ParaId, other: ParaId) -> Self::RelayChainCall; + + /// Wrap the final calls into the latest Xcm format. + /// + /// * call: The relaychain call to be executed + /// * extra_fee: The extra fee (in relaychain currency) used for buying the + /// `weight` and `debt`. + /// * weight: The weight limit used for XCM. + /// * debt: The weight limit used to process the call. + fn finalize_call_into_xcm_message(call: Vec, extra_fee: Self::Balance, weight: Weight) -> Xcm<()>; +}