Unverified Commit f1c42ce6 authored by Shawn Tabrizi's avatar Shawn Tabrizi Committed by GitHub
Browse files

Introduce System Parachains into Registrar (#2858)

* initial stuff

* adjust deposit

* remove unused

* weight stuff

* Update integration_tests.rs

* Update paras_registrar.rs

* Update paras_registrar.rs

* add test

* Update paras_registrar.rs

Co-authored-by: parity-processbot <>
parent 11a9afa9
Pipeline #133855 failed with stages
in 20 minutes and 55 seconds
...@@ -131,11 +131,6 @@ impl Id { ...@@ -131,11 +131,6 @@ impl Id {
pub const fn new(id: u32) -> Self { pub const fn new(id: u32) -> Self {
Self(id) Self(id)
} }
/// Returns `true` if this parachain runs with system-level privileges.
/// Use IsSystem instead.
#[deprecated]
pub fn is_system(&self) -> bool { self.0 < USER_INDEX_START }
} }
pub trait IsSystem { pub trait IsSystem {
......
This diff is collapsed.
...@@ -26,7 +26,7 @@ use frame_support::{ ...@@ -26,7 +26,7 @@ use frame_support::{
}; };
use frame_system::{self, ensure_root, ensure_signed}; use frame_system::{self, ensure_root, ensure_signed};
use primitives::v1::{ use primitives::v1::{
Id as ParaId, ValidationCode, HeadData, Id as ParaId, ValidationCode, HeadData, LOWEST_USER_ID,
}; };
use runtime_parachains::{ use runtime_parachains::{
paras::{ paras::{
...@@ -56,6 +56,7 @@ type BalanceOf<T> = ...@@ -56,6 +56,7 @@ type BalanceOf<T> =
pub trait WeightInfo { pub trait WeightInfo {
fn register() -> Weight; fn register() -> Weight;
fn force_register() -> Weight;
fn deregister() -> Weight; fn deregister() -> Weight;
fn swap() -> Weight; fn swap() -> Weight;
} }
...@@ -63,6 +64,7 @@ pub trait WeightInfo { ...@@ -63,6 +64,7 @@ pub trait WeightInfo {
pub struct TestWeightInfo; pub struct TestWeightInfo;
impl WeightInfo for TestWeightInfo { impl WeightInfo for TestWeightInfo {
fn register() -> Weight { 0 } fn register() -> Weight { 0 }
fn force_register() -> Weight { 0 }
fn deregister() -> Weight { 0 } fn deregister() -> Weight { 0 }
fn swap() -> Weight { 0 } fn swap() -> Weight { 0 }
} }
...@@ -148,6 +150,8 @@ decl_error! { ...@@ -148,6 +150,8 @@ decl_error! {
CannotUpgrade, CannotUpgrade,
/// Para is locked from manipulation by the manager. Must use parachain or relay chain governance. /// Para is locked from manipulation by the manager. Must use parachain or relay chain governance.
ParaLocked, ParaLocked,
/// The id you are trying to register is reserved for system parachains.
InvalidParaId,
} }
} }
...@@ -171,7 +175,8 @@ decl_module! { ...@@ -171,7 +175,8 @@ decl_module! {
/// This function must be called by a signed origin. /// This function must be called by a signed origin.
/// ///
/// The origin must pay a deposit for the registration information, /// The origin must pay a deposit for the registration information,
/// including the genesis information and validation code. /// including the genesis information and validation code. ParaId
/// must be greater than or equal to 1000.
#[weight = T::WeightInfo::register()] #[weight = T::WeightInfo::register()]
pub fn register( pub fn register(
origin, origin,
...@@ -180,7 +185,27 @@ decl_module! { ...@@ -180,7 +185,27 @@ decl_module! {
validation_code: ValidationCode, validation_code: ValidationCode,
) -> DispatchResult { ) -> DispatchResult {
let who = ensure_signed(origin)?; let who = ensure_signed(origin)?;
Self::do_register(who, id, genesis_head, validation_code) ensure!(id >= LOWEST_USER_ID, Error::<T>::InvalidParaId);
Self::do_register(who, None, id, genesis_head, validation_code)
}
/// Force the registration of a Para Id on the relay chain.
///
/// This function must be called by a Root origin.
///
/// The deposit taken can be specified for this registration. Any ParaId
/// can be registered, including sub-1000 IDs which are System Parachains.
#[weight = T::WeightInfo::force_register()]
pub fn force_register(
origin,
who: T::AccountId,
deposit: BalanceOf<T>,
id: ParaId,
genesis_head: HeadData,
validation_code: ValidationCode,
) -> DispatchResult {
ensure_root(origin)?;
Self::do_register(who, Some(deposit), id, genesis_head, validation_code)
} }
/// Deregister a Para Id, freeing all data and returning any deposit. /// Deregister a Para Id, freeing all data and returning any deposit.
...@@ -236,6 +261,16 @@ decl_module! { ...@@ -236,6 +261,16 @@ decl_module! {
PendingSwap::insert(id, other); PendingSwap::insert(id, other);
} }
} }
/// Remove a manager lock from a para. This will allow the manager of a
/// previously locked para to deregister or swap a para without using governance.
///
/// Can only be called by the Root origin.
#[weight = T::DbWeight::get().reads_writes(1, 1)]
fn force_remove_lock(origin, para: ParaId) {
ensure_root(origin)?;
Self::remove_lock(para);
}
} }
} }
...@@ -273,13 +308,16 @@ impl<T: Config> Registrar for Module<T> { ...@@ -273,13 +308,16 @@ impl<T: Config> Registrar for Module<T> {
} }
// Register a Para ID under control of `manager`. // Register a Para ID under control of `manager`.
//
// Note this is a backend registration api, so verification of ParaId
// is not done here to prevent.
fn register( fn register(
manager: T::AccountId, manager: T::AccountId,
id: ParaId, id: ParaId,
genesis_head: HeadData, genesis_head: HeadData,
validation_code: ValidationCode, validation_code: ValidationCode,
) -> DispatchResult { ) -> DispatchResult {
Self::do_register(manager, id, genesis_head, validation_code) Self::do_register(manager, None, id, genesis_head, validation_code)
} }
// Deregister a Para ID, free any data, and return any deposits. // Deregister a Para ID, free any data, and return any deposits.
...@@ -357,6 +395,7 @@ impl<T: Config> Module<T> { ...@@ -357,6 +395,7 @@ impl<T: Config> Module<T> {
/// system with the given information. /// system with the given information.
fn do_register( fn do_register(
who: T::AccountId, who: T::AccountId,
deposit_override: Option<BalanceOf<T>>,
id: ParaId, id: ParaId,
genesis_head: HeadData, genesis_head: HeadData,
validation_code: ValidationCode, validation_code: ValidationCode,
...@@ -369,6 +408,7 @@ impl<T: Config> Module<T> { ...@@ -369,6 +408,7 @@ impl<T: Config> Module<T> {
false false
)?; )?;
let deposit = deposit_override.unwrap_or(deposit);
<T as Config>::Currency::reserve(&who, deposit)?; <T as Config>::Currency::reserve(&who, deposit)?;
let info = ParaInfo { let info = ParaInfo {
manager: who.clone(), manager: who.clone(),
...@@ -610,39 +650,39 @@ mod tests { ...@@ -610,39 +650,39 @@ mod tests {
fn end_to_end_scenario_works() { fn end_to_end_scenario_works() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
run_to_block(1); run_to_block(1);
// 32 is not yet registered // 1032 is not yet registered
assert!(!Parachains::is_parathread(32.into())); assert!(!Parachains::is_parathread(1032.into()));
// We register the Para ID // We register the Para ID
assert_ok!(Registrar::register( assert_ok!(Registrar::register(
Origin::signed(1), Origin::signed(1),
32.into(), 1032.into(),
test_genesis_head(32), test_genesis_head(32),
test_validation_code(32), test_validation_code(32),
)); ));
run_to_session(2); run_to_session(2);
// It is now a parathread. // It is now a parathread.
assert!(Parachains::is_parathread(32.into())); assert!(Parachains::is_parathread(1032.into()));
assert!(!Parachains::is_parachain(32.into())); assert!(!Parachains::is_parachain(1032.into()));
// Some other external process will elevate parathread to parachain // Some other external process will elevate parathread to parachain
assert_ok!(Registrar::make_parachain(32.into())); assert_ok!(Registrar::make_parachain(1032.into()));
run_to_session(4); run_to_session(4);
// It is now a parachain. // It is now a parachain.
assert!(!Parachains::is_parathread(32.into())); assert!(!Parachains::is_parathread(1032.into()));
assert!(Parachains::is_parachain(32.into())); assert!(Parachains::is_parachain(1032.into()));
// Turn it back into a parathread // Turn it back into a parathread
assert_ok!(Registrar::make_parathread(32.into())); assert_ok!(Registrar::make_parathread(1032.into()));
run_to_session(6); run_to_session(6);
assert!(Parachains::is_parathread(32.into())); assert!(Parachains::is_parathread(1032.into()));
assert!(!Parachains::is_parachain(32.into())); assert!(!Parachains::is_parachain(1032.into()));
// Deregister it // Deregister it
assert_ok!(Registrar::deregister( assert_ok!(Registrar::deregister(
Origin::root(), Origin::root(),
32.into(), 1032.into(),
)); ));
run_to_session(8); run_to_session(8);
// It is nothing // It is nothing
assert!(!Parachains::is_parathread(32.into())); assert!(!Parachains::is_parathread(1032.into()));
assert!(!Parachains::is_parachain(32.into())); assert!(!Parachains::is_parachain(1032.into()));
}); });
} }
...@@ -650,15 +690,15 @@ mod tests { ...@@ -650,15 +690,15 @@ mod tests {
fn register_works() { fn register_works() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
run_to_block(1); run_to_block(1);
assert!(!Parachains::is_parathread(32.into())); assert!(!Parachains::is_parathread(1032.into()));
assert_ok!(Registrar::register( assert_ok!(Registrar::register(
Origin::signed(1), Origin::signed(1),
32.into(), 1032.into(),
test_genesis_head(32), test_genesis_head(32),
test_validation_code(32), test_validation_code(32),
)); ));
run_to_session(2); run_to_session(2);
assert!(Parachains::is_parathread(32.into())); assert!(Parachains::is_parathread(1032.into()));
assert_eq!( assert_eq!(
Balances::reserved_balance(&1), Balances::reserved_balance(&1),
<Test as Config>::ParaDeposit::get() + 64 * <Test as Config>::DataDepositPerByte::get() <Test as Config>::ParaDeposit::get() + 64 * <Test as Config>::DataDepositPerByte::get()
...@@ -669,22 +709,30 @@ mod tests { ...@@ -669,22 +709,30 @@ mod tests {
#[test] #[test]
fn register_handles_basic_errors() { fn register_handles_basic_errors() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
// Successfully register 32 // Can't register system parachain
assert_ok!(Registrar::register( assert_noop!(Registrar::register(
Origin::signed(1), Origin::signed(1),
32.into(), 32.into(),
test_genesis_head(<Test as super::Config>::MaxHeadSize::get() as usize), test_genesis_head(<Test as super::Config>::MaxHeadSize::get() as usize),
test_validation_code(<Test as super::Config>::MaxCodeSize::get() as usize), test_validation_code(<Test as super::Config>::MaxCodeSize::get() as usize),
), Error::<Test>::InvalidParaId);
// Successfully register 1032
assert_ok!(Registrar::register(
Origin::signed(1),
1032.into(),
test_genesis_head(<Test as super::Config>::MaxHeadSize::get() as usize),
test_validation_code(<Test as super::Config>::MaxCodeSize::get() as usize),
)); ));
run_to_session(2); run_to_session(2);
assert_ok!(Registrar::deregister(Origin::root(), 32u32.into())); assert_ok!(Registrar::deregister(Origin::root(), 1032.into()));
// Can't do it again // Can't do it again until offboarded from the paras backend
assert_noop!(Registrar::register( assert_noop!(Registrar::register(
Origin::signed(1), Origin::signed(1),
32.into(), 1032.into(),
test_genesis_head(<Test as super::Config>::MaxHeadSize::get() as usize), test_genesis_head(<Test as super::Config>::MaxHeadSize::get() as usize),
test_validation_code(<Test as super::Config>::MaxCodeSize::get() as usize), test_validation_code(<Test as super::Config>::MaxCodeSize::get() as usize),
), Error::<Test>::AlreadyRegistered); ), Error::<Test>::AlreadyRegistered);
...@@ -692,7 +740,7 @@ mod tests { ...@@ -692,7 +740,7 @@ mod tests {
// Head Size Check // Head Size Check
assert_noop!(Registrar::register( assert_noop!(Registrar::register(
Origin::signed(2), Origin::signed(2),
23.into(), 1023.into(),
test_genesis_head((<Test as super::Config>::MaxHeadSize::get() + 1) as usize), test_genesis_head((<Test as super::Config>::MaxHeadSize::get() + 1) as usize),
test_validation_code(<Test as super::Config>::MaxCodeSize::get() as usize), test_validation_code(<Test as super::Config>::MaxCodeSize::get() as usize),
), Error::<Test>::HeadDataTooLarge); ), Error::<Test>::HeadDataTooLarge);
...@@ -700,7 +748,7 @@ mod tests { ...@@ -700,7 +748,7 @@ mod tests {
// Code Size Check // Code Size Check
assert_noop!(Registrar::register( assert_noop!(Registrar::register(
Origin::signed(2), Origin::signed(2),
23.into(), 1023.into(),
test_genesis_head(<Test as super::Config>::MaxHeadSize::get() as usize), test_genesis_head(<Test as super::Config>::MaxHeadSize::get() as usize),
test_validation_code((<Test as super::Config>::MaxCodeSize::get() + 1) as usize), test_validation_code((<Test as super::Config>::MaxCodeSize::get() + 1) as usize),
), Error::<Test>::CodeTooLarge); ), Error::<Test>::CodeTooLarge);
...@@ -708,7 +756,7 @@ mod tests { ...@@ -708,7 +756,7 @@ mod tests {
// Needs enough funds for deposit // Needs enough funds for deposit
assert_noop!(Registrar::register( assert_noop!(Registrar::register(
Origin::signed(1337), Origin::signed(1337),
23.into(), 1023.into(),
test_genesis_head(<Test as super::Config>::MaxHeadSize::get() as usize), test_genesis_head(<Test as super::Config>::MaxHeadSize::get() as usize),
test_validation_code(<Test as super::Config>::MaxCodeSize::get() as usize), test_validation_code(<Test as super::Config>::MaxCodeSize::get() as usize),
), BalancesError::<Test, _>::InsufficientBalance); ), BalancesError::<Test, _>::InsufficientBalance);
...@@ -719,10 +767,10 @@ mod tests { ...@@ -719,10 +767,10 @@ mod tests {
fn deregister_works() { fn deregister_works() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
run_to_block(1); run_to_block(1);
assert!(!Parachains::is_parathread(32.into())); assert!(!Parachains::is_parathread(1032.into()));
assert_ok!(Registrar::register( assert_ok!(Registrar::register(
Origin::signed(1), Origin::signed(1),
32.into(), 1032.into(),
test_genesis_head(32), test_genesis_head(32),
test_validation_code(32), test_validation_code(32),
)); ));
...@@ -731,13 +779,13 @@ mod tests { ...@@ -731,13 +779,13 @@ mod tests {
<Test as Config>::ParaDeposit::get() + 64 * <Test as Config>::DataDepositPerByte::get() <Test as Config>::ParaDeposit::get() + 64 * <Test as Config>::DataDepositPerByte::get()
); );
run_to_session(2); run_to_session(2);
assert!(Parachains::is_parathread(32.into())); assert!(Parachains::is_parathread(1032.into()));
assert_ok!(Registrar::deregister( assert_ok!(Registrar::deregister(
Origin::root(), Origin::root(),
32.into(), 1032.into(),
)); ));
run_to_session(4); run_to_session(4);
assert!(paras::Module::<Test>::lifecycle(32.into()).is_none()); assert!(paras::Module::<Test>::lifecycle(1032.into()).is_none());
assert_eq!(Balances::reserved_balance(&1), 0); assert_eq!(Balances::reserved_balance(&1), 0);
}); });
} }
...@@ -746,26 +794,26 @@ mod tests { ...@@ -746,26 +794,26 @@ mod tests {
fn deregister_handles_basic_errors() { fn deregister_handles_basic_errors() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
run_to_block(1); run_to_block(1);
assert!(!Parachains::is_parathread(32.into())); assert!(!Parachains::is_parathread(1032.into()));
assert_ok!(Registrar::register( assert_ok!(Registrar::register(
Origin::signed(1), Origin::signed(1),
32.into(), 1032.into(),
test_genesis_head(32), test_genesis_head(32),
test_validation_code(32), test_validation_code(32),
)); ));
run_to_session(2); run_to_session(2);
assert!(Parachains::is_parathread(32.into())); assert!(Parachains::is_parathread(1032.into()));
// Owner check // Owner check
assert_noop!(Registrar::deregister( assert_noop!(Registrar::deregister(
Origin::signed(2), Origin::signed(2),
32.into(), 1032.into(),
), BadOrigin); ), BadOrigin);
assert_ok!(Registrar::make_parachain(32.into())); assert_ok!(Registrar::make_parachain(1032.into()));
run_to_session(4); run_to_session(4);
// Cant directly deregister parachain // Cant directly deregister parachain
assert_noop!(Registrar::deregister( assert_noop!(Registrar::deregister(
Origin::root(), Origin::root(),
32.into(), 1032.into(),
), Error::<Test>::NotParathread); ), Error::<Test>::NotParathread);
}); });
} }
...@@ -773,57 +821,57 @@ mod tests { ...@@ -773,57 +821,57 @@ mod tests {
#[test] #[test]
fn swap_works() { fn swap_works() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
// Successfully register 23 and 32 // Successfully register 1023 and 1032
assert_ok!(Registrar::register( assert_ok!(Registrar::register(
Origin::signed(1), Origin::signed(1),
23.into(), 1023.into(),
test_genesis_head(<Test as super::Config>::MaxHeadSize::get() as usize), test_genesis_head(<Test as super::Config>::MaxHeadSize::get() as usize),
test_validation_code(<Test as super::Config>::MaxCodeSize::get() as usize), test_validation_code(<Test as super::Config>::MaxCodeSize::get() as usize),
)); ));
assert_ok!(Registrar::register( assert_ok!(Registrar::register(
Origin::signed(2), Origin::signed(2),
32.into(), 1032.into(),
test_genesis_head(<Test as super::Config>::MaxHeadSize::get() as usize), test_genesis_head(<Test as super::Config>::MaxHeadSize::get() as usize),
test_validation_code(<Test as super::Config>::MaxCodeSize::get() as usize), test_validation_code(<Test as super::Config>::MaxCodeSize::get() as usize),
)); ));
run_to_session(2); run_to_session(2);
// Upgrade 23 into a parachain // Upgrade 1023 into a parachain
assert_ok!(Registrar::make_parachain(23.into())); assert_ok!(Registrar::make_parachain(1023.into()));
run_to_session(4); run_to_session(4);
// Roles are as we expect // Roles are as we expect
assert!(Parachains::is_parachain(23.into())); assert!(Parachains::is_parachain(1023.into()));
assert!(!Parachains::is_parathread(23.into())); assert!(!Parachains::is_parathread(1023.into()));
assert!(!Parachains::is_parachain(32.into())); assert!(!Parachains::is_parachain(1032.into()));
assert!(Parachains::is_parathread(32.into())); assert!(Parachains::is_parathread(1032.into()));
// Both paras initiate a swap // Both paras initiate a swap
assert_ok!(Registrar::swap( assert_ok!(Registrar::swap(
para_origin(23.into()), para_origin(1023.into()),
23.into(), 1023.into(),
32.into(), 1032.into(),
)); ));
assert_ok!(Registrar::swap( assert_ok!(Registrar::swap(
para_origin(32.into()), para_origin(1032.into()),
32.into(), 1032.into(),
23.into(), 1023.into(),
)); ));
run_to_session(6); run_to_session(6);
// Deregister a parathread that was originally a parachain // Deregister a parathread that was originally a parachain
assert_eq!(Parachains::lifecycle(23u32.into()), Some(ParaLifecycle::Parathread)); assert_eq!(Parachains::lifecycle(1023.into()), Some(ParaLifecycle::Parathread));
assert_ok!(Registrar::deregister(runtime_parachains::Origin::Parachain(23u32.into()).into(), 23u32.into())); assert_ok!(Registrar::deregister(runtime_parachains::Origin::Parachain(1023.into()).into(), 1023.into()));
run_to_block(21); run_to_block(21);
// Roles are swapped // Roles are swapped
assert!(!Parachains::is_parachain(23.into())); assert!(!Parachains::is_parachain(1023.into()));
assert!(Parachains::is_parathread(23.into())); assert!(Parachains::is_parathread(1023.into()));
assert!(Parachains::is_parachain(32.into())); assert!(Parachains::is_parachain(1032.into()));
assert!(!Parachains::is_parathread(32.into())); assert!(!Parachains::is_parathread(1032.into()));
}); });
} }
...@@ -834,7 +882,7 @@ mod tests { ...@@ -834,7 +882,7 @@ mod tests {
assert_ok!(Registrar::register( assert_ok!(Registrar::register(
Origin::signed(1), Origin::signed(1),
1u32.into(), 1001.into(),
vec![1; 3].into(), vec![1; 3].into(),
vec![1, 2, 3].into() vec![1, 2, 3].into()
)); ));
...@@ -842,15 +890,15 @@ mod tests { ...@@ -842,15 +890,15 @@ mod tests {
// 2 session changes to fully onboard. // 2 session changes to fully onboard.
run_to_session(2); run_to_session(2);
assert_eq!(Parachains::lifecycle(1u32.into()), Some(ParaLifecycle::Parathread)); assert_eq!(Parachains::lifecycle(1001.into()), Some(ParaLifecycle::Parathread));
assert_ok!(Registrar::deregister(Origin::root(), 1u32.into())); assert_ok!(Registrar::deregister(Origin::root(), 1001.into()));
// Cannot register while it is offboarding. // Cannot register while it is offboarding.
run_to_session(3); run_to_session(3);