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 relay_parent_descendants: Default::default(),
350 collator_peer_id: None,
351 };
352
353 let _ = cumulus_pallet_parachain_system::Pallet::<Runtime>::set_validation_data(
354 Runtime::RuntimeOrigin::none(),
355 inherent_data,
356 );
357 let _ = pallet_timestamp::Pallet::<Runtime>::set(
358 Runtime::RuntimeOrigin::none(),
359 300_u32.into(),
360 );
361 AllPalletsWithoutSystem::on_finalize(next_block_number);
362 let header = frame_system::Pallet::<Runtime>::finalize();
363 last_header = Some(header);
364 }
365 last_header.expect("run_to_block empty block range")
366 }
367
368 pub fn root_origin() -> <Runtime as frame_system::Config>::RuntimeOrigin {
369 <Runtime as frame_system::Config>::RuntimeOrigin::root()
370 }
371
372 pub fn block_number() -> U256 {
373 frame_system::Pallet::<Runtime>::block_number().into()
374 }
375
376 pub fn origin_of(
377 account_id: AccountIdOf<Runtime>,
378 ) -> <Runtime as frame_system::Config>::RuntimeOrigin {
379 <Runtime as frame_system::Config>::RuntimeOrigin::signed(account_id.into())
380 }
381}
382
383impl<XcmConfig: xcm_executor::Config, AllPalletsWithoutSystem>
384 RuntimeHelper<XcmConfig, AllPalletsWithoutSystem>
385{
386 pub fn do_transfer(
387 from: Location,
388 to: Location,
389 (asset, amount): (Location, u128),
390 ) -> Result<AssetsInHolding, XcmError> {
391 <XcmConfig::AssetTransactor as TransactAsset>::transfer_asset(
392 &Asset { id: AssetId(asset), fun: Fungible(amount) },
393 &from,
394 &to,
395 &XcmContext::with_message_id([0; 32]),
398 )
399 }
400}
401
402impl<
403 Runtime: pallet_xcm::Config + cumulus_pallet_parachain_system::Config,
404 AllPalletsWithoutSystem,
405 > RuntimeHelper<Runtime, AllPalletsWithoutSystem>
406{
407 pub fn do_teleport_assets<HrmpChannelOpener>(
408 origin: <Runtime as frame_system::Config>::RuntimeOrigin,
409 dest: Location,
410 beneficiary: Location,
411 (asset, amount): (Location, u128),
412 open_hrmp_channel: Option<(u32, u32)>,
413 included_head: HeaderFor<Runtime>,
414 slot_digest: &[u8],
415 slot_durations: &SlotDurations,
416 ) -> DispatchResult
417 where
418 HrmpChannelOpener: frame_support::inherent::ProvideInherent<
419 Call = cumulus_pallet_parachain_system::Call<Runtime>,
420 >,
421 {
422 if let Some((source_para_id, target_para_id)) = open_hrmp_channel {
424 mock_open_hrmp_channel::<Runtime, HrmpChannelOpener>(
425 source_para_id.into(),
426 target_para_id.into(),
427 included_head,
428 slot_digest,
429 slot_durations,
430 );
431 }
432
433 <pallet_xcm::Pallet<Runtime>>::limited_teleport_assets(
435 origin,
436 Box::new(dest.into()),
437 Box::new(beneficiary.into()),
438 Box::new((AssetId(asset), amount).into()),
439 0,
440 Unlimited,
441 )
442 }
443}
444
445impl<
446 Runtime: cumulus_pallet_parachain_system::Config + pallet_xcm::Config,
447 AllPalletsWithoutSystem,
448 > RuntimeHelper<Runtime, AllPalletsWithoutSystem>
449{
450 #[deprecated(
451 note = "Will be removed after Aug 2025; It uses hard-coded `Location::parent()`, \
452 use `execute_as_governance_call` instead."
453 )]
454 pub fn execute_as_governance(call: Vec<u8>) -> Outcome {
455 let xcm = Xcm(vec![
457 UnpaidExecution { weight_limit: Unlimited, check_origin: None },
458 Transact {
459 origin_kind: OriginKind::Superuser,
460 call: call.into(),
461 fallback_max_weight: None,
462 },
463 ExpectTransactStatus(MaybeErrorCode::Success),
464 ]);
465
466 let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256);
468 <<Runtime as pallet_xcm::Config>::XcmExecutor>::prepare_and_execute(
469 Location::parent(),
470 xcm,
471 &mut hash,
472 Self::xcm_max_weight(XcmReceivedFrom::Parent),
473 Weight::zero(),
474 )
475 }
476
477 pub fn execute_as_governance_call<Call: Dispatchable + Encode>(
478 call: Call,
479 governance_origin: GovernanceOrigin<Call::RuntimeOrigin>,
480 ) -> Result<(), Either<DispatchError, InstructionError>> {
481 let execute_xcm = |call: Call, governance_location, descend_origin| {
483 let xcm = if let Some(descend_origin) = descend_origin {
485 Xcm::builder_unsafe().descend_origin(descend_origin)
486 } else {
487 Xcm::builder_unsafe()
488 }
489 .unpaid_execution(Unlimited, None)
490 .transact(OriginKind::Superuser, None, call.encode())
491 .expect_transact_status(MaybeErrorCode::Success)
492 .build();
493
494 let xcm_max_weight = Self::xcm_max_weight_for_location(&governance_location);
495 let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256);
496
497 <<Runtime as pallet_xcm::Config>::XcmExecutor>::prepare_and_execute(
498 governance_location,
499 xcm,
500 &mut hash,
501 xcm_max_weight,
502 Weight::zero(),
503 )
504 };
505
506 match governance_origin {
507 GovernanceOrigin::Location(location) =>
508 execute_xcm(call, location, None).ensure_complete().map_err(Either::Right),
509 GovernanceOrigin::LocationAndDescendOrigin(location, descend_origin) =>
510 execute_xcm(call, location, Some(descend_origin))
511 .ensure_complete()
512 .map_err(Either::Right),
513 GovernanceOrigin::Origin(origin) =>
514 call.dispatch(origin).map(|_| ()).map_err(|e| Either::Left(e.error)),
515 }
516 }
517
518 pub fn execute_as_origin<Call: GetDispatchInfo + Encode>(
519 (origin, origin_kind): (Location, OriginKind),
520 call: Call,
521 maybe_buy_execution_fee: Option<Asset>,
522 ) -> Outcome {
523 let mut instructions = if let Some(buy_execution_fee) = maybe_buy_execution_fee {
524 vec![
525 WithdrawAsset(buy_execution_fee.clone().into()),
526 BuyExecution { fees: buy_execution_fee.clone(), weight_limit: Unlimited },
527 ]
528 } else {
529 vec![UnpaidExecution { check_origin: None, weight_limit: Unlimited }]
530 };
531
532 instructions.extend(vec![
534 Transact { origin_kind, call: call.encode().into(), fallback_max_weight: None },
535 ExpectTransactStatus(MaybeErrorCode::Success),
536 ]);
537 let xcm = Xcm(instructions);
538 let xcm_max_weight = Self::xcm_max_weight_for_location(&origin);
539
540 let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256);
542 <<Runtime as pallet_xcm::Config>::XcmExecutor>::prepare_and_execute(
543 origin,
544 xcm,
545 &mut hash,
546 xcm_max_weight,
547 Weight::zero(),
548 )
549 }
550}
551
552#[derive(Clone)]
554pub enum GovernanceOrigin<RuntimeOrigin> {
555 Location(Location),
556 LocationAndDescendOrigin(Location, InteriorLocation),
557 Origin(RuntimeOrigin),
558}
559
560pub enum XcmReceivedFrom {
561 Parent,
562 Sibling,
563}
564
565impl<ParachainSystem: cumulus_pallet_parachain_system::Config, AllPalletsWithoutSystem>
566 RuntimeHelper<ParachainSystem, AllPalletsWithoutSystem>
567{
568 pub fn xcm_max_weight(from: XcmReceivedFrom) -> Weight {
569 match from {
570 XcmReceivedFrom::Parent => ParachainSystem::ReservedDmpWeight::get(),
571 XcmReceivedFrom::Sibling => ParachainSystem::ReservedXcmpWeight::get(),
572 }
573 }
574
575 pub fn xcm_max_weight_for_location(location: &Location) -> Weight {
576 Self::xcm_max_weight(if location == &Location::parent() {
577 XcmReceivedFrom::Parent
578 } else {
579 XcmReceivedFrom::Sibling
580 })
581 }
582}
583
584impl<Runtime: frame_system::Config + pallet_xcm::Config, AllPalletsWithoutSystem>
585 RuntimeHelper<Runtime, AllPalletsWithoutSystem>
586{
587 pub fn assert_pallet_xcm_event_outcome(
588 unwrap_pallet_xcm_event: &Box<dyn Fn(Vec<u8>) -> Option<pallet_xcm::Event<Runtime>>>,
589 assert_outcome: fn(Outcome),
590 ) {
591 assert_outcome(Self::get_pallet_xcm_event_outcome(unwrap_pallet_xcm_event));
592 }
593
594 pub fn get_pallet_xcm_event_outcome(
595 unwrap_pallet_xcm_event: &Box<dyn Fn(Vec<u8>) -> Option<pallet_xcm::Event<Runtime>>>,
596 ) -> Outcome {
597 <frame_system::Pallet<Runtime>>::events()
598 .into_iter()
599 .filter_map(|e| unwrap_pallet_xcm_event(e.event.encode()))
600 .find_map(|e| match e {
601 pallet_xcm::Event::Attempted { outcome } => Some(outcome),
602 _ => None,
603 })
604 .expect("No `pallet_xcm::Event::Attempted(outcome)` event found!")
605 }
606}
607
608impl<
609 Runtime: frame_system::Config + cumulus_pallet_xcmp_queue::Config,
610 AllPalletsWithoutSystem,
611 > RuntimeHelper<Runtime, AllPalletsWithoutSystem>
612{
613 pub fn xcmp_queue_message_sent(
614 unwrap_xcmp_queue_event: Box<
615 dyn Fn(Vec<u8>) -> Option<cumulus_pallet_xcmp_queue::Event<Runtime>>,
616 >,
617 ) -> Option<XcmHash> {
618 <frame_system::Pallet<Runtime>>::events()
619 .into_iter()
620 .filter_map(|e| unwrap_xcmp_queue_event(e.event.encode()))
621 .find_map(|e| match e {
622 cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { message_hash } =>
623 Some(message_hash),
624 _ => None,
625 })
626 }
627}
628
629pub fn assert_metadata<Fungibles, AccountId>(
630 asset_id: impl Into<Fungibles::AssetId> + Clone,
631 expected_name: &str,
632 expected_symbol: &str,
633 expected_decimals: u8,
634) where
635 Fungibles: frame_support::traits::fungibles::metadata::Inspect<AccountId>
636 + frame_support::traits::fungibles::Inspect<AccountId>,
637{
638 assert_eq!(Fungibles::name(asset_id.clone().into()), Vec::from(expected_name),);
639 assert_eq!(Fungibles::symbol(asset_id.clone().into()), Vec::from(expected_symbol),);
640 assert_eq!(Fungibles::decimals(asset_id.into()), expected_decimals);
641}
642
643pub fn assert_total<Fungibles, AccountId>(
644 asset_id: impl Into<Fungibles::AssetId> + Clone,
645 expected_total_issuance: impl Into<Fungibles::Balance>,
646 expected_active_issuance: impl Into<Fungibles::Balance>,
647) where
648 Fungibles: frame_support::traits::fungibles::metadata::Inspect<AccountId>
649 + frame_support::traits::fungibles::Inspect<AccountId>,
650{
651 assert_eq!(Fungibles::total_issuance(asset_id.clone().into()), expected_total_issuance.into());
652 assert_eq!(Fungibles::active_issuance(asset_id.into()), expected_active_issuance.into());
653}
654
655pub fn mock_open_hrmp_channel<
664 C: cumulus_pallet_parachain_system::Config,
665 T: ProvideInherent<Call = cumulus_pallet_parachain_system::Call<C>>,
666>(
667 sender: ParaId,
668 recipient: ParaId,
669 included_head: HeaderFor<C>,
670 mut slot_digest: &[u8],
671 slot_durations: &SlotDurations,
672) {
673 let slot = Slot::decode(&mut slot_digest).expect("failed to decode digest");
674 let timestamp = slot.saturating_mul(slot_durations.para.as_millis());
676 let relay_slot = Slot::from_timestamp(timestamp.into(), slot_durations.relay);
677
678 let n = 1_u32;
679 let mut sproof_builder = RelayStateSproofBuilder {
680 para_id: sender,
681 included_para_head: Some(HeadData(included_head.encode())),
682 hrmp_egress_channel_index: Some(vec![recipient]),
683 current_slot: relay_slot,
684 ..Default::default()
685 };
686 sproof_builder.hrmp_channels.insert(
687 HrmpChannelId { sender, recipient },
688 AbridgedHrmpChannel {
689 max_capacity: 10,
690 max_total_size: 10_000_000_u32,
691 max_message_size: 10_000_000_u32,
692 msg_count: 0,
693 total_size: 0_u32,
694 mqc_head: None,
695 },
696 );
697
698 let (relay_parent_storage_root, relay_chain_state) = sproof_builder.into_state_root_and_proof();
699 let vfp = PersistedValidationData {
700 relay_parent_number: n as RelayChainBlockNumber,
701 relay_parent_storage_root,
702 ..Default::default()
703 };
704 let inherent_data = {
707 let mut inherent_data = InherentData::default();
708 let system_inherent_data = ParachainInherentData {
709 validation_data: vfp,
710 relay_chain_state,
711 downward_messages: Default::default(),
712 horizontal_messages: Default::default(),
713 relay_parent_descendants: Default::default(),
714 collator_peer_id: None,
715 };
716 inherent_data
717 .put_data(
718 cumulus_primitives_parachain_inherent::INHERENT_IDENTIFIER,
719 &system_inherent_data,
720 )
721 .expect("failed to put VFP inherent");
722 inherent_data
723 };
724
725 T::create_inherent(&inherent_data)
727 .expect("got an inherent")
728 .dispatch_bypass_filter(RawOrigin::None.into())
729 .expect("dispatch succeeded");
730}
731
732impl<HrmpChannelSource: cumulus_primitives_core::XcmpMessageSource, AllPalletsWithoutSystem>
733 RuntimeHelper<HrmpChannelSource, AllPalletsWithoutSystem>
734{
735 pub fn take_xcm(sent_to_para_id: ParaId) -> Option<VersionedXcm<()>> {
736 match HrmpChannelSource::take_outbound_messages(10)[..] {
737 [(para_id, ref mut xcm_message_data)] if para_id.eq(&sent_to_para_id.into()) => {
738 let mut xcm_message_data = &xcm_message_data[..];
739 let _ = XcmpMessageFormat::decode(&mut xcm_message_data).expect("valid format");
741 VersionedXcm::<()>::decode_with_depth_limit(
742 MAX_XCM_DECODE_DEPTH,
743 &mut xcm_message_data,
744 )
745 .map(|x| Some(x))
746 .expect("result with xcm")
747 },
748 _ => return None,
749 }
750 }
751}