feat: Rebrand Polkadot/Substrate references to PezkuwiChain
This commit systematically rebrands various references from Parity Technologies' Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk. Key changes include: - Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks. - Modified internal documentation and code comments to reflect PezkuwiChain naming and structure. - Replaced direct references to with or specific paths within the for XCM, Pezkuwi, and other modules. - Cleaned up deprecated issue and PR references in various and files, particularly in and modules. - Adjusted image and logo URLs in documentation to point to PezkuwiChain assets. - Removed or rephrased comments related to external Polkadot/Substrate PRs and issues. This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
[package]
|
||||
name = "teyrchains-common"
|
||||
version = "7.0.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
description = "Logic which is common to all teyrchain runtimes"
|
||||
license = "Apache-2.0"
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
codec = { features = ["derive"], workspace = true }
|
||||
scale-info = { features = ["derive"], workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
# Bizinikiwi
|
||||
pezframe-support = { workspace = true }
|
||||
pezframe-system = { workspace = true }
|
||||
pezpallet-asset-tx-payment = { workspace = true }
|
||||
pezpallet-assets = { workspace = true }
|
||||
pezpallet-authorship = { workspace = true }
|
||||
pezpallet-balances = { workspace = true }
|
||||
pezpallet-message-queue = { workspace = true }
|
||||
pezpallet-treasury = { workspace = true }
|
||||
pezsp-consensus-aura = { workspace = true }
|
||||
pezsp-core = { workspace = true }
|
||||
pezsp-io = { workspace = true }
|
||||
pezsp-runtime = { workspace = true }
|
||||
|
||||
# Pezkuwi
|
||||
pezpallet-xcm = { workspace = true }
|
||||
pezkuwi-primitives = { workspace = true }
|
||||
pezkuwi-runtime-common = { workspace = true }
|
||||
xcm = { workspace = true }
|
||||
xcm-executor = { workspace = true }
|
||||
|
||||
# Pezcumulus
|
||||
pezcumulus-primitives-core = { workspace = true }
|
||||
pezcumulus-primitives-utility = { workspace = true }
|
||||
pezpallet-collator-selection = { workspace = true }
|
||||
teyrchain-info = { workspace = true }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"codec/std",
|
||||
"pezcumulus-primitives-core/std",
|
||||
"pezcumulus-primitives-utility/std",
|
||||
"pezframe-support/std",
|
||||
"pezframe-system/std",
|
||||
"pezpallet-asset-tx-payment/std",
|
||||
"pezpallet-assets/std",
|
||||
"pezpallet-authorship/std",
|
||||
"pezpallet-balances/std",
|
||||
"pezpallet-collator-selection/std",
|
||||
"pezpallet-message-queue/std",
|
||||
"pezpallet-treasury/std",
|
||||
"pezpallet-xcm/std",
|
||||
"pezkuwi-primitives/std",
|
||||
"pezkuwi-runtime-common/std",
|
||||
"scale-info/std",
|
||||
"pezsp-consensus-aura/std",
|
||||
"pezsp-core/std",
|
||||
"pezsp-io/std",
|
||||
"pezsp-runtime/std",
|
||||
"teyrchain-info/std",
|
||||
"tracing/std",
|
||||
"xcm-executor/std",
|
||||
"xcm/std",
|
||||
]
|
||||
runtime-benchmarks = [
|
||||
"pezcumulus-primitives-core/runtime-benchmarks",
|
||||
"pezcumulus-primitives-utility/runtime-benchmarks",
|
||||
"pezframe-support/runtime-benchmarks",
|
||||
"pezframe-system/runtime-benchmarks",
|
||||
"pezpallet-asset-tx-payment/runtime-benchmarks",
|
||||
"pezpallet-assets/runtime-benchmarks",
|
||||
"pezpallet-authorship/runtime-benchmarks",
|
||||
"pezpallet-balances/runtime-benchmarks",
|
||||
"pezpallet-collator-selection/runtime-benchmarks",
|
||||
"pezpallet-message-queue/runtime-benchmarks",
|
||||
"pezpallet-treasury/runtime-benchmarks",
|
||||
"pezpallet-xcm/runtime-benchmarks",
|
||||
"pezkuwi-primitives/runtime-benchmarks",
|
||||
"pezkuwi-runtime-common/runtime-benchmarks",
|
||||
"pezsp-consensus-aura/runtime-benchmarks",
|
||||
"pezsp-io/runtime-benchmarks",
|
||||
"pezsp-runtime/runtime-benchmarks",
|
||||
"teyrchain-info/runtime-benchmarks",
|
||||
"xcm-executor/runtime-benchmarks",
|
||||
"xcm/runtime-benchmarks",
|
||||
]
|
||||
|
||||
try-runtime = [
|
||||
"pezframe-support/try-runtime",
|
||||
"pezframe-system/try-runtime",
|
||||
"pezpallet-asset-tx-payment/try-runtime",
|
||||
"pezpallet-assets/try-runtime",
|
||||
"pezpallet-authorship/try-runtime",
|
||||
"pezpallet-balances/try-runtime",
|
||||
"pezpallet-collator-selection/try-runtime",
|
||||
"pezpallet-message-queue/try-runtime",
|
||||
"pezpallet-treasury/try-runtime",
|
||||
"pezpallet-xcm/try-runtime",
|
||||
"pezkuwi-runtime-common/try-runtime",
|
||||
"pezsp-runtime/try-runtime",
|
||||
"teyrchain-info/try-runtime",
|
||||
]
|
||||
@@ -0,0 +1,347 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Auxiliary struct/enums for teyrchain runtimes.
|
||||
//! Taken from pezkuwi/runtime/common (at a21cd64) and adapted for teyrchains.
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use core::marker::PhantomData;
|
||||
use pezframe_support::traits::{
|
||||
fungible, fungibles, tokens::imbalance::ResolveTo, Contains, ContainsPair, Currency, Defensive,
|
||||
Get, Imbalance, OnUnbalanced, OriginTrait,
|
||||
};
|
||||
use pezpallet_asset_tx_payment::HandleCredit;
|
||||
use pezpallet_collator_selection::StakingPotAccountId;
|
||||
use pezsp_runtime::traits::Zero;
|
||||
use xcm::latest::{
|
||||
Asset, AssetId, Fungibility, Fungibility::Fungible, Junction, Junctions::Here, Location,
|
||||
Parent, WeightLimit,
|
||||
};
|
||||
use xcm_executor::traits::ConvertLocation;
|
||||
|
||||
/// Type alias to conveniently refer to `pezframe_system`'s `Config::AccountId`.
|
||||
pub type AccountIdOf<T> = <T as pezframe_system::Config>::AccountId;
|
||||
|
||||
/// Type alias to conveniently refer to the `Currency::NegativeImbalance` associated type.
|
||||
pub type NegativeImbalance<T> = <pezpallet_balances::Pallet<T> as Currency<
|
||||
<T as pezframe_system::Config>::AccountId,
|
||||
>>::NegativeImbalance;
|
||||
|
||||
/// Implementation of `OnUnbalanced` that deposits the fees into a staking pot for later payout.
|
||||
#[deprecated(
|
||||
note = "ToStakingPot is deprecated and will be removed after March 2024. Please use pezframe_support::traits::tokens::imbalance::ResolveTo instead."
|
||||
)]
|
||||
pub struct ToStakingPot<R>(PhantomData<R>);
|
||||
#[allow(deprecated)]
|
||||
impl<R> OnUnbalanced<NegativeImbalance<R>> for ToStakingPot<R>
|
||||
where
|
||||
R: pezpallet_balances::Config + pezpallet_collator_selection::Config,
|
||||
AccountIdOf<R>: From<pezkuwi_primitives::AccountId> + Into<pezkuwi_primitives::AccountId>,
|
||||
<R as pezframe_system::Config>::RuntimeEvent: From<pezpallet_balances::Event<R>>,
|
||||
{
|
||||
fn on_nonzero_unbalanced(amount: NegativeImbalance<R>) {
|
||||
let staking_pot = <pezpallet_collator_selection::Pallet<R>>::account_id();
|
||||
// In case of error: Will drop the result triggering the `OnDrop` of the imbalance.
|
||||
<pezpallet_balances::Pallet<R>>::resolve_creating(&staking_pot, amount);
|
||||
}
|
||||
}
|
||||
|
||||
/// Fungible implementation of `OnUnbalanced` that deals with the fees by combining tip and fee and
|
||||
/// passing the result on to `ToStakingPot`.
|
||||
pub struct DealWithFees<R>(PhantomData<R>);
|
||||
impl<R> OnUnbalanced<fungible::Credit<R::AccountId, pezpallet_balances::Pallet<R>>> for DealWithFees<R>
|
||||
where
|
||||
R: pezpallet_balances::Config + pezpallet_collator_selection::Config,
|
||||
AccountIdOf<R>: From<pezkuwi_primitives::AccountId> + Into<pezkuwi_primitives::AccountId>,
|
||||
<R as pezframe_system::Config>::RuntimeEvent: From<pezpallet_balances::Event<R>>,
|
||||
{
|
||||
fn on_unbalanceds(
|
||||
mut fees_then_tips: impl Iterator<
|
||||
Item = fungible::Credit<R::AccountId, pezpallet_balances::Pallet<R>>,
|
||||
>,
|
||||
) {
|
||||
if let Some(mut fees) = fees_then_tips.next() {
|
||||
if let Some(tips) = fees_then_tips.next() {
|
||||
tips.merge_into(&mut fees);
|
||||
}
|
||||
ResolveTo::<StakingPotAccountId<R>, pezpallet_balances::Pallet<R>>::on_unbalanced(fees)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A `HandleCredit` implementation that naively transfers the fees to the block author.
|
||||
/// Will drop and burn the assets in case the transfer fails.
|
||||
pub struct AssetsToBlockAuthor<R, I>(PhantomData<(R, I)>);
|
||||
impl<R, I> HandleCredit<AccountIdOf<R>, pezpallet_assets::Pallet<R, I>> for AssetsToBlockAuthor<R, I>
|
||||
where
|
||||
I: 'static,
|
||||
R: pezpallet_authorship::Config + pezpallet_assets::Config<I>,
|
||||
AccountIdOf<R>: From<pezkuwi_primitives::AccountId> + Into<pezkuwi_primitives::AccountId>,
|
||||
{
|
||||
fn handle_credit(credit: fungibles::Credit<AccountIdOf<R>, pezpallet_assets::Pallet<R, I>>) {
|
||||
use pezframe_support::traits::fungibles::Balanced;
|
||||
if let Some(author) = pezpallet_authorship::Pallet::<R>::author() {
|
||||
// In case of error: Will drop the result triggering the `OnDrop` of the imbalance.
|
||||
let _ = pezpallet_assets::Pallet::<R, I>::resolve(&author, credit).defensive();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Allow checking in assets that have issuance > 0.
|
||||
pub struct NonZeroIssuance<AccountId, Assets>(PhantomData<(AccountId, Assets)>);
|
||||
impl<AccountId, Assets> Contains<<Assets as fungibles::Inspect<AccountId>>::AssetId>
|
||||
for NonZeroIssuance<AccountId, Assets>
|
||||
where
|
||||
Assets: fungibles::Inspect<AccountId>,
|
||||
{
|
||||
fn contains(id: &<Assets as fungibles::Inspect<AccountId>>::AssetId) -> bool {
|
||||
!Assets::total_issuance(id.clone()).is_zero()
|
||||
}
|
||||
}
|
||||
|
||||
/// Allow checking in assets that exists.
|
||||
pub struct AssetExists<AccountId, Assets>(PhantomData<(AccountId, Assets)>);
|
||||
impl<AccountId, Assets> Contains<<Assets as fungibles::Inspect<AccountId>>::AssetId>
|
||||
for AssetExists<AccountId, Assets>
|
||||
where
|
||||
Assets: fungibles::Inspect<AccountId>,
|
||||
{
|
||||
fn contains(id: &<Assets as fungibles::Inspect<AccountId>>::AssetId) -> bool {
|
||||
Assets::asset_exists(id.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// Asset filter that allows all assets from a certain location.
|
||||
pub struct AssetsFrom<T>(PhantomData<T>);
|
||||
impl<T: Get<Location>> ContainsPair<Asset, Location> for AssetsFrom<T> {
|
||||
fn contains(asset: &Asset, origin: &Location) -> bool {
|
||||
let loc = T::get();
|
||||
&loc == origin &&
|
||||
matches!(asset, Asset { id: AssetId(asset_loc), fun: Fungible(_a) }
|
||||
if asset_loc.match_and_split(&loc).is_some())
|
||||
}
|
||||
}
|
||||
|
||||
/// Type alias to conveniently refer to the `Currency::Balance` associated type.
|
||||
pub type BalanceOf<T> =
|
||||
<pezpallet_balances::Pallet<T> as Currency<<T as pezframe_system::Config>::AccountId>>::Balance;
|
||||
|
||||
/// Implements `OnUnbalanced::on_unbalanced` to teleport slashed assets to relay chain treasury
|
||||
/// account.
|
||||
pub struct ToParentTreasury<TreasuryAccount, AccountIdConverter, T>(
|
||||
PhantomData<(TreasuryAccount, AccountIdConverter, T)>,
|
||||
);
|
||||
|
||||
impl<TreasuryAccount, AccountIdConverter, T> OnUnbalanced<NegativeImbalance<T>>
|
||||
for ToParentTreasury<TreasuryAccount, AccountIdConverter, T>
|
||||
where
|
||||
T: pezpallet_balances::Config + pezpallet_xcm::Config + pezframe_system::Config,
|
||||
<<T as pezframe_system::Config>::RuntimeOrigin as OriginTrait>::AccountId: From<AccountIdOf<T>>,
|
||||
[u8; 32]: From<<T as pezframe_system::Config>::AccountId>,
|
||||
TreasuryAccount: Get<AccountIdOf<T>>,
|
||||
AccountIdConverter: ConvertLocation<AccountIdOf<T>>,
|
||||
BalanceOf<T>: Into<Fungibility>,
|
||||
{
|
||||
fn on_unbalanced(amount: NegativeImbalance<T>) {
|
||||
let amount = match amount.drop_zero() {
|
||||
Ok(..) => return,
|
||||
Err(amount) => amount,
|
||||
};
|
||||
let imbalance = amount.peek();
|
||||
let root_location: Location = Here.into();
|
||||
let root_account: AccountIdOf<T> =
|
||||
match AccountIdConverter::convert_location(&root_location) {
|
||||
Some(a) => a,
|
||||
None => {
|
||||
tracing::warn!(target: "xcm::on_unbalanced", "Failed to convert root origin into account id");
|
||||
return;
|
||||
},
|
||||
};
|
||||
let treasury_account: AccountIdOf<T> = TreasuryAccount::get();
|
||||
|
||||
<pezpallet_balances::Pallet<T>>::resolve_creating(&root_account, amount);
|
||||
|
||||
let result = <pezpallet_xcm::Pallet<T>>::limited_teleport_assets(
|
||||
<<T as pezframe_system::Config>::RuntimeOrigin>::root(),
|
||||
Box::new(Parent.into()),
|
||||
Box::new(
|
||||
Junction::AccountId32 { network: None, id: treasury_account.into() }
|
||||
.into_location()
|
||||
.into(),
|
||||
),
|
||||
Box::new((Parent, imbalance).into()),
|
||||
Box::new(Parent.into()),
|
||||
WeightLimit::Unlimited,
|
||||
);
|
||||
|
||||
if let Err(err) = result {
|
||||
tracing::warn!(target: "xcm::on_unbalanced", error=?err, "Failed to teleport slashed assets");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use pezframe_support::{
|
||||
derive_impl, parameter_types,
|
||||
traits::{ConstU32, FindAuthor, ValidatorRegistration},
|
||||
PalletId,
|
||||
};
|
||||
use pezframe_system::{limits, EnsureRoot};
|
||||
use pezpallet_collator_selection::IdentityCollator;
|
||||
use pezkuwi_primitives::AccountId;
|
||||
use pezsp_core::H256;
|
||||
use pezsp_runtime::{
|
||||
traits::{BlakeTwo256, IdentityLookup},
|
||||
BuildStorage, Perbill,
|
||||
};
|
||||
use xcm::prelude::*;
|
||||
|
||||
type Block = pezframe_system::mocking::MockBlock<Test>;
|
||||
const TEST_ACCOUNT: AccountId = AccountId::new([1; 32]);
|
||||
|
||||
pezframe_support::construct_runtime!(
|
||||
pub enum Test
|
||||
{
|
||||
System: pezframe_system::{Pallet, Call, Config<T>, Storage, Event<T>},
|
||||
Balances: pezpallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||
CollatorSelection: pezpallet_collator_selection::{Pallet, Call, Storage, Event<T>},
|
||||
}
|
||||
);
|
||||
|
||||
parameter_types! {
|
||||
pub BlockLength: limits::BlockLength = limits::BlockLength::max(2 * 1024);
|
||||
pub const AvailableBlockRatio: Perbill = Perbill::one();
|
||||
}
|
||||
|
||||
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
|
||||
impl pezframe_system::Config for Test {
|
||||
type BaseCallFilter = pezframe_support::traits::Everything;
|
||||
type RuntimeOrigin = RuntimeOrigin;
|
||||
type Nonce = u64;
|
||||
type RuntimeCall = RuntimeCall;
|
||||
type Hash = H256;
|
||||
type Hashing = BlakeTwo256;
|
||||
type AccountId = AccountId;
|
||||
type Lookup = IdentityLookup<Self::AccountId>;
|
||||
type Block = Block;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type BlockLength = BlockLength;
|
||||
type BlockWeights = ();
|
||||
type DbWeight = ();
|
||||
type Version = ();
|
||||
type PalletInfo = PalletInfo;
|
||||
type AccountData = pezpallet_balances::AccountData<u64>;
|
||||
type OnNewAccount = ();
|
||||
type OnKilledAccount = ();
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = ();
|
||||
type OnSetCode = ();
|
||||
type MaxConsumers = pezframe_support::traits::ConstU32<16>;
|
||||
}
|
||||
|
||||
#[derive_impl(pezpallet_balances::config_preludes::TestDefaultConfig)]
|
||||
impl pezpallet_balances::Config for Test {
|
||||
type AccountStore = System;
|
||||
}
|
||||
|
||||
pub struct OneAuthor;
|
||||
impl FindAuthor<AccountId> for OneAuthor {
|
||||
fn find_author<'a, I>(_: I) -> Option<AccountId>
|
||||
where
|
||||
I: 'a,
|
||||
{
|
||||
Some(TEST_ACCOUNT)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IsRegistered;
|
||||
impl ValidatorRegistration<AccountId> for IsRegistered {
|
||||
fn is_registered(_id: &AccountId) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
pub const PotId: PalletId = PalletId(*b"PotStake");
|
||||
}
|
||||
|
||||
impl pezpallet_collator_selection::Config for Test {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Currency = Balances;
|
||||
type UpdateOrigin = EnsureRoot<AccountId>;
|
||||
type PotId = PotId;
|
||||
type MaxCandidates = ConstU32<20>;
|
||||
type MinEligibleCollators = ConstU32<1>;
|
||||
type MaxInvulnerables = ConstU32<20>;
|
||||
type ValidatorId = <Self as pezframe_system::Config>::AccountId;
|
||||
type ValidatorIdOf = IdentityCollator;
|
||||
type ValidatorRegistration = IsRegistered;
|
||||
type KickThreshold = ();
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
impl pezpallet_authorship::Config for Test {
|
||||
type FindAuthor = OneAuthor;
|
||||
type EventHandler = ();
|
||||
}
|
||||
|
||||
pub fn new_test_ext() -> pezsp_io::TestExternalities {
|
||||
let mut t = pezframe_system::GenesisConfig::<Test>::default().build_storage().unwrap();
|
||||
// We use default for brevity, but you can configure as desired if needed.
|
||||
pezpallet_balances::GenesisConfig::<Test>::default()
|
||||
.assimilate_storage(&mut t)
|
||||
.unwrap();
|
||||
t.into()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fees_and_tip_split() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let fee =
|
||||
<pezpallet_balances::Pallet<Test> as pezframe_support::traits::fungible::Balanced<
|
||||
AccountId,
|
||||
>>::issue(10);
|
||||
let tip =
|
||||
<pezpallet_balances::Pallet<Test> as pezframe_support::traits::fungible::Balanced<
|
||||
AccountId,
|
||||
>>::issue(20);
|
||||
|
||||
assert_eq!(Balances::free_balance(TEST_ACCOUNT), 0);
|
||||
|
||||
DealWithFees::on_unbalanceds(vec![fee, tip].into_iter());
|
||||
|
||||
// Author gets 100% of tip and 100% of fee = 30
|
||||
assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 30);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assets_from_filters_correctly() {
|
||||
parameter_types! {
|
||||
pub SomeSiblingTeyrchain: Location = (Parent, Teyrchain(1234)).into();
|
||||
}
|
||||
|
||||
let asset_location = SomeSiblingTeyrchain::get()
|
||||
.pushed_with_interior(GeneralIndex(42))
|
||||
.expect("location will only have 2 junctions; qed");
|
||||
let asset = Asset { id: AssetId(asset_location), fun: 1_000_000u128.into() };
|
||||
assert!(
|
||||
AssetsFrom::<SomeSiblingTeyrchain>::contains(&asset, &SomeSiblingTeyrchain::get()),
|
||||
"AssetsFrom should allow assets from any of its interior locations"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
pub mod impls;
|
||||
pub mod message_queue;
|
||||
pub mod pay;
|
||||
pub mod xcm_config;
|
||||
pub use constants::*;
|
||||
pub use opaque::*;
|
||||
pub use types::*;
|
||||
|
||||
/// Common types of teyrchains.
|
||||
mod types {
|
||||
use pezsp_runtime::traits::{IdentifyAccount, Verify};
|
||||
|
||||
/// An index to a block.
|
||||
pub type BlockNumber = u32;
|
||||
|
||||
/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
|
||||
pub type Signature = pezsp_runtime::MultiSignature;
|
||||
|
||||
/// Some way of identifying an account on the chain. We intentionally make it equivalent
|
||||
/// to the public key of our transaction signing scheme.
|
||||
pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
|
||||
|
||||
/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
|
||||
/// never know...
|
||||
pub type AccountIndex = u32;
|
||||
|
||||
/// Balance of an account.
|
||||
pub type Balance = u128;
|
||||
|
||||
/// Index of a transaction in the chain.
|
||||
pub type Nonce = u32;
|
||||
|
||||
/// A hash of some data used by the chain.
|
||||
pub type Hash = pezsp_core::H256;
|
||||
|
||||
/// Digest item type.
|
||||
pub type DigestItem = pezsp_runtime::generic::DigestItem;
|
||||
|
||||
// Aura consensus authority.
|
||||
pub type AuraId = pezsp_consensus_aura::sr25519::AuthorityId;
|
||||
|
||||
// Aura consensus authority used by Asset Hub Pezkuwi.
|
||||
//
|
||||
// Because of registering the authorities with an ed25519 key before switching from Shell
|
||||
// to Asset Hub Pezkuwi, we were required to deploy a hotfix that changed Asset Hub Pezkuwi's
|
||||
// Aura keys to ed22519. In the future that may change again.
|
||||
pub type AssetHubPezkuwiAuraId = pezsp_consensus_aura::ed25519::AuthorityId;
|
||||
|
||||
// Id used for identifying assets.
|
||||
pub type AssetIdForTrustBackedAssets = u32;
|
||||
|
||||
// Id used for identifying non-fungible collections.
|
||||
pub type CollectionId = u32;
|
||||
|
||||
// Id used for identifying non-fungible items.
|
||||
pub type ItemId = u32;
|
||||
}
|
||||
|
||||
/// Common constants of teyrchains.
|
||||
mod constants {
|
||||
use super::types::BlockNumber;
|
||||
use pezframe_support::{
|
||||
weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight},
|
||||
PalletId,
|
||||
};
|
||||
use pezsp_runtime::Perbill;
|
||||
|
||||
/// This determines the average expected block time that we are targeting. Blocks will be
|
||||
/// produced at a minimum duration defined by `SLOT_DURATION`. `SLOT_DURATION` is picked up by
|
||||
/// `pezpallet_timestamp` which is in turn picked up by `pezpallet_aura` to implement `fn
|
||||
/// slot_duration()`.
|
||||
///
|
||||
/// Change this to adjust the block time.
|
||||
pub const MILLISECS_PER_BLOCK: u64 = 12000;
|
||||
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
|
||||
|
||||
// Time is measured by number of blocks.
|
||||
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
|
||||
pub const HOURS: BlockNumber = MINUTES * 60;
|
||||
pub const DAYS: BlockNumber = HOURS * 24;
|
||||
|
||||
/// We assume that ~5% of the block weight is consumed by `on_initialize` handlers. This is
|
||||
/// used to limit the maximal weight of a single extrinsic.
|
||||
pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(5);
|
||||
/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used by
|
||||
/// Operational extrinsics.
|
||||
pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
|
||||
|
||||
/// We allow for 0.5 seconds of compute with a 6 second average block time.
|
||||
pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(
|
||||
WEIGHT_REF_TIME_PER_SECOND.saturating_div(2),
|
||||
pezkuwi_primitives::MAX_POV_SIZE as u64,
|
||||
);
|
||||
|
||||
/// We allow for 2 seconds of compute with a 6 second average block.
|
||||
pub const MAXIMUM_BLOCK_WEIGHT_FOR_ASYNC_BACKING: Weight = Weight::from_parts(
|
||||
WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2),
|
||||
pezkuwi_primitives::MAX_POV_SIZE as u64,
|
||||
);
|
||||
|
||||
/// Treasury pallet id of the local chain, used to convert into AccountId
|
||||
pub const TREASURY_PALLET_ID: PalletId = PalletId(*b"py/trsry");
|
||||
}
|
||||
|
||||
/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
|
||||
/// the specifics of the runtime. They can then be made to be agnostic over specific formats
|
||||
/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
|
||||
/// to even the core data structures.
|
||||
pub mod opaque {
|
||||
use super::*;
|
||||
use pezsp_runtime::{generic, traits::BlakeTwo256};
|
||||
|
||||
pub use pezsp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
|
||||
/// Opaque block header type.
|
||||
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
||||
/// Opaque block type.
|
||||
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
||||
/// Opaque block identifier type.
|
||||
pub type BlockId = generic::BlockId<Block>;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Pezcumulus.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Helpers to deal with configuring the message queue in the runtime.
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
|
||||
use pezframe_support::traits::{QueueFootprint, QueuePausedQuery};
|
||||
use pezpallet_message_queue::OnQueueChanged;
|
||||
|
||||
/// Narrow the scope of the `Inner` query from `AggregateMessageOrigin` to `ParaId`.
|
||||
///
|
||||
/// All non-`Sibling` variants will be ignored.
|
||||
pub struct NarrowOriginToSibling<Inner>(PhantomData<Inner>);
|
||||
impl<Inner: QueuePausedQuery<ParaId>> QueuePausedQuery<AggregateMessageOrigin>
|
||||
for NarrowOriginToSibling<Inner>
|
||||
{
|
||||
fn is_paused(origin: &AggregateMessageOrigin) -> bool {
|
||||
match origin {
|
||||
AggregateMessageOrigin::Sibling(id) => Inner::is_paused(id),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner: OnQueueChanged<ParaId>> OnQueueChanged<AggregateMessageOrigin>
|
||||
for NarrowOriginToSibling<Inner>
|
||||
{
|
||||
fn on_queue_changed(origin: AggregateMessageOrigin, fp: QueueFootprint) {
|
||||
if let AggregateMessageOrigin::Sibling(id) = origin {
|
||||
Inner::on_queue_changed(id, fp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a sibling `ParaId` to an `AggregateMessageOrigin`.
|
||||
pub struct ParaIdToSibling;
|
||||
impl pezsp_runtime::traits::Convert<ParaId, AggregateMessageOrigin> for ParaIdToSibling {
|
||||
fn convert(para_id: ParaId) -> AggregateMessageOrigin {
|
||||
AggregateMessageOrigin::Sibling(para_id)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// This file is part of Pezcumulus.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
|
||||
use pezframe_support::traits::{
|
||||
fungibles,
|
||||
tokens::{PaymentStatus, Preservation},
|
||||
};
|
||||
use pezkuwi_runtime_common::impls::VersionedLocatableAsset;
|
||||
use pezsp_runtime::{traits::TypedGet, DispatchError, RuntimeDebug};
|
||||
use xcm::latest::prelude::*;
|
||||
use xcm_executor::traits::ConvertLocation;
|
||||
|
||||
/// Versioned locatable account type which contains both an XCM `location` and `account_id` to
|
||||
/// identify an account which exists on some chain.
|
||||
#[derive(
|
||||
Encode,
|
||||
Decode,
|
||||
Eq,
|
||||
PartialEq,
|
||||
Clone,
|
||||
RuntimeDebug,
|
||||
scale_info::TypeInfo,
|
||||
MaxEncodedLen,
|
||||
DecodeWithMemTracking,
|
||||
)]
|
||||
pub enum VersionedLocatableAccount {
|
||||
#[codec(index = 4)]
|
||||
V4 { location: xcm::v4::Location, account_id: xcm::v4::Location },
|
||||
#[codec(index = 5)]
|
||||
V5 { location: xcm::v5::Location, account_id: xcm::v5::Location },
|
||||
}
|
||||
|
||||
/// Pay on the local chain with `fungibles` implementation if the beneficiary and the asset are both
|
||||
/// local.
|
||||
pub struct LocalPay<F, A, C>(core::marker::PhantomData<(F, A, C)>);
|
||||
impl<A, F, C> pezframe_support::traits::tokens::Pay for LocalPay<F, A, C>
|
||||
where
|
||||
A: TypedGet,
|
||||
F: fungibles::Mutate<A::Type, AssetId = xcm::v5::Location> + fungibles::Create<A::Type>,
|
||||
C: ConvertLocation<A::Type>,
|
||||
A::Type: Eq + Clone,
|
||||
{
|
||||
type Balance = F::Balance;
|
||||
type Beneficiary = VersionedLocatableAccount;
|
||||
type AssetKind = VersionedLocatableAsset;
|
||||
type Id = QueryId;
|
||||
type Error = DispatchError;
|
||||
fn pay(
|
||||
who: &Self::Beneficiary,
|
||||
asset: Self::AssetKind,
|
||||
amount: Self::Balance,
|
||||
) -> Result<Self::Id, Self::Error> {
|
||||
let who = Self::match_location(who).map_err(|_| DispatchError::Unavailable)?;
|
||||
let asset = Self::match_asset(&asset).map_err(|_| DispatchError::Unavailable)?;
|
||||
<F as fungibles::Mutate<_>>::transfer(
|
||||
asset,
|
||||
&A::get(),
|
||||
&who,
|
||||
amount,
|
||||
Preservation::Expendable,
|
||||
)?;
|
||||
// We use `QueryId::MAX` as a constant identifier for these payments since they are always
|
||||
// processed immediately and successfully on the local chain. The `QueryId` type is used to
|
||||
// maintain compatibility with XCM payment implementations.
|
||||
Ok(Self::Id::MAX)
|
||||
}
|
||||
fn check_payment(_: Self::Id) -> PaymentStatus {
|
||||
PaymentStatus::Success
|
||||
}
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
fn ensure_successful(_: &Self::Beneficiary, asset: Self::AssetKind, amount: Self::Balance) {
|
||||
let asset = Self::match_asset(&asset).expect("invalid asset");
|
||||
<F as fungibles::Create<_>>::create(asset.clone(), A::get(), true, amount).unwrap();
|
||||
<F as fungibles::Mutate<_>>::mint_into(asset, &A::get(), amount).unwrap();
|
||||
}
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
fn ensure_concluded(_: Self::Id) {}
|
||||
}
|
||||
|
||||
impl<A, F, C> LocalPay<F, A, C>
|
||||
where
|
||||
A: TypedGet,
|
||||
F: fungibles::Mutate<A::Type> + fungibles::Create<A::Type>,
|
||||
C: ConvertLocation<A::Type>,
|
||||
A::Type: Eq + Clone,
|
||||
{
|
||||
fn match_location(who: &VersionedLocatableAccount) -> Result<A::Type, ()> {
|
||||
// only applicable for the local accounts
|
||||
let account_id = match who {
|
||||
VersionedLocatableAccount::V4 { location, account_id } if location.is_here() =>
|
||||
&account_id.clone().try_into().map_err(|_| ())?,
|
||||
VersionedLocatableAccount::V5 { location, account_id } if location.is_here() =>
|
||||
account_id,
|
||||
_ => return Err(()),
|
||||
};
|
||||
C::convert_location(account_id).ok_or(())
|
||||
}
|
||||
fn match_asset(asset: &VersionedLocatableAsset) -> Result<xcm::v5::Location, ()> {
|
||||
match asset {
|
||||
VersionedLocatableAsset::V4 { location, asset_id } if location.is_here() =>
|
||||
asset_id.clone().try_into().map(|a: xcm::v5::AssetId| a.0).map_err(|_| ()),
|
||||
VersionedLocatableAsset::V5 { location, asset_id } if location.is_here() =>
|
||||
Ok(asset_id.clone().0),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
pub mod benchmarks {
|
||||
use super::*;
|
||||
use core::marker::PhantomData;
|
||||
use pezframe_support::traits::Get;
|
||||
use pezpallet_treasury::ArgumentsFactory as TreasuryArgumentsFactory;
|
||||
use pezsp_core::ConstU8;
|
||||
|
||||
/// Provides factory methods for the `AssetKind` and the `Beneficiary` that are applicable for
|
||||
/// the payout made by [`LocalPay`].
|
||||
///
|
||||
/// ### Parameters:
|
||||
/// - `PalletId`: The ID of the assets registry pallet.
|
||||
/// - `AssetId`: The ID of the asset that will be created for the benchmark within `PalletId`.
|
||||
pub struct LocalPayArguments<PalletId = ConstU8<0>>(PhantomData<PalletId>);
|
||||
impl<PalletId: Get<u8>>
|
||||
TreasuryArgumentsFactory<VersionedLocatableAsset, VersionedLocatableAccount>
|
||||
for LocalPayArguments<PalletId>
|
||||
{
|
||||
fn create_asset_kind(seed: u32) -> VersionedLocatableAsset {
|
||||
VersionedLocatableAsset::V5 {
|
||||
location: Location::new(0, []),
|
||||
asset_id: Location::new(
|
||||
0,
|
||||
[PalletInstance(PalletId::get()), GeneralIndex(seed.into())],
|
||||
)
|
||||
.into(),
|
||||
}
|
||||
}
|
||||
fn create_beneficiary(seed: [u8; 32]) -> VersionedLocatableAccount {
|
||||
VersionedLocatableAccount::V5 {
|
||||
location: Location::new(0, []),
|
||||
account_id: Location::new(0, [AccountId32 { network: None, id: seed }]),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::impls::AccountIdOf;
|
||||
use core::marker::PhantomData;
|
||||
use cumulus_primitives_core::{IsSystem, ParaId};
|
||||
use pezframe_support::{
|
||||
traits::{fungibles::Inspect, tokens::ConversionToAssetBalance, Contains, ContainsPair},
|
||||
weights::Weight,
|
||||
};
|
||||
use pezsp_runtime::traits::Get;
|
||||
use xcm::latest::prelude::*;
|
||||
|
||||
/// A `ChargeFeeInFungibles` implementation that converts the output of
|
||||
/// a given WeightToFee implementation an amount charged in
|
||||
/// a particular assetId from pezpallet-assets
|
||||
pub struct AssetFeeAsExistentialDepositMultiplier<
|
||||
Runtime,
|
||||
WeightToFee,
|
||||
BalanceConverter,
|
||||
AssetInstance: 'static,
|
||||
>(PhantomData<(Runtime, WeightToFee, BalanceConverter, AssetInstance)>);
|
||||
impl<CurrencyBalance, Runtime, WeightToFee, BalanceConverter, AssetInstance>
|
||||
cumulus_primitives_utility::ChargeWeightInFungibles<
|
||||
AccountIdOf<Runtime>,
|
||||
pezpallet_assets::Pallet<Runtime, AssetInstance>,
|
||||
> for AssetFeeAsExistentialDepositMultiplier<Runtime, WeightToFee, BalanceConverter, AssetInstance>
|
||||
where
|
||||
Runtime: pezpallet_assets::Config<AssetInstance>,
|
||||
WeightToFee: pezframe_support::weights::WeightToFee<Balance = CurrencyBalance>,
|
||||
BalanceConverter: ConversionToAssetBalance<
|
||||
CurrencyBalance,
|
||||
<Runtime as pezpallet_assets::Config<AssetInstance>>::AssetId,
|
||||
<Runtime as pezpallet_assets::Config<AssetInstance>>::Balance,
|
||||
>,
|
||||
<BalanceConverter as ConversionToAssetBalance<
|
||||
CurrencyBalance,
|
||||
<Runtime as pezpallet_assets::Config<AssetInstance>>::AssetId,
|
||||
<Runtime as pezpallet_assets::Config<AssetInstance>>::Balance,
|
||||
>>::Error: core::fmt::Debug,
|
||||
{
|
||||
fn charge_weight_in_fungibles(
|
||||
asset_id: <pezpallet_assets::Pallet<Runtime, AssetInstance> as Inspect<
|
||||
AccountIdOf<Runtime>,
|
||||
>>::AssetId,
|
||||
weight: Weight,
|
||||
) -> Result<
|
||||
<pezpallet_assets::Pallet<Runtime, AssetInstance> as Inspect<AccountIdOf<Runtime>>>::Balance,
|
||||
XcmError,
|
||||
> {
|
||||
let amount = WeightToFee::weight_to_fee(&weight);
|
||||
// If the amount gotten is not at least the ED, then make it be the ED of the asset
|
||||
// This is to avoid burning assets and decreasing the supply
|
||||
let asset_amount = BalanceConverter::to_asset_balance(amount, asset_id)
|
||||
.map_err(|error| {
|
||||
tracing::debug!(target: "xcm::charge_weight_in_fungibles", ?error, "AssetFeeAsExistentialDepositMultiplier cannot convert to valid balance (possibly below ED)");
|
||||
XcmError::TooExpensive
|
||||
})?;
|
||||
Ok(asset_amount)
|
||||
}
|
||||
}
|
||||
|
||||
/// Accepts an asset if it is a native asset from a particular `Location`.
|
||||
pub struct ConcreteNativeAssetFrom<LocationValue>(PhantomData<LocationValue>);
|
||||
impl<LocationValue: Get<Location>> ContainsPair<Asset, Location>
|
||||
for ConcreteNativeAssetFrom<LocationValue>
|
||||
{
|
||||
fn contains(asset: &Asset, origin: &Location) -> bool {
|
||||
tracing::trace!(
|
||||
target: "xcm::filter_asset_location",
|
||||
?asset, ?origin, location=?LocationValue::get(),
|
||||
"ConcreteNativeAsset"
|
||||
);
|
||||
asset.id.0 == *origin && origin == &LocationValue::get()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RelayOrOtherSystemTeyrchains<
|
||||
SystemTeyrchainMatcher: Contains<Location>,
|
||||
Runtime: teyrchain_info::Config,
|
||||
> {
|
||||
_runtime: PhantomData<(SystemTeyrchainMatcher, Runtime)>,
|
||||
}
|
||||
impl<SystemTeyrchainMatcher: Contains<Location>, Runtime: teyrchain_info::Config> Contains<Location>
|
||||
for RelayOrOtherSystemTeyrchains<SystemTeyrchainMatcher, Runtime>
|
||||
{
|
||||
fn contains(l: &Location) -> bool {
|
||||
let self_para_id: u32 = teyrchain_info::Pallet::<Runtime>::get().into();
|
||||
if let (0, [Teyrchain(para_id)]) = l.unpack() {
|
||||
if *para_id == self_para_id {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
matches!(l.unpack(), (1, [])) || SystemTeyrchainMatcher::contains(l)
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains all sibling system teyrchains, including the one where this matcher is used.
|
||||
///
|
||||
/// This structure can only be used at a teyrchain level. In the Relay Chain, please use
|
||||
/// the `xcm_builder::IsChildSystemTeyrchain` matcher.
|
||||
pub struct AllSiblingSystemTeyrchains;
|
||||
impl Contains<Location> for AllSiblingSystemTeyrchains {
|
||||
fn contains(l: &Location) -> bool {
|
||||
tracing::trace!(target: "xcm::contains", location=?l, "AllSiblingSystemTeyrchains");
|
||||
match l.unpack() {
|
||||
// System teyrchain
|
||||
(1, [Teyrchain(id)]) => ParaId::from(*id).is_system(),
|
||||
// Everything else
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Accepts an asset if it is a concrete asset from the system (Relay Chain or system teyrchain).
|
||||
pub struct ConcreteAssetFromSystem<AssetLocation>(PhantomData<AssetLocation>);
|
||||
impl<AssetLocation: Get<Location>> ContainsPair<Asset, Location>
|
||||
for ConcreteAssetFromSystem<AssetLocation>
|
||||
{
|
||||
fn contains(asset: &Asset, origin: &Location) -> bool {
|
||||
tracing::trace!(target: "xcm::contains", ?asset, ?origin, "ConcreteAssetFromSystem");
|
||||
let is_system = match origin.unpack() {
|
||||
// The Relay Chain
|
||||
(1, []) => true,
|
||||
// System teyrchain
|
||||
(1, [Teyrchain(id)]) => ParaId::from(*id).is_system(),
|
||||
// Others
|
||||
_ => false,
|
||||
};
|
||||
asset.id.0 == AssetLocation::get() && is_system
|
||||
}
|
||||
}
|
||||
|
||||
/// Filter to check if a given location is the parent Relay Chain or a sibling teyrchain.
|
||||
///
|
||||
/// This type should only be used within the context of a teyrchain, since it does not verify that
|
||||
/// the parent is indeed a Relay Chain.
|
||||
pub struct ParentRelayOrSiblingTeyrchains;
|
||||
impl Contains<Location> for ParentRelayOrSiblingTeyrchains {
|
||||
fn contains(location: &Location) -> bool {
|
||||
matches!(location.unpack(), (1, []) | (1, [Teyrchain(_)]))
|
||||
}
|
||||
}
|
||||
|
||||
/// Filter to check if a given `target` location represents the same AccountId32 as `origin`,
|
||||
/// but coming from another sibling system chain.
|
||||
///
|
||||
/// This type should only be used within the context of a teyrchain, to allow accounts on system
|
||||
/// chains to Alias to the same accounts on the local chain.
|
||||
pub struct AliasAccountId32FromSiblingSystemChain;
|
||||
impl ContainsPair<Location, Location> for AliasAccountId32FromSiblingSystemChain {
|
||||
fn contains(origin: &Location, target: &Location) -> bool {
|
||||
let result = match origin.unpack() {
|
||||
// `origin` is AccountId32 on sibling system teyrchain
|
||||
(1, [Teyrchain(para_id), AccountId32 { network: _, id: origin }])
|
||||
if ParaId::from(*para_id).is_system() =>
|
||||
{
|
||||
match target.unpack() {
|
||||
// `target` is local AccountId32 and matches `origin` remote account
|
||||
(0, [AccountId32 { network: _, id: target }]) => target.eq(origin),
|
||||
_ => false,
|
||||
}
|
||||
},
|
||||
_ => false,
|
||||
};
|
||||
tracing::trace!(
|
||||
target: "xcm::contains",
|
||||
?origin, ?target, ?result,
|
||||
"AliasAccountId32FromSiblingSystemChain"
|
||||
);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pezframe_support::{parameter_types, traits::Contains};
|
||||
|
||||
use super::{
|
||||
AliasAccountId32FromSiblingSystemChain, AllSiblingSystemTeyrchains, Asset,
|
||||
ConcreteAssetFromSystem, ContainsPair, GeneralIndex, Here, Location, PalletInstance,
|
||||
Parent, Teyrchain,
|
||||
};
|
||||
use pezkuwi_primitives::LOWEST_PUBLIC_ID;
|
||||
use xcm::latest::prelude::*;
|
||||
|
||||
parameter_types! {
|
||||
pub const RelayLocation: Location = Location::parent();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn concrete_asset_from_relay_works() {
|
||||
let expected_asset: Asset = (Parent, 1000000).into();
|
||||
let expected_origin: Location = (Parent, Here).into();
|
||||
|
||||
assert!(<ConcreteAssetFromSystem<RelayLocation>>::contains(
|
||||
&expected_asset,
|
||||
&expected_origin
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn concrete_asset_from_sibling_system_para_fails_for_wrong_asset() {
|
||||
let unexpected_assets: Vec<Asset> = vec![
|
||||
(Here, 1000000).into(),
|
||||
((PalletInstance(50), GeneralIndex(1)), 1000000).into(),
|
||||
((Parent, Teyrchain(1000), PalletInstance(50), GeneralIndex(1)), 1000000).into(),
|
||||
];
|
||||
let expected_origin: Location = (Parent, Teyrchain(1000)).into();
|
||||
|
||||
unexpected_assets.iter().for_each(|asset| {
|
||||
assert!(!<ConcreteAssetFromSystem<RelayLocation>>::contains(asset, &expected_origin));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn concrete_asset_from_sibling_system_para_works_for_correct_asset() {
|
||||
// (para_id, expected_result)
|
||||
let test_data = vec![
|
||||
(0, true),
|
||||
(1, true),
|
||||
(1000, true),
|
||||
(1999, true),
|
||||
(2000, false), // Not a System Teyrchain
|
||||
(2001, false), // Not a System Teyrchain
|
||||
];
|
||||
|
||||
let expected_asset: Asset = (Parent, 1000000).into();
|
||||
|
||||
for (para_id, expected_result) in test_data {
|
||||
let origin: Location = (Parent, Teyrchain(para_id)).into();
|
||||
assert_eq!(
|
||||
expected_result,
|
||||
<ConcreteAssetFromSystem<RelayLocation>>::contains(&expected_asset, &origin)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_sibling_system_teyrchains_works() {
|
||||
// system teyrchain
|
||||
assert!(AllSiblingSystemTeyrchains::contains(&Location::new(1, [Teyrchain(1)])));
|
||||
// non-system teyrchain
|
||||
assert!(!AllSiblingSystemTeyrchains::contains(&Location::new(
|
||||
1,
|
||||
[Teyrchain(LOWEST_PUBLIC_ID.into())]
|
||||
)));
|
||||
// when used at relay chain
|
||||
assert!(!AllSiblingSystemTeyrchains::contains(&Location::new(0, [Teyrchain(1)])));
|
||||
// when used with non-teyrchain
|
||||
assert!(!AllSiblingSystemTeyrchains::contains(&Location::new(1, [OnlyChild])));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alias_accountid32_from_sibling_system_teyrchains() {
|
||||
let acc_42 = AccountId32 { network: None, id: [42u8; 32] };
|
||||
let acc_13 = AccountId32 { network: None, id: [13u8; 32] };
|
||||
// origin acc_42 on sibling system teyrchain aliases into local acc_42
|
||||
assert!(AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(1, [Teyrchain(1), acc_42]),
|
||||
&Location::new(0, [acc_42])
|
||||
));
|
||||
// if target is not local account, always fails
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(1, [Teyrchain(1), acc_42]),
|
||||
&Location::new(0, [])
|
||||
));
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(1, [Teyrchain(1), acc_42]),
|
||||
&Location::new(0, [Teyrchain(1)])
|
||||
));
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(1, [Teyrchain(1), acc_42]),
|
||||
&Location::new(0, [GeneralIndex(42)])
|
||||
));
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(1, [Teyrchain(1), acc_42]),
|
||||
&Location::new(1, [acc_42])
|
||||
));
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(1, [Teyrchain(1), acc_42]),
|
||||
&Location::new(2, [acc_42])
|
||||
));
|
||||
// origin acc_13 on sibling system teyrchain CANNOT alias into local acc_42
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(1, [Teyrchain(1), acc_13]),
|
||||
&Location::new(0, [acc_42])
|
||||
));
|
||||
// origin acc_42 on sibling non-system teyrchain CANNOT alias into local acc_42
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(1, [Teyrchain(LOWEST_PUBLIC_ID.into()), acc_42]),
|
||||
&Location::new(0, [acc_42])
|
||||
));
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(0, [acc_13]),
|
||||
&Location::new(0, [acc_13]),
|
||||
));
|
||||
assert!(!AliasAccountId32FromSiblingSystemChain::contains(
|
||||
&Location::new(0, [acc_42]),
|
||||
&Location::new(1, [Teyrchain(1), acc_42]),
|
||||
));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user