1717//! Pallet to handle parachain registration and related fund management.
1818//! In essence this is a simple wrapper around `paras`.
1919
20+ pub mod migration;
21+
2022use frame_support:: {
2123 dispatch:: DispatchResult ,
2224 ensure,
@@ -35,7 +37,7 @@ use sp_std::{prelude::*, result};
3537use crate :: traits:: { OnSwap , Registrar } ;
3638pub use pallet:: * ;
3739use parity_scale_codec:: { Decode , Encode } ;
38- use runtime_parachains:: paras:: ParaKind ;
40+ use runtime_parachains:: paras:: { OnNewHead , ParaKind } ;
3941use scale_info:: TypeInfo ;
4042use sp_runtime:: {
4143 traits:: { CheckedSub , Saturating } ,
@@ -49,7 +51,15 @@ pub struct ParaInfo<Account, Balance> {
4951 /// The amount reserved by the `manager` account for the registration.
5052 deposit : Balance ,
5153 /// Whether the para registration should be locked from being controlled by the manager.
52- locked : bool ,
54+ /// None means the lock had not been explicitly set, and should be treated as false.
55+ locked : Option < bool > ,
56+ }
57+
58+ impl < Account , Balance > ParaInfo < Account , Balance > {
59+ /// Returns if the para is locked.
60+ pub fn is_locked ( & self ) -> bool {
61+ self . locked . unwrap_or ( false )
62+ }
5363}
5464
5565type BalanceOf < T > =
@@ -96,8 +106,12 @@ pub mod pallet {
96106 use frame_support:: pallet_prelude:: * ;
97107 use frame_system:: pallet_prelude:: * ;
98108
109+ /// The current storage version.
110+ const STORAGE_VERSION : StorageVersion = StorageVersion :: new ( 1 ) ;
111+
99112 #[ pallet:: pallet]
100113 #[ pallet:: without_storage_info]
114+ #[ pallet:: storage_version( STORAGE_VERSION ) ]
101115 pub struct Pallet < T > ( _ ) ;
102116
103117 #[ pallet:: config]
@@ -446,12 +460,12 @@ impl<T: Config> Registrar for Pallet<T> {
446460
447461 // Apply a lock to the parachain.
448462 fn apply_lock ( id : ParaId ) {
449- Paras :: < T > :: mutate ( id, |x| x. as_mut ( ) . map ( |info| info. locked = true ) ) ;
463+ Paras :: < T > :: mutate ( id, |x| x. as_mut ( ) . map ( |info| info. locked = Some ( true ) ) ) ;
450464 }
451465
452466 // Remove a lock from the parachain.
453467 fn remove_lock ( id : ParaId ) {
454- Paras :: < T > :: mutate ( id, |x| x. as_mut ( ) . map ( |info| info. locked = false ) ) ;
468+ Paras :: < T > :: mutate ( id, |x| x. as_mut ( ) . map ( |info| info. locked = Some ( false ) ) ) ;
455469 }
456470
457471 // Register a Para ID under control of `manager`.
@@ -481,9 +495,7 @@ impl<T: Config> Registrar for Pallet<T> {
481495 ) ;
482496 runtime_parachains:: schedule_parathread_upgrade :: < T > ( id)
483497 . map_err ( |_| Error :: < T > :: CannotUpgrade ) ?;
484- // Once a para has upgraded to a parachain, it can no longer be managed by the owner.
485- // Intentionally, the flag stays with the para even after downgrade.
486- Self :: apply_lock ( id) ;
498+
487499 Ok ( ( ) )
488500 }
489501
@@ -533,7 +545,7 @@ impl<T: Config> Pallet<T> {
533545 . map_err ( |e| e. into ( ) )
534546 . and_then ( |who| -> DispatchResult {
535547 let para_info = Paras :: < T > :: get ( id) . ok_or ( Error :: < T > :: NotRegistered ) ?;
536- ensure ! ( !para_info. locked , Error :: <T >:: ParaLocked ) ;
548+ ensure ! ( !para_info. is_locked ( ) , Error :: <T >:: ParaLocked ) ;
537549 ensure ! ( para_info. manager == who, Error :: <T >:: NotOwner ) ;
538550 Ok ( ( ) )
539551 } )
@@ -566,7 +578,7 @@ impl<T: Config> Pallet<T> {
566578
567579 let deposit = deposit_override. unwrap_or_else ( T :: ParaDeposit :: get) ;
568580 <T as Config >:: Currency :: reserve ( & who, deposit) ?;
569- let info = ParaInfo { manager : who. clone ( ) , deposit, locked : false } ;
581+ let info = ParaInfo { manager : who. clone ( ) , deposit, locked : None } ;
570582
571583 Paras :: < T > :: insert ( id, info) ;
572584 Self :: deposit_event ( Event :: < T > :: Reserved { para_id : id, who } ) ;
@@ -585,7 +597,7 @@ impl<T: Config> Pallet<T> {
585597 ) -> DispatchResult {
586598 let deposited = if let Some ( para_data) = Paras :: < T > :: get ( id) {
587599 ensure ! ( para_data. manager == who, Error :: <T >:: NotOwner ) ;
588- ensure ! ( !para_data. locked , Error :: <T >:: ParaLocked ) ;
600+ ensure ! ( !para_data. is_locked ( ) , Error :: <T >:: ParaLocked ) ;
589601 para_data. deposit
590602 } else {
591603 ensure ! ( !ensure_reserved, Error :: <T >:: NotReserved ) ;
@@ -601,7 +613,7 @@ impl<T: Config> Pallet<T> {
601613 } else if let Some ( rebate) = deposited. checked_sub ( & deposit) {
602614 <T as Config >:: Currency :: unreserve ( & who, rebate) ;
603615 } ;
604- let info = ParaInfo { manager : who. clone ( ) , deposit, locked : false } ;
616+ let info = ParaInfo { manager : who. clone ( ) , deposit, locked : None } ;
605617
606618 Paras :: < T > :: insert ( id, info) ;
607619 // We check above that para has no lifecycle, so this should not fail.
@@ -665,6 +677,21 @@ impl<T: Config> Pallet<T> {
665677 }
666678}
667679
680+ impl < T : Config > OnNewHead for Pallet < T > {
681+ fn on_new_head ( id : ParaId , _head : & HeadData ) -> Weight {
682+ // mark the parachain locked if the locked value is not already set
683+ let mut writes = 0 ;
684+ if let Some ( mut info) = Paras :: < T > :: get ( id) {
685+ if info. locked . is_none ( ) {
686+ info. locked = Some ( true ) ;
687+ Paras :: < T > :: insert ( id, info) ;
688+ writes += 1 ;
689+ }
690+ }
691+ T :: DbWeight :: get ( ) . reads_writes ( 1 , writes)
692+ }
693+ }
694+
668695#[ cfg( test) ]
669696mod tests {
670697 use super :: * ;
@@ -784,6 +811,7 @@ mod tests {
784811 type UnsignedPriority = ParasUnsignedPriority ;
785812 type QueueFootprinter = ( ) ;
786813 type NextSessionRotation = crate :: mock:: TestNextSessionRotation ;
814+ type OnNewHead = ( ) ;
787815 }
788816
789817 impl configuration:: Config for Test {
@@ -1270,8 +1298,10 @@ mod tests {
12701298 ) ) ;
12711299
12721300 assert_noop ! ( Registrar :: add_lock( RuntimeOrigin :: signed( 2 ) , para_id) , BadOrigin ) ;
1273- // Once they begin onboarding, we lock them in.
1274- assert_ok ! ( Registrar :: add_lock( RuntimeOrigin :: signed( 1 ) , para_id) ) ;
1301+
1302+ // Once they produces new block, we lock them in.
1303+ Registrar :: on_new_head ( para_id, & Default :: default ( ) ) ;
1304+
12751305 // Owner cannot pass origin check when checking lock
12761306 assert_noop ! (
12771307 Registrar :: ensure_root_para_or_owner( RuntimeOrigin :: signed( 1 ) , para_id) ,
@@ -1283,6 +1313,11 @@ mod tests {
12831313 assert_ok ! ( Registrar :: remove_lock( para_origin( para_id) , para_id) ) ;
12841314 // Owner can pass origin check again
12851315 assert_ok ! ( Registrar :: ensure_root_para_or_owner( RuntimeOrigin :: signed( 1 ) , para_id) ) ;
1316+
1317+ // Won't lock again after it is unlocked
1318+ Registrar :: on_new_head ( para_id, & Default :: default ( ) ) ;
1319+
1320+ assert_ok ! ( Registrar :: ensure_root_para_or_owner( RuntimeOrigin :: signed( 1 ) , para_id) ) ;
12861321 } ) ;
12871322 }
12881323
0 commit comments