Skip to content

Commit 300bd20

Browse files
authored
Runtime Migration: Move from LockableCurrency to fungible::Hold (#140)
* Move sp-core from dev.deps to deps * Add Lock -> Hold balance migration * Add runtime upgrade for pallet_parachain_staking * Add Migration History * Add few comments * feat: filter out staking calls
1 parent 886c527 commit 300bd20

File tree

4 files changed

+155
-41
lines changed

4 files changed

+155
-41
lines changed

pallets/parachain-staking/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ frame-support.workspace = true
2828
frame-system.workspace = true
2929
sp-runtime.workspace = true
3030
sp-std.workspace = true
31+
sp-core.workspace = true
3132
substrate-fixed.workspace = true
3233
sp-staking.workspace = true
3334
pallet-authorship.workspace = true
@@ -38,7 +39,6 @@ pallet-balances.workspace = true
3839
pallet-aura.workspace = true
3940
pallet-timestamp.workspace = true
4041
similar-asserts = "1.1.0"
41-
sp-core.workspace = true
4242
sp-io.workspace = true
4343
sp-consensus-aura.workspace = true
4444

+3-39
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,6 @@
11
# Migration History
22

3-
## Calculate outgoing rewards based on pending revoke and decrease changes
3+
## Move from LockableCurrency to fungible::Hold
44

5-
- [Migration PR `#1408`](https://github.com/PureStake/moonbeam/pull/1408)
6-
7-
## Patch delegations total mismatch
8-
9-
- [Migration PR `#1291`](https://github.com/PureStake/moonbeam/pull/1291)
10-
11-
## Split candidate state for PoV optimization
12-
13-
- [Migration PR `#1117`](https://github.com/PureStake/moonbeam/pull/1117)
14-
15-
## Increase max delegations per candidate
16-
17-
- [Migration PR `#1096`](https://github.com/PureStake/moonbeam/pull/1096)
18-
- [Migratio bugfix `#1112`](https://github.com/PureStake/moonbeam/pull/1112)
19-
20-
## Manual Exits and Patch Lack of Delay for bond\_{more, less}
21-
22-
- [Migration PR `#810`](https://github.com/PureStake/moonbeam/pull/810)
23-
- [Migration Removal PR `#?`]()
24-
25-
## Purge Stale Storage
26-
27-
- [Migration PR `#970`](https://github.com/PureStake/moonbeam/pull/970)
28-
29-
## Delay nominator exits by changing NominatorState and ExitQueue
30-
31-
- [Migration PR `#610`](https://github.com/PureStake/moonbeam/pull/610)
32-
- [Migration Removal PR `#662`](https://github.com/PureStake/moonbeam/pull/662)
33-
34-
## Patch nomination DOS attack vector by changing CollatorState
35-
36-
- [Migration PR `#505`](https://github.com/PureStake/moonbeam/pull/505)
37-
- [Migration Removal PR `#553`](https://github.com/PureStake/moonbeam/pull/553)
38-
39-
## Patch underflow bug and correct Total storage item
40-
41-
- [Migration PR `#502`](https://github.com/PureStake/moonbeam/pull/502)
42-
- [Migration Removal PR `#553`](https://github.com/PureStake/moonbeam/pull/553)
5+
- [Migration PR `#132`](https://github.com/Polimec/polimec-node/pull/132)
6+
- [Migration Removal PR `#TBD`]()

pallets/parachain-staking/src/migrations.rs

+144
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,147 @@
1515
// along with Moonbeam. If not, see <http://www.gnu.org/licenses/>.
1616

1717
//! # Migrations
18+
//!
19+
#[allow(unused_imports)]
20+
use crate::*;
21+
22+
// Substrate
23+
use frame_support::traits::{
24+
fungible::{InspectHold, MutateHold},
25+
Currency, Get, LockIdentifier, LockableCurrency, ReservableCurrency,
26+
};
27+
#[allow(unused_imports)]
28+
use frame_support::{dispatch::DispatchError, log, migration, storage::unhashed};
29+
use parity_scale_codec::Encode;
30+
use sp_core::hexdisplay::HexDisplay;
31+
#[allow(unused_imports)]
32+
use sp_std::vec::Vec;
33+
34+
// Lock Identifiers used in the old version of the pallet.
35+
const COLLATOR_LOCK_ID: LockIdentifier = *b"stkngcol";
36+
const DELEGATOR_LOCK_ID: LockIdentifier = *b"stkngdel";
37+
38+
pub struct CustomOnRuntimeUpgrade<T, OldCurrency>
39+
where
40+
T: Config,
41+
OldCurrency: 'static
42+
+ LockableCurrency<<T as frame_system::Config>::AccountId>
43+
+ Currency<<T as frame_system::Config>::AccountId>
44+
+ ReservableCurrency<<T as frame_system::Config>::AccountId>,
45+
{
46+
_phantom: sp_std::marker::PhantomData<(T, OldCurrency)>,
47+
}
48+
49+
impl<T, OldCurrency> frame_support::traits::OnRuntimeUpgrade for CustomOnRuntimeUpgrade<T, OldCurrency>
50+
where
51+
T: Config,
52+
OldCurrency: 'static
53+
+ LockableCurrency<<T as frame_system::Config>::AccountId>
54+
+ Currency<<T as frame_system::Config>::AccountId>
55+
+ ReservableCurrency<<T as frame_system::Config>::AccountId>,
56+
BalanceOf<T>: From<OldCurrency::Balance>,
57+
{
58+
#[cfg(feature = "try-runtime")]
59+
fn pre_upgrade() -> Result<Vec<u8>, DispatchError> {
60+
let active_collators = CandidatePool::<T>::get().0;
61+
62+
for bond_info in active_collators {
63+
let owner = bond_info.owner;
64+
let balance = OldCurrency::free_balance(&owner);
65+
log::info!(
66+
"Collator: {:?} OldCurrency::free_balance pre_upgrade {:?}",
67+
HexDisplay::from(&owner.encode()),
68+
balance
69+
);
70+
}
71+
72+
Ok(Vec::new())
73+
}
74+
75+
#[cfg(feature = "try-runtime")]
76+
fn post_upgrade(_state: Vec<u8>) -> Result<(), DispatchError> {
77+
let active_collators = CandidatePool::<T>::get().0;
78+
79+
for bond_info in active_collators {
80+
let owner = bond_info.owner;
81+
let balance = OldCurrency::free_balance(&owner);
82+
log::info!(
83+
"Collator: {:?} OldCurrency::free_balance post_upgrade {:?}",
84+
HexDisplay::from(&owner.encode()),
85+
balance
86+
);
87+
}
88+
89+
Ok(())
90+
}
91+
92+
fn on_runtime_upgrade() -> frame_support::weights::Weight {
93+
log::info!("Parachain Staking: on_runtime_upgrade");
94+
let mut read_ops = 0u64;
95+
let mut write_ops = 0u64;
96+
97+
// Get all the active collators
98+
let active_collators = CandidatePool::<T>::get().0;
99+
read_ops += 1;
100+
101+
for bond_info in active_collators {
102+
let owner = bond_info.owner;
103+
log::info!("Parachain Staking: migrating collator {:?}", HexDisplay::from(&owner.encode()));
104+
105+
let candidate_info = CandidateInfo::<T>::get(&owner).unwrap();
106+
let bond_amount = candidate_info.bond;
107+
read_ops += 1;
108+
log::info!("Parachain Staking: bond_amount {:?}", bond_amount);
109+
110+
let already_held: <T as Config>::Balance =
111+
T::Currency::balance_on_hold(&HoldReason::StakingCollator.into(), &owner);
112+
read_ops += 1;
113+
114+
// Check if the lock is already held, to make migration idempotent
115+
if already_held == bond_amount {
116+
log::info!("Parachain Staking: already held {:?}", already_held);
117+
} else {
118+
// Remove the lock from the old currency
119+
OldCurrency::remove_lock(COLLATOR_LOCK_ID, &owner);
120+
write_ops += 1;
121+
122+
// Hold the new currency
123+
T::Currency::hold(&HoldReason::StakingCollator.into(), &owner, bond_amount).unwrap_or_else(|err| {
124+
log::error!("Failed to add lock to parachain staking currency: {:?}", err);
125+
});
126+
write_ops += 1;
127+
128+
// Get all the delegations for the collator
129+
if let Some(delegations) = TopDelegations::<T>::get(&owner) {
130+
read_ops += 1;
131+
for delegation in delegations.delegations {
132+
// Process each delegation
133+
log::info!(
134+
"Delegator: {:?}, Amount: {:?}",
135+
HexDisplay::from(&delegation.owner.encode()),
136+
delegation.amount
137+
);
138+
139+
// Remove the lock from the old currency
140+
OldCurrency::remove_lock(DELEGATOR_LOCK_ID, &delegation.owner);
141+
write_ops += 1;
142+
143+
// Hold the new currency
144+
T::Currency::hold(&HoldReason::StakingDelegator.into(), &delegation.owner, delegation.amount)
145+
.unwrap_or_else(|err| {
146+
log::error!("Failed to add lock to parachain staking currency: {:?}", err);
147+
});
148+
write_ops += 1;
149+
}
150+
} else {
151+
// Handle the case where there are no delegations for the account
152+
log::info!("No delegations found for the given account.");
153+
}
154+
}
155+
}
156+
157+
log::info!("Parachain Staking: read_ops {:?} | write_ops: {:?}", read_ops, write_ops);
158+
159+
<T as frame_system::Config>::DbWeight::get().reads_writes(read_ops, write_ops)
160+
}
161+
}

runtimes/base/src/lib.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ pub mod migrations {
128128
cumulus_pallet_xcmp_queue::migration::Migration<Runtime>,
129129
cumulus_pallet_dmp_queue::migration::Migration<Runtime>,
130130
custom_migrations::CustomOnRuntimeUpgrade,
131+
pallet_parachain_staking::migrations::CustomOnRuntimeUpgrade<Runtime, Balances>,
131132
);
132133
}
133134

@@ -197,13 +198,18 @@ impl Contains<RuntimeCall> for BaseCallFilter {
197198
fn contains(c: &RuntimeCall) -> bool {
198199
use pallet_balances::Call::*;
199200
match c {
201+
// Transferability lock.
200202
RuntimeCall::Balances(inner_call) => match inner_call {
201203
transfer { .. } => false,
202204
transfer_all { .. } => false,
203205
transfer_keep_alive { .. } => false,
204206
transfer_allow_death { .. } => false,
205207
_ => true,
206208
},
209+
// Staking "disabled" @ TGE.
210+
RuntimeCall::ParachainStaking(inner_call) => match inner_call {
211+
_ => false,
212+
},
207213
_ => true,
208214
}
209215
}
@@ -293,7 +299,7 @@ impl pallet_balances::Config for Runtime {
293299
type Balance = Balance;
294300
type DustRemoval = ();
295301
type ExistentialDeposit = ExistentialDeposit;
296-
type FreezeIdentifier = ();
302+
type FreezeIdentifier = RuntimeFreezeReason;
297303
type MaxFreezes = MaxReserves;
298304
type MaxHolds = MaxLocks;
299305
type MaxLocks = MaxLocks;

0 commit comments

Comments
 (0)