mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 09:21:04 +00:00
paras: initialize_para_now and ParachainsCache (#4934)
This commit adds a new primitive called `ParachainsCache` to manipulate the `Parachains` storage entry in a more convenient way. Then, on top of that, this commit changes the logic of `initialize_para_now` so that it is identical to what is used for initialization of onboarding.
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
use crate::{
|
||||
configuration::Pallet as Configuration,
|
||||
hrmp::{Pallet as Hrmp, *},
|
||||
paras::Pallet as Paras,
|
||||
paras::{Pallet as Paras, ParachainsCache},
|
||||
shared::Pallet as Shared,
|
||||
};
|
||||
use frame_support::{assert_ok, traits::Currency};
|
||||
@@ -26,14 +26,16 @@ type BalanceOf<T> =
|
||||
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
|
||||
|
||||
fn register_parachain_with_balance<T: Config>(id: ParaId, balance: BalanceOf<T>) {
|
||||
assert_ok!(Paras::<T>::initialize_para_now(
|
||||
let mut parachains = ParachainsCache::new();
|
||||
Paras::<T>::initialize_para_now(
|
||||
&mut parachains,
|
||||
id,
|
||||
crate::paras::ParaGenesisArgs {
|
||||
&crate::paras::ParaGenesisArgs {
|
||||
parachain: true,
|
||||
genesis_head: vec![1].into(),
|
||||
validation_code: vec![1].into(),
|
||||
},
|
||||
));
|
||||
);
|
||||
T::Currency::make_free_balance_be(&id.into_account(), balance);
|
||||
}
|
||||
|
||||
|
||||
@@ -537,6 +537,8 @@ pub mod pallet {
|
||||
StorageValue<_, Vec<ValidationCodeHash>, ValueQuery>;
|
||||
|
||||
/// All parachains. Ordered ascending by `ParaId`. Parathreads are not included.
|
||||
///
|
||||
/// Consider using the [`ParachainsCache`] type of modifying.
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn parachains)]
|
||||
pub(crate) type Parachains<T: Config> = StorageValue<_, Vec<ParaId>, ValueQuery>;
|
||||
@@ -683,30 +685,14 @@ pub mod pallet {
|
||||
#[pallet::genesis_build]
|
||||
impl<T: Config> GenesisBuild<T> for GenesisConfig {
|
||||
fn build(&self) {
|
||||
let mut parachains: Vec<_> = self
|
||||
.paras
|
||||
.iter()
|
||||
.filter(|(_, args)| args.parachain)
|
||||
.map(|&(ref id, _)| id)
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
parachains.sort();
|
||||
parachains.dedup();
|
||||
|
||||
Parachains::<T>::put(¶chains);
|
||||
|
||||
let mut parachains = ParachainsCache::new();
|
||||
for (id, genesis_args) in &self.paras {
|
||||
let code_hash = genesis_args.validation_code.hash();
|
||||
<Pallet<T>>::increase_code_ref(&code_hash, &genesis_args.validation_code);
|
||||
<Pallet<T> as Store>::CurrentCodeHash::insert(&id, &code_hash);
|
||||
<Pallet<T> as Store>::Heads::insert(&id, &genesis_args.genesis_head);
|
||||
if genesis_args.parachain {
|
||||
ParaLifecycles::<T>::insert(&id, ParaLifecycle::Parachain);
|
||||
} else {
|
||||
ParaLifecycles::<T>::insert(&id, ParaLifecycle::Parathread);
|
||||
if genesis_args.validation_code.0.is_empty() {
|
||||
panic!("empty validation code is not allowed in genesis");
|
||||
}
|
||||
Pallet::<T>::initialize_para_now(&mut parachains, *id, genesis_args);
|
||||
}
|
||||
// parachains are flushed on drop
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1082,7 +1068,7 @@ impl<T: Config> Pallet<T> {
|
||||
// Returns the list of outgoing paras from the actions queue.
|
||||
fn apply_actions_queue(session: SessionIndex) -> Vec<ParaId> {
|
||||
let actions = ActionsQueue::<T>::take(session);
|
||||
let mut parachains = <Self as Store>::Parachains::get();
|
||||
let mut parachains = ParachainsCache::new();
|
||||
let now = <frame_system::Pallet<T>>::block_number();
|
||||
let mut outgoing = Vec::new();
|
||||
|
||||
@@ -1093,49 +1079,23 @@ impl<T: Config> Pallet<T> {
|
||||
},
|
||||
Some(ParaLifecycle::Onboarding) => {
|
||||
if let Some(genesis_data) = <Self as Store>::UpcomingParasGenesis::take(¶) {
|
||||
if genesis_data.parachain {
|
||||
if let Err(i) = parachains.binary_search(¶) {
|
||||
parachains.insert(i, para);
|
||||
}
|
||||
ParaLifecycles::<T>::insert(¶, ParaLifecycle::Parachain);
|
||||
} else {
|
||||
ParaLifecycles::<T>::insert(¶, ParaLifecycle::Parathread);
|
||||
}
|
||||
|
||||
// HACK: see the notice in `schedule_para_initialize`.
|
||||
//
|
||||
// Apparently, this is left over from a prior version of the runtime.
|
||||
// To handle this we just insert the code and link the current code hash
|
||||
// to it.
|
||||
if !genesis_data.validation_code.0.is_empty() {
|
||||
let code_hash = genesis_data.validation_code.hash();
|
||||
Self::increase_code_ref(&code_hash, &genesis_data.validation_code);
|
||||
<Self as Store>::CurrentCodeHash::insert(¶, code_hash);
|
||||
}
|
||||
|
||||
<Self as Store>::Heads::insert(¶, genesis_data.genesis_head);
|
||||
Self::initialize_para_now(&mut parachains, para, &genesis_data);
|
||||
}
|
||||
},
|
||||
// Upgrade a parathread to a parachain
|
||||
Some(ParaLifecycle::UpgradingParathread) => {
|
||||
if let Err(i) = parachains.binary_search(¶) {
|
||||
parachains.insert(i, para);
|
||||
}
|
||||
parachains.add(para);
|
||||
ParaLifecycles::<T>::insert(¶, ParaLifecycle::Parachain);
|
||||
},
|
||||
// Downgrade a parachain to a parathread
|
||||
Some(ParaLifecycle::DowngradingParachain) => {
|
||||
if let Ok(i) = parachains.binary_search(¶) {
|
||||
parachains.remove(i);
|
||||
}
|
||||
parachains.remove(para);
|
||||
ParaLifecycles::<T>::insert(¶, ParaLifecycle::Parathread);
|
||||
},
|
||||
// Offboard a parathread or parachain from the system
|
||||
Some(ParaLifecycle::OffboardingParachain) |
|
||||
Some(ParaLifecycle::OffboardingParathread) => {
|
||||
if let Ok(i) = parachains.binary_search(¶) {
|
||||
parachains.remove(i);
|
||||
}
|
||||
parachains.remove(para);
|
||||
|
||||
<Self as Store>::Heads::remove(¶);
|
||||
<Self as Store>::FutureCodeUpgrades::remove(¶);
|
||||
@@ -1178,8 +1138,8 @@ impl<T: Config> Pallet<T> {
|
||||
});
|
||||
}
|
||||
|
||||
// Place the new parachains set in storage.
|
||||
<Self as Store>::Parachains::set(parachains);
|
||||
// Persist parachains into the storage explicitly.
|
||||
drop(parachains);
|
||||
|
||||
return outgoing
|
||||
}
|
||||
@@ -1994,19 +1954,73 @@ impl<T: Config> Pallet<T> {
|
||||
Heads::<T>::insert(para_id, head_data);
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
pub(crate) fn initialize_para_now(id: ParaId, genesis: ParaGenesisArgs) -> DispatchResult {
|
||||
// first queue this para actions..
|
||||
let _ = Self::schedule_para_initialize(id, genesis)?;
|
||||
/// A low-level function to eagerly initialize a given para.
|
||||
pub(crate) fn initialize_para_now(
|
||||
parachains: &mut ParachainsCache<T>,
|
||||
id: ParaId,
|
||||
genesis_data: &ParaGenesisArgs,
|
||||
) {
|
||||
if genesis_data.parachain {
|
||||
parachains.add(id);
|
||||
ParaLifecycles::<T>::insert(&id, ParaLifecycle::Parachain);
|
||||
} else {
|
||||
ParaLifecycles::<T>::insert(&id, ParaLifecycle::Parathread);
|
||||
}
|
||||
|
||||
// .. and immediately apply them.
|
||||
Self::apply_actions_queue(Self::scheduled_session());
|
||||
// HACK: see the notice in `schedule_para_initialize`.
|
||||
//
|
||||
// Apparently, this is left over from a prior version of the runtime.
|
||||
// To handle this we just insert the code and link the current code hash
|
||||
// to it.
|
||||
if !genesis_data.validation_code.0.is_empty() {
|
||||
let code_hash = genesis_data.validation_code.hash();
|
||||
Self::increase_code_ref(&code_hash, &genesis_data.validation_code);
|
||||
CurrentCodeHash::<T>::insert(&id, code_hash);
|
||||
}
|
||||
|
||||
// ensure it has become a para.
|
||||
ensure!(
|
||||
ParaLifecycles::<T>::get(id) == Some(ParaLifecycle::Parachain),
|
||||
"Parachain not created properly"
|
||||
);
|
||||
Ok(())
|
||||
Heads::<T>::insert(&id, &genesis_data.genesis_head);
|
||||
}
|
||||
}
|
||||
|
||||
/// An overlay over the `Parachains` storage entry that provides a convenient interface for adding
|
||||
/// or removing parachains in bulk.
|
||||
pub(crate) struct ParachainsCache<T: Config> {
|
||||
// `None` here means the parachains list has not been accessed yet, nevermind modified.
|
||||
parachains: Option<Vec<ParaId>>,
|
||||
_config: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: Config> ParachainsCache<T> {
|
||||
pub fn new() -> Self {
|
||||
Self { parachains: None, _config: PhantomData }
|
||||
}
|
||||
|
||||
fn ensure_initialized(&mut self) -> &mut Vec<ParaId> {
|
||||
self.parachains.get_or_insert_with(|| Parachains::<T>::get())
|
||||
}
|
||||
|
||||
/// Adds the given para id to the list.
|
||||
pub fn add(&mut self, id: ParaId) {
|
||||
let parachains = self.ensure_initialized();
|
||||
if let Err(i) = parachains.binary_search(&id) {
|
||||
parachains.insert(i, id);
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes the given para id from the list of parachains. Does nothing if the id is not in the
|
||||
/// list.
|
||||
pub fn remove(&mut self, id: ParaId) {
|
||||
let parachains = self.ensure_initialized();
|
||||
if let Ok(i) = parachains.binary_search(&id) {
|
||||
parachains.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> Drop for ParachainsCache<T> {
|
||||
fn drop(&mut self) {
|
||||
if let Some(parachains) = self.parachains.take() {
|
||||
Parachains::<T>::put(¶chains);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1020,6 +1020,7 @@ fn pvf_check_coalescing_onboarding_and_upgrade() {
|
||||
|
||||
let a = ParaId::from(111);
|
||||
let b = ParaId::from(222);
|
||||
let existing_code: ValidationCode = vec![1, 2, 3].into();
|
||||
let validation_code: ValidationCode = vec![3, 2, 1].into();
|
||||
|
||||
let paras = vec![(
|
||||
@@ -1027,7 +1028,7 @@ fn pvf_check_coalescing_onboarding_and_upgrade() {
|
||||
ParaGenesisArgs {
|
||||
parachain: true,
|
||||
genesis_head: Default::default(),
|
||||
validation_code: ValidationCode(vec![]), // valid since in genesis
|
||||
validation_code: existing_code,
|
||||
},
|
||||
)];
|
||||
|
||||
@@ -1159,6 +1160,7 @@ fn pvf_check_onboarding_reject_on_expiry() {
|
||||
#[test]
|
||||
fn pvf_check_upgrade_reject() {
|
||||
let a = ParaId::from(111);
|
||||
let old_code: ValidationCode = vec![1, 2, 3].into();
|
||||
let new_code: ValidationCode = vec![3, 2, 1].into();
|
||||
|
||||
let paras = vec![(
|
||||
@@ -1166,7 +1168,7 @@ fn pvf_check_upgrade_reject() {
|
||||
ParaGenesisArgs {
|
||||
parachain: false,
|
||||
genesis_head: Default::default(),
|
||||
validation_code: ValidationCode(vec![]), // valid since in genesis
|
||||
validation_code: old_code,
|
||||
},
|
||||
)];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user