pallet_contracts_mock_network/mocks/
msg_queue.rs
1use codec::{Decode, Encode};
20
21use frame_support::weights::Weight;
22use polkadot_parachain_primitives::primitives::{
23 DmpMessageHandler, Id as ParaId, XcmpMessageFormat, XcmpMessageHandler,
24};
25use polkadot_primitives::BlockNumber as RelayBlockNumber;
26use sp_runtime::traits::{Get, Hash};
27
28use xcm::{latest::prelude::*, VersionedXcm};
29
30#[frame_support::pallet]
31pub mod pallet {
32 use super::*;
33 use frame_support::pallet_prelude::*;
34
35 #[pallet::config]
36 pub trait Config: frame_system::Config {
37 #[allow(deprecated)]
38 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
39 type XcmExecutor: ExecuteXcm<Self::RuntimeCall>;
40 }
41
42 #[pallet::call]
43 impl<T: Config> Pallet<T> {}
44
45 #[pallet::pallet]
46 #[pallet::without_storage_info]
47 pub struct Pallet<T>(_);
48
49 #[pallet::storage]
50 pub(super) type ParachainId<T: Config> = StorageValue<_, ParaId, ValueQuery>;
51
52 #[pallet::storage]
53 pub(super) type ReceivedDmp<T: Config> = StorageValue<_, Vec<Xcm<T::RuntimeCall>>, ValueQuery>;
55
56 impl<T: Config> Get<ParaId> for Pallet<T> {
57 fn get() -> ParaId {
58 ParachainId::<T>::get()
59 }
60 }
61
62 pub type MessageId = [u8; 32];
63
64 #[pallet::event]
65 #[pallet::generate_deposit(pub(super) fn deposit_event)]
66 pub enum Event<T: Config> {
67 Success(Option<T::Hash>),
69 Fail(Option<T::Hash>, XcmError),
71 BadVersion(Option<T::Hash>),
73 BadFormat(Option<T::Hash>),
75
76 InvalidFormat(MessageId),
79 UnsupportedVersion(MessageId),
81 ExecutedDownward(MessageId, Outcome),
83 }
84
85 impl<T: Config> Pallet<T> {
86 pub fn set_para_id(para_id: ParaId) {
87 ParachainId::<T>::put(para_id);
88 }
89
90 pub fn parachain_id() -> ParaId {
91 ParachainId::<T>::get()
92 }
93
94 pub fn received_dmp() -> Vec<Xcm<T::RuntimeCall>> {
95 ReceivedDmp::<T>::get()
96 }
97
98 fn handle_xcmp_message(
99 sender: ParaId,
100 _sent_at: RelayBlockNumber,
101 xcm: VersionedXcm<T::RuntimeCall>,
102 max_weight: Weight,
103 ) -> Result<Weight, XcmError> {
104 let hash = Encode::using_encoded(&xcm, T::Hashing::hash);
105 let mut message_hash = Encode::using_encoded(&xcm, sp_io::hashing::blake2_256);
106 let (result, event) = match Xcm::<T::RuntimeCall>::try_from(xcm) {
107 Ok(xcm) => {
108 let location = (Parent, Parachain(sender.into()));
109 match T::XcmExecutor::prepare_and_execute(
110 location,
111 xcm,
112 &mut message_hash,
113 max_weight,
114 Weight::zero(),
115 ) {
116 Outcome::Error(InstructionError { error, .. }) =>
117 (Err(error), Event::Fail(Some(hash), error)),
118 Outcome::Complete { used } => (Ok(used), Event::Success(Some(hash))),
119 Outcome::Incomplete {
122 used, error: InstructionError { error, .. }, ..
123 } => (Ok(used), Event::Fail(Some(hash), error)),
124 }
125 },
126 Err(()) => (Err(XcmError::UnhandledXcmVersion), Event::BadVersion(Some(hash))),
127 };
128 Self::deposit_event(event);
129 result
130 }
131 }
132
133 impl<T: Config> XcmpMessageHandler for Pallet<T> {
134 fn handle_xcmp_messages<'a, I: Iterator<Item = (ParaId, RelayBlockNumber, &'a [u8])>>(
135 iter: I,
136 max_weight: Weight,
137 ) -> Weight {
138 for (sender, sent_at, data) in iter {
139 let mut data_ref = data;
140 let _ = XcmpMessageFormat::decode(&mut data_ref)
141 .expect("Simulator encodes with versioned xcm format; qed");
142
143 let mut remaining_fragments = data_ref;
144 while !remaining_fragments.is_empty() {
145 if let Ok(xcm) =
146 VersionedXcm::<T::RuntimeCall>::decode(&mut remaining_fragments)
147 {
148 let _ = Self::handle_xcmp_message(sender, sent_at, xcm, max_weight);
149 } else {
150 debug_assert!(false, "Invalid incoming XCMP message data");
151 }
152 }
153 }
154 max_weight
155 }
156 }
157
158 impl<T: Config> DmpMessageHandler for Pallet<T> {
159 fn handle_dmp_messages(
160 iter: impl Iterator<Item = (RelayBlockNumber, Vec<u8>)>,
161 limit: Weight,
162 ) -> Weight {
163 for (_i, (_sent_at, data)) in iter.enumerate() {
164 let mut id = sp_io::hashing::blake2_256(&data[..]);
165 let maybe_versioned = VersionedXcm::<T::RuntimeCall>::decode(&mut &data[..]);
166 match maybe_versioned {
167 Err(_) => {
168 Self::deposit_event(Event::InvalidFormat(id));
169 },
170 Ok(versioned) => match Xcm::try_from(versioned) {
171 Err(()) => Self::deposit_event(Event::UnsupportedVersion(id)),
172 Ok(x) => {
173 let outcome = T::XcmExecutor::prepare_and_execute(
174 Parent,
175 x.clone(),
176 &mut id,
177 limit,
178 Weight::zero(),
179 );
180 ReceivedDmp::<T>::append(x);
181 Self::deposit_event(Event::ExecutedDownward(id, outcome));
182 },
183 },
184 }
185 }
186 limit
187 }
188 }
189}