mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 12:51:02 +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::{
|
use crate::{
|
||||||
configuration::Pallet as Configuration,
|
configuration::Pallet as Configuration,
|
||||||
hrmp::{Pallet as Hrmp, *},
|
hrmp::{Pallet as Hrmp, *},
|
||||||
paras::Pallet as Paras,
|
paras::{Pallet as Paras, ParachainsCache},
|
||||||
shared::Pallet as Shared,
|
shared::Pallet as Shared,
|
||||||
};
|
};
|
||||||
use frame_support::{assert_ok, traits::Currency};
|
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;
|
<<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>) {
|
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,
|
id,
|
||||||
crate::paras::ParaGenesisArgs {
|
&crate::paras::ParaGenesisArgs {
|
||||||
parachain: true,
|
parachain: true,
|
||||||
genesis_head: vec![1].into(),
|
genesis_head: vec![1].into(),
|
||||||
validation_code: vec![1].into(),
|
validation_code: vec![1].into(),
|
||||||
},
|
},
|
||||||
));
|
);
|
||||||
T::Currency::make_free_balance_be(&id.into_account(), balance);
|
T::Currency::make_free_balance_be(&id.into_account(), balance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -537,6 +537,8 @@ pub mod pallet {
|
|||||||
StorageValue<_, Vec<ValidationCodeHash>, ValueQuery>;
|
StorageValue<_, Vec<ValidationCodeHash>, ValueQuery>;
|
||||||
|
|
||||||
/// All parachains. Ordered ascending by `ParaId`. Parathreads are not included.
|
/// All parachains. Ordered ascending by `ParaId`. Parathreads are not included.
|
||||||
|
///
|
||||||
|
/// Consider using the [`ParachainsCache`] type of modifying.
|
||||||
#[pallet::storage]
|
#[pallet::storage]
|
||||||
#[pallet::getter(fn parachains)]
|
#[pallet::getter(fn parachains)]
|
||||||
pub(crate) type Parachains<T: Config> = StorageValue<_, Vec<ParaId>, ValueQuery>;
|
pub(crate) type Parachains<T: Config> = StorageValue<_, Vec<ParaId>, ValueQuery>;
|
||||||
@@ -683,30 +685,14 @@ pub mod pallet {
|
|||||||
#[pallet::genesis_build]
|
#[pallet::genesis_build]
|
||||||
impl<T: Config> GenesisBuild<T> for GenesisConfig {
|
impl<T: Config> GenesisBuild<T> for GenesisConfig {
|
||||||
fn build(&self) {
|
fn build(&self) {
|
||||||
let mut parachains: Vec<_> = self
|
let mut parachains = ParachainsCache::new();
|
||||||
.paras
|
|
||||||
.iter()
|
|
||||||
.filter(|(_, args)| args.parachain)
|
|
||||||
.map(|&(ref id, _)| id)
|
|
||||||
.cloned()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
parachains.sort();
|
|
||||||
parachains.dedup();
|
|
||||||
|
|
||||||
Parachains::<T>::put(¶chains);
|
|
||||||
|
|
||||||
for (id, genesis_args) in &self.paras {
|
for (id, genesis_args) in &self.paras {
|
||||||
let code_hash = genesis_args.validation_code.hash();
|
if genesis_args.validation_code.0.is_empty() {
|
||||||
<Pallet<T>>::increase_code_ref(&code_hash, &genesis_args.validation_code);
|
panic!("empty validation code is not allowed in genesis");
|
||||||
<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);
|
|
||||||
}
|
}
|
||||||
|
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.
|
// Returns the list of outgoing paras from the actions queue.
|
||||||
fn apply_actions_queue(session: SessionIndex) -> Vec<ParaId> {
|
fn apply_actions_queue(session: SessionIndex) -> Vec<ParaId> {
|
||||||
let actions = ActionsQueue::<T>::take(session);
|
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 now = <frame_system::Pallet<T>>::block_number();
|
||||||
let mut outgoing = Vec::new();
|
let mut outgoing = Vec::new();
|
||||||
|
|
||||||
@@ -1093,49 +1079,23 @@ impl<T: Config> Pallet<T> {
|
|||||||
},
|
},
|
||||||
Some(ParaLifecycle::Onboarding) => {
|
Some(ParaLifecycle::Onboarding) => {
|
||||||
if let Some(genesis_data) = <Self as Store>::UpcomingParasGenesis::take(¶) {
|
if let Some(genesis_data) = <Self as Store>::UpcomingParasGenesis::take(¶) {
|
||||||
if genesis_data.parachain {
|
Self::initialize_para_now(&mut parachains, para, &genesis_data);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Upgrade a parathread to a parachain
|
// Upgrade a parathread to a parachain
|
||||||
Some(ParaLifecycle::UpgradingParathread) => {
|
Some(ParaLifecycle::UpgradingParathread) => {
|
||||||
if let Err(i) = parachains.binary_search(¶) {
|
parachains.add(para);
|
||||||
parachains.insert(i, para);
|
|
||||||
}
|
|
||||||
ParaLifecycles::<T>::insert(¶, ParaLifecycle::Parachain);
|
ParaLifecycles::<T>::insert(¶, ParaLifecycle::Parachain);
|
||||||
},
|
},
|
||||||
// Downgrade a parachain to a parathread
|
// Downgrade a parachain to a parathread
|
||||||
Some(ParaLifecycle::DowngradingParachain) => {
|
Some(ParaLifecycle::DowngradingParachain) => {
|
||||||
if let Ok(i) = parachains.binary_search(¶) {
|
parachains.remove(para);
|
||||||
parachains.remove(i);
|
|
||||||
}
|
|
||||||
ParaLifecycles::<T>::insert(¶, ParaLifecycle::Parathread);
|
ParaLifecycles::<T>::insert(¶, ParaLifecycle::Parathread);
|
||||||
},
|
},
|
||||||
// Offboard a parathread or parachain from the system
|
// Offboard a parathread or parachain from the system
|
||||||
Some(ParaLifecycle::OffboardingParachain) |
|
Some(ParaLifecycle::OffboardingParachain) |
|
||||||
Some(ParaLifecycle::OffboardingParathread) => {
|
Some(ParaLifecycle::OffboardingParathread) => {
|
||||||
if let Ok(i) = parachains.binary_search(¶) {
|
parachains.remove(para);
|
||||||
parachains.remove(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
<Self as Store>::Heads::remove(¶);
|
<Self as Store>::Heads::remove(¶);
|
||||||
<Self as Store>::FutureCodeUpgrades::remove(¶);
|
<Self as Store>::FutureCodeUpgrades::remove(¶);
|
||||||
@@ -1178,8 +1138,8 @@ impl<T: Config> Pallet<T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Place the new parachains set in storage.
|
// Persist parachains into the storage explicitly.
|
||||||
<Self as Store>::Parachains::set(parachains);
|
drop(parachains);
|
||||||
|
|
||||||
return outgoing
|
return outgoing
|
||||||
}
|
}
|
||||||
@@ -1994,19 +1954,73 @@ impl<T: Config> Pallet<T> {
|
|||||||
Heads::<T>::insert(para_id, head_data);
|
Heads::<T>::insert(para_id, head_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "runtime-benchmarks")]
|
/// A low-level function to eagerly initialize a given para.
|
||||||
pub(crate) fn initialize_para_now(id: ParaId, genesis: ParaGenesisArgs) -> DispatchResult {
|
pub(crate) fn initialize_para_now(
|
||||||
// first queue this para actions..
|
parachains: &mut ParachainsCache<T>,
|
||||||
let _ = Self::schedule_para_initialize(id, genesis)?;
|
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.
|
// HACK: see the notice in `schedule_para_initialize`.
|
||||||
Self::apply_actions_queue(Self::scheduled_session());
|
//
|
||||||
|
// 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.
|
Heads::<T>::insert(&id, &genesis_data.genesis_head);
|
||||||
ensure!(
|
}
|
||||||
ParaLifecycles::<T>::get(id) == Some(ParaLifecycle::Parachain),
|
}
|
||||||
"Parachain not created properly"
|
|
||||||
);
|
/// An overlay over the `Parachains` storage entry that provides a convenient interface for adding
|
||||||
Ok(())
|
/// 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 a = ParaId::from(111);
|
||||||
let b = ParaId::from(222);
|
let b = ParaId::from(222);
|
||||||
|
let existing_code: ValidationCode = vec![1, 2, 3].into();
|
||||||
let validation_code: ValidationCode = vec![3, 2, 1].into();
|
let validation_code: ValidationCode = vec![3, 2, 1].into();
|
||||||
|
|
||||||
let paras = vec![(
|
let paras = vec![(
|
||||||
@@ -1027,7 +1028,7 @@ fn pvf_check_coalescing_onboarding_and_upgrade() {
|
|||||||
ParaGenesisArgs {
|
ParaGenesisArgs {
|
||||||
parachain: true,
|
parachain: true,
|
||||||
genesis_head: Default::default(),
|
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]
|
#[test]
|
||||||
fn pvf_check_upgrade_reject() {
|
fn pvf_check_upgrade_reject() {
|
||||||
let a = ParaId::from(111);
|
let a = ParaId::from(111);
|
||||||
|
let old_code: ValidationCode = vec![1, 2, 3].into();
|
||||||
let new_code: ValidationCode = vec![3, 2, 1].into();
|
let new_code: ValidationCode = vec![3, 2, 1].into();
|
||||||
|
|
||||||
let paras = vec![(
|
let paras = vec![(
|
||||||
@@ -1166,7 +1168,7 @@ fn pvf_check_upgrade_reject() {
|
|||||||
ParaGenesisArgs {
|
ParaGenesisArgs {
|
||||||
parachain: false,
|
parachain: false,
|
||||||
genesis_head: Default::default(),
|
genesis_head: Default::default(),
|
||||||
validation_code: ValidationCode(vec![]), // valid since in genesis
|
validation_code: old_code,
|
||||||
},
|
},
|
||||||
)];
|
)];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user