Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MESH-1250: on_runtime_upgrade, clear V1 PIPs storage. #591

Merged
merged 1 commit into from Sep 8, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
54 changes: 53 additions & 1 deletion pallets/pips/src/lib.rs
Expand Up @@ -330,7 +330,9 @@ pub trait Trait:
frame_system::Trait + pallet_timestamp::Trait + IdentityTrait + CommonTrait
{
/// Currency type for this module.
type Currency: LockableCurrencyExt<Self::AccountId, Moment = Self::BlockNumber>;
// TODO(centril): Remove `ReservableCurrency` bound once `on_runtime_upgrade` is nixed.
type Currency: LockableCurrencyExt<Self::AccountId, Moment = Self::BlockNumber>
+ frame_support::traits::ReservableCurrency<Self::AccountId>;

/// Origin for proposals.
type CommitteeOrigin: EnsureOrigin<Self::Origin>;
Expand Down Expand Up @@ -548,6 +550,56 @@ decl_module! {

fn deposit_event() = default;

fn on_runtime_upgrade() -> Weight {
// Larger goal here is to clear Governance V1.
use frame_support::{
storage::{unhashed, IterableStorageDoubleMap, migration::StorageIterator},
traits::ReservableCurrency,
Twox128, StorageHasher
};

// 1. Start with refunding all deposits.
// As we've `drain`ed `Deposits`, we need not do so again below.
for (_, _, depo) in <Deposits<T>>::drain() {
<T as Trait>::Currency::unreserve(&depo.owner, depo.amount);
}

// 2. Then we clear various storage items that were present on V1.
// For future reference, the storage items are defined in:
// https://github.com/PolymathNetwork/Polymesh/blob/0047b2570e7ac57771b4153d25867166e8091b9a/pallets/pips/src/lib.rs#L308-L357

// 2a) Clear all the `map`s and `double_map`s by fully consuming a draining iterator.
for item in &[
"ProposalMetadata",
"ProposalsMaturingAt",
"Proposals",
"ProposalResult",
"Referendums",
"ScheduledReferendumsAt",
"ProposalVotes",
] {
StorageIterator::<()>::new(b"Pips", item.as_bytes()).drain().for_each(drop)
}

// 2b) Reset the PIP ID sequence to `0`.
PipIdSequence::kill();

// 2c) Remove items no longer used in V2.
fn storage_value_final_key(module: &[u8], item: &[u8]) -> [u8; 32] {
let mut final_key = [0u8; 32];
final_key[0..16].copy_from_slice(&Twox128::hash(module));
final_key[16..32].copy_from_slice(&Twox128::hash(item));
final_key
}
for item in &["ProposalDuration", "QuorumThreshold"] {
unhashed::kill(&storage_value_final_key(b"Pips", item.as_bytes()));
}

// Done; we've cleared all V1 storage needed; V2 can now be filled in.
// As for the weight, clearing costs much more than this, but let's pretend.
0
}

/// Change whether completed PIPs are pruned. Can only be called by governance council
///
/// # Arguments
Expand Down