1#![cfg_attr(not(feature = "std"), no_std)]
69
70extern crate alloc;
71
72use alloc::vec::Vec;
73use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
74use frame_support::{
75 ensure,
76 traits::{Consideration, EnsureOrigin, Footprint},
77};
78use registrar_primitives::{
79 FailureReason, MessageToPara, MessageToParaV1, MessageToRelay, MessageToRelayV1, Outcome,
80 ParaId,
81};
82use scale_info::TypeInfo;
83use sp_core::H256;
84use sp_runtime::{
85 traits::{BlockNumberProvider, Saturating},
86 DispatchError, DispatchResult,
87};
88
89pub use pallet::*;
90pub use weights::WeightInfo;
91
92pub mod weights;
93
94#[cfg(feature = "runtime-benchmarks")]
95mod benchmarking;
96#[cfg(test)]
97mod mock;
98#[cfg(test)]
99mod tests;
100
101pub type ProvidedBlockNumberOf<T> =
107 <<T as Config>::BlockNumberProvider as BlockNumberProvider>::BlockNumber;
108
109pub trait SendToRelay {
111 type AccountId;
113
114 #[allow(clippy::result_unit_err)]
119 fn send(message: MessageToRelay<Self::AccountId>) -> Result<(), ()>;
120}
121
122#[cfg(feature = "std")]
123impl SendToRelay for () {
124 type AccountId = sp_runtime::AccountId32;
125
126 fn send(_message: MessageToRelay<Self::AccountId>) -> Result<(), ()> {
127 Ok(())
128 }
129}
130
131#[derive(
133 Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, Debug, TypeInfo, MaxEncodedLen,
134)]
135pub enum RegistrationState<Ticket, BlockNumber> {
136 Reserved,
138 Pending {
140 ticket: Ticket,
142 cancellable_at: BlockNumber,
149 message_id: u64,
151 },
152 Registered {
154 ticket: Ticket,
156 },
157 Deregistering {
165 ticket: Ticket,
167 can_retry_after: BlockNumber,
171 message_id: u64,
173 },
174}
175
176#[derive(
178 Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, TypeInfo, MaxEncodedLen, Debug,
179)]
180pub struct ParaInfo<AccountId, ReservationTicket, RegistrationTicket, BlockNumber> {
181 pub manager: AccountId,
183 pub reservation: ReservationTicket,
185 pub state: RegistrationState<RegistrationTicket, BlockNumber>,
187 pub locked: Option<bool>,
190}
191
192impl<AccountId, ReservationTicket, RegistrationTicket, BlockNumber>
193 ParaInfo<AccountId, ReservationTicket, RegistrationTicket, BlockNumber>
194{
195 pub fn is_locked(&self) -> bool {
197 self.locked.unwrap_or(false)
198 }
199}
200
201pub type ParaInfoOf<T> = ParaInfo<
203 <T as frame_system::Config>::AccountId,
204 <T as Config>::ReservationConsideration,
205 <T as Config>::RegistrationConsideration,
206 ProvidedBlockNumberOf<T>,
207>;
208
209#[frame_support::pallet]
210pub mod pallet {
211 use super::*;
212 use frame_support::pallet_prelude::{DispatchResult, *};
213 use frame_system::pallet_prelude::*;
214
215 #[pallet::config]
216 pub trait Config: frame_system::Config {
217 type ReservationConsideration: Consideration<Self::AccountId, Footprint>;
220
221 type RegistrationConsideration: Consideration<Self::AccountId, Footprint>;
224
225 type SendToRelay: SendToRelay<AccountId = Self::AccountId>;
227
228 type RelayOrigin: EnsureOrigin<Self::RuntimeOrigin>;
230
231 type ParachainOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = ParaId>;
233
234 #[pallet::constant]
239 type FirstPublicParaId: Get<ParaId>;
240
241 #[pallet::constant]
246 type MinCodeSize: Get<u32>;
247
248 #[pallet::constant]
252 type MaxCodeSize: Get<u32>;
253
254 #[pallet::constant]
258 type MaxHeadDataSize: Get<u32>;
259
260 #[pallet::constant]
265 type PendingDeadline: Get<ProvidedBlockNumberOf<Self>>;
266
267 type BlockNumberProvider: BlockNumberProvider;
273
274 type WeightInfo: WeightInfo;
276 }
277
278 #[pallet::pallet]
279 pub struct Pallet<T>(_);
280
281 #[pallet::composite_enum]
283 pub enum HoldReason {
284 #[codec(index = 0)]
286 ParaIdReservation,
287 #[codec(index = 1)]
289 Registration,
290 }
291
292 #[pallet::storage]
294 pub type NextFreeParaId<T: Config> = StorageValue<_, ParaId, ValueQuery>;
295
296 #[pallet::storage]
301 pub type NextMessageId<T: Config> = StorageValue<_, u64, ValueQuery>;
302
303 #[pallet::storage]
305 pub type Paras<T: Config> = StorageMap<_, Blake2_128Concat, ParaId, ParaInfoOf<T>>;
306
307 #[pallet::event]
308 #[pallet::generate_deposit(pub(super) fn deposit_event)]
309 pub enum Event<T: Config> {
310 Reserved { para_id: ParaId, who: T::AccountId },
312 RegisterRequested { para_id: ParaId, message_id: u64, manager: T::AccountId },
314 Registered { para_id: ParaId, message_id: u64, manager: T::AccountId },
316 RegistrationFailed {
318 para_id: ParaId,
319 message_id: u64,
320 manager: T::AccountId,
321 reason: FailureReason,
322 },
323 CancelRequested { para_id: ParaId, message_id: u64, manager: T::AccountId },
326 RegistrationCancelled { para_id: ParaId, message_id: u64, manager: T::AccountId },
328 ReservationDropped { para_id: ParaId, manager: T::AccountId },
330 DeregisterRequested { para_id: ParaId, message_id: u64, manager: T::AccountId },
333 Deregistered { para_id: ParaId, message_id: u64, manager: T::AccountId },
335 DeregistrationFailed {
337 para_id: ParaId,
338 message_id: u64,
339 manager: T::AccountId,
340 reason: FailureReason,
341 },
342 ParaLocked { para_id: ParaId },
344 ParaUnlocked { para_id: ParaId },
346 Unexpected(UnexpectedKind),
348 }
349
350 #[derive(
353 Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, Debug, TypeInfo, MaxEncodedLen,
354 )]
355 pub enum UnexpectedKind {
356 RegisterResponseForUnknownPara { para_id: ParaId, message_id: u64 },
358 RegisterResponseNotPending { para_id: ParaId, message_id: u64 },
360 HeadNotedForUnknownPara { para_id: ParaId },
362 CancelResponseForUnknownPara { para_id: ParaId, message_id: u64 },
364 CancelRefused { para_id: ParaId, message_id: u64, reason: FailureReason },
367 HeadNotedForUnregisteredPara { para_id: ParaId },
369 DeregisterResponseForUnknownPara { para_id: ParaId, message_id: u64 },
371 DeregisterResponseNotDeregistering { para_id: ParaId, message_id: u64 },
373 StaleResponse { para_id: ParaId, message_id: u64, expected: u64 },
375 ResponseNeverArrived { para_id: ParaId, message_id: u64 },
377 DepositNotReleased { para_id: ParaId, error: DispatchError },
379 }
380
381 #[pallet::error]
382 pub enum Error<T> {
383 NotReserved,
385 NotOwner,
387 AlreadyRegistered,
389 NotPending,
391 CannotCancelYet,
393 HeadDataTooLarge,
395 CodeTooLarge,
397 CodeTooSmall,
399 SendFailed,
401 NoFreeParaId,
403 ParaLocked,
405 AlreadyLocked,
407 NotLocked,
409 NotRegistered,
411 Unimplemented,
413 CannotRetryYet,
415 }
416
417 #[pallet::hooks]
418 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
419 fn integrity_test() {
420 assert!(
422 T::MinCodeSize::get() <= T::MaxCodeSize::get(),
423 "MinCodeSize ({}) must not exceed MaxCodeSize ({})",
424 T::MinCodeSize::get(),
425 T::MaxCodeSize::get(),
426 );
427 }
428 }
429
430 #[pallet::call]
431 impl<T: Config> Pallet<T> {
432 #[pallet::call_index(0)]
436 #[pallet::weight(T::WeightInfo::receive())]
437 pub fn receive(origin: OriginFor<T>, message: MessageToPara) -> DispatchResult {
438 T::RelayOrigin::ensure_origin_or_root(origin)?;
439
440 match message {
441 MessageToPara::V1(MessageToParaV1::RegisterResponse {
442 para_id,
443 message_id,
444 outcome,
445 }) => Self::on_register_response(para_id, message_id, outcome),
446 MessageToPara::V1(MessageToParaV1::CancelResponse {
447 para_id,
448 message_id,
449 outcome,
450 }) => Self::on_cancel_response(para_id, message_id, outcome),
451 MessageToPara::V1(MessageToParaV1::DeregisterResponse {
452 para_id,
453 message_id,
454 outcome,
455 }) => Self::on_deregister_response(para_id, message_id, outcome),
456 MessageToPara::V1(MessageToParaV1::CodeUpgradeResponse {
457 para_id,
458 message_id,
459 outcome,
460 }) => Self::on_code_upgrade_response(para_id, message_id, outcome),
461 MessageToPara::V1(MessageToParaV1::CodeUpgradeScheduled {
462 para_id,
463 message_id,
464 }) => Self::on_code_upgrade_scheduled(para_id, message_id),
465 MessageToPara::V1(MessageToParaV1::SetHeadResponse {
466 para_id,
467 message_id,
468 outcome,
469 }) => Self::on_set_head_response(para_id, message_id, outcome),
470 MessageToPara::V1(MessageToParaV1::HeadNoted { para_id }) => {
471 Self::on_head_noted(para_id)
472 },
473 }
474 }
475
476 #[pallet::call_index(1)]
481 #[pallet::weight(T::WeightInfo::reserve())]
482 pub fn reserve(origin: OriginFor<T>) -> DispatchResult {
483 let who = ensure_signed(origin)?;
484
485 let para_id = NextFreeParaId::<T>::get().max(T::FirstPublicParaId::get());
486 let next = para_id.checked_add(1).ok_or(Error::<T>::NoFreeParaId)?;
487 ensure!(!Paras::<T>::contains_key(para_id), Error::<T>::AlreadyRegistered);
488
489 let reservation = T::ReservationConsideration::new(&who, Footprint::from_parts(1, 0))?;
490
491 Paras::<T>::insert(
492 para_id,
493 ParaInfo {
494 manager: who.clone(),
495 reservation,
496 state: RegistrationState::Reserved,
497 locked: None,
498 },
499 );
500 NextFreeParaId::<T>::put(next);
501
502 Self::deposit_event(Event::Reserved { para_id, who });
503 Ok(())
504 }
505
506 #[pallet::call_index(2)]
518 #[pallet::weight(T::WeightInfo::register(genesis_head.len() as u32))]
519 pub fn register(
520 origin: OriginFor<T>,
521 para_id: ParaId,
522 genesis_head: Vec<u8>,
523 code_len: u32,
524 code_hash: H256,
525 ) -> DispatchResult {
526 let who = ensure_signed(origin)?;
527
528 let mut info = Paras::<T>::get(para_id).ok_or(Error::<T>::NotReserved)?;
529 ensure!(info.manager == who, Error::<T>::NotOwner);
530 ensure!(
531 matches!(info.state, RegistrationState::Reserved),
532 Error::<T>::AlreadyRegistered
533 );
534
535 let head_len = genesis_head.len() as u32;
536 ensure!(head_len <= T::MaxHeadDataSize::get(), Error::<T>::HeadDataTooLarge);
537 ensure!(code_len >= T::MinCodeSize::get(), Error::<T>::CodeTooSmall);
538 ensure!(code_len <= T::MaxCodeSize::get(), Error::<T>::CodeTooLarge);
539
540 let ticket = T::RegistrationConsideration::new(
541 &who,
542 Self::registration_footprint(head_len, code_len),
543 )?;
544
545 let cancellable_at = T::BlockNumberProvider::current_block_number()
546 .saturating_add(T::PendingDeadline::get());
547 let message_id = Self::next_message_id();
548 info.state = RegistrationState::Pending { ticket, cancellable_at, message_id };
549 Paras::<T>::insert(para_id, info);
550
551 T::SendToRelay::send(MessageToRelay::V1(MessageToRelayV1::Register {
553 para_id,
554 message_id,
555 manager: who.clone(),
556 genesis_head,
557 code_hash,
558 code_len,
559 }))
560 .map_err(|()| Error::<T>::SendFailed)?;
561
562 Self::deposit_event(Event::RegisterRequested { para_id, message_id, manager: who });
563 Ok(())
564 }
565
566 #[pallet::call_index(3)]
581 #[pallet::weight(T::WeightInfo::cancel_registration())]
582 pub fn cancel_registration(origin: OriginFor<T>, para_id: ParaId) -> DispatchResult {
583 let who = ensure_signed(origin)?;
584
585 let mut info = Paras::<T>::get(para_id).ok_or(Error::<T>::NotReserved)?;
586 ensure!(info.manager == who, Error::<T>::NotOwner);
587 let RegistrationState::Pending { ticket, cancellable_at, message_id: awaited } =
588 info.state
589 else {
590 return Err(Error::<T>::NotPending.into());
591 };
592 let now = T::BlockNumberProvider::current_block_number();
593 ensure!(now >= cancellable_at, Error::<T>::CannotCancelYet);
594
595 Self::report_unexpected(UnexpectedKind::ResponseNeverArrived {
598 para_id,
599 message_id: awaited,
600 });
601
602 let message_id = Self::next_message_id();
605 info.state = RegistrationState::Pending {
606 ticket,
607 cancellable_at: now.saturating_add(T::PendingDeadline::get()),
608 message_id,
609 };
610 Paras::<T>::insert(para_id, info);
611
612 T::SendToRelay::send(MessageToRelay::V1(MessageToRelayV1::CancelRegistration {
614 para_id,
615 message_id,
616 }))
617 .map_err(|()| Error::<T>::SendFailed)?;
618
619 Self::deposit_event(Event::CancelRequested { para_id, message_id, manager: who });
620 Ok(())
621 }
622
623 #[pallet::call_index(4)]
625 #[pallet::weight(T::WeightInfo::add_lock())]
626 pub fn add_lock(origin: OriginFor<T>, para_id: ParaId) -> DispatchResult {
627 let mut info = Paras::<T>::get(para_id).ok_or(Error::<T>::NotReserved)?;
628 Self::ensure_root_para_or_manager(origin, para_id, &info)?;
629 ensure!(!info.is_locked(), Error::<T>::AlreadyLocked);
630 ensure!(
631 matches!(info.state, RegistrationState::Registered { .. }),
632 Error::<T>::NotRegistered
633 );
634
635 info.locked = Some(true);
636 Paras::<T>::insert(para_id, info);
637
638 Self::deposit_event(Event::ParaLocked { para_id });
639 Ok(())
640 }
641
642 #[pallet::call_index(5)]
646 #[pallet::weight(T::WeightInfo::remove_lock())]
647 pub fn remove_lock(origin: OriginFor<T>, para_id: ParaId) -> DispatchResult {
648 Self::ensure_root_or_para(origin, para_id)?;
649 let mut info = Paras::<T>::get(para_id).ok_or(Error::<T>::NotReserved)?;
650 ensure!(info.is_locked(), Error::<T>::NotLocked);
651
652 info.locked = Some(false);
653 Paras::<T>::insert(para_id, info);
654
655 Self::deposit_event(Event::ParaUnlocked { para_id });
656 Ok(())
657 }
658
659 #[pallet::call_index(6)]
667 #[pallet::weight(
668 T::WeightInfo::deregister_reserved()
669 .max(T::WeightInfo::deregister_registered())
670 .max(T::WeightInfo::deregister_retry())
671 )]
672 pub fn deregister(origin: OriginFor<T>, para_id: ParaId) -> DispatchResult {
673 let mut info = Paras::<T>::get(para_id).ok_or(Error::<T>::NotReserved)?;
674 Self::ensure_root_para_or_manager(origin, para_id, &info)?;
675
676 let manager = info.manager.clone();
677 let now = T::BlockNumberProvider::current_block_number();
678 let ticket = match info.state {
679 RegistrationState::Reserved => {
681 info.reservation.drop(&manager)?;
682 Paras::<T>::remove(para_id);
683 Self::deposit_event(Event::ReservationDropped { para_id, manager });
684 return Ok(());
685 },
686 RegistrationState::Pending { .. } => return Err(Error::<T>::NotRegistered.into()),
687 RegistrationState::Registered { ticket } => ticket,
688 RegistrationState::Deregistering {
689 ticket,
690 can_retry_after,
691 message_id: awaited,
692 } => {
693 ensure!(now >= can_retry_after, Error::<T>::CannotRetryYet);
694 Self::report_unexpected(UnexpectedKind::ResponseNeverArrived {
695 para_id,
696 message_id: awaited,
697 });
698 ticket
699 },
700 };
701
702 let message_id = Self::next_message_id();
703 info.state = RegistrationState::Deregistering {
704 ticket,
705 can_retry_after: now.saturating_add(T::PendingDeadline::get()),
706 message_id,
707 };
708 Paras::<T>::insert(para_id, info);
709
710 T::SendToRelay::send(MessageToRelay::V1(MessageToRelayV1::Deregister {
712 para_id,
713 message_id,
714 }))
715 .map_err(|()| Error::<T>::SendFailed)?;
716
717 Self::deposit_event(Event::DeregisterRequested { para_id, message_id, manager });
718 Ok(())
719 }
720
721 #[pallet::call_index(7)]
722 #[pallet::weight(Weight::MAX)]
723 pub fn schedule_code_upgrade(
724 origin: OriginFor<T>,
725 para_id: ParaId,
726 code_hash: H256,
727 code_len: u32,
728 ) -> DispatchResult {
729 let _ = (origin, para_id, code_hash, code_len);
730 Err(Error::<T>::Unimplemented.into())
732 }
733
734 #[pallet::call_index(8)]
735 #[pallet::weight(Weight::MAX)]
736 pub fn set_current_head(
737 origin: OriginFor<T>,
738 para_id: ParaId,
739 head: Vec<u8>,
740 ) -> DispatchResult {
741 let _ = (origin, para_id, head);
742 Err(Error::<T>::Unimplemented.into())
744 }
745
746 #[pallet::call_index(9)]
747 #[pallet::weight(Weight::MAX)]
748 pub fn force_register(
749 origin: OriginFor<T>,
750 para_id: ParaId,
751 manager: T::AccountId,
752 genesis_head: Vec<u8>,
753 code_len: u32,
754 code_hash: H256,
755 ) -> DispatchResult {
756 let _ = (origin, para_id, manager, genesis_head, code_len, code_hash);
757 Err(Error::<T>::Unimplemented.into())
759 }
760 }
761}
762
763impl<T: Config> Pallet<T> {
764 pub fn registration_footprint(head_len: u32, code_len: u32) -> Footprint {
766 Footprint::from_parts(1, head_len.saturating_add(code_len) as usize)
767 }
768
769 fn ensure_root_para_or_manager(
771 origin: frame_system::pallet_prelude::OriginFor<T>,
772 para_id: ParaId,
773 info: &ParaInfoOf<T>,
774 ) -> DispatchResult {
775 if let Ok(id) = T::ParachainOrigin::ensure_origin(origin.clone()) {
776 ensure!(id == para_id, Error::<T>::NotOwner);
777 return Ok(());
778 }
779 if let Ok(who) = frame_system::ensure_signed(origin.clone()) {
780 ensure!(who == info.manager, Error::<T>::NotOwner);
781 ensure!(!info.is_locked(), Error::<T>::ParaLocked);
782 return Ok(());
783 }
784 frame_system::ensure_root(origin)?;
785 Ok(())
786 }
787
788 fn ensure_root_or_para(
790 origin: frame_system::pallet_prelude::OriginFor<T>,
791 para_id: ParaId,
792 ) -> DispatchResult {
793 if frame_system::ensure_root(origin.clone()).is_ok() {
794 return Ok(());
795 }
796 let id = T::ParachainOrigin::ensure_origin(origin)?;
797 ensure!(id == para_id, Error::<T>::NotOwner);
798 Ok(())
799 }
800
801 fn report_unexpected(kind: UnexpectedKind) {
803 log::error!(target: "runtime::registrar-para", "unexpected: {kind:?}");
804 Self::deposit_event(Event::Unexpected(kind));
805 }
806
807 fn release_or_report<C: Consideration<T::AccountId, Footprint>>(
809 ticket: C,
810 who: &T::AccountId,
811 para_id: ParaId,
812 ) {
813 if let Err(error) = ticket.drop(who) {
814 Self::report_unexpected(UnexpectedKind::DepositNotReleased { para_id, error });
815 }
816 }
817
818 fn next_message_id() -> u64 {
820 NextMessageId::<T>::mutate(|next| {
821 let id = *next;
822 *next = next.wrapping_add(1);
823 id
824 })
825 }
826
827 fn on_register_response(para_id: ParaId, message_id: u64, outcome: Outcome) -> DispatchResult {
833 let Some(mut info) = Paras::<T>::get(para_id) else {
834 Self::report_unexpected(UnexpectedKind::RegisterResponseForUnknownPara {
835 para_id,
836 message_id,
837 });
838 return Ok(());
839 };
840 let RegistrationState::Pending { ticket, message_id: expected, .. } = info.state else {
841 Self::report_unexpected(UnexpectedKind::RegisterResponseNotPending {
842 para_id,
843 message_id,
844 });
845 return Ok(());
846 };
847 if message_id != expected {
848 Self::report_unexpected(UnexpectedKind::StaleResponse {
849 para_id,
850 message_id,
851 expected,
852 });
853 return Ok(());
854 }
855
856 let manager = info.manager.clone();
857 match outcome {
858 Ok(()) => {
859 info.state = RegistrationState::Registered { ticket };
860 Paras::<T>::insert(para_id, info);
861 Self::deposit_event(Event::Registered { para_id, message_id, manager });
862 },
863 Err(reason) => {
864 Self::release_or_report(ticket, &manager, para_id);
865 info.state = RegistrationState::Reserved;
866 Paras::<T>::insert(para_id, info);
867 Self::deposit_event(Event::RegistrationFailed {
868 para_id,
869 message_id,
870 manager,
871 reason,
872 });
873 },
874 }
875
876 Ok(())
877 }
878
879 fn on_head_noted(para_id: ParaId) -> DispatchResult {
881 let Some(mut info) = Paras::<T>::get(para_id) else {
882 Self::report_unexpected(UnexpectedKind::HeadNotedForUnknownPara { para_id });
883 return Ok(());
884 };
885
886 if info.locked.is_some() {
887 return Ok(());
888 }
889
890 if !matches!(info.state, RegistrationState::Registered { .. }) {
891 Self::report_unexpected(UnexpectedKind::HeadNotedForUnregisteredPara { para_id });
892 }
893
894 info.locked = Some(true);
895 Paras::<T>::insert(para_id, info);
896
897 Self::deposit_event(Event::ParaLocked { para_id });
898
899 Ok(())
900 }
901
902 fn on_cancel_response(para_id: ParaId, message_id: u64, outcome: Outcome) -> DispatchResult {
912 let Some(mut info) = Paras::<T>::get(para_id) else {
913 Self::report_unexpected(UnexpectedKind::CancelResponseForUnknownPara {
914 para_id,
915 message_id,
916 });
917 return Ok(());
918 };
919 let RegistrationState::Pending { ticket, message_id: expected, .. } = info.state else {
920 log::debug!(
921 target: "runtime::registrar-para",
922 "cancel response for para {para_id} which is no longer pending, dropping",
923 );
924 return Ok(());
925 };
926 if message_id != expected {
927 Self::report_unexpected(UnexpectedKind::StaleResponse {
928 para_id,
929 message_id,
930 expected,
931 });
932 return Ok(());
933 }
934
935 let manager = info.manager.clone();
936 match outcome {
937 Ok(()) => {
938 Self::release_or_report(ticket, &manager, para_id);
939 info.state = RegistrationState::Reserved;
940 Paras::<T>::insert(para_id, info);
941 Self::deposit_event(Event::RegistrationCancelled { para_id, message_id, manager });
942 },
943 Err(FailureReason::AlreadyRegistered) => {
944 info.state = RegistrationState::Registered { ticket };
945 Paras::<T>::insert(para_id, info);
946 Self::deposit_event(Event::Registered { para_id, message_id, manager });
947 },
948 Err(reason) => {
951 Self::report_unexpected(UnexpectedKind::CancelRefused {
952 para_id,
953 message_id,
954 reason,
955 });
956 },
957 }
958
959 Ok(())
960 }
961
962 fn on_deregister_response(
967 para_id: ParaId,
968 message_id: u64,
969 outcome: Outcome,
970 ) -> DispatchResult {
971 let Some(mut info) = Paras::<T>::get(para_id) else {
972 Self::report_unexpected(UnexpectedKind::DeregisterResponseForUnknownPara {
973 para_id,
974 message_id,
975 });
976 return Ok(());
977 };
978 let RegistrationState::Deregistering { ticket, message_id: expected, .. } = info.state
979 else {
980 Self::report_unexpected(UnexpectedKind::DeregisterResponseNotDeregistering {
981 para_id,
982 message_id,
983 });
984 return Ok(());
985 };
986 if message_id != expected {
987 Self::report_unexpected(UnexpectedKind::StaleResponse {
988 para_id,
989 message_id,
990 expected,
991 });
992 return Ok(());
993 }
994
995 let manager = info.manager.clone();
996 match outcome {
997 Ok(()) => {
998 Self::release_or_report(ticket, &manager, para_id);
999 Self::release_or_report(info.reservation, &manager, para_id);
1000 Paras::<T>::remove(para_id);
1001 Self::deposit_event(Event::Deregistered { para_id, message_id, manager });
1002 },
1003 Err(reason) => {
1004 info.state = RegistrationState::Registered { ticket };
1005 Paras::<T>::insert(para_id, info);
1006 Self::deposit_event(Event::DeregistrationFailed {
1007 para_id,
1008 message_id,
1009 manager,
1010 reason,
1011 });
1012 },
1013 }
1014
1015 Ok(())
1016 }
1017
1018 fn on_code_upgrade_response(
1019 para_id: ParaId,
1020 message_id: u64,
1021 outcome: Result<u32, FailureReason>,
1022 ) -> DispatchResult {
1023 let _ = (para_id, message_id, outcome);
1024 Err(Error::<T>::Unimplemented.into())
1026 }
1027
1028 fn on_code_upgrade_scheduled(para_id: ParaId, message_id: u64) -> DispatchResult {
1029 let _ = (para_id, message_id);
1030 Err(Error::<T>::Unimplemented.into())
1032 }
1033
1034 fn on_set_head_response(para_id: ParaId, message_id: u64, outcome: Outcome) -> DispatchResult {
1035 let _ = (para_id, message_id, outcome);
1036 Err(Error::<T>::Unimplemented.into())
1038 }
1039}