Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 1 addition & 141 deletions examples/src/simple_test_net/asset_hub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

//! Asset hub parachain runtime mock.

use super::{Balance, ForeignChainAliasAccount, UNITS};
use super::{mock_msg_queue::pallet as mock_msg_queue, Balance, ForeignChainAliasAccount, UNITS};
use codec::{Decode, Encode};
use core::marker::PhantomData;
use frame_support::{
Expand Down Expand Up @@ -324,146 +324,6 @@ impl Config for XcmConfig {
type SafeCallFilter = Everything;
}

#[frame_support::pallet]
pub mod mock_msg_queue {
use super::*;
use frame_support::pallet_prelude::*;

#[pallet::config]
pub trait Config: frame_system::Config {
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
type XcmExecutor: ExecuteXcm<Self::RuntimeCall>;
}

#[pallet::call]
impl<T: Config> Pallet<T> {}

#[pallet::pallet]
#[pallet::without_storage_info]
pub struct Pallet<T>(_);

#[pallet::storage]
#[pallet::getter(fn parachain_id)]
pub(super) type ParachainId<T: Config> = StorageValue<_, ParaId, ValueQuery>;

#[pallet::storage]
#[pallet::getter(fn received_dmp)]
/// A queue of received DMP messages
pub(super) type ReceivedDmp<T: Config> = StorageValue<_, Vec<Xcm<T::RuntimeCall>>, ValueQuery>;

impl<T: Config> Get<ParaId> for Pallet<T> {
fn get() -> ParaId {
Self::parachain_id()
}
}

pub type MessageId = [u8; 32];

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
// XCMP
/// Some XCM was executed OK.
Success(Option<T::Hash>),
/// Some XCM failed.
Fail(Option<T::Hash>, XcmError),
/// Bad XCM version used.
BadVersion(Option<T::Hash>),
/// Bad XCM format used.
BadFormat(Option<T::Hash>),

// DMP
/// Downward message is invalid XCM.
InvalidFormat(MessageId),
/// Downward message is unsupported version of XCM.
UnsupportedVersion(MessageId),
/// Downward message executed with the given outcome.
ExecutedDownward(MessageId, Outcome),
}

impl<T: Config> Pallet<T> {
pub fn set_para_id(para_id: ParaId) {
ParachainId::<T>::put(para_id);
}

fn handle_xcmp_message(
sender: ParaId,
_sent_at: RelayBlockNumber,
xcm: VersionedXcm<T::RuntimeCall>,
max_weight: Weight,
) -> Result<Weight, XcmError> {
let hash = Encode::using_encoded(&xcm, T::Hashing::hash);
let message_hash = Encode::using_encoded(&xcm, sp_io::hashing::blake2_256);
let (result, event) = match Xcm::<T::RuntimeCall>::try_from(xcm) {
Ok(xcm) => {
let location = (Parent, Parachain(sender.into()));
match T::XcmExecutor::execute_xcm(location, xcm, message_hash, max_weight) {
Outcome::Error(e) => (Err(e.clone()), Event::Fail(Some(hash), e)),
Outcome::Complete(w) => (Ok(w), Event::Success(Some(hash))),
// As far as the caller is concerned, this was dispatched without error, so
// we just report the weight used.
Outcome::Incomplete(w, e) => (Ok(w), Event::Fail(Some(hash), e)),
}
},
Err(()) => (Err(XcmError::UnhandledXcmVersion), Event::BadVersion(Some(hash))),
};
Self::deposit_event(event);
result
}
}

impl<T: Config> XcmpMessageHandler for Pallet<T> {
fn handle_xcmp_messages<'a, I: Iterator<Item = (ParaId, RelayBlockNumber, &'a [u8])>>(
iter: I,
max_weight: Weight,
) -> Weight {
for (sender, sent_at, data) in iter {
let mut data_ref = data;
let _ = XcmpMessageFormat::decode(&mut data_ref)
.expect("Simulator encodes with versioned xcm format; qed");

let mut remaining_fragments = &data_ref[..];
while !remaining_fragments.is_empty() {
if let Ok(xcm) =
VersionedXcm::<T::RuntimeCall>::decode(&mut remaining_fragments)
{
let _ = Self::handle_xcmp_message(sender, sent_at, xcm, max_weight);
} else {
debug_assert!(false, "Invalid incoming XCMP message data");
}
}
}
max_weight
}
}

impl<T: Config> DmpMessageHandler for Pallet<T> {
fn handle_dmp_messages(
iter: impl Iterator<Item = (RelayBlockNumber, Vec<u8>)>,
limit: Weight,
) -> Weight {
for (_i, (_sent_at, data)) in iter.enumerate() {
let id = sp_io::hashing::blake2_256(&data[..]);
let maybe_versioned = VersionedXcm::<T::RuntimeCall>::decode(&mut &data[..]);
match maybe_versioned {
Err(_) => {
Self::deposit_event(Event::InvalidFormat(id));
},
Ok(versioned) => match Xcm::try_from(versioned) {
Err(()) => Self::deposit_event(Event::UnsupportedVersion(id)),
Ok(x) => {
let outcome = T::XcmExecutor::execute_xcm(Parent, x.clone(), id, limit);
<ReceivedDmp<T>>::append(x);
Self::deposit_event(Event::ExecutedDownward(id, outcome));
},
},
}
}
limit
}
}
}

impl mock_msg_queue::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type XcmExecutor = XcmExecutor<XcmConfig>;
Expand Down
172 changes: 172 additions & 0 deletions examples/src/simple_test_net/mock_msg_queue.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
// Copyright Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot 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.

// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.

//! Parachain runtime mock.

use codec::{Decode, Encode};

use frame_support::weights::Weight;
use polkadot_parachain::primitives::{
DmpMessageHandler, Id as ParaId, XcmpMessageFormat, XcmpMessageHandler,
};
use polkadot_primitives::BlockNumber as RelayBlockNumber;
use sp_runtime::traits::{Get, Hash};

use sp_std::prelude::*;
use xcm::{latest::prelude::*, VersionedXcm};

#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_support::pallet_prelude::*;

#[pallet::config]
pub trait Config: frame_system::Config {
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
type XcmExecutor: ExecuteXcm<Self::RuntimeCall>;
}

#[pallet::call]
impl<T: Config> Pallet<T> {}

#[pallet::pallet]
#[pallet::without_storage_info]
pub struct Pallet<T>(_);

#[pallet::storage]
#[pallet::getter(fn parachain_id)]
pub(super) type ParachainId<T: Config> = StorageValue<_, ParaId, ValueQuery>;

#[pallet::storage]
#[pallet::getter(fn received_dmp)]
/// A queue of received DMP messages
pub(super) type ReceivedDmp<T: Config> = StorageValue<_, Vec<Xcm<T::RuntimeCall>>, ValueQuery>;

impl<T: Config> Get<ParaId> for Pallet<T> {
fn get() -> ParaId {
Self::parachain_id()
}
}

pub type MessageId = [u8; 32];

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
// XCMP
/// Some XCM was executed OK.
Success(Option<T::Hash>),
/// Some XCM failed.
Fail(Option<T::Hash>, XcmError),
/// Bad XCM version used.
BadVersion(Option<T::Hash>),
/// Bad XCM format used.
BadFormat(Option<T::Hash>),

// DMP
/// Downward message is invalid XCM.
InvalidFormat(MessageId),
/// Downward message is unsupported version of XCM.
UnsupportedVersion(MessageId),
/// Downward message executed with the given outcome.
ExecutedDownward(MessageId, Outcome),
}

impl<T: Config> Pallet<T> {
pub fn set_para_id(para_id: ParaId) {
ParachainId::<T>::put(para_id);
}

fn handle_xcmp_message(
sender: ParaId,
_sent_at: RelayBlockNumber,
xcm: VersionedXcm<T::RuntimeCall>,
max_weight: Weight,
) -> Result<Weight, XcmError> {
let hash = Encode::using_encoded(&xcm, T::Hashing::hash);
let message_hash = Encode::using_encoded(&xcm, sp_io::hashing::blake2_256);
let (result, event) = match Xcm::<T::RuntimeCall>::try_from(xcm) {
Ok(xcm) => {
let location = (Parent, Parachain(sender.into()));
match T::XcmExecutor::execute_xcm(location, xcm, message_hash, max_weight) {
Outcome::Error(e) => (Err(e.clone()), Event::Fail(Some(hash), e)),
Outcome::Complete(w) => (Ok(w), Event::Success(Some(hash))),
// As far as the caller is concerned, this was dispatched without error, so
// we just report the weight used.
Outcome::Incomplete(w, e) => (Ok(w), Event::Fail(Some(hash), e)),
}
}
Err(()) => (
Err(XcmError::UnhandledXcmVersion),
Event::BadVersion(Some(hash)),
),
};
Self::deposit_event(event);
result
}
}

impl<T: Config> XcmpMessageHandler for Pallet<T> {
fn handle_xcmp_messages<'a, I: Iterator<Item = (ParaId, RelayBlockNumber, &'a [u8])>>(
iter: I,
max_weight: Weight,
) -> Weight {
for (sender, sent_at, data) in iter {
let mut data_ref = data;
let _ = XcmpMessageFormat::decode(&mut data_ref)
.expect("Simulator encodes with versioned xcm format; qed");

let mut remaining_fragments = &data_ref[..];
while !remaining_fragments.is_empty() {
if let Ok(xcm) =
VersionedXcm::<T::RuntimeCall>::decode(&mut remaining_fragments)
{
let _ = Self::handle_xcmp_message(sender, sent_at, xcm, max_weight);
} else {
debug_assert!(false, "Invalid incoming XCMP message data");
}
}
}
max_weight
}
}

impl<T: Config> DmpMessageHandler for Pallet<T> {
fn handle_dmp_messages(
iter: impl Iterator<Item = (RelayBlockNumber, Vec<u8>)>,
limit: Weight,
) -> Weight {
for (_i, (_sent_at, data)) in iter.enumerate() {
let id = sp_io::hashing::blake2_256(&data[..]);
let maybe_versioned = VersionedXcm::<T::RuntimeCall>::decode(&mut &data[..]);
match maybe_versioned {
Err(_) => {
Self::deposit_event(Event::InvalidFormat(id));
}
Ok(versioned) => match Xcm::try_from(versioned) {
Err(()) => Self::deposit_event(Event::UnsupportedVersion(id)),
Ok(x) => {
let outcome = T::XcmExecutor::execute_xcm(Parent, x.clone(), id, limit);
<ReceivedDmp<T>>::append(x);
Self::deposit_event(Event::ExecutedDownward(id, outcome));
}
},
}
}
limit
}
}
}
28 changes: 16 additions & 12 deletions examples/src/simple_test_net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
#![allow(dead_code)]
pub mod mock_msg_queue;
pub mod parachain;
pub mod relay_chain;

Expand Down Expand Up @@ -138,17 +139,21 @@ pub fn para_ext(para_id: u32) -> sp_io::TestExternalities {
};

pallet_balances::GenesisConfig::<Runtime> {
balances: vec![(ALICE, INITIAL_BALANCE), (relay_sovereign_account_id(), INITIAL_BALANCE), (BOB, INITIAL_BALANCE)]
.into_iter()
.chain(other_para_ids.iter().map(
// Initial balance of native token for ALICE on all sibling sovereign accounts
|&para_id| (sibling_account_sovereign_account_id(para_id, ALICE), INITIAL_BALANCE),
))
.chain(other_para_ids.iter().map(
// Initial balance of native token all sibling sovereign accounts
|&para_id| (sibling_sovereign_account_id(para_id), INITIAL_BALANCE),
))
.collect(),
balances: vec![
(ALICE, INITIAL_BALANCE),
(relay_sovereign_account_id(), INITIAL_BALANCE),
(BOB, INITIAL_BALANCE),
]
.into_iter()
.chain(other_para_ids.iter().map(
// Initial balance of native token for ALICE on all sibling sovereign accounts
|&para_id| (sibling_account_sovereign_account_id(para_id, ALICE), INITIAL_BALANCE),
))
.chain(other_para_ids.iter().map(
// Initial balance of native token all sibling sovereign accounts
|&para_id| (sibling_sovereign_account_id(para_id), INITIAL_BALANCE),
))
.collect(),
}
.assimilate_storage(&mut t)
.unwrap();
Expand Down Expand Up @@ -180,7 +185,6 @@ pub fn para_ext(para_id: u32) -> sp_io::TestExternalities {
.assimilate_storage(&mut t)
.unwrap();


let mut ext = sp_io::TestExternalities::new(t);
ext.execute_with(|| {
sp_tracing::try_init_simple();
Expand Down
Loading