Skip to content

Commit 06d7a04

Browse files
committed
Add storage migration for the Operator structure change
Signed-off-by: linning <[email protected]>
1 parent ed9ead8 commit 06d7a04

File tree

4 files changed

+167
-2
lines changed

4 files changed

+167
-2
lines changed

crates/pallet-domains/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ mod tests;
2727
pub mod block_tree;
2828
mod bundle_storage_fund;
2929
pub mod domain_registry;
30+
pub mod migration;
3031
pub mod runtime_registry;
3132
mod staking;
3233
mod staking_epoch;
@@ -160,7 +161,7 @@ pub type BlockTreeNodeFor<T> = crate::block_tree::BlockTreeNode<
160161
>;
161162

162163
/// The current storage version.
163-
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
164+
const STORAGE_VERSION: StorageVersion = StorageVersion::new(2);
164165

165166
/// The number of bundle of a particular domain to be included in the block is probabilistic
166167
/// and based on the consensus chain slot probability and domain bundle slot probability, usually
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
//! Migration module for pallet-domains
2+
use crate::{Config, Pallet};
3+
use frame_support::migrations::VersionedMigration;
4+
use frame_support::traits::UncheckedOnRuntimeUpgrade;
5+
use frame_support::weights::Weight;
6+
7+
pub type VersionCheckedMigrateDomainsV1ToV2<T> = VersionedMigration<
8+
1,
9+
2,
10+
VersionUncheckedMigrateV1ToV2<T>,
11+
Pallet<T>,
12+
<T as frame_system::Config>::DbWeight,
13+
>;
14+
15+
pub struct VersionUncheckedMigrateV1ToV2<T>(sp_std::marker::PhantomData<T>);
16+
impl<T: Config> UncheckedOnRuntimeUpgrade for VersionUncheckedMigrateV1ToV2<T> {
17+
fn on_runtime_upgrade() -> Weight {
18+
operator_structure_migration::migrate_operator_structure::<T>()
19+
}
20+
}
21+
22+
mod operator_structure_migration {
23+
use crate::pallet::Operators as OperatorsV2;
24+
use crate::staking::{Operator as OperatorV2, OperatorStatus};
25+
use crate::{BalanceOf, Config, DomainBlockNumberFor, Pallet};
26+
use codec::{Decode, Encode};
27+
use frame_support::pallet_prelude::{OptionQuery, TypeInfo, Weight};
28+
use frame_support::{storage_alias, Identity};
29+
use sp_core::Get;
30+
use sp_domains::{DomainId, OperatorId, OperatorPublicKey};
31+
use sp_runtime::Percent;
32+
33+
#[derive(TypeInfo, Debug, Encode, Decode, Clone, PartialEq, Eq)]
34+
pub struct Operator<Balance, Share, DomainBlockNumber> {
35+
pub signing_key: OperatorPublicKey,
36+
pub current_domain_id: DomainId,
37+
pub next_domain_id: DomainId,
38+
pub minimum_nominator_stake: Balance,
39+
pub nomination_tax: Percent,
40+
/// Total active stake of combined nominators under this operator.
41+
pub current_total_stake: Balance,
42+
/// Total rewards this operator received this current epoch.
43+
pub current_epoch_rewards: Balance,
44+
/// Total shares of all the nominators under this operator.
45+
pub current_total_shares: Share,
46+
/// The status of the operator, it may be stale due to the `OperatorStatus::PendingSlash` is
47+
/// not assigned to this field directly, thus MUST use the `status()` method to query the status
48+
/// instead.
49+
pub(super) partial_status: OperatorStatus<DomainBlockNumber>,
50+
/// Total deposits during the previous epoch
51+
pub deposits_in_epoch: Balance,
52+
/// Total withdrew shares during the previous epoch
53+
pub withdrawals_in_epoch: Share,
54+
/// Total balance deposited to the bundle storage fund
55+
pub total_storage_fee_deposit: Balance,
56+
}
57+
58+
#[storage_alias]
59+
pub type Operators<T: Config> = StorageMap<
60+
Pallet<T>,
61+
Identity,
62+
OperatorId,
63+
Operator<BalanceOf<T>, <T as Config>::Share, DomainBlockNumberFor<T>>,
64+
OptionQuery,
65+
>;
66+
67+
pub(super) fn migrate_operator_structure<T: Config>() -> Weight {
68+
// On Taurus, the operator 0-8 are registered before the runtime upgrade that brings the new
69+
// structure, for operator (if any) registered after that runtime upgrade it should be in new
70+
// structure already, thus the migration should only handle operator 0-8
71+
let affected_operator = 8;
72+
let mut operator_count = 0;
73+
for operator_id in 0..=affected_operator {
74+
if let Some(operator) = Operators::<T>::take(operator_id) {
75+
OperatorsV2::<T>::set(
76+
operator_id,
77+
Some(OperatorV2 {
78+
signing_key: operator.signing_key,
79+
current_domain_id: operator.current_domain_id,
80+
next_domain_id: operator.next_domain_id,
81+
minimum_nominator_stake: operator.minimum_nominator_stake,
82+
nomination_tax: operator.nomination_tax,
83+
current_total_stake: operator.current_total_stake,
84+
current_total_shares: operator.current_total_shares,
85+
partial_status: operator.partial_status,
86+
deposits_in_epoch: operator.deposits_in_epoch,
87+
withdrawals_in_epoch: operator.withdrawals_in_epoch,
88+
total_storage_fee_deposit: operator.total_storage_fee_deposit,
89+
}),
90+
);
91+
operator_count += 1;
92+
}
93+
}
94+
95+
// 1 read and 1 write per old operator
96+
// 1 write per new operator
97+
T::DbWeight::get().reads_writes(operator_count, operator_count * 2)
98+
}
99+
}
100+
101+
#[cfg(test)]
102+
mod tests {
103+
use super::operator_structure_migration::{migrate_operator_structure, Operator, Operators};
104+
use crate::pallet::Operators as OperatorsV2;
105+
use crate::staking::{Operator as OperatorV2, OperatorStatus};
106+
use crate::tests::{new_test_ext, Test};
107+
use crate::Config;
108+
use sp_core::crypto::Ss58Codec;
109+
use sp_domains::OperatorPublicKey;
110+
111+
#[test]
112+
fn test_operator_structure_migration() {
113+
let mut ext = new_test_ext();
114+
let operator_id = 0;
115+
let operator = Operator {
116+
signing_key: OperatorPublicKey::from_ss58check(
117+
"5Gv1Uopoqo1k7125oDtFSCmxH4DzuCiBU7HBKu2bF1GZFsEb",
118+
)
119+
.unwrap(),
120+
current_domain_id: 0u32.into(),
121+
next_domain_id: 0u32.into(),
122+
minimum_nominator_stake: <Test as Config>::MinNominatorStake::get(),
123+
nomination_tax: Default::default(),
124+
current_total_stake: 1u32.into(),
125+
current_epoch_rewards: 2u32.into(),
126+
current_total_shares: 3u32.into(),
127+
partial_status: OperatorStatus::Registered,
128+
deposits_in_epoch: 4u32.into(),
129+
withdrawals_in_epoch: 5u32.into(),
130+
total_storage_fee_deposit: 6u32.into(),
131+
};
132+
133+
ext.execute_with(|| Operators::<Test>::set(operator_id, Some(operator.clone())));
134+
135+
ext.commit_all().unwrap();
136+
137+
ext.execute_with(|| {
138+
let weights = migrate_operator_structure::<Test>();
139+
assert_eq!(
140+
weights,
141+
<Test as frame_system::Config>::DbWeight::get().reads_writes(1, 2),
142+
);
143+
assert_eq!(
144+
OperatorsV2::<Test>::get(operator_id),
145+
Some(OperatorV2 {
146+
signing_key: operator.signing_key,
147+
current_domain_id: operator.current_domain_id,
148+
next_domain_id: operator.next_domain_id,
149+
minimum_nominator_stake: operator.minimum_nominator_stake,
150+
nomination_tax: operator.nomination_tax,
151+
current_total_stake: operator.current_total_stake,
152+
current_total_shares: operator.current_total_shares,
153+
partial_status: operator.partial_status,
154+
deposits_in_epoch: operator.deposits_in_epoch,
155+
withdrawals_in_epoch: operator.withdrawals_in_epoch,
156+
total_storage_fee_deposit: operator.total_storage_fee_deposit,
157+
})
158+
);
159+
});
160+
}
161+
}

crates/pallet-domains/src/staking.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,8 @@ pub struct Operator<Balance, Share, DomainBlockNumber> {
186186
/// The status of the operator, it may be stale due to the `OperatorStatus::PendingSlash` is
187187
/// not assigned to this field directly, thus MUST use the `status()` method to query the status
188188
/// instead.
189-
partial_status: OperatorStatus<DomainBlockNumber>,
189+
/// TODO: export `partial_status` for migration usage, remove `pub(crate)`once migration are done
190+
pub(crate) partial_status: OperatorStatus<DomainBlockNumber>,
190191
/// Total deposits during the previous epoch
191192
pub deposits_in_epoch: Balance,
192193
/// Total withdrew shares during the previous epoch

crates/subspace-runtime/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,8 @@ pub type Executive = frame_executive::Executive<
978978
frame_system::ChainContext<Runtime>,
979979
Runtime,
980980
AllPalletsWithSystem,
981+
// TODO: remove once the migrations are done
982+
pallet_domains::migration::VersionCheckedMigrateDomainsV1ToV2<Runtime>,
981983
>;
982984

983985
fn extract_segment_headers(ext: &UncheckedExtrinsic) -> Option<Vec<SegmentHeader>> {

0 commit comments

Comments
 (0)