1use core::marker::PhantomData;
17
18use codec::{Decode, DecodeLimit};
19use cumulus_primitives_core::{
20 relay_chain::Slot, AbridgedHrmpChannel, ParaId, PersistedValidationData,
21};
22use cumulus_primitives_parachain_inherent::ParachainInherentData;
23use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder;
24use frame_support::{
25 dispatch::{DispatchResult, GetDispatchInfo, RawOrigin},
26 inherent::{InherentData, ProvideInherent},
27 pallet_prelude::Get,
28 traits::{OnFinalize, OnInitialize, OriginTrait, UnfilteredDispatchable},
29 weights::Weight,
30};
31use frame_system::pallet_prelude::{BlockNumberFor, HeaderFor};
32use polkadot_parachain_primitives::primitives::{
33 HeadData, HrmpChannelId, RelayChainBlockNumber, XcmpMessageFormat,
34};
35use sp_consensus_aura::{SlotDuration, AURA_ENGINE_ID};
36use sp_core::{Encode, U256};
37use sp_runtime::{
38 traits::{Dispatchable, Header},
39 BuildStorage, Digest, DigestItem, DispatchError, Either, SaturatedConversion,
40};
41use xcm::{
42 latest::{Asset, Location, XcmContext, XcmHash},
43 prelude::*,
44 VersionedXcm, MAX_XCM_DECODE_DEPTH,
45};
46use xcm_executor::{traits::TransactAsset, AssetsInHolding};
47
48pub mod test_cases;
49
50pub type BalanceOf<Runtime> = <Runtime as pallet_balances::Config>::Balance;
51pub type AccountIdOf<Runtime> = <Runtime as frame_system::Config>::AccountId;
52pub type RuntimeCallOf<Runtime> = <Runtime as frame_system::Config>::RuntimeCall;
53pub type RuntimeOriginOf<Runtime> = <Runtime as frame_system::Config>::RuntimeOrigin;
54pub type ValidatorIdOf<Runtime> = <Runtime as pallet_session::Config>::ValidatorId;
55pub type SessionKeysOf<Runtime> = <Runtime as pallet_session::Config>::Keys;
56
57pub struct CollatorSessionKey<
58 Runtime: frame_system::Config + pallet_balances::Config + pallet_session::Config,
59> {
60 collator: AccountIdOf<Runtime>,
61 validator: ValidatorIdOf<Runtime>,
62 key: SessionKeysOf<Runtime>,
63}
64
65pub struct CollatorSessionKeys<
66 Runtime: frame_system::Config + pallet_balances::Config + pallet_session::Config,
67> {
68 items: Vec<CollatorSessionKey<Runtime>>,
69}
70
71impl<Runtime: frame_system::Config + pallet_balances::Config + pallet_session::Config>
72 CollatorSessionKey<Runtime>
73{
74 pub fn new(
75 collator: AccountIdOf<Runtime>,
76 validator: ValidatorIdOf<Runtime>,
77 key: SessionKeysOf<Runtime>,
78 ) -> Self {
79 Self { collator, validator, key }
80 }
81}
82
83impl<Runtime: frame_system::Config + pallet_balances::Config + pallet_session::Config> Default
84 for CollatorSessionKeys<Runtime>
85{
86 fn default() -> Self {
87 Self { items: vec![] }
88 }
89}
90
91impl<Runtime: frame_system::Config + pallet_balances::Config + pallet_session::Config>
92 CollatorSessionKeys<Runtime>
93{
94 pub fn new(
95 collator: AccountIdOf<Runtime>,
96 validator: ValidatorIdOf<Runtime>,
97 key: SessionKeysOf<Runtime>,
98 ) -> Self {
99 Self { items: vec![CollatorSessionKey::new(collator, validator, key)] }
100 }
101
102 pub fn add(mut self, item: CollatorSessionKey<Runtime>) -> Self {
103 self.items.push(item);
104 self
105 }
106
107 pub fn collators(&self) -> Vec<AccountIdOf<Runtime>> {
108 self.items.iter().map(|item| item.collator.clone()).collect::<Vec<_>>()
109 }
110
111 pub fn session_keys(
112 &self,
113 ) -> Vec<(AccountIdOf<Runtime>, ValidatorIdOf<Runtime>, SessionKeysOf<Runtime>)> {
114 self.items
115 .iter()
116 .map(|item| (item.collator.clone(), item.validator.clone(), item.key.clone()))
117 .collect::<Vec<_>>()
118 }
119}
120
121pub struct SlotDurations {
122 pub relay: SlotDuration,
123 pub para: SlotDuration,
124}
125
126pub trait BasicParachainRuntime:
129 frame_system::Config
130 + pallet_balances::Config
131 + pallet_session::Config
132 + pallet_xcm::Config
133 + parachain_info::Config
134 + pallet_collator_selection::Config
135 + cumulus_pallet_parachain_system::Config
136 + pallet_timestamp::Config
137{
138}
139
140impl<T> BasicParachainRuntime for T
141where
142 T: frame_system::Config
143 + pallet_balances::Config
144 + pallet_session::Config
145 + pallet_xcm::Config
146 + parachain_info::Config
147 + pallet_collator_selection::Config
148 + cumulus_pallet_parachain_system::Config
149 + pallet_timestamp::Config,
150 ValidatorIdOf<T>: From<AccountIdOf<T>>,
151{
152}
153
154pub struct ExtBuilder<Runtime: BasicParachainRuntime> {
156 balances: Vec<(AccountIdOf<Runtime>, BalanceOf<Runtime>)>,
158 collators: Vec<AccountIdOf<Runtime>>,
160 keys: Vec<(AccountIdOf<Runtime>, ValidatorIdOf<Runtime>, SessionKeysOf<Runtime>)>,
162 safe_xcm_version: Option<XcmVersion>,
164 para_id: Option<ParaId>,
166 _runtime: PhantomData<Runtime>,
167}
168
169impl<Runtime: BasicParachainRuntime> Default for ExtBuilder<Runtime> {
170 fn default() -> ExtBuilder<Runtime> {
171 ExtBuilder {
172 balances: vec![],
173 collators: vec![],
174 keys: vec![],
175 safe_xcm_version: None,
176 para_id: None,
177 _runtime: PhantomData,
178 }
179 }
180}
181
182impl<Runtime: BasicParachainRuntime> ExtBuilder<Runtime> {
183 pub fn with_balances(
184 mut self,
185 balances: Vec<(AccountIdOf<Runtime>, BalanceOf<Runtime>)>,
186 ) -> Self {
187 self.balances = balances;
188 self
189 }
190 pub fn with_collators(mut self, collators: Vec<AccountIdOf<Runtime>>) -> Self {
191 self.collators = collators;
192 self
193 }
194
195 pub fn with_session_keys(
196 mut self,
197 keys: Vec<(AccountIdOf<Runtime>, ValidatorIdOf<Runtime>, SessionKeysOf<Runtime>)>,
198 ) -> Self {
199 self.keys = keys;
200 self
201 }
202
203 pub fn with_tracing(self) -> Self {
204 sp_tracing::try_init_simple();
205 self
206 }
207
208 pub fn with_safe_xcm_version(mut self, safe_xcm_version: XcmVersion) -> Self {
209 self.safe_xcm_version = Some(safe_xcm_version);
210 self
211 }
212
213 pub fn with_para_id(mut self, para_id: ParaId) -> Self {
214 self.para_id = Some(para_id);
215 self
216 }
217
218 pub fn build(self) -> sp_io::TestExternalities {
219 let mut t = frame_system::GenesisConfig::<Runtime>::default().build_storage().unwrap();
220
221 pallet_xcm::GenesisConfig::<Runtime> {
222 safe_xcm_version: self.safe_xcm_version,
223 ..Default::default()
224 }
225 .assimilate_storage(&mut t)
226 .unwrap();
227
228 if let Some(para_id) = self.para_id {
229 parachain_info::GenesisConfig::<Runtime> {
230 parachain_id: para_id,
231 ..Default::default()
232 }
233 .assimilate_storage(&mut t)
234 .unwrap();
235 }
236
237 pallet_balances::GenesisConfig::<Runtime> { balances: self.balances, ..Default::default() }
238 .assimilate_storage(&mut t)
239 .unwrap();
240
241 pallet_collator_selection::GenesisConfig::<Runtime> {
242 invulnerables: self.collators.clone(),
243 candidacy_bond: Default::default(),
244 desired_candidates: Default::default(),
245 }
246 .assimilate_storage(&mut t)
247 .unwrap();
248
249 pallet_session::GenesisConfig::<Runtime> { keys: self.keys, ..Default::default() }
250 .assimilate_storage(&mut t)
251 .unwrap();
252
253 let mut ext = sp_io::TestExternalities::new(t);
254
255 ext.execute_with(|| {
256 frame_system::Pallet::<Runtime>::set_block_number(1u32.into());
257 });
258
259 ext
260 }
261}
262
263pub struct RuntimeHelper<Runtime, AllPalletsWithoutSystem>(
264 PhantomData<(Runtime, AllPalletsWithoutSystem)>,
265);
266impl<
269 Runtime: frame_system::Config + cumulus_pallet_parachain_system::Config + pallet_timestamp::Config,
270 AllPalletsWithoutSystem,
271 > RuntimeHelper<Runtime, AllPalletsWithoutSystem>
272where
273 AccountIdOf<Runtime>:
274 Into<<<Runtime as frame_system::Config>::RuntimeOrigin as OriginTrait>::AccountId>,
275 AllPalletsWithoutSystem:
276 OnInitialize<BlockNumberFor<Runtime>> + OnFinalize<BlockNumberFor<Runtime>>,
277{
278 pub fn run_to_block(n: u32, author: AccountIdOf<Runtime>) -> HeaderFor<Runtime> {
279 let mut last_header = None;
280 loop {
281 let block_number = frame_system::Pallet::<Runtime>::block_number();
282 if block_number >= n.into() {
283 break
284 }
285 let header = frame_system::Pallet::<Runtime>::finalize();
290
291 let pre_digest =
292 Digest { logs: vec![DigestItem::PreRuntime(AURA_ENGINE_ID, author.encode())] };
293 frame_system::Pallet::<Runtime>::reset_events();
294
295 let next_block_number = block_number + 1u32.into();
296 frame_system::Pallet::<Runtime>::initialize(
297 &next_block_number,
298 &header.hash(),
299 &pre_digest,
300 );
301 AllPalletsWithoutSystem::on_initialize(next_block_number);
302 last_header = Some(header);
303 }
304 last_header.expect("run_to_block empty block range")
305 }
306
307 pub fn run_to_block_with_finalize(n: u32) -> HeaderFor<Runtime> {
308 let mut last_header = None;
309 loop {
310 let block_number = frame_system::Pallet::<Runtime>::block_number();
311 if block_number >= n.into() {
312 break
313 }
314 let header = frame_system::Pallet::<Runtime>::finalize();
316
317 let pre_digest = Digest {
318 logs: vec![DigestItem::PreRuntime(AURA_ENGINE_ID, block_number.encode())],
319 };
320 frame_system::Pallet::<Runtime>::reset_events();
321
322 let next_block_number = block_number + 1u32.into();
323 frame_system::Pallet::<Runtime>::initialize(
324 &next_block_number,
325 &header.hash(),
326 &pre_digest,
327 );
328 AllPalletsWithoutSystem::on_initialize(next_block_number);
329
330 let parent_head = HeadData(header.encode());
331 let sproof_builder = RelayStateSproofBuilder {
332 para_id: <Runtime>::SelfParaId::get(),
333 included_para_head: parent_head.clone().into(),
334 ..Default::default()
335 };
336
337 let (relay_parent_storage_root, relay_chain_state) =
338 sproof_builder.into_state_root_and_proof();
339 let inherent_data = ParachainInherentData {
340 validation_data: PersistedValidationData {
341 parent_head,
342 relay_parent_number: (block_number.saturated_into::<u32>() * 2 + 1).into(),
343 relay_parent_storage_root,
344 max_pov_size: 100_000_000,
345 },
346 relay_chain_state,
347 downward_messages: Default::default(),
348 horizontal_messages: Default::default(),
349 };
350
351 let _ = cumulus_pallet_parachain_system::Pallet::<Runtime>::set_validation_data(
352 Runtime::RuntimeOrigin::none(),
353 inherent_data,
354 );
355 let _ = pallet_timestamp::Pallet::<Runtime>::set(
356 Runtime::RuntimeOrigin::none(),
357 300_u32.into(),
358 );
359 AllPalletsWithoutSystem::on_finalize(next_block_number);
360 let header = frame_system::Pallet::<Runtime>::finalize();
361 last_header = Some(header);
362 }
363 last_header.expect("run_to_block empty block range")
364 }
365
366 pub fn root_origin() -> <Runtime as frame_system::Config>::RuntimeOrigin {
367 <Runtime as frame_system::Config>::RuntimeOrigin::root()
368 }
369
370 pub fn block_number() -> U256 {
371 frame_system::Pallet::<Runtime>::block_number().into()
372 }
373
374 pub fn origin_of(
375 account_id: AccountIdOf<Runtime>,
376 ) -> <Runtime as frame_system::Config>::RuntimeOrigin {
377 <Runtime as frame_system::Config>::RuntimeOrigin::signed(account_id.into())
378 }
379}
380
381impl<XcmConfig: xcm_executor::Config, AllPalletsWithoutSystem>
382 RuntimeHelper<XcmConfig, AllPalletsWithoutSystem>
383{
384 pub fn do_transfer(
385 from: Location,
386 to: Location,
387 (asset, amount): (Location, u128),
388 ) -> Result<AssetsInHolding, XcmError> {
389 <XcmConfig::AssetTransactor as TransactAsset>::transfer_asset(
390 &Asset { id: AssetId(asset), fun: Fungible(amount) },
391 &from,
392 &to,
393 &XcmContext::with_message_id([0; 32]),
396 )
397 }
398}
399
400impl<
401 Runtime: pallet_xcm::Config + cumulus_pallet_parachain_system::Config,
402 AllPalletsWithoutSystem,
403 > RuntimeHelper<Runtime, AllPalletsWithoutSystem>
404{
405 pub fn do_teleport_assets<HrmpChannelOpener>(
406 origin: <Runtime as frame_system::Config>::RuntimeOrigin,
407 dest: Location,
408 beneficiary: Location,
409 (asset, amount): (Location, u128),
410 open_hrmp_channel: Option<(u32, u32)>,
411 included_head: HeaderFor<Runtime>,
412 slot_digest: &[u8],
413 slot_durations: &SlotDurations,
414 ) -> DispatchResult
415 where
416 HrmpChannelOpener: frame_support::inherent::ProvideInherent<
417 Call = cumulus_pallet_parachain_system::Call<Runtime>,
418 >,
419 {
420 if let Some((source_para_id, target_para_id)) = open_hrmp_channel {
422 mock_open_hrmp_channel::<Runtime, HrmpChannelOpener>(
423 source_para_id.into(),
424 target_para_id.into(),
425 included_head,
426 slot_digest,
427 slot_durations,
428 );
429 }
430
431 <pallet_xcm::Pallet<Runtime>>::limited_teleport_assets(
433 origin,
434 Box::new(dest.into()),
435 Box::new(beneficiary.into()),
436 Box::new((AssetId(asset), amount).into()),
437 0,
438 Unlimited,
439 )
440 }
441}
442
443impl<
444 Runtime: cumulus_pallet_parachain_system::Config + pallet_xcm::Config,
445 AllPalletsWithoutSystem,
446 > RuntimeHelper<Runtime, AllPalletsWithoutSystem>
447{
448 #[deprecated(
449 note = "Will be removed after Aug 2025; It uses hard-coded `Location::parent()`, \
450 use `execute_as_governance_call` instead."
451 )]
452 pub fn execute_as_governance(call: Vec<u8>) -> Outcome {
453 let xcm = Xcm(vec![
455 UnpaidExecution { weight_limit: Unlimited, check_origin: None },
456 Transact {
457 origin_kind: OriginKind::Superuser,
458 call: call.into(),
459 fallback_max_weight: None,
460 },
461 ExpectTransactStatus(MaybeErrorCode::Success),
462 ]);
463
464 let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256);
466 <<Runtime as pallet_xcm::Config>::XcmExecutor>::prepare_and_execute(
467 Location::parent(),
468 xcm,
469 &mut hash,
470 Self::xcm_max_weight(XcmReceivedFrom::Parent),
471 Weight::zero(),
472 )
473 }
474
475 pub fn execute_as_governance_call<Call: Dispatchable + Encode>(
476 call: Call,
477 governance_origin: GovernanceOrigin<Call::RuntimeOrigin>,
478 ) -> Result<(), Either<DispatchError, XcmError>> {
479 let execute_xcm = |call: Call, governance_location, descend_origin| {
481 let xcm = if let Some(descend_origin) = descend_origin {
483 Xcm::builder_unsafe().descend_origin(descend_origin)
484 } else {
485 Xcm::builder_unsafe()
486 }
487 .unpaid_execution(Unlimited, None)
488 .transact(OriginKind::Superuser, None, call.encode())
489 .expect_transact_status(MaybeErrorCode::Success)
490 .build();
491
492 let xcm_max_weight = Self::xcm_max_weight_for_location(&governance_location);
493 let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256);
494
495 <<Runtime as pallet_xcm::Config>::XcmExecutor>::prepare_and_execute(
496 governance_location,
497 xcm,
498 &mut hash,
499 xcm_max_weight,
500 Weight::zero(),
501 )
502 };
503
504 match governance_origin {
505 GovernanceOrigin::Location(location) =>
506 execute_xcm(call, location, None).ensure_complete().map_err(Either::Right),
507 GovernanceOrigin::LocationAndDescendOrigin(location, descend_origin) =>
508 execute_xcm(call, location, Some(descend_origin))
509 .ensure_complete()
510 .map_err(Either::Right),
511 GovernanceOrigin::Origin(origin) =>
512 call.dispatch(origin).map(|_| ()).map_err(|e| Either::Left(e.error)),
513 }
514 }
515
516 pub fn execute_as_origin<Call: GetDispatchInfo + Encode>(
517 (origin, origin_kind): (Location, OriginKind),
518 call: Call,
519 maybe_buy_execution_fee: Option<Asset>,
520 ) -> Outcome {
521 let mut instructions = if let Some(buy_execution_fee) = maybe_buy_execution_fee {
522 vec![
523 WithdrawAsset(buy_execution_fee.clone().into()),
524 BuyExecution { fees: buy_execution_fee.clone(), weight_limit: Unlimited },
525 ]
526 } else {
527 vec![UnpaidExecution { check_origin: None, weight_limit: Unlimited }]
528 };
529
530 instructions.extend(vec![
532 Transact { origin_kind, call: call.encode().into(), fallback_max_weight: None },
533 ExpectTransactStatus(MaybeErrorCode::Success),
534 ]);
535 let xcm = Xcm(instructions);
536 let xcm_max_weight = Self::xcm_max_weight_for_location(&origin);
537
538 let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256);
540 <<Runtime as pallet_xcm::Config>::XcmExecutor>::prepare_and_execute(
541 origin,
542 xcm,
543 &mut hash,
544 xcm_max_weight,
545 Weight::zero(),
546 )
547 }
548}
549
550#[derive(Clone)]
552pub enum GovernanceOrigin<RuntimeOrigin> {
553 Location(Location),
554 LocationAndDescendOrigin(Location, InteriorLocation),
555 Origin(RuntimeOrigin),
556}
557
558pub enum XcmReceivedFrom {
559 Parent,
560 Sibling,
561}
562
563impl<ParachainSystem: cumulus_pallet_parachain_system::Config, AllPalletsWithoutSystem>
564 RuntimeHelper<ParachainSystem, AllPalletsWithoutSystem>
565{
566 pub fn xcm_max_weight(from: XcmReceivedFrom) -> Weight {
567 match from {
568 XcmReceivedFrom::Parent => ParachainSystem::ReservedDmpWeight::get(),
569 XcmReceivedFrom::Sibling => ParachainSystem::ReservedXcmpWeight::get(),
570 }
571 }
572
573 pub fn xcm_max_weight_for_location(location: &Location) -> Weight {
574 Self::xcm_max_weight(if location == &Location::parent() {
575 XcmReceivedFrom::Parent
576 } else {
577 XcmReceivedFrom::Sibling
578 })
579 }
580}
581
582impl<Runtime: frame_system::Config + pallet_xcm::Config, AllPalletsWithoutSystem>
583 RuntimeHelper<Runtime, AllPalletsWithoutSystem>
584{
585 pub fn assert_pallet_xcm_event_outcome(
586 unwrap_pallet_xcm_event: &Box<dyn Fn(Vec<u8>) -> Option<pallet_xcm::Event<Runtime>>>,
587 assert_outcome: fn(Outcome),
588 ) {
589 assert_outcome(Self::get_pallet_xcm_event_outcome(unwrap_pallet_xcm_event));
590 }
591
592 pub fn get_pallet_xcm_event_outcome(
593 unwrap_pallet_xcm_event: &Box<dyn Fn(Vec<u8>) -> Option<pallet_xcm::Event<Runtime>>>,
594 ) -> Outcome {
595 <frame_system::Pallet<Runtime>>::events()
596 .into_iter()
597 .filter_map(|e| unwrap_pallet_xcm_event(e.event.encode()))
598 .find_map(|e| match e {
599 pallet_xcm::Event::Attempted { outcome } => Some(outcome),
600 _ => None,
601 })
602 .expect("No `pallet_xcm::Event::Attempted(outcome)` event found!")
603 }
604}
605
606impl<
607 Runtime: frame_system::Config + cumulus_pallet_xcmp_queue::Config,
608 AllPalletsWithoutSystem,
609 > RuntimeHelper<Runtime, AllPalletsWithoutSystem>
610{
611 pub fn xcmp_queue_message_sent(
612 unwrap_xcmp_queue_event: Box<
613 dyn Fn(Vec<u8>) -> Option<cumulus_pallet_xcmp_queue::Event<Runtime>>,
614 >,
615 ) -> Option<XcmHash> {
616 <frame_system::Pallet<Runtime>>::events()
617 .into_iter()
618 .filter_map(|e| unwrap_xcmp_queue_event(e.event.encode()))
619 .find_map(|e| match e {
620 cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { message_hash } =>
621 Some(message_hash),
622 _ => None,
623 })
624 }
625}
626
627pub fn assert_metadata<Fungibles, AccountId>(
628 asset_id: impl Into<Fungibles::AssetId> + Clone,
629 expected_name: &str,
630 expected_symbol: &str,
631 expected_decimals: u8,
632) where
633 Fungibles: frame_support::traits::fungibles::metadata::Inspect<AccountId>
634 + frame_support::traits::fungibles::Inspect<AccountId>,
635{
636 assert_eq!(Fungibles::name(asset_id.clone().into()), Vec::from(expected_name),);
637 assert_eq!(Fungibles::symbol(asset_id.clone().into()), Vec::from(expected_symbol),);
638 assert_eq!(Fungibles::decimals(asset_id.into()), expected_decimals);
639}
640
641pub fn assert_total<Fungibles, AccountId>(
642 asset_id: impl Into<Fungibles::AssetId> + Clone,
643 expected_total_issuance: impl Into<Fungibles::Balance>,
644 expected_active_issuance: impl Into<Fungibles::Balance>,
645) where
646 Fungibles: frame_support::traits::fungibles::metadata::Inspect<AccountId>
647 + frame_support::traits::fungibles::Inspect<AccountId>,
648{
649 assert_eq!(Fungibles::total_issuance(asset_id.clone().into()), expected_total_issuance.into());
650 assert_eq!(Fungibles::active_issuance(asset_id.into()), expected_active_issuance.into());
651}
652
653pub fn mock_open_hrmp_channel<
662 C: cumulus_pallet_parachain_system::Config,
663 T: ProvideInherent<Call = cumulus_pallet_parachain_system::Call<C>>,
664>(
665 sender: ParaId,
666 recipient: ParaId,
667 included_head: HeaderFor<C>,
668 mut slot_digest: &[u8],
669 slot_durations: &SlotDurations,
670) {
671 let slot = Slot::decode(&mut slot_digest).expect("failed to decode digest");
672 let timestamp = slot.saturating_mul(slot_durations.para.as_millis());
674 let relay_slot = Slot::from_timestamp(timestamp.into(), slot_durations.relay);
675
676 let n = 1_u32;
677 let mut sproof_builder = RelayStateSproofBuilder {
678 para_id: sender,
679 included_para_head: Some(HeadData(included_head.encode())),
680 hrmp_egress_channel_index: Some(vec![recipient]),
681 current_slot: relay_slot,
682 ..Default::default()
683 };
684 sproof_builder.hrmp_channels.insert(
685 HrmpChannelId { sender, recipient },
686 AbridgedHrmpChannel {
687 max_capacity: 10,
688 max_total_size: 10_000_000_u32,
689 max_message_size: 10_000_000_u32,
690 msg_count: 0,
691 total_size: 0_u32,
692 mqc_head: None,
693 },
694 );
695
696 let (relay_parent_storage_root, relay_chain_state) = sproof_builder.into_state_root_and_proof();
697 let vfp = PersistedValidationData {
698 relay_parent_number: n as RelayChainBlockNumber,
699 relay_parent_storage_root,
700 ..Default::default()
701 };
702 let inherent_data = {
705 let mut inherent_data = InherentData::default();
706 let system_inherent_data = ParachainInherentData {
707 validation_data: vfp,
708 relay_chain_state,
709 downward_messages: Default::default(),
710 horizontal_messages: Default::default(),
711 };
712 inherent_data
713 .put_data(
714 cumulus_primitives_parachain_inherent::INHERENT_IDENTIFIER,
715 &system_inherent_data,
716 )
717 .expect("failed to put VFP inherent");
718 inherent_data
719 };
720
721 T::create_inherent(&inherent_data)
723 .expect("got an inherent")
724 .dispatch_bypass_filter(RawOrigin::None.into())
725 .expect("dispatch succeeded");
726}
727
728impl<HrmpChannelSource: cumulus_primitives_core::XcmpMessageSource, AllPalletsWithoutSystem>
729 RuntimeHelper<HrmpChannelSource, AllPalletsWithoutSystem>
730{
731 pub fn take_xcm(sent_to_para_id: ParaId) -> Option<VersionedXcm<()>> {
732 match HrmpChannelSource::take_outbound_messages(10)[..] {
733 [(para_id, ref mut xcm_message_data)] if para_id.eq(&sent_to_para_id.into()) => {
734 let mut xcm_message_data = &xcm_message_data[..];
735 let _ = XcmpMessageFormat::decode(&mut xcm_message_data).expect("valid format");
737 VersionedXcm::<()>::decode_with_depth_limit(
738 MAX_XCM_DECODE_DEPTH,
739 &mut xcm_message_data,
740 )
741 .map(|x| Some(x))
742 .expect("result with xcm")
743 },
744 _ => return None,
745 }
746 }
747}