Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
paras: initialize_para_now and ParachainsCache
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
pepyakin committed Feb 21, 2022
1 parent db56d0b commit 92c0ce5
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 70 deletions.
10 changes: 6 additions & 4 deletions runtime/parachains/src/hrmp/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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);
}

Expand Down
146 changes: 80 additions & 66 deletions runtime/parachains/src/paras/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand Down Expand Up @@ -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(&parachains);

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
}
}

Expand Down Expand Up @@ -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();

Expand All @@ -1093,49 +1079,23 @@ impl<T: Config> Pallet<T> {
},
Some(ParaLifecycle::Onboarding) => {
if let Some(genesis_data) = <Self as Store>::UpcomingParasGenesis::take(&para) {
if genesis_data.parachain {
if let Err(i) = parachains.binary_search(&para) {
parachains.insert(i, para);
}
ParaLifecycles::<T>::insert(&para, ParaLifecycle::Parachain);
} else {
ParaLifecycles::<T>::insert(&para, 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(&para, code_hash);
}

<Self as Store>::Heads::insert(&para, 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(&para) {
parachains.insert(i, para);
}
parachains.add(para);
ParaLifecycles::<T>::insert(&para, ParaLifecycle::Parachain);
},
// Downgrade a parachain to a parathread
Some(ParaLifecycle::DowngradingParachain) => {
if let Ok(i) = parachains.binary_search(&para) {
parachains.remove(i);
}
parachains.remove(para);
ParaLifecycles::<T>::insert(&para, ParaLifecycle::Parathread);
},
// Offboard a parathread or parachain from the system
Some(ParaLifecycle::OffboardingParachain) |
Some(ParaLifecycle::OffboardingParathread) => {
if let Ok(i) = parachains.binary_search(&para) {
parachains.remove(i);
}
parachains.remove(para);

<Self as Store>::Heads::remove(&para);
<Self as Store>::FutureCodeUpgrades::remove(&para);
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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);
}

// 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);
}

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>,
}

// .. and immediately apply them.
Self::apply_actions_queue(Self::scheduled_session());
impl<T: Config> ParachainsCache<T> {
pub fn new() -> Self {
Self { parachains: None, _config: PhantomData }
}

// ensure it has become a para.
ensure!(
ParaLifecycles::<T>::get(id) == Some(ParaLifecycle::Parachain),
"Parachain not created properly"
);
Ok(())
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(&parachains);
}
}
}

0 comments on commit 92c0ce5

Please sign in to comment.