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

Commit 4177af7

Browse files
committed
explicit lifecycle tracking for paras
1 parent addbeb2 commit 4177af7

2 files changed

Lines changed: 138 additions & 34 deletions

File tree

runtime/parachains/src/lib.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ mod mock;
4444

4545
pub use origin::{Origin, ensure_parachain};
4646
use primitives::v1::Id as ParaId;
47+
use parity_scale_codec::{Encode, Decode};
48+
use sp_core::RuntimeDebug;
4749

4850
/// Schedule a para to be initialized at the start of the next session with the given genesis data.
4951
pub fn schedule_para_initialize<T: paras::Config>(
@@ -85,3 +87,22 @@ pub fn schedule_para_upgrade<T: paras::Config>(id: ParaId) {
8587
pub fn schedule_para_downgrade<T: paras::Config>(id: ParaId) {
8688
paras::Module::<T>::schedule_para_downgrade(id);
8789
}
90+
91+
/// The possible states of a para, to take into account delayed lifecycle changes.
92+
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
93+
pub enum ParaLifecycle {
94+
/// Para ID is new and is onboarding as a Parathread.
95+
OnboardingAsParathread,
96+
/// Para ID is new and is onboarding as a Parachain.
97+
OnboardingAsParachain,
98+
/// Para ID is a Parathread.
99+
Parathread,
100+
/// Para ID is a Parachain.
101+
Parachain,
102+
/// Para ID is a Parathread which is upgrading to a Parachain.
103+
UpgradingToParachain,
104+
/// Para ID is a Parachain which is downgrading to a Parathread.
105+
DowngradingToParathread,
106+
/// Para ID is being offboarded.
107+
Outgoing,
108+
}

runtime/parachains/src/paras.rs

Lines changed: 117 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use frame_support::{
3737
weights::Weight,
3838
};
3939
use parity_scale_codec::{Encode, Decode};
40-
use crate::{configuration, initializer::SessionChangeNotification};
40+
use crate::{configuration, initializer::SessionChangeNotification, ParaLifecycle};
4141
use sp_core::RuntimeDebug;
4242

4343
#[cfg(feature = "std")]
@@ -180,8 +180,8 @@ decl_storage! {
180180
trait Store for Module<T: Config> as Paras {
181181
/// All parachains. Ordered ascending by ParaId. Parathreads are not included.
182182
Parachains get(fn parachains): Vec<ParaId>;
183-
/// All parathreads.
184-
Parathreads: map hasher(twox_64_concat) ParaId => Option<()>;
183+
/// The current lifecycle of a all known Para IDs.
184+
ParaLifecycles: map hasher(twox_64_concat) ParaId => Option<ParaLifecycle>;
185185
/// The head-data of every registered para.
186186
Heads get(fn para_head): map hasher(twox_64_concat) ParaId => Option<HeadData>;
187187
/// The validation code of every live para.
@@ -285,13 +285,12 @@ impl<T: Config> Module<T> {
285285
for outgoing_para in outgoing {
286286
if let Ok(i) = parachains.binary_search(&outgoing_para) {
287287
parachains.remove(i);
288-
} else {
289-
<Self as Store>::Parathreads::remove(&outgoing_para);
290288
}
291289

292290
<Self as Store>::Heads::remove(&outgoing_para);
293291
<Self as Store>::FutureCodeUpgrades::remove(&outgoing_para);
294292
<Self as Store>::FutureCode::remove(&outgoing_para);
293+
ParaLifecycles::remove(&outgoing_para);
295294

296295
let removed_code = <Self as Store>::CurrentCode::take(&outgoing_para);
297296
if let Some(removed_code) = removed_code {
@@ -313,10 +312,11 @@ impl<T: Config> Module<T> {
313312

314313
if genesis_data.parachain {
315314
if let Err(i) = parachains.binary_search(&upcoming_para) {
315+
ParaLifecycles::insert(&upcoming_para, ParaLifecycle::Parachain);
316316
parachains.insert(i, upcoming_para);
317317
}
318318
} else {
319-
<Self as Store>::Parathreads::insert(&upcoming_para, ());
319+
ParaLifecycles::insert(&upcoming_para, ParaLifecycle::Parathread);
320320
}
321321

322322
<Self as Store>::Heads::insert(&upcoming_para, genesis_data.genesis_head);
@@ -328,11 +328,15 @@ impl<T: Config> Module<T> {
328328
fn apply_upgrades(parachains: &mut Vec<ParaId>) {
329329
let upgrades = UpcomingUpgrades::take();
330330
for para in upgrades {
331-
if Parathreads::take(&para).is_some() {
332-
if let Err(i) = parachains.binary_search(&para) {
333-
parachains.insert(i, para);
331+
ParaLifecycles::mutate(&para, |v| {
332+
if *v == Some(ParaLifecycle::UpgradingToParachain) {
333+
if let Err(i) = parachains.binary_search(&para) {
334+
ParaLifecycles::insert(&para, ParaLifecycle::Parachain);
335+
parachains.insert(i, para);
336+
}
337+
*v = Some(ParaLifecycle::Parachain);
334338
}
335-
}
339+
});
336340
}
337341
}
338342

@@ -342,7 +346,7 @@ impl<T: Config> Module<T> {
342346
for para in downgrades {
343347
if let Ok(i) = parachains.binary_search(&para) {
344348
parachains.remove(i);
345-
Parathreads::insert(&para, ());
349+
ParaLifecycles::insert(&para, ParaLifecycle::Parathread);
346350
}
347351
}
348352
}
@@ -441,6 +445,12 @@ impl<T: Config> Module<T> {
441445
return weight;
442446
}
443447

448+
if genesis.parachain {
449+
ParaLifecycles::insert(&id, ParaLifecycle::OnboardingAsParachain);
450+
} else {
451+
ParaLifecycles::insert(&id, ParaLifecycle::OnboardingAsParathread);
452+
}
453+
444454
UpcomingParasGenesis::insert(&id, &genesis);
445455

446456
T::DbWeight::get().reads_writes(1, 2)
@@ -452,9 +462,10 @@ impl<T: Config> Module<T> {
452462
match v.binary_search(&id) {
453463
Ok(i) => {
454464
v.remove(i);
455-
UpcomingParasGenesis::remove(id);
465+
UpcomingParasGenesis::remove(&id);
466+
ParaLifecycles::remove(&id);
456467
// If a para was only in the pending state it should not be moved to `Outgoing`
457-
return T::DbWeight::get().reads_writes(2, 2);
468+
return T::DbWeight::get().reads_writes(2, 3);
458469
}
459470
Err(_) => T::DbWeight::get().reads_writes(1, 0),
460471
}
@@ -465,7 +476,8 @@ impl<T: Config> Module<T> {
465476
Ok(_) => T::DbWeight::get().reads_writes(1, 0),
466477
Err(i) => {
467478
v.insert(i, id);
468-
T::DbWeight::get().reads_writes(1, 1)
479+
ParaLifecycles::insert(&id, ParaLifecycle::Outgoing);
480+
T::DbWeight::get().reads_writes(1, 2)
469481
}
470482
}
471483
});
@@ -474,15 +486,57 @@ impl<T: Config> Module<T> {
474486
}
475487

476488
#[allow(dead_code)]
477-
pub(crate) fn schedule_para_upgrade(para: ParaId) -> Weight {
478-
UpcomingUpgrades::append(para);
479-
T::DbWeight::get().writes(1)
489+
pub(crate) fn schedule_para_upgrade(id: ParaId) -> Weight {
490+
if ParaLifecycles::get(&id) != Some(ParaLifecycle::Parathread) {
491+
let weight = T::DbWeight::get().reads_writes(1, 0);
492+
return weight;
493+
}
494+
495+
let dup = UpcomingUpgrades::mutate(|v| {
496+
match v.binary_search(&id) {
497+
Ok(_) => true,
498+
Err(i) => {
499+
v.insert(i, id);
500+
false
501+
}
502+
}
503+
});
504+
505+
ParaLifecycles::insert(&id, ParaLifecycle::UpgradingToParachain);
506+
507+
if dup {
508+
let weight = T::DbWeight::get().reads_writes(2, 1);
509+
return weight;
510+
}
511+
512+
T::DbWeight::get().reads_writes(2, 2)
480513
}
481514

482515
#[allow(dead_code)]
483-
pub(crate) fn schedule_para_downgrade(para: ParaId) -> Weight {
484-
UpcomingDowngrades::append(para);
485-
T::DbWeight::get().writes(1)
516+
pub(crate) fn schedule_para_downgrade(id: ParaId) -> Weight {
517+
if ParaLifecycles::get(&id) != Some(ParaLifecycle::Parachain) {
518+
let weight = T::DbWeight::get().reads_writes(1, 0);
519+
return weight;
520+
}
521+
522+
let dup = UpcomingDowngrades::mutate(|v| {
523+
match v.binary_search(&id) {
524+
Ok(_) => true,
525+
Err(i) => {
526+
v.insert(i, id);
527+
false
528+
}
529+
}
530+
});
531+
532+
ParaLifecycles::insert(&id, ParaLifecycle::DowngradingToParathread);
533+
534+
if dup {
535+
let weight = T::DbWeight::get().reads_writes(2, 1);
536+
return weight;
537+
}
538+
539+
T::DbWeight::get().reads_writes(2, 2)
486540
}
487541

488542
/// Schedule a future code upgrade of the given parachain, to be applied after inclusion
@@ -584,22 +638,30 @@ impl<T: Config> Module<T> {
584638

585639
/// Returns whether the given ID refers to a valid para.
586640
pub fn is_valid_para(id: ParaId) -> bool {
587-
Self::is_parachain(id) || Self::is_parathread(id)
641+
match ParaLifecycles::get(&id) {
642+
Some(ParaLifecycle::Parachain) |
643+
Some(ParaLifecycle::Parathread) |
644+
Some(ParaLifecycle::UpgradingToParachain) |
645+
Some(ParaLifecycle::DowngradingToParathread)
646+
=> true,
647+
_ => false,
648+
}
588649
}
589650

590651
/// Whether a para ID corresponds to any live parathread.
591652
pub fn is_parachain(id: ParaId) -> bool {
592-
Parachains::get().binary_search(&id).is_ok()
653+
match ParaLifecycles::get(&id) {
654+
Some(ParaLifecycle::Parachain) => true,
655+
_ => false,
656+
}
593657
}
594658

595659
/// Whether a para ID corresponds to any live parathread.
596660
pub fn is_parathread(id: ParaId) -> bool {
597-
Parathreads::get(&id).is_some()
598-
}
599-
600-
/// Wether a para ID is in in the onboarding queue.
601-
pub fn is_upcoming(id: ParaId) -> bool {
602-
UpcomingParas::get().binary_search(&id).is_ok()
661+
match ParaLifecycles::get(&id) {
662+
Some(ParaLifecycle::Parathread) => true,
663+
_ => false,
664+
}
603665
}
604666

605667
/// The block number of the last scheduled upgrade of the requested para. Includes future upgrades
@@ -1178,23 +1240,33 @@ mod tests {
11781240
);
11791241

11801242
assert_eq!(<Paras as Store>::UpcomingParas::get(), vec![c, b, a]);
1181-
assert!(<Paras as Store>::Parathreads::get(&a).is_none());
11821243

1244+
// Lifecycle is tracked correctly
1245+
assert_eq!(ParaLifecycles::get(&a), Some(ParaLifecycle::OnboardingAsParathread));
1246+
assert_eq!(ParaLifecycles::get(&b), Some(ParaLifecycle::OnboardingAsParachain));
1247+
assert_eq!(ParaLifecycles::get(&c), Some(ParaLifecycle::OnboardingAsParachain));
11831248

11841249
// run to block without session change.
11851250
run_to_block(2, None);
11861251

11871252
assert_eq!(Paras::parachains(), Vec::new());
11881253
assert_eq!(<Paras as Store>::UpcomingParas::get(), vec![c, b, a]);
1189-
assert!(<Paras as Store>::Parathreads::get(&a).is_none());
1254+
1255+
// Lifecycle is tracked correctly
1256+
assert_eq!(ParaLifecycles::get(&a), Some(ParaLifecycle::OnboardingAsParathread));
1257+
assert_eq!(ParaLifecycles::get(&b), Some(ParaLifecycle::OnboardingAsParachain));
1258+
assert_eq!(ParaLifecycles::get(&c), Some(ParaLifecycle::OnboardingAsParachain));
11901259

11911260

11921261
run_to_block(3, Some(vec![3]));
11931262

11941263
assert_eq!(Paras::parachains(), vec![c, b]);
11951264
assert_eq!(<Paras as Store>::UpcomingParas::get(), Vec::new());
11961265

1197-
assert!(<Paras as Store>::Parathreads::get(&a).is_some());
1266+
// Lifecycle is tracked correctly
1267+
assert_eq!(ParaLifecycles::get(&a), Some(ParaLifecycle::Parathread));
1268+
assert_eq!(ParaLifecycles::get(&b), Some(ParaLifecycle::Parachain));
1269+
assert_eq!(ParaLifecycles::get(&c), Some(ParaLifecycle::Parachain));
11981270

11991271
assert_eq!(Paras::current_code(&a), Some(vec![2].into()));
12001272
assert_eq!(Paras::current_code(&b), Some(vec![1].into()));
@@ -1239,15 +1311,23 @@ mod tests {
12391311
);
12401312

12411313
assert_eq!(<Paras as Store>::UpcomingParas::get(), vec![c, b, a]);
1242-
assert!(<Paras as Store>::Parathreads::get(&a).is_none());
1314+
1315+
// Lifecycle is tracked correctly
1316+
assert_eq!(ParaLifecycles::get(&a), Some(ParaLifecycle::OnboardingAsParathread));
1317+
assert_eq!(ParaLifecycles::get(&b), Some(ParaLifecycle::OnboardingAsParachain));
1318+
assert_eq!(ParaLifecycles::get(&c), Some(ParaLifecycle::OnboardingAsParachain));
12431319

12441320

12451321
// run to block without session change.
12461322
run_to_block(2, None);
12471323

12481324
assert_eq!(Paras::parachains(), Vec::new());
12491325
assert_eq!(<Paras as Store>::UpcomingParas::get(), vec![c, b, a]);
1250-
assert!(<Paras as Store>::Parathreads::get(&a).is_none());
1326+
1327+
// Lifecycle is tracked correctly
1328+
assert_eq!(ParaLifecycles::get(&a), Some(ParaLifecycle::OnboardingAsParathread));
1329+
assert_eq!(ParaLifecycles::get(&b), Some(ParaLifecycle::OnboardingAsParachain));
1330+
assert_eq!(ParaLifecycles::get(&c), Some(ParaLifecycle::OnboardingAsParachain));
12511331

12521332
Paras::schedule_para_cleanup(c);
12531333

@@ -1258,7 +1338,10 @@ mod tests {
12581338
assert_eq!(<Paras as Store>::UpcomingParas::get(), Vec::new());
12591339
assert!(<Paras as Store>::UpcomingParasGenesis::get(a).is_none());
12601340

1261-
assert!(<Paras as Store>::Parathreads::get(&a).is_some());
1341+
// Lifecycle is tracked correctly
1342+
assert_eq!(ParaLifecycles::get(&a), Some(ParaLifecycle::Parathread));
1343+
assert_eq!(ParaLifecycles::get(&b), Some(ParaLifecycle::Parachain));
1344+
assert_eq!(ParaLifecycles::get(&c), None);
12621345

12631346
assert_eq!(Paras::current_code(&a), Some(vec![2].into()));
12641347
assert_eq!(Paras::current_code(&b), Some(vec![1].into()));

0 commit comments

Comments
 (0)