Session Delayed Para Changes / Actions Queue (#2406)

* initial implementation of lifecycles and upgrades

* clean up a bit

* fix doc comment

* more rigid lifecycle checks

* include paras which are transitioning, and lifecycle query

* format guide

* update api

* update guide

* explicit outgoing state, fix genesis

* handle outgoing with transitioning paras

* do not include transitioning paras in identifier

* Update roadmap/implementers-guide/src/runtime/paras.md

* Update roadmap/implementers-guide/src/runtime/paras.md

* Update roadmap/implementers-guide/src/runtime/paras.md

* Apply suggestions from code review

* Use matches macro

* Correct terms

* Apply suggestions from code review

* actions queue

* Revert "actions queue"

This reverts commit b2e9011ec8937d6c73e99292416c9692aeb30f73.

* collapse onboarding state

* starting actions queue

* consolidate actions queue

* schedule para initialize result

* more actions queue for upgrade/downgrade

* clean up with fully implemented actions queue

* fix tests

* fix scheduler tests

* fix hrmp tests

* fix test

* doc fixes

* fix hrmp test w/ valid para

* Update paras.md

* fix paras registrar

* Update propose_parachain.rs

* fix merge

* Introduce "shared" module

* fix rococo build

* fix up and use shared

* guide updates

* add shared config to common tests

* add shared to test-runtime

* remove println

* fix note

Co-authored-by: Gavin Wood <gavin@parity.io>
This commit is contained in:
Shawn Tabrizi
2021-02-18 23:20:18 -04:00
committed by GitHub
parent 006602eff2
commit a5defa7c7f
20 changed files with 654 additions and 698 deletions
+47 -37
View File
@@ -88,6 +88,8 @@ decl_error! {
ParathreadsRegistrationDisabled,
/// The validation code provided doesn't start with the Wasm file magic string.
DefinitelyNotWasm,
/// Cannot deregister para
CannotDeregister,
}
}
@@ -113,22 +115,18 @@ decl_module! {
ensure!(!Paras::contains_key(id), Error::<T>::ParaAlreadyExists);
let outgoing = <paras::Module<T>>::outgoing_paras();
ensure!(outgoing.binary_search(&id).is_err(), Error::<T>::ParaAlreadyExists);
<T as Config>::Currency::reserve(&who, T::ParathreadDeposit::get())?;
<Debtors<T>>::insert(id, who);
Paras::insert(id, false);
let genesis = ParaGenesisArgs {
genesis_head,
validation_code,
parachain: false,
};
ensure!(paras::Module::<T>::can_schedule_para_initialize(&id, &genesis), Error::<T>::ParaAlreadyExists);
<T as Config>::Currency::reserve(&who, T::ParathreadDeposit::get())?;
runtime_parachains::schedule_para_initialize::<T>(id, genesis);
<Debtors<T>>::insert(id, who);
Paras::insert(id, false);
// Checked this shouldn't fail above.
let _ = runtime_parachains::schedule_para_initialize::<T>(id, genesis);
Ok(())
}
@@ -146,14 +144,16 @@ decl_module! {
ensure!(ParathreadsRegistrationEnabled::get(), Error::<T>::ParathreadsRegistrationDisabled);
let is_parachain = Paras::take(id).ok_or(Error::<T>::InvalidChainId)?;
let is_parachain = Paras::get(id).ok_or(Error::<T>::InvalidChainId)?;
ensure!(!is_parachain, Error::<T>::InvalidThreadId);
runtime_parachains::schedule_para_cleanup::<T>(id).map_err(|_| Error::<T>::CannotDeregister)?;
let debtor = <Debtors<T>>::take(id);
let _ = <T as Config>::Currency::unreserve(&debtor, T::ParathreadDeposit::get());
runtime_parachains::schedule_para_cleanup::<T>(id);
Paras::remove(&id);
PendingSwap::remove(&id);
Ok(())
}
@@ -176,7 +176,6 @@ decl_module! {
Ok(())
}
/// Swap a parachain with another parachain or parathread. The origin must be a `Parachain`.
/// The swap will happen only if there is already an opposite swap pending. If there is not,
/// the swap will be stored in the pending swaps map, ready for a later confirmatory swap.
@@ -222,30 +221,27 @@ impl<T: Config> Module<T> {
ensure!(!Paras::contains_key(id), Error::<T>::ParaAlreadyExists);
ensure!(validation_code.0.starts_with(WASM_MAGIC), Error::<T>::DefinitelyNotWasm);
let outgoing = <paras::Module<T>>::outgoing_paras();
ensure!(outgoing.binary_search(&id).is_err(), Error::<T>::ParaAlreadyExists);
Paras::insert(id, true);
let genesis = ParaGenesisArgs {
genesis_head,
validation_code,
parachain: true,
};
runtime_parachains::schedule_para_initialize::<T>(id, genesis);
runtime_parachains::schedule_para_initialize::<T>(id, genesis).map_err(|_| Error::<T>::ParaAlreadyExists)?;
Paras::insert(id, true);
Ok(())
}
/// Deregister a parachain with the given ID. Must be called by root.
pub fn deregister_parachain(id: ParaId) -> DispatchResult {
let is_parachain = Paras::take(id).ok_or(Error::<T>::InvalidChainId)?;
let is_parachain = Paras::get(id).ok_or(Error::<T>::InvalidChainId)?;
ensure!(is_parachain, Error::<T>::InvalidChainId);
runtime_parachains::schedule_para_cleanup::<T>(id);
runtime_parachains::schedule_para_cleanup::<T>(id).map_err(|_| Error::<T>::CannotDeregister)?;
Paras::remove(&id);
PendingSwap::remove(&id);
Ok(())
}
@@ -267,10 +263,13 @@ mod tests {
use frame_system::limits;
use frame_support::{
traits::{Randomness, OnInitialize, OnFinalize},
assert_ok, parameter_types,
assert_ok, assert_noop, parameter_types,
};
use keyring::Sr25519Keyring;
use runtime_parachains::{initializer, configuration, inclusion, session_info, scheduler, dmp, ump, hrmp};
use runtime_parachains::{
initializer, configuration, inclusion, session_info, scheduler, dmp, ump, hrmp, shared,
ParaLifecycle,
};
use frame_support::traits::OneSessionHandler;
use crate::paras_registrar;
@@ -309,7 +308,7 @@ mod tests {
parameter_types! {
pub const BlockHashCount: u32 = 250;
pub BlockWeights: limits::BlockWeights =
limits::BlockWeights::with_sensible_defaults(4 * 1024 * 1024, NORMAL_RATIO);
frame_system::limits::BlockWeights::simple_max(1024);
pub BlockLength: limits::BlockLength =
limits::BlockLength::max_with_normal_ratio(4 * 1024 * 1024, NORMAL_RATIO);
}
@@ -370,7 +369,7 @@ mod tests {
}
parameter_types! {
pub const Period: BlockNumber = 1;
pub const Period: BlockNumber = 3;
pub const Offset: BlockNumber = 0;
pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17);
pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE;
@@ -432,6 +431,8 @@ mod tests {
type WeightInfo = ();
}
impl shared::Config for Test {}
impl dmp::Config for Test {}
impl ump::Config for Test {
@@ -590,7 +591,7 @@ mod tests {
Initializer::on_finalize(System::block_number());
}
// Session change every 3 blocks.
if (b + 1) % 3 == 0 {
if (b + 1) % Period::get() == 0 {
println!("New session at {}", System::block_number());
Initializer::on_new_session(
false,
@@ -601,6 +602,7 @@ mod tests {
System::set_block_number(b + 1);
println!("Initializing {}", System::block_number());
System::on_initialize(System::block_number());
Session::on_initialize(System::block_number());
Initializer::on_initialize(System::block_number());
}
}
@@ -643,7 +645,7 @@ mod tests {
assert_eq!(Balances::free_balance(3u64) + ParathreadDeposit::get(), orig_bal);
assert_eq!(Balances::reserved_balance(3u64), ParathreadDeposit::get());
run_to_block(3);
run_to_block(10);
assert_ok!(Registrar::deregister_parachain(2u32.into()));
@@ -690,10 +692,12 @@ mod tests {
assert_ok!(Registrar::swap(runtime_parachains::Origin::Parachain(2u32.into()).into(), 8u32.into()));
assert_ok!(Registrar::swap(runtime_parachains::Origin::Parachain(8u32.into()).into(), 2u32.into()));
run_to_block(15);
// Deregister a parathread that was originally a parachain
assert_ok!(Registrar::deregister_parathread(runtime_parachains::Origin::Parachain(2u32.into()).into()));
run_to_block(12);
run_to_block(21);
// Funds are correctly returned
assert_eq!(Balances::free_balance(1), initial_1_balance);
@@ -712,20 +716,26 @@ mod tests {
WASM_MAGIC.to_vec().into(),
));
run_to_block(4);
// 2 session changes to fully onboard.
run_to_block(12);
assert_eq!(Parachains::lifecycle(1u32.into()), Some(ParaLifecycle::Parachain));
assert_ok!(Registrar::deregister_parachain(1u32.into()));
run_to_block(5);
run_to_block(13);
assert!(Registrar::register_parachain(
assert_eq!(Parachains::lifecycle(1u32.into()), Some(ParaLifecycle::OffboardingParachain));
assert_noop!(Registrar::register_parachain(
1u32.into(),
vec![1; 3].into(),
WASM_MAGIC.to_vec().into(),
).is_err());
), Error::<Test>::ParaAlreadyExists);
// The session will be changed on the 6th block, as part of finalization. The change
// will be observed on the 7th.
run_to_block(7);
// Need 2 session changes to see the effect, which takes place by block 13.
run_to_block(18);
assert!(Parachains::lifecycle(1u32.into()).is_none());
assert_ok!(Registrar::register_parachain(
1u32.into(),
vec![1; 3].into(),