Skip to content

Commit b1dae95

Browse files
authored
fix: Collator Storage (#253)
* fix: use correct old key name * fix: check for empty collator set * fix: move storage keeping the old name didn't work with the js-api * chore: bump runtime & version * improve migration * increase default version & remove test the test didn't make any sense migrations should only run with old storage. The test was initialized with new storage...
1 parent 4cc5bf0 commit b1dae95

File tree

17 files changed

+94
-74
lines changed

17 files changed

+94
-74
lines changed

Cargo.lock

+10-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

nodes/parachain/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build = "build.rs"
44
description = "KILT parachain"
55
edition = "2018"
66
name = "kilt-parachain"
7-
version = "0.25.1"
7+
version = "0.25.2"
88

99
[[bin]]
1010
name = "kilt-parachain"

nodes/standalone/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ authors = ["KILT <info@kilt.io>"]
33
build = "build.rs"
44
edition = "2018"
55
name = "mashnet-node"
6-
version = "0.25.1"
6+
version = "0.25.2"
77

88
[[bin]]
99
name = "mashnet-node"

pallets/attestation/Cargo.toml

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description = "Enables adding and revoking attestations."
44
edition = "2018"
55
name = "attestation"
66
repository = "https://github.com/KILTprotocol/mashnet-node"
7-
version = "0.25.1"
7+
version = "0.25.2"
88

99
[package.metadata.docs.rs]
1010
targets = ["x86_64-unknown-linux-gnu"]
@@ -13,8 +13,8 @@ targets = ["x86_64-unknown-linux-gnu"]
1313
substrate-wasm-builder-runner = {version = "3.0.0"}
1414

1515
[dev-dependencies]
16-
ctype = {features = ["mock"], path = "../ctype", version = "0.25.1"}
17-
delegation = {features = ["mock"], path = "../delegation", version = "0.25.1"}
16+
ctype = {features = ["mock"], path = "../ctype", version = "0.25.2"}
17+
delegation = {features = ["mock"], path = "../delegation", version = "0.25.2"}
1818
kilt-primitives = {default-features = false, path = "../../primitives"}
1919
serde = {version = "1.0.101"}
2020
sp-core = {branch = "polkadot-v0.9.9", default-features = false, git = "https://github.com/paritytech/substrate"}
@@ -23,8 +23,8 @@ sp-keystore = {branch = "polkadot-v0.9.9", default-features = false, git = "http
2323

2424
[dependencies]
2525
# Internal dependencies
26-
ctype = {default-features = false, path = "../ctype", version = "0.25.1"}
27-
delegation = {default-features = false, path = "../delegation", version = "0.25.1"}
26+
ctype = {default-features = false, path = "../ctype", version = "0.25.2"}
27+
delegation = {default-features = false, path = "../delegation", version = "0.25.2"}
2828
kilt-primitives = {default-features = false, optional = true, path = "../../primitives"}
2929

3030
#External dependencies

pallets/ctype/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description = "Enables adding CTypes."
44
edition = "2018"
55
name = "ctype"
66
repository = "https://github.com/KILTprotocol/mashnet-node"
7-
version = "0.25.1"
7+
version = "0.25.2"
88

99
[package.metadata.docs.rs]
1010
targets = ["x86_64-unknown-linux-gnu"]

pallets/delegation/Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description = "Enables creating and revoking root nodes of delegation hierarchie
44
edition = "2018"
55
name = "delegation"
66
repository = "https://github.com/KILTprotocol/mashnet-node"
7-
version = "0.25.1"
7+
version = "0.25.2"
88

99
[package.metadata.docs.rs]
1010
targets = ["x86_64-unknown-linux-gnu"]
@@ -13,7 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"]
1313
substrate-wasm-builder-runner = {version = "3.0.0"}
1414

1515
[dev-dependencies]
16-
ctype = {features = ["mock"], path = "../ctype", version = "0.25.1"}
16+
ctype = {features = ["mock"], path = "../ctype", version = "0.25.2"}
1717
env_logger = {version = "0.8.4"}
1818
kilt-primitives = {default-features = false, path = "../../primitives"}
1919
serde = {version = "1.0.101"}
@@ -22,7 +22,7 @@ sp-keystore = {branch = "polkadot-v0.9.9", default-features = false, git = "http
2222

2323
[dependencies]
2424
# Internal dependencies
25-
ctype = {default-features = false, path = "../ctype", version = "0.25.1"}
25+
ctype = {default-features = false, path = "../ctype", version = "0.25.2"}
2626
kilt-primitives = {default-features = false, path = "../../primitives"}
2727

2828
#External dependencies

pallets/did/Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description = "Enables adding and removing decentralized identifiers (DIDs)."
44
edition = "2018"
55
name = "did"
66
repository = "https://github.com/KILTprotocol/mashnet-node"
7-
version = "0.25.1"
7+
version = "0.25.2"
88

99
[package.metadata.docs.rs]
1010
targets = ["x86_64-unknown-linux-gnu"]
@@ -16,12 +16,12 @@ substrate-wasm-builder-runner = {version = "3.0.0"}
1616
env_logger = {version = "0.8.3"}
1717
serde = {version = "1.0.101"}
1818

19-
ctype = {features = ["mock"], path = "../ctype", version = "0.25.1"}
19+
ctype = {features = ["mock"], path = "../ctype", version = "0.25.2"}
2020
kilt-primitives = {default-features = false, path = "../../primitives"}
2121

2222
[dependencies]
2323
# Internal dependencies
24-
ctype = {optional = true, path = "../ctype", version = "0.25.1"}
24+
ctype = {optional = true, path = "../ctype", version = "0.25.2"}
2525
kilt-primitives = {default-features = false, path = "../../primitives"}
2626

2727
# External dependencies

pallets/parachain-staking/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ name = "parachain-staking"
66
version = "1.0.0"
77

88
[dependencies]
9+
hex-literal = "0.2.1"
910
kilt-primitives = { path = "../../primitives", default-features = false }
1011
log = "*"
1112
parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] }

pallets/parachain-staking/src/lib.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,6 @@ pub mod pallet {
593593
/// It maps from an account to its information.
594594
#[pallet::storage]
595595
#[pallet::getter(fn candidate_pool)]
596-
#[pallet::storage_prefix = "CollatorState"]
597596
pub(crate) type CandidatePool<T: Config> = StorageMap<
598597
_,
599598
Twox64Concat,
@@ -614,7 +613,6 @@ pub mod pallet {
614613
/// non collating candidates is not included in [TotalCollatorStake].
615614
#[pallet::storage]
616615
#[pallet::getter(fn total_collator_stake)]
617-
#[pallet::storage_prefix = "Total"]
618616
pub(crate) type TotalCollatorStake<T: Config> = StorageValue<_, TotalStake<BalanceOf<T>>, ValueQuery>;
619617

620618
/// The collator candidates with the highest amount of stake.
@@ -628,7 +626,6 @@ pub mod pallet {
628626
/// that a collator can drop out of the collator set by reducing his stake.
629627
#[pallet::storage]
630628
#[pallet::getter(fn top_candidates)]
631-
#[pallet::storage_prefix = "CollatorPool"]
632629
pub(crate) type TopCandidates<T: Config> =
633630
StorageValue<_, OrderedSet<Stake<T::AccountId, BalanceOf<T>>, T::MaxTopCandidates>, ValueQuery>;
634631

@@ -2607,7 +2604,14 @@ pub mod pallet {
26072604
DispatchClass::Mandatory,
26082605
);
26092606

2610-
Some(Pallet::<T>::selected_candidates().to_vec())
2607+
let collators = Pallet::<T>::selected_candidates().to_vec();
2608+
if collators.is_empty() {
2609+
// we never want to pass an empty set of collators. This would brick the chain.
2610+
log::error!("💥 keeping old session because of empty collator set!");
2611+
None
2612+
} else {
2613+
Some(collators)
2614+
}
26112615
}
26122616

26132617
fn end_session(_end_index: SessionIndex) {

pallets/parachain-staking/src/migrations.rs

+1-35
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ impl StakingStorageVersion {
7474
// old version anymore.
7575
impl Default for StakingStorageVersion {
7676
fn default() -> Self {
77-
Self::V4
77+
Self::V5
7878
}
7979
}
8080

@@ -191,37 +191,3 @@ impl<T: Config> StakingStorageMigrator<T> {
191191
Ok(())
192192
}
193193
}
194-
195-
// Tests for the entire storage migrator.
196-
#[cfg(test)]
197-
mod tests {
198-
use super::*;
199-
200-
use crate::mock::Test as TestRuntime;
201-
202-
#[test]
203-
fn ok_from_default_migration() {
204-
let mut ext = mock::ExtBuilder::default()
205-
.with_balances((0..15).into_iter().map(|n| (n, 120)).collect())
206-
.with_collators((0..15).into_iter().map(|n| (n, 100)).collect())
207-
.build();
208-
ext.execute_with(|| {
209-
#[cfg(feature = "try-runtime")]
210-
if StakingStorageVersion::default() != StakingStorageVersion::latest() {
211-
#[cfg(feature = "try-runtime")]
212-
assert!(
213-
StakingStorageMigrator::<TestRuntime>::pre_migrate().is_ok(),
214-
"Storage pre-migrate from default version should not fail."
215-
);
216-
217-
StakingStorageMigrator::<TestRuntime>::migrate();
218-
219-
#[cfg(feature = "try-runtime")]
220-
assert!(
221-
StakingStorageMigrator::<TestRuntime>::post_migrate().is_ok(),
222-
"Storage post-migrate from default version should not fail."
223-
);
224-
}
225-
});
226-
}
227-
}

pallets/parachain-staking/src/migrations/v5.rs

+54-6
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,17 @@
1616

1717
// If you feel like getting in touch with us, you can do so at info@botlabs.org
1818

19-
use crate::{migrations::StakingStorageVersion, CandidateCount, CandidatePool, Config, StorageVersion};
20-
use frame_support::{dispatch::Weight, storage::StorageValue, traits::Get};
19+
use crate::{
20+
migrations::StakingStorageVersion,
21+
set::OrderedSet,
22+
types::{BalanceOf, Candidate, Stake, TotalStake},
23+
CandidateCount, CandidatePool, Config, StorageVersion, TopCandidates, TotalCollatorStake,
24+
};
25+
use frame_support::{
26+
dispatch::Weight,
27+
storage::{IterableStorageMap, StorageValue},
28+
traits::Get,
29+
};
2130

2231
#[cfg(feature = "try-runtime")]
2332
pub(crate) fn pre_migrate<T: Config>() -> Result<(), &'static str> {
@@ -31,21 +40,57 @@ pub(crate) fn migrate<T: Config>() -> Weight {
3140
// Kill selected candidates list
3241
old::SelectedCandidates::<T>::kill();
3342

34-
// count candidates
35-
let counter: u32 = CandidatePool::<T>::iter().fold(0, |acc, _| acc.saturating_add(1));
43+
// migrate CandidatePool to TopCandidates
44+
// DANGER: this needs to happen before we write to the new CandidatePool!
45+
let old_candidate_pool = old::CandidatePool::<T>::get();
46+
TopCandidates::<T>::put(old_candidate_pool);
47+
old::CandidatePool::<T>::kill();
48+
49+
// Copy over total
50+
let total = old::Total::<T>::get();
51+
TotalCollatorStake::<T>::set(total);
52+
old::Total::<T>::kill();
53+
54+
// kill, copy & count candidates
55+
let counter: u32 = old::CollatorState::<T>::drain().fold(0, |acc, (key, candidate)| {
56+
CandidatePool::<T>::insert(&key, candidate);
57+
acc.saturating_add(1)
58+
});
3659
CandidateCount::<T>::put(counter);
3760

3861
// update storage version
3962
StorageVersion::<T>::put(StakingStorageVersion::V5);
4063
log::info!("Completed staking migration to StakingStorageVersion::V5");
4164

42-
T::DbWeight::get().reads_writes(counter.saturating_add(2).into(), 3)
65+
// Writes: 3 * Kill, 3 * Put, `counter` * inserts, at max 32 additional kills <
66+
// counter + 38 Reads: (counter + 2) * get
67+
T::DbWeight::get().reads_writes(counter.saturating_add(38).into(), counter.saturating_add(2).into())
4368
}
4469

4570
#[cfg(feature = "try-runtime")]
4671
pub(crate) fn post_migrate<T: Config>() -> Result<(), &'static str> {
72+
use sp_runtime::SaturatedConversion;
73+
4774
assert_eq!(StorageVersion::<T>::get(), StakingStorageVersion::V5);
48-
assert!(CandidateCount::<T>::get() > T::MinCollators::get());
75+
log::info!(
76+
"CandidateCount = {} >= {} = MinCollators",
77+
CandidateCount::<T>::get(),
78+
T::MinCollators::get()
79+
);
80+
assert!(CandidateCount::<T>::get() >= T::MinCollators::get());
81+
log::info!(
82+
"TopCandidates = {} >= {} = MinCollators",
83+
TopCandidates::<T>::get().len(),
84+
T::MinCollators::get()
85+
);
86+
assert!(TopCandidates::<T>::get().len().saturated_into::<u32>() >= T::MinCollators::get());
87+
assert!(TopCandidates::<T>::get().len().saturated_into::<u32>() <= CandidateCount::<T>::get());
88+
assert!(
89+
TotalCollatorStake::<T>::get().collators
90+
>= CandidateCount::<T>::get().saturated_into::<BalanceOf<T>>() * T::MinCollatorStake::get()
91+
);
92+
let counter: u32 = old::CollatorState::<T>::iter().fold(0, |acc, (_, _)| acc.saturating_add(1));
93+
assert!(counter == 0);
4994
Ok(())
5095
}
5196

@@ -60,7 +105,10 @@ pub(crate) mod old {
60105

61106
decl_storage! {
62107
trait Store for OldPallet<T: Config> as ParachainStaking {
108+
pub(crate) Total: TotalStake<BalanceOf<T>>;
63109
pub(crate) SelectedCandidates: Vec<T::AccountId>;
110+
pub(crate) CollatorState: map hasher(twox_64_concat) T::AccountId => Option<Candidate<T::AccountId, BalanceOf<T>, T::MaxDelegatorsPerCollator>>;
111+
pub(crate) CandidatePool: OrderedSet<Stake<T::AccountId, BalanceOf<T>>, T::MaxTopCandidates>;
64112
}
65113
}
66114
}

runtimes/peregrine/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
authors = ["KILT <info@kilt.io>"]
33
edition = "2018"
44
name = "peregrine-runtime"
5-
version = "0.25.1"
5+
version = "0.25.2"
66

77
[dependencies]
88
bitflags = {version = "1.2.1", default-features = false}

0 commit comments

Comments
 (0)