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

Fix Society v2 migration #14421

Merged
merged 43 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
984ac11
fix society v2 migration
liamaharon Jun 20, 2023
d67ae41
Update frame/society/src/migrations.rs
kianenigma Jun 20, 2023
93cca30
Update frame/society/src/migrations.rs
liamaharon Jun 21, 2023
e7b08e1
Update frame/society/src/migrations.rs
liamaharon Jun 22, 2023
315c1f4
Merge branch 'master' of github.com:paritytech/substrate into liam-so…
liamaharon Jun 27, 2023
54f3108
Merge branch 'liam-society-v2-migration' of github.com:paritytech/sub…
liamaharon Jun 27, 2023
7ea67b3
Merge branch 'master' of github.com:paritytech/substrate into liam-so…
liamaharon Jun 30, 2023
039a55b
Merge branch 'master' of github.com:paritytech/substrate into liam-so…
liamaharon Jul 2, 2023
81725a2
update for versioned upgrade
liamaharon Jul 2, 2023
4929c1a
Merge branch 'master' of github.com:paritytech/substrate into liam-so…
liamaharon Jul 2, 2023
ab2aa97
fix society v2 migration
liamaharon Jul 2, 2023
61af5d9
remove references to members being sorted from commnets
liamaharon Jul 3, 2023
46913c3
fix type
liamaharon Jul 3, 2023
8cce590
fix can_migrate check
liamaharon Jul 3, 2023
88e0836
add sanity log
liamaharon Jul 3, 2023
af97daa
fix sanity check
liamaharon Jul 3, 2023
0b4abd8
kick ci
liamaharon Jul 3, 2023
400304c
kick ci
liamaharon Jul 3, 2023
afd9e93
run tests with --experimental flag
liamaharon Jul 3, 2023
c7e4ca3
Merge branch 'liam-society-v2-migration' of github.com:paritytech/sub…
liamaharon Jul 4, 2023
e1f3c01
versioned migration cleanup
liamaharon Jul 4, 2023
1a6f08e
Merge branch 'master' of github.com:paritytech/substrate into liam-so…
liamaharon Jul 4, 2023
568440b
revert pipeline change
liamaharon Jul 4, 2023
2897ad5
use defensive!
liamaharon Jul 4, 2023
039d3e1
semicolons
liamaharon Jul 5, 2023
c1dd3e7
Merge branches 'master' and 'master' of github.com:paritytech/substra…
liamaharon Jul 6, 2023
f17bf46
defensive and doc comment
liamaharon Jul 6, 2023
b07294a
address pr comment
liamaharon Jul 6, 2023
a769e38
feature gate the versioned migration
liamaharon Jul 6, 2023
b039f09
defensive_unwrap_or
liamaharon Jul 6, 2023
f344dcb
fix test
liamaharon Jul 6, 2023
93d7ae4
fix doc comment
liamaharon Jul 6, 2023
803d114
change defensive to a log warning
liamaharon Jul 6, 2023
e1c2599
remove can_migrate anti-pattern
liamaharon Jul 7, 2023
1f9e5fe
Update frame/society/Cargo.toml
liamaharon Jul 7, 2023
87b3ee1
add experimental feature warning to doc comment
liamaharon Jul 11, 2023
9f0e4f9
Merge branch 'master' of github.com:paritytech/substrate into liam-so…
liamaharon Jul 11, 2023
28c36cc
update doc comment
liamaharon Jul 12, 2023
9878670
Merge branch 'master' of github.com:paritytech/substrate into liam-so…
liamaharon Jul 12, 2023
3461900
bump ci
liamaharon Jul 12, 2023
5b6b1a1
kick ci
liamaharon Jul 12, 2023
b0f08e0
kick ci
liamaharon Jul 12, 2023
20083ca
kick ci
liamaharon Jul 12, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion frame/society/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ sp-io = { version = "23.0.0", default-features = false, path = "../../primitives
sp-arithmetic = { version = "16.0.0", default-features = false, path = "../../primitives/arithmetic" }
sp-runtime = { version = "24.0.0", default-features = false, path = "../../primitives/runtime" }
frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, path = "../benchmarking" }
frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
frame-support = { version = "4.0.0-dev", default-features = false, path = "../support", features=["experimental"] }
ggwpez marked this conversation as resolved.
Show resolved Hide resolved
frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }

[dev-dependencies]
Expand Down
14 changes: 7 additions & 7 deletions frame/society/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,12 +466,12 @@ pub struct GroupParams<Balance> {

pub type GroupParamsFor<T, I> = GroupParams<BalanceOf<T, I>>;

pub(crate) const STORAGE_VERSION: StorageVersion = StorageVersion::new(2);

#[frame_support::pallet]
pub mod pallet {
use super::*;

const STORAGE_VERSION: StorageVersion = StorageVersion::new(2);

#[pallet::pallet]
#[pallet::storage_version(STORAGE_VERSION)]
#[pallet::without_storage_info]
Expand Down Expand Up @@ -1681,8 +1681,8 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
bids.iter().any(|bid| bid.who == *who)
}

/// Add a member to the sorted members list. If the user is already a member, do nothing.
/// Can fail when `MaxMember` limit is reached, but in that case it has no side-effects.
/// Add a member to the members list. If the user is already a member, do nothing. Can fail when
/// `MaxMember` limit is reached, but in that case it has no side-effects.
///
/// Set the `payouts` for the member. NOTE: This *WILL NOT RESERVE THE FUNDS TO MAKE THE
/// PAYOUT*. Only set this to be non-empty if you already have the funds reserved in the Payouts
Expand All @@ -1703,7 +1703,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
Ok(())
}

/// Add a member back to the sorted members list, setting their `rank` and `payouts`.
/// Add a member back to the members list, setting their `rank` and `payouts`.
///
/// Can fail when `MaxMember` limit is reached, but in that case it has no side-effects.
///
Expand All @@ -1713,8 +1713,8 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
Self::insert_member(who, rank)
}

/// Add a member to the sorted members list. If the user is already a member, do nothing.
/// Can fail when `MaxMember` limit is reached, but in that case it has no side-effects.
/// Add a member to the members list. If the user is already a member, do nothing. Can fail when
/// `MaxMember` limit is reached, but in that case it has no side-effects.
fn add_new_member(who: &T::AccountId, rank: Rank) -> DispatchResult {
Self::insert_member(who, rank)
}
Expand Down
68 changes: 55 additions & 13 deletions frame/society/src/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@

use super::*;
use codec::{Decode, Encode};
use frame_support::traits::{Instance, OnRuntimeUpgrade};
use frame_support::{
migrations::VersionedRuntimeUpgrade,
traits::{Instance, OnRuntimeUpgrade},
};

#[cfg(feature = "try-runtime")]
use sp_runtime::TryRuntimeError;
Expand All @@ -28,15 +31,15 @@ use sp_runtime::TryRuntimeError;
const TARGET: &'static str = "runtime::society::migration";

/// This migration moves all the state to v2 of Society.
pub struct MigrateToV2<T: Config<I>, I: 'static, PastPayouts>(
pub struct VersionUncheckedMigrateToV2<T: Config<I>, I: 'static, PastPayouts>(
sp_std::marker::PhantomData<(T, I, PastPayouts)>,
);

impl<
T: Config<I>,
I: Instance + 'static,
PastPayouts: Get<Vec<(<T as frame_system::Config>::AccountId, BalanceOf<T, I>)>>,
> OnRuntimeUpgrade for MigrateToV2<T, I, PastPayouts>
> OnRuntimeUpgrade for VersionUncheckedMigrateToV2<T, I, PastPayouts>
{
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
Expand All @@ -50,14 +53,20 @@ impl<
}

fn on_runtime_upgrade() -> Weight {
let current = Pallet::<T, I>::current_storage_version();
let onchain = Pallet::<T, I>::on_chain_storage_version();
if current == 2 && onchain == 0 {
from_original::<T, I>(&mut PastPayouts::get())
} else {
if onchain < 2 {
log::info!(
"Running migration with current storage version {:?} / onchain {:?}",
current,
target: TARGET,
"Running migration against onchain version {:?}",
onchain
);
let weight = from_original::<T, I>(&mut PastPayouts::get());
crate::STORAGE_VERSION.put::<Pallet<T, I>>();
weight
} else {
log::warn!(
liamaharon marked this conversation as resolved.
Show resolved Hide resolved
target: TARGET,
"Migration is a noop. onchain version: {:?}",
onchain
);
T::DbWeight::get().reads(1)
Expand Down Expand Up @@ -95,6 +104,14 @@ impl<
}
}

pub type VersionCheckedMigrateToV2<T, I, PastPayouts> = VersionedRuntimeUpgrade<
liamaharon marked this conversation as resolved.
Show resolved Hide resolved
0,
2,
VersionUncheckedMigrateToV2<T, I, PastPayouts>,
crate::pallet::Pallet<T, I>,
<T as frame_system::Config>::DbWeight,
>;

pub(crate) mod old {
use super::*;
use frame_support::storage_alias;
Expand Down Expand Up @@ -181,7 +198,7 @@ pub(crate) mod old {
}

pub fn can_migrate<T: Config<I>, I: Instance + 'static>() -> bool {
old::Members::<T, I>::exists()
Members::<T, I>::iter().next().is_none()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rococo old::Members is empty, making can_migrate return a false negative.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now you only return true if the list is empty? I'm confused.

Copy link
Contributor Author

@liamaharon liamaharon Jul 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Members are the new members. It returns true if new members are empty, signifying the old members have not yet been migrated.

old::Members is empty on Rococo, which was causing can_migrate to return false when it is supposed to return true (otherwise the on-chain version will not be updated to 2).

}

/// Will panic if there are any inconsistencies in the pallet's state or old keys remaining.
Expand Down Expand Up @@ -236,9 +253,9 @@ pub fn assert_internal_consistency<T: Config<I>, I: Instance + 'static>() {
pub fn from_original<T: Config<I>, I: Instance + 'static>(
past_payouts: &mut [(<T as frame_system::Config>::AccountId, BalanceOf<T, I>)],
) -> Weight {
// First check that this is the original state layout. This is easy since the original layout
// contained the Members value, and this value no longer exists in the new layout.
if !old::Members::<T, I>::exists() {
// First check that this is the original state layout. This is easy since the new layout
// contains a new Members value, which did not exist in the old layout.
if !can_migrate::<T, I>() {
liamaharon marked this conversation as resolved.
Show resolved Hide resolved
log::warn!(target: TARGET, "Skipping MigrateToV2 migration since it appears unapplicable");
// Already migrated or no data to migrate: Bail.
return T::DbWeight::get().reads(1)
Expand Down Expand Up @@ -281,6 +298,31 @@ pub fn from_original<T: Config<I>, I: Instance + 'static>(
let record = MemberRecord { index: member_count, rank: 0, strikes, vouching };
Members::<T, I>::insert(&member, record);
MemberByIndex::<T, I>::insert(member_count, &member);

// The founder must be the first member in Society V2. If we find the founder not in index
// zero, we swap it with the first member.
if member == Founder::<T, I>::get().expect("founder is always set; qed") && member_count > 0
liamaharon marked this conversation as resolved.
Show resolved Hide resolved
{
let member_to_swap = MemberByIndex::<T, I>::get(0)
.expect("member_count > 0, we must have at least 1 member; qed");
liamaharon marked this conversation as resolved.
Show resolved Hide resolved
// Swap the founder with the first member in MemberByIndex.
MemberByIndex::<T, I>::swap(0, member_count);
// Update the indicies of the swapped member MemberRecords.
Members::<T, I>::mutate(&member, |m| {
if let Some(member) = m {
member.index = 0;
} else {
log::error!("Member somehow disapeared from storage after it was inserted")
liamaharon marked this conversation as resolved.
Show resolved Hide resolved
}
});
Members::<T, I>::mutate(&member_to_swap, |m| {
if let Some(member) = m {
member.index = member_count;
} else {
log::error!("Member somehow disapeared from storage after it was queried")
}
});
}
member_count.saturating_inc();
}
MemberCount::<T, I>::put(member_count);
Expand Down
34 changes: 17 additions & 17 deletions frame/support/src/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,6 @@ use sp_core::Get;
use sp_io::{hashing::twox_128, storage::clear_prefix, KillStorageResult};
use sp_std::marker::PhantomData;

#[cfg(feature = "try-runtime")]
use sp_std::vec::Vec;

#[cfg(feature = "experimental")]
use crate::traits::OnRuntimeUpgrade;

/// Make it easier to write versioned runtime upgrades.
///
/// [`VersionedRuntimeUpgrade`] allows developers to write migrations without worrying about
Expand Down Expand Up @@ -57,13 +51,19 @@ use crate::traits::OnRuntimeUpgrade;
/// // OnRuntimeUpgrade implementation...
/// }
///
/// pub type VersionCheckedMigrateV5ToV6<Runtime, Pallet, DbWeight> =
/// VersionedRuntimeUpgrade<5, 6, VersionUncheckedMigrateV5ToV6<Runtime>, Pallet, DbWeight>;
/// pub type VersionCheckedMigrateV5ToV6<T, I> =
/// VersionedRuntimeUpgrade<
/// 5,
/// 6,
/// VersionUncheckedMigrateV5ToV6<T, I>,
/// crate::pallet::Pallet<T, I>,
/// <T as frame_system::Config>::DbWeight
/// >;
///
/// // Migrations tuple to pass to the Executive pallet:
/// pub type Migrations = (
/// // other migrations...
/// VersionCheckedMigrateV5ToV6<Runtime, Balances, RuntimeDbWeight>,
/// VersionCheckedMigrateV5ToV6<T, ()>,
/// // other migrations...
/// );
/// ```
Expand All @@ -78,7 +78,7 @@ pub struct VersionedRuntimeUpgrade<const FROM: u16, const TO: u16, Inner, Pallet
#[derive(codec::Encode, codec::Decode)]
pub enum VersionedPostUpgradeData {
/// The migration ran, inner vec contains pre_upgrade data.
MigrationExecuted(Vec<u8>),
MigrationExecuted(sp_std::vec::Vec<u8>),
/// This migration is a noop, do not run post_upgrade checks.
Noop,
}
Expand All @@ -93,16 +93,16 @@ pub enum VersionedPostUpgradeData {
impl<
const FROM: u16,
const TO: u16,
Inner: OnRuntimeUpgrade,
Inner: crate::traits::OnRuntimeUpgrade,
Pallet: GetStorageVersion<CurrentStorageVersion = StorageVersion> + PalletInfoAccess,
DbWeight: Get<RuntimeDbWeight>,
> OnRuntimeUpgrade for VersionedRuntimeUpgrade<FROM, TO, Inner, Pallet, DbWeight>
> crate::traits::OnRuntimeUpgrade for VersionedRuntimeUpgrade<FROM, TO, Inner, Pallet, DbWeight>
{
/// Executes pre_upgrade if the migration will run, and wraps the pre_upgrade bytes in
/// [`VersionedPostUpgradeData`] before passing them to post_upgrade, so it knows whether the
/// migration ran or not.
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
fn pre_upgrade() -> Result<sp_std::vec::Vec<u8>, sp_runtime::TryRuntimeError> {
use codec::Encode;
let on_chain_version = Pallet::on_chain_storage_version();
if on_chain_version == FROM {
Expand Down Expand Up @@ -152,7 +152,7 @@ impl<
/// the migration ran, and [`VersionedPostUpgradeData::Noop`] otherwise.
#[cfg(feature = "try-runtime")]
fn post_upgrade(
versioned_post_upgrade_data_bytes: Vec<u8>,
versioned_post_upgrade_data_bytes: sp_std::vec::Vec<u8>,
) -> Result<(), sp_runtime::TryRuntimeError> {
use codec::DecodeAll;
match <VersionedPostUpgradeData>::decode_all(&mut &versioned_post_upgrade_data_bytes[..])
Expand Down Expand Up @@ -321,7 +321,7 @@ impl<P: Get<&'static str>, DbWeight: Get<RuntimeDbWeight>> frame_support::traits
}

#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
fn pre_upgrade() -> Result<sp_std::vec::Vec<u8>, sp_runtime::TryRuntimeError> {
use crate::storage::unhashed::contains_prefixed_key;

let hashed_prefix = twox_128(P::get().as_bytes());
Expand All @@ -332,11 +332,11 @@ impl<P: Get<&'static str>, DbWeight: Get<RuntimeDbWeight>> frame_support::traits
P::get()
),
};
Ok(Vec::new())
Ok(sp_std::vec::Vec::new())
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(_state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
fn post_upgrade(_state: sp_std::vec::Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
use crate::storage::unhashed::contains_prefixed_key;

let hashed_prefix = twox_128(P::get().as_bytes());
Expand Down