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:
2025-12-14 00:04:10 +03:00
parent 286de54384
commit 1c0e57d984
9084 changed files with 997839 additions and 997557 deletions
@@ -0,0 +1,95 @@
[package]
name = "teyrchains-runtimes-test-utils"
version = "7.0.0"
authors.workspace = true
edition.workspace = true
description = "Utils for Runtimes testing"
license = "Apache-2.0"
homepage.workspace = true
repository.workspace = true
[lints]
workspace = true
[dependencies]
codec = { features = ["derive", "max-encoded-len"], workspace = true }
# Bizinikiwi
pezframe-support = { workspace = true }
pezframe-system = { workspace = true }
pezpallet-balances = { workspace = true }
pezpallet-session = { workspace = true }
pezpallet-timestamp = { workspace = true }
pezsp-consensus-aura = { workspace = true }
pezsp-core = { workspace = true }
pezsp-io = { workspace = true }
pezsp-runtime = { workspace = true }
pezsp-tracing = { workspace = true, default-features = true }
# Pezcumulus
pezcumulus-pezpallet-teyrchain-system = { workspace = true }
pezcumulus-pezpallet-xcmp-queue = { workspace = true }
pezcumulus-primitives-core = { workspace = true }
pezcumulus-primitives-teyrchain-inherent = { workspace = true }
pezcumulus-test-relay-sproof-builder = { workspace = true }
pezpallet-collator-selection = { workspace = true }
teyrchain-info = { workspace = true }
teyrchains-common = { workspace = true }
# Pezkuwi
pezpallet-xcm = { workspace = true }
pezkuwi-teyrchain-primitives = { workspace = true }
xcm = { workspace = true }
xcm-executor = { workspace = true }
xcm-runtime-apis = { workspace = true }
[features]
default = ["std"]
std = [
"codec/std",
"pezcumulus-pezpallet-teyrchain-system/std",
"pezcumulus-pezpallet-xcmp-queue/std",
"pezcumulus-primitives-core/std",
"pezcumulus-primitives-teyrchain-inherent/std",
"pezcumulus-test-relay-sproof-builder/std",
"pezframe-support/std",
"pezframe-system/std",
"pezpallet-balances/std",
"pezpallet-collator-selection/std",
"pezpallet-session/std",
"pezpallet-timestamp/std",
"pezpallet-xcm/std",
"pezkuwi-teyrchain-primitives/std",
"pezsp-consensus-aura/std",
"pezsp-core/std",
"pezsp-io/std",
"pezsp-runtime/std",
"teyrchain-info/std",
"teyrchains-common/std",
"xcm-executor/std",
"xcm-runtime-apis/std",
"xcm/std",
]
runtime-benchmarks = [
"pezcumulus-pezpallet-teyrchain-system/runtime-benchmarks",
"pezcumulus-pezpallet-xcmp-queue/runtime-benchmarks",
"pezcumulus-primitives-core/runtime-benchmarks",
"pezcumulus-primitives-teyrchain-inherent/runtime-benchmarks",
"pezcumulus-test-relay-sproof-builder/runtime-benchmarks",
"pezframe-support/runtime-benchmarks",
"pezframe-system/runtime-benchmarks",
"pezpallet-balances/runtime-benchmarks",
"pezpallet-collator-selection/runtime-benchmarks",
"pezpallet-session/runtime-benchmarks",
"pezpallet-timestamp/runtime-benchmarks",
"pezpallet-xcm/runtime-benchmarks",
"pezkuwi-teyrchain-primitives/runtime-benchmarks",
"pezsp-consensus-aura/runtime-benchmarks",
"pezsp-io/runtime-benchmarks",
"pezsp-runtime/runtime-benchmarks",
"teyrchain-info/runtime-benchmarks",
"teyrchains-common/runtime-benchmarks",
"xcm-executor/runtime-benchmarks",
"xcm-runtime-apis/runtime-benchmarks",
"xcm/runtime-benchmarks",
]
@@ -0,0 +1,766 @@
// 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 core::marker::PhantomData;
use codec::{Decode, DecodeLimit};
use cumulus_pallet_teyrchain_system::teyrchain_inherent::{
deconstruct_teyrchain_inherent_data, InboundMessagesData,
};
use cumulus_primitives_core::{
relay_chain::Slot, AbridgedHrmpChannel, ParaId, PersistedValidationData,
};
use cumulus_primitives_teyrchain_inherent::TeyrchainInherentData;
use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder;
use pezframe_support::{
dispatch::{DispatchResult, GetDispatchInfo, RawOrigin},
inherent::{InherentData, ProvideInherent},
pezpallet_prelude::Get,
traits::{OnFinalize, OnInitialize, OriginTrait, UnfilteredDispatchable},
weights::Weight,
};
use pezframe_system::pezpallet_prelude::{BlockNumberFor, HeaderFor};
use pezkuwi_teyrchain_primitives::primitives::{
HeadData, HrmpChannelId, RelayChainBlockNumber, XcmpMessageFormat,
};
use pezsp_consensus_aura::{SlotDuration, AURA_ENGINE_ID};
use pezsp_core::{Encode, U256};
use pezsp_runtime::{
traits::{Dispatchable, Header},
BuildStorage, Digest, DigestItem, DispatchError, Either, SaturatedConversion,
};
use xcm::{
latest::{Asset, Location, XcmContext, XcmHash},
prelude::*,
VersionedXcm, MAX_XCM_DECODE_DEPTH,
};
use xcm_executor::{traits::TransactAsset, AssetsInHolding};
pub mod test_cases;
pub type BalanceOf<Runtime> = <Runtime as pezpallet_balances::Config>::Balance;
pub type AccountIdOf<Runtime> = <Runtime as pezframe_system::Config>::AccountId;
pub type RuntimeCallOf<Runtime> = <Runtime as pezframe_system::Config>::RuntimeCall;
pub type RuntimeOriginOf<Runtime> = <Runtime as pezframe_system::Config>::RuntimeOrigin;
pub type ValidatorIdOf<Runtime> = <Runtime as pezpallet_session::Config>::ValidatorId;
pub type SessionKeysOf<Runtime> = <Runtime as pezpallet_session::Config>::Keys;
pub struct CollatorSessionKey<
Runtime: pezframe_system::Config + pezpallet_balances::Config + pezpallet_session::Config,
> {
collator: AccountIdOf<Runtime>,
validator: ValidatorIdOf<Runtime>,
key: SessionKeysOf<Runtime>,
}
pub struct CollatorSessionKeys<
Runtime: pezframe_system::Config + pezpallet_balances::Config + pezpallet_session::Config,
> {
items: Vec<CollatorSessionKey<Runtime>>,
}
impl<Runtime: pezframe_system::Config + pezpallet_balances::Config + pezpallet_session::Config>
CollatorSessionKey<Runtime>
{
pub fn new(
collator: AccountIdOf<Runtime>,
validator: ValidatorIdOf<Runtime>,
key: SessionKeysOf<Runtime>,
) -> Self {
Self { collator, validator, key }
}
}
impl<Runtime: pezframe_system::Config + pezpallet_balances::Config + pezpallet_session::Config> Default
for CollatorSessionKeys<Runtime>
{
fn default() -> Self {
Self { items: vec![] }
}
}
impl<Runtime: pezframe_system::Config + pezpallet_balances::Config + pezpallet_session::Config>
CollatorSessionKeys<Runtime>
{
pub fn new(
collator: AccountIdOf<Runtime>,
validator: ValidatorIdOf<Runtime>,
key: SessionKeysOf<Runtime>,
) -> Self {
Self { items: vec![CollatorSessionKey::new(collator, validator, key)] }
}
pub fn add(mut self, item: CollatorSessionKey<Runtime>) -> Self {
self.items.push(item);
self
}
pub fn collators(&self) -> Vec<AccountIdOf<Runtime>> {
self.items.iter().map(|item| item.collator.clone()).collect::<Vec<_>>()
}
pub fn session_keys(
&self,
) -> Vec<(AccountIdOf<Runtime>, ValidatorIdOf<Runtime>, SessionKeysOf<Runtime>)> {
self.items
.iter()
.map(|item| (item.collator.clone(), item.validator.clone(), item.key.clone()))
.collect::<Vec<_>>()
}
}
pub struct SlotDurations {
pub relay: SlotDuration,
pub para: SlotDuration,
}
/// A set of traits for a minimal teyrchain runtime, that may be used in conjunction with the
/// `ExtBuilder` and the `RuntimeHelper`.
pub trait BasicTeyrchainRuntime:
pezframe_system::Config
+ pezpallet_balances::Config
+ pezpallet_session::Config
+ pezpallet_xcm::Config
+ teyrchain_info::Config
+ pezpallet_collator_selection::Config
+ cumulus_pallet_teyrchain_system::Config
+ pezpallet_timestamp::Config
{
}
impl<T> BasicTeyrchainRuntime for T
where
T: pezframe_system::Config
+ pezpallet_balances::Config
+ pezpallet_session::Config
+ pezpallet_xcm::Config
+ teyrchain_info::Config
+ pezpallet_collator_selection::Config
+ cumulus_pallet_teyrchain_system::Config
+ pezpallet_timestamp::Config,
ValidatorIdOf<T>: From<AccountIdOf<T>>,
{
}
/// Basic builder based on balances, collators and pezpallet_session.
pub struct ExtBuilder<Runtime: BasicTeyrchainRuntime> {
// endowed accounts with balances
balances: Vec<(AccountIdOf<Runtime>, BalanceOf<Runtime>)>,
// collators to test block prod
collators: Vec<AccountIdOf<Runtime>>,
// keys added to pallet session
keys: Vec<(AccountIdOf<Runtime>, ValidatorIdOf<Runtime>, SessionKeysOf<Runtime>)>,
// safe XCM version for pezpallet_xcm
safe_xcm_version: Option<XcmVersion>,
// para id
para_id: Option<ParaId>,
_runtime: PhantomData<Runtime>,
}
impl<Runtime: BasicTeyrchainRuntime> Default for ExtBuilder<Runtime> {
fn default() -> ExtBuilder<Runtime> {
ExtBuilder {
balances: vec![],
collators: vec![],
keys: vec![],
safe_xcm_version: None,
para_id: None,
_runtime: PhantomData,
}
}
}
impl<Runtime: BasicTeyrchainRuntime> ExtBuilder<Runtime> {
pub fn with_balances(
mut self,
balances: Vec<(AccountIdOf<Runtime>, BalanceOf<Runtime>)>,
) -> Self {
self.balances = balances;
self
}
pub fn with_collators(mut self, collators: Vec<AccountIdOf<Runtime>>) -> Self {
self.collators = collators;
self
}
pub fn with_session_keys(
mut self,
keys: Vec<(AccountIdOf<Runtime>, ValidatorIdOf<Runtime>, SessionKeysOf<Runtime>)>,
) -> Self {
self.keys = keys;
self
}
pub fn with_tracing(self) -> Self {
pezsp_tracing::try_init_simple();
self
}
pub fn with_safe_xcm_version(mut self, safe_xcm_version: XcmVersion) -> Self {
self.safe_xcm_version = Some(safe_xcm_version);
self
}
pub fn with_para_id(mut self, para_id: ParaId) -> Self {
self.para_id = Some(para_id);
self
}
pub fn build(self) -> pezsp_io::TestExternalities {
let mut t = pezframe_system::GenesisConfig::<Runtime>::default().build_storage().unwrap();
pezpallet_xcm::GenesisConfig::<Runtime> {
safe_xcm_version: self.safe_xcm_version,
..Default::default()
}
.assimilate_storage(&mut t)
.unwrap();
if let Some(para_id) = self.para_id {
teyrchain_info::GenesisConfig::<Runtime> {
teyrchain_id: para_id,
..Default::default()
}
.assimilate_storage(&mut t)
.unwrap();
}
pezpallet_balances::GenesisConfig::<Runtime> { balances: self.balances, ..Default::default() }
.assimilate_storage(&mut t)
.unwrap();
pezpallet_collator_selection::GenesisConfig::<Runtime> {
invulnerables: self.collators.clone(),
candidacy_bond: Default::default(),
desired_candidates: Default::default(),
}
.assimilate_storage(&mut t)
.unwrap();
pezpallet_session::GenesisConfig::<Runtime> { keys: self.keys, ..Default::default() }
.assimilate_storage(&mut t)
.unwrap();
let mut ext = pezsp_io::TestExternalities::new(t);
ext.execute_with(|| {
pezframe_system::Pallet::<Runtime>::set_block_number(1u32.into());
});
ext
}
}
pub struct RuntimeHelper<Runtime, AllPalletsWithoutSystem>(
PhantomData<(Runtime, AllPalletsWithoutSystem)>,
);
/// Utility function that advances the chain to the desired block number.
/// If an author is provided, that author information is injected to all the blocks in the meantime.
impl<
Runtime: pezframe_system::Config + cumulus_pallet_teyrchain_system::Config + pezpallet_timestamp::Config,
AllPalletsWithoutSystem,
> RuntimeHelper<Runtime, AllPalletsWithoutSystem>
where
AccountIdOf<Runtime>:
Into<<<Runtime as pezframe_system::Config>::RuntimeOrigin as OriginTrait>::AccountId>,
AllPalletsWithoutSystem:
OnInitialize<BlockNumberFor<Runtime>> + OnFinalize<BlockNumberFor<Runtime>>,
{
pub fn run_to_block(n: u32, author: AccountIdOf<Runtime>) -> HeaderFor<Runtime> {
let mut last_header = None;
loop {
let block_number = pezframe_system::Pallet::<Runtime>::block_number();
if block_number >= n.into() {
break;
}
// Set the new block number and author
// Inherent is not created at every block, don't finalize teyrchain
// system to avoid panicking.
let header = pezframe_system::Pallet::<Runtime>::finalize();
let pre_digest =
Digest { logs: vec![DigestItem::PreRuntime(AURA_ENGINE_ID, author.encode())] };
pezframe_system::Pallet::<Runtime>::reset_events();
let next_block_number = block_number + 1u32.into();
pezframe_system::Pallet::<Runtime>::initialize(
&next_block_number,
&header.hash(),
&pre_digest,
);
AllPalletsWithoutSystem::on_initialize(next_block_number);
last_header = Some(header);
}
last_header.expect("run_to_block empty block range")
}
pub fn run_to_block_with_finalize(n: u32) -> HeaderFor<Runtime> {
let mut last_header = None;
loop {
let block_number = pezframe_system::Pallet::<Runtime>::block_number();
if block_number >= n.into() {
break;
}
// Set the new block number and author
let header = pezframe_system::Pallet::<Runtime>::finalize();
let pre_digest = Digest {
logs: vec![DigestItem::PreRuntime(AURA_ENGINE_ID, block_number.encode())],
};
pezframe_system::Pallet::<Runtime>::reset_events();
let next_block_number = block_number + 1u32.into();
pezframe_system::Pallet::<Runtime>::initialize(
&next_block_number,
&header.hash(),
&pre_digest,
);
AllPalletsWithoutSystem::on_initialize(next_block_number);
let parent_head = HeadData(header.encode());
let sproof_builder = RelayStateSproofBuilder {
para_id: <Runtime>::SelfParaId::get(),
included_para_head: parent_head.clone().into(),
..Default::default()
};
let (relay_parent_storage_root, relay_chain_state) =
sproof_builder.into_state_root_and_proof();
let inherent_data = TeyrchainInherentData {
validation_data: PersistedValidationData {
parent_head,
relay_parent_number: (block_number.saturated_into::<u32>() * 2 + 1).into(),
relay_parent_storage_root,
max_pov_size: 100_000_000,
},
relay_chain_state,
downward_messages: Default::default(),
horizontal_messages: Default::default(),
relay_parent_descendants: Default::default(),
collator_peer_id: None,
};
let (inherent_data, downward_messages, horizontal_messages) =
deconstruct_teyrchain_inherent_data(inherent_data);
let _ = cumulus_pallet_teyrchain_system::Pallet::<Runtime>::set_validation_data(
Runtime::RuntimeOrigin::none(),
inherent_data,
InboundMessagesData::new(
downward_messages.into_abridged(&mut usize::MAX.clone()),
horizontal_messages.into_abridged(&mut usize::MAX.clone()),
),
);
let _ = pezpallet_timestamp::Pallet::<Runtime>::set(
Runtime::RuntimeOrigin::none(),
300_u32.into(),
);
AllPalletsWithoutSystem::on_finalize(next_block_number);
let header = pezframe_system::Pallet::<Runtime>::finalize();
last_header = Some(header);
}
last_header.expect("run_to_block empty block range")
}
pub fn root_origin() -> <Runtime as pezframe_system::Config>::RuntimeOrigin {
<Runtime as pezframe_system::Config>::RuntimeOrigin::root()
}
pub fn block_number() -> U256 {
pezframe_system::Pallet::<Runtime>::block_number().into()
}
pub fn origin_of(
account_id: AccountIdOf<Runtime>,
) -> <Runtime as pezframe_system::Config>::RuntimeOrigin {
<Runtime as pezframe_system::Config>::RuntimeOrigin::signed(account_id.into())
}
}
impl<XcmConfig: xcm_executor::Config, AllPalletsWithoutSystem>
RuntimeHelper<XcmConfig, AllPalletsWithoutSystem>
{
pub fn do_transfer(
from: Location,
to: Location,
(asset, amount): (Location, u128),
) -> Result<AssetsInHolding, XcmError> {
<XcmConfig::AssetTransactor as TransactAsset>::transfer_asset(
&Asset { id: AssetId(asset), fun: Fungible(amount) },
&from,
&to,
// We aren't able to track the XCM that initiated the fee deposit, so we create a
// fake message hash here
&XcmContext::with_message_id([0; 32]),
)
}
}
impl<
Runtime: pezpallet_xcm::Config + cumulus_pallet_teyrchain_system::Config,
AllPalletsWithoutSystem,
> RuntimeHelper<Runtime, AllPalletsWithoutSystem>
{
pub fn do_teleport_assets<HrmpChannelOpener>(
origin: <Runtime as pezframe_system::Config>::RuntimeOrigin,
dest: Location,
beneficiary: Location,
(asset, amount): (Location, u128),
open_hrmp_channel: Option<(u32, u32)>,
included_head: HeaderFor<Runtime>,
slot_digest: &[u8],
slot_durations: &SlotDurations,
) -> DispatchResult
where
HrmpChannelOpener: pezframe_support::inherent::ProvideInherent<
Call = cumulus_pallet_teyrchain_system::Call<Runtime>,
>,
{
// open hrmp (if needed)
if let Some((source_para_id, target_para_id)) = open_hrmp_channel {
mock_open_hrmp_channel::<Runtime, HrmpChannelOpener>(
source_para_id.into(),
target_para_id.into(),
included_head,
slot_digest,
slot_durations,
);
}
// do teleport
<pezpallet_xcm::Pallet<Runtime>>::limited_teleport_assets(
origin,
Box::new(dest.into()),
Box::new(beneficiary.into()),
Box::new((AssetId(asset.clone()), amount).into()),
Box::new(AssetId(asset).into()),
Unlimited,
)
}
}
impl<
Runtime: cumulus_pallet_teyrchain_system::Config + pezpallet_xcm::Config,
AllPalletsWithoutSystem,
> RuntimeHelper<Runtime, AllPalletsWithoutSystem>
{
#[deprecated(
note = "Will be removed after Aug 2025; It uses hard-coded `Location::parent()`, \
use `execute_as_governance_call` instead."
)]
pub fn execute_as_governance(call: Vec<u8>) -> Outcome {
// prepare xcm as governance will do
let xcm = Xcm(vec![
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
Transact {
origin_kind: OriginKind::Superuser,
call: call.into(),
fallback_max_weight: None,
},
ExpectTransactStatus(MaybeErrorCode::Success),
]);
// execute xcm as parent origin
let mut hash = xcm.using_encoded(pezsp_io::hashing::blake2_256);
<<Runtime as pezpallet_xcm::Config>::XcmExecutor>::prepare_and_execute(
Location::parent(),
xcm,
&mut hash,
Self::xcm_max_weight(XcmReceivedFrom::Parent),
Weight::zero(),
)
}
pub fn execute_as_governance_call<Call: Dispatchable + Encode>(
call: Call,
governance_origin: GovernanceOrigin<Call::RuntimeOrigin>,
) -> Result<(), Either<DispatchError, InstructionError>> {
// execute xcm as governance would send
let execute_xcm = |call: Call, governance_location, descend_origin| {
// prepare xcm
let xcm = if let Some(descend_origin) = descend_origin {
Xcm::builder_unsafe().descend_origin(descend_origin)
} else {
Xcm::builder_unsafe()
}
.unpaid_execution(Unlimited, None)
.transact(OriginKind::Superuser, None, call.encode())
.expect_transact_status(MaybeErrorCode::Success)
.build();
let xcm_max_weight = Self::xcm_max_weight_for_location(&governance_location);
let mut hash = xcm.using_encoded(pezsp_io::hashing::blake2_256);
<<Runtime as pezpallet_xcm::Config>::XcmExecutor>::prepare_and_execute(
governance_location,
xcm,
&mut hash,
xcm_max_weight,
Weight::zero(),
)
};
match governance_origin {
// we are simulating a case of receiving an XCM
// and Location::Here() is not a valid destionation for XcmRouter in the fist place
GovernanceOrigin::Location(location) if location == Location::here() => {
panic!("Location::here() not supported, use GovernanceOrigin::Origin instead")
},
GovernanceOrigin::Location(location) =>
execute_xcm(call, location, None).ensure_complete().map_err(Either::Right),
GovernanceOrigin::LocationAndDescendOrigin(location, descend_origin) =>
execute_xcm(call, location, Some(descend_origin))
.ensure_complete()
.map_err(Either::Right),
GovernanceOrigin::Origin(origin) =>
call.dispatch(origin).map(|_| ()).map_err(|e| Either::Left(e.error)),
}
}
pub fn execute_as_origin<Call: GetDispatchInfo + Encode>(
(origin, origin_kind): (Location, OriginKind),
call: Call,
maybe_buy_execution_fee: Option<Asset>,
) -> Outcome {
let mut instructions = if let Some(buy_execution_fee) = maybe_buy_execution_fee {
vec![
WithdrawAsset(buy_execution_fee.clone().into()),
BuyExecution { fees: buy_execution_fee.clone(), weight_limit: Unlimited },
]
} else {
vec![UnpaidExecution { check_origin: None, weight_limit: Unlimited }]
};
// prepare `Transact` xcm
instructions.extend(vec![
Transact { origin_kind, call: call.encode().into(), fallback_max_weight: None },
ExpectTransactStatus(MaybeErrorCode::Success),
]);
let xcm = Xcm(instructions);
let xcm_max_weight = Self::xcm_max_weight_for_location(&origin);
// execute xcm as parent origin
let mut hash = xcm.using_encoded(pezsp_io::hashing::blake2_256);
<<Runtime as pezpallet_xcm::Config>::XcmExecutor>::prepare_and_execute(
origin,
xcm,
&mut hash,
xcm_max_weight,
Weight::zero(),
)
}
}
/// Enum representing governance origin/location.
#[derive(Clone)]
pub enum GovernanceOrigin<RuntimeOrigin> {
Location(Location),
LocationAndDescendOrigin(Location, InteriorLocation),
Origin(RuntimeOrigin),
}
pub enum XcmReceivedFrom {
Parent,
Sibling,
}
impl<TeyrchainSystem: cumulus_pallet_teyrchain_system::Config, AllPalletsWithoutSystem>
RuntimeHelper<TeyrchainSystem, AllPalletsWithoutSystem>
{
pub fn xcm_max_weight(from: XcmReceivedFrom) -> Weight {
match from {
XcmReceivedFrom::Parent => TeyrchainSystem::ReservedDmpWeight::get(),
XcmReceivedFrom::Sibling => TeyrchainSystem::ReservedXcmpWeight::get(),
}
}
pub fn xcm_max_weight_for_location(location: &Location) -> Weight {
Self::xcm_max_weight(if location == &Location::parent() {
XcmReceivedFrom::Parent
} else {
XcmReceivedFrom::Sibling
})
}
}
impl<Runtime: pezframe_system::Config + pezpallet_xcm::Config, AllPalletsWithoutSystem>
RuntimeHelper<Runtime, AllPalletsWithoutSystem>
{
pub fn assert_pallet_xcm_event_outcome(
unwrap_pallet_xcm_event: &Box<dyn Fn(Vec<u8>) -> Option<pezpallet_xcm::Event<Runtime>>>,
assert_outcome: fn(Outcome),
) {
assert_outcome(Self::get_pallet_xcm_event_outcome(unwrap_pallet_xcm_event));
}
pub fn get_pallet_xcm_event_outcome(
unwrap_pallet_xcm_event: &Box<dyn Fn(Vec<u8>) -> Option<pezpallet_xcm::Event<Runtime>>>,
) -> Outcome {
<pezframe_system::Pallet<Runtime>>::events()
.into_iter()
.filter_map(|e| unwrap_pallet_xcm_event(e.event.encode()))
.find_map(|e| match e {
pezpallet_xcm::Event::Attempted { outcome } => Some(outcome),
_ => None,
})
.expect("No `pezpallet_xcm::Event::Attempted(outcome)` event found!")
}
}
impl<
Runtime: pezframe_system::Config + cumulus_pallet_xcmp_queue::Config,
AllPalletsWithoutSystem,
> RuntimeHelper<Runtime, AllPalletsWithoutSystem>
{
pub fn xcmp_queue_message_sent(
unwrap_xcmp_queue_event: Box<
dyn Fn(Vec<u8>) -> Option<cumulus_pallet_xcmp_queue::Event<Runtime>>,
>,
) -> Option<XcmHash> {
<pezframe_system::Pallet<Runtime>>::events()
.into_iter()
.filter_map(|e| unwrap_xcmp_queue_event(e.event.encode()))
.find_map(|e| match e {
cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { message_hash } =>
Some(message_hash),
_ => None,
})
}
}
pub fn assert_metadata<Fungibles, AccountId>(
asset_id: impl Into<Fungibles::AssetId> + Clone,
expected_name: &str,
expected_symbol: &str,
expected_decimals: u8,
) where
Fungibles: pezframe_support::traits::fungibles::metadata::Inspect<AccountId>
+ pezframe_support::traits::fungibles::Inspect<AccountId>,
{
assert_eq!(Fungibles::name(asset_id.clone().into()), Vec::from(expected_name),);
assert_eq!(Fungibles::symbol(asset_id.clone().into()), Vec::from(expected_symbol),);
assert_eq!(Fungibles::decimals(asset_id.into()), expected_decimals);
}
pub fn assert_total<Fungibles, AccountId>(
asset_id: impl Into<Fungibles::AssetId> + Clone,
expected_total_issuance: impl Into<Fungibles::Balance>,
expected_active_issuance: impl Into<Fungibles::Balance>,
) where
Fungibles: pezframe_support::traits::fungibles::metadata::Inspect<AccountId>
+ pezframe_support::traits::fungibles::Inspect<AccountId>,
{
assert_eq!(Fungibles::total_issuance(asset_id.clone().into()), expected_total_issuance.into());
assert_eq!(Fungibles::active_issuance(asset_id.into()), expected_active_issuance.into());
}
/// Helper function which emulates opening HRMP channel which is needed for `XcmpQueue` to pass.
///
/// Calls teyrchain-system's `create_inherent` in case the channel hasn't been opened before, and
/// thus requires additional parameters for validating it: latest included teyrchain head and
/// teyrchain AuRa-slot.
///
/// AuRa consensus hook expects pallets to be initialized, before calling this function make sure to
/// `run_to_block` at least once.
pub fn mock_open_hrmp_channel<
C: cumulus_pallet_teyrchain_system::Config,
T: ProvideInherent<Call = cumulus_pallet_teyrchain_system::Call<C>>,
>(
sender: ParaId,
recipient: ParaId,
included_head: HeaderFor<C>,
mut slot_digest: &[u8],
slot_durations: &SlotDurations,
) {
let slot = Slot::decode(&mut slot_digest).expect("failed to decode digest");
// Convert para slot to relay chain.
let timestamp = slot.saturating_mul(slot_durations.para.as_millis());
let relay_slot = Slot::from_timestamp(timestamp.into(), slot_durations.relay);
let n = 1_u32;
let mut sproof_builder = RelayStateSproofBuilder {
para_id: sender,
included_para_head: Some(HeadData(included_head.encode())),
hrmp_egress_channel_index: Some(vec![recipient]),
current_slot: relay_slot,
..Default::default()
};
sproof_builder.hrmp_channels.insert(
HrmpChannelId { sender, recipient },
AbridgedHrmpChannel {
max_capacity: 10,
max_total_size: 10_000_000_u32,
max_message_size: 10_000_000_u32,
msg_count: 0,
total_size: 0_u32,
mqc_head: None,
},
);
let (relay_parent_storage_root, relay_chain_state) = sproof_builder.into_state_root_and_proof();
let vfp = PersistedValidationData {
relay_parent_number: n as RelayChainBlockNumber,
relay_parent_storage_root,
..Default::default()
};
// It is insufficient to push the validation function params
// to storage; they must also be included in the inherent data.
let inherent_data = {
let mut inherent_data = InherentData::default();
let system_inherent_data = TeyrchainInherentData {
validation_data: vfp,
relay_chain_state,
downward_messages: Default::default(),
horizontal_messages: Default::default(),
relay_parent_descendants: Default::default(),
collator_peer_id: None,
};
inherent_data
.put_data(
cumulus_primitives_teyrchain_inherent::INHERENT_IDENTIFIER,
&system_inherent_data,
)
.expect("failed to put VFP inherent");
inherent_data
};
// execute the block
T::create_inherent(&inherent_data)
.expect("got an inherent")
.dispatch_bypass_filter(RawOrigin::None.into())
.expect("dispatch succeeded");
}
impl<HrmpChannelSource: cumulus_primitives_core::XcmpMessageSource, AllPalletsWithoutSystem>
RuntimeHelper<HrmpChannelSource, AllPalletsWithoutSystem>
{
pub fn take_xcm(sent_to_para_id: ParaId) -> Option<VersionedXcm<()>> {
match HrmpChannelSource::take_outbound_messages(10)[..] {
[(para_id, ref mut xcm_message_data)] if para_id.eq(&sent_to_para_id.into()) => {
let mut xcm_message_data = &xcm_message_data[..];
// decode
let _ = XcmpMessageFormat::decode(&mut xcm_message_data).expect("valid format");
VersionedXcm::<()>::decode_with_depth_limit(
MAX_XCM_DECODE_DEPTH,
&mut xcm_message_data,
)
.map(|x| Some(x))
.expect("result with xcm")
},
_ => return None,
}
}
}
@@ -0,0 +1,253 @@
// 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.
//! Module contains predefined test-case scenarios for `Runtime` with common functionality.
use crate::{
AccountIdOf, BasicTeyrchainRuntime, CollatorSessionKeys, ExtBuilder, GovernanceOrigin,
RuntimeCallOf, RuntimeOriginOf, ValidatorIdOf,
};
use codec::Encode;
use pezframe_support::{
assert_ok,
traits::{Get, OriginTrait},
weights::WeightToFee as WeightToFeeT,
};
use pezsp_runtime::{
traits::{Block as BlockT, SaturatedConversion, StaticLookup},
DispatchError, Either,
};
use teyrchains_common::AccountId;
use xcm::prelude::InstructionError;
use xcm_runtime_apis::fees::{
runtime_decl_for_xcm_payment_api::XcmPaymentApiV2, Error as XcmPaymentApiError,
};
type RuntimeHelper<Runtime, AllPalletsWithoutSystem = ()> =
crate::RuntimeHelper<Runtime, AllPalletsWithoutSystem>;
/// Test-case makes sure that `Runtime` can change storage constant via governance-like call
pub fn change_storage_constant_by_governance_works<Runtime, StorageConstant, StorageConstantType>(
collator_session_key: CollatorSessionKeys<Runtime>,
runtime_para_id: u32,
governance_origin: GovernanceOrigin<RuntimeOriginOf<Runtime>>,
storage_constant_key_value: fn() -> (Vec<u8>, StorageConstantType),
new_storage_constant_value: fn(&StorageConstantType) -> StorageConstantType,
) where
Runtime: pezframe_system::Config
+ pezpallet_balances::Config
+ pezpallet_session::Config
+ pezpallet_xcm::Config
+ teyrchain_info::Config
+ pezpallet_collator_selection::Config
+ cumulus_pallet_teyrchain_system::Config
+ pezpallet_timestamp::Config,
ValidatorIdOf<Runtime>: From<AccountIdOf<Runtime>>,
StorageConstant: Get<StorageConstantType>,
StorageConstantType: Encode + PartialEq + std::fmt::Debug,
{
ExtBuilder::<Runtime>::default()
.with_collators(collator_session_key.collators())
.with_session_keys(collator_session_key.session_keys())
.with_para_id(runtime_para_id.into())
.with_tracing()
.build()
.execute_with(|| {
let (storage_constant_key, storage_constant_init_value): (
Vec<u8>,
StorageConstantType,
) = storage_constant_key_value();
// check delivery reward constant before (not stored yet, just as default value is used)
assert_eq!(StorageConstant::get(), storage_constant_init_value);
assert_eq!(pezsp_io::storage::get(&storage_constant_key), None);
let new_storage_constant_value =
new_storage_constant_value(&storage_constant_init_value);
assert_ne!(new_storage_constant_value, storage_constant_init_value);
// encode `set_storage` call
let set_storage_call =
RuntimeCallOf::<Runtime>::from(pezframe_system::Call::<Runtime>::set_storage {
items: vec![(
storage_constant_key.clone(),
new_storage_constant_value.encode(),
)],
});
// execute XCM with Transact to `set_storage` as governance does
assert_ok!(RuntimeHelper::<Runtime>::execute_as_governance_call(
set_storage_call,
governance_origin
));
// check delivery reward constant after (stored)
assert_eq!(StorageConstant::get(), new_storage_constant_value);
assert_eq!(
pezsp_io::storage::get(&storage_constant_key),
Some(new_storage_constant_value.encode().into())
);
})
}
/// Test-case makes sure that `Runtime` can change storage constant via governance-like call
pub fn set_storage_keys_by_governance_works<Runtime>(
collator_session_key: CollatorSessionKeys<Runtime>,
runtime_para_id: u32,
governance_origin: GovernanceOrigin<RuntimeOriginOf<Runtime>>,
storage_items: Vec<(Vec<u8>, Vec<u8>)>,
initialize_storage: impl FnOnce() -> (),
assert_storage: impl FnOnce() -> (),
) where
Runtime: pezframe_system::Config
+ pezpallet_balances::Config
+ pezpallet_session::Config
+ pezpallet_xcm::Config
+ teyrchain_info::Config
+ pezpallet_collator_selection::Config
+ cumulus_pallet_teyrchain_system::Config
+ pezpallet_timestamp::Config,
ValidatorIdOf<Runtime>: From<AccountIdOf<Runtime>>,
{
let mut runtime = ExtBuilder::<Runtime>::default()
.with_collators(collator_session_key.collators())
.with_session_keys(collator_session_key.session_keys())
.with_para_id(runtime_para_id.into())
.with_tracing()
.build();
runtime.execute_with(|| {
initialize_storage();
});
runtime.execute_with(|| {
// encode `kill_storage` call
let kill_storage_call =
RuntimeCallOf::<Runtime>::from(pezframe_system::Call::<Runtime>::set_storage {
items: storage_items.clone(),
});
// execute XCM with Transact to `set_storage` as governance does
assert_ok!(RuntimeHelper::<Runtime>::execute_as_governance_call(
kill_storage_call,
governance_origin
));
});
runtime.execute_with(|| {
assert_storage();
});
}
pub fn xcm_payment_api_with_native_token_works<
Runtime,
RuntimeCall,
RuntimeOrigin,
Block,
WeightToFee,
>()
where
Runtime: XcmPaymentApiV2<Block>
+ pezframe_system::Config<RuntimeOrigin = RuntimeOrigin, AccountId = AccountId>
+ pezpallet_balances::Config<Balance = u128>
+ pezpallet_session::Config
+ pezpallet_xcm::Config
+ teyrchain_info::Config
+ pezpallet_collator_selection::Config
+ cumulus_pallet_teyrchain_system::Config
+ cumulus_pallet_xcmp_queue::Config
+ pezpallet_timestamp::Config,
ValidatorIdOf<Runtime>: From<AccountIdOf<Runtime>>,
RuntimeOrigin: OriginTrait<AccountId = <Runtime as pezframe_system::Config>::AccountId>,
<<Runtime as pezframe_system::Config>::Lookup as StaticLookup>::Source:
From<<Runtime as pezframe_system::Config>::AccountId>,
Block: BlockT,
WeightToFee: WeightToFeeT,
{
use xcm::prelude::*;
ExtBuilder::<Runtime>::default().build().execute_with(|| {
let transfer_amount = 100u128;
let xcm_to_weigh = Xcm::<RuntimeCall>::builder_unsafe()
.withdraw_asset((Here, transfer_amount))
.buy_execution((Here, transfer_amount), Unlimited)
.deposit_asset(AllCounted(1), [1u8; 32])
.build();
let versioned_xcm_to_weigh = VersionedXcm::from(xcm_to_weigh.clone().into());
// We first try calling it with a lower XCM version.
let lower_version_xcm_to_weigh =
versioned_xcm_to_weigh.clone().into_version(XCM_VERSION - 1).unwrap();
let xcm_weight = Runtime::query_xcm_weight(lower_version_xcm_to_weigh)
.expect("xcm weight must be computed");
let expected_weight_fee: u128 = WeightToFee::weight_to_fee(&xcm_weight).saturated_into();
let native_token: Location = Parent.into();
let native_token_versioned = VersionedAssetId::from(AssetId(native_token));
let lower_version_native_token =
native_token_versioned.clone().into_version(XCM_VERSION - 1).unwrap();
let execution_fees =
Runtime::query_weight_to_asset_fee(xcm_weight, lower_version_native_token)
.expect("weight must be converted to native fee");
assert_eq!(execution_fees, expected_weight_fee);
// Now we call it with the latest version.
let xcm_weight =
Runtime::query_xcm_weight(versioned_xcm_to_weigh).expect("xcm weight must be computed");
let expected_weight_fee: u128 = WeightToFee::weight_to_fee(&xcm_weight).saturated_into();
let execution_fees = Runtime::query_weight_to_asset_fee(xcm_weight, native_token_versioned)
.expect("weight must be converted to native fee");
assert_eq!(execution_fees, expected_weight_fee);
// If we call it with anything other than the native token it will error.
let non_existent_token: Location = Here.into();
let non_existent_token_versioned = VersionedAssetId::from(AssetId(non_existent_token));
let execution_fees =
Runtime::query_weight_to_asset_fee(xcm_weight, non_existent_token_versioned);
assert_eq!(execution_fees, Err(XcmPaymentApiError::AssetNotFound));
});
}
/// Generic test case for Pezcumulus-based teyrchain that verifies if runtime can process
/// `pezframe_system::Call::authorize_upgrade` from governance system.
pub fn can_governance_authorize_upgrade<Runtime, RuntimeOrigin>(
governance_origin: GovernanceOrigin<RuntimeOrigin>,
) -> Result<(), Either<DispatchError, InstructionError>>
where
Runtime: BasicTeyrchainRuntime
+ pezframe_system::Config<RuntimeOrigin = RuntimeOrigin, AccountId = AccountId>,
{
ExtBuilder::<Runtime>::default().build().execute_with(|| {
// check before
assert!(pezframe_system::Pallet::<Runtime>::authorized_upgrade().is_none());
// execute call as governance does
let code_hash = Runtime::Hash::default();
let authorize_upgrade_call: <Runtime as pezframe_system::Config>::RuntimeCall =
pezframe_system::Call::<Runtime>::authorize_upgrade { code_hash }.into();
RuntimeHelper::<Runtime>::execute_as_governance_call(
authorize_upgrade_call,
governance_origin,
)?;
// check after
match pezframe_system::Pallet::<Runtime>::authorized_upgrade() {
None => Err(Either::Left(pezframe_system::Error::<Runtime>::NothingAuthorized.into())),
Some(_) => Ok(()),
}
})
}