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

[AHM] Add multisig migration #534

Merged
merged 5 commits into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions integration-tests/ahm/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.

use asset_hub_polkadot_runtime::Block as AssetHubBlock;
use cumulus_primitives_core::{AggregateMessageOrigin, InboundDownwardMessage};
use frame_support::traits::EnqueueMessage;
use polkadot_runtime::Block as PolkadotBlock;
use remote_externalities::{Builder, Mode, OfflineConfig, RemoteExternalities};
use sp_runtime::BoundedVec;

const LOG_RC: &str = "runtime::relay";
const LOG_AH: &str = "runtime::asset-hub";
Expand Down Expand Up @@ -73,3 +76,17 @@ pub fn next_block_ah() {
frame_system::Pallet::<polkadot_runtime::Runtime>::reset_events();
<asset_hub_polkadot_runtime::AhMigrator as frame_support::traits::OnInitialize<_>>::on_initialize(now + 1);
}

/// Enqueue DMP messages on the parachain side.
///
/// This bypasses `set_validation_data` and `enqueue_inbound_downward_messages` by just directly
/// enqueuing them.
pub fn enqueue_dmp(msgs: Vec<InboundDownwardMessage>) {
for msg in msgs {
let bounded_msg: BoundedVec<u8, _> = msg.msg.try_into().expect("DMP message too big");
asset_hub_polkadot_runtime::MessageQueue::enqueue_message(
bounded_msg.as_bounded_slice(),
AggregateMessageOrigin::Parent,
);
}
}
35 changes: 10 additions & 25 deletions integration-tests/ahm/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,10 @@

use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
use frame_support::{pallet_prelude::*, traits::*, weights::WeightMeter};
use pallet_rc_migrator::RcMigrationStage;
use pallet_rc_migrator::{MigrationStage, RcMigrationStage};
use polkadot_primitives::InboundDownwardMessage;
use polkadot_runtime::RcMigrator;
use sp_core::H256;
use sp_io::TestExternalities;
use sp_storage::StateVersion;
use std::cell::OnceCell;
use remote_externalities::RemoteExternalities;
use tokio::sync::mpsc::channel;

use asset_hub_polkadot_runtime::{Block as AssetHubBlock, Runtime as AssetHub};
use polkadot_runtime::{Block as PolkadotBlock, Runtime as Polkadot};
Expand All @@ -61,13 +58,15 @@ async fn account_migration_works() {

let new_dmps =
runtime_parachains::dmp::DownwardMessageQueues::<Polkadot>::take(para_id);
if new_dmps.is_empty() && !dmps.is_empty() {
break;
}
dmps.extend(new_dmps);
}

dmps
if RcMigrationStage::<Polkadot>::get() ==
pallet_rc_migrator::MigrationStage::MultisigMigrationDone
{
log::info!("Multisig migration done");
break dmps;
}
}
});
rc.commit_all().unwrap();
log::info!("Num of RC->AH DMP messages: {}", dmp_messages.len());
Expand Down Expand Up @@ -95,17 +94,3 @@ async fn account_migration_works() {
// some overweight ones.
});
}

/// Enqueue DMP messages on the parachain side.
///
/// This bypasses `set_validation_data` and `enqueue_inbound_downward_messages` by just directly
/// enqueuing them.
fn enqueue_dmp(msgs: Vec<InboundDownwardMessage>) {
for msg in msgs {
let bounded_msg: BoundedVec<u8, _> = msg.msg.try_into().expect("DMP message too big");
asset_hub_polkadot_runtime::MessageQueue::enqueue_message(
bounded_msg.as_bounded_slice(),
AggregateMessageOrigin::Parent,
);
}
}
5 changes: 5 additions & 0 deletions pallets/ah-migrator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ frame-support = { workspace = true }
frame-system = { workspace = true }
log = { workspace = true }
pallet-balances = { workspace = true }
pallet-multisig = { workspace = true }
pallet-nomination-pools = { workspace = true }
pallet-preimage = { workspace = true }
pallet-rc-migrator = { workspace = true }
Expand All @@ -29,6 +30,7 @@ sp-core = { workspace = true }
sp-io = { workspace = true }
sp-runtime = { workspace = true }
sp-std = { workspace = true }
hex-literal = { workspace = true }

[features]
default = ["std"]
Expand All @@ -39,6 +41,7 @@ std = [
"frame-system/std",
"log/std",
"pallet-balances/std",
"pallet-multisig/std",
"pallet-nomination-pools/std",
"pallet-preimage/std",
"pallet-rc-migrator/std",
Expand All @@ -60,6 +63,7 @@ runtime-benchmarks = [
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-multisig/runtime-benchmarks",
"pallet-nomination-pools/runtime-benchmarks",
"pallet-preimage/runtime-benchmarks",
"pallet-rc-migrator/runtime-benchmarks",
Expand All @@ -74,6 +78,7 @@ try-runtime = [
"frame-support/try-runtime",
"frame-system/try-runtime",
"pallet-balances/try-runtime",
"pallet-multisig/try-runtime",
"pallet-nomination-pools/try-runtime",
"pallet-preimage/try-runtime",
"pallet-rc-migrator/try-runtime",
Expand Down
113 changes: 113 additions & 0 deletions pallets/ah-migrator/src/account.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// This file is part of Substrate.

// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Account balance migration.

use crate::{types::*, *};

impl<T: Config> Pallet<T> {
pub fn do_receive_accounts(
accounts: Vec<RcAccount<T::AccountId, T::Balance, T::RcHoldReason, T::RcFreezeReason>>,
) -> Result<(), Error<T>> {
log::info!(target: LOG_TARGET, "Integrating {} accounts", accounts.len());

for account in accounts {
let _: Result<(), ()> = with_transaction_opaque_err::<(), (), _>(|| {
match Self::do_receive_account(account) {
Ok(()) => TransactionOutcome::Commit(Ok(())),
Err(_) => TransactionOutcome::Rollback(Ok(())),
}
})
.expect("Always returning Ok; qed");
}

Ok(())
}

/// MAY CHANGED STORAGE ON ERROR RETURN
pub fn do_receive_account(
account: RcAccount<T::AccountId, T::Balance, T::RcHoldReason, T::RcFreezeReason>,
) -> Result<(), Error<T>> {
let who = account.who;
let total_balance = account.free + account.reserved;
let minted = match <T as pallet::Config>::Currency::mint_into(&who, total_balance) {
Ok(minted) => minted,
Err(e) => {
log::error!(target: LOG_TARGET, "Failed to mint into account {}: {:?}", who.to_ss58check(), e);
return Err(Error::<T>::TODO);
},
};
debug_assert!(minted == total_balance);

for hold in account.holds {
if let Err(e) = <T as pallet::Config>::Currency::hold(
&T::RcToAhHoldReason::convert(hold.id),
&who,
hold.amount,
) {
log::error!(target: LOG_TARGET, "Failed to hold into account {}: {:?}", who.to_ss58check(), e);
return Err(Error::<T>::TODO);
}
}

if let Err(e) = <T as pallet::Config>::Currency::reserve(&who, account.unnamed_reserve) {
log::error!(target: LOG_TARGET, "Failed to reserve into account {}: {:?}", who.to_ss58check(), e);
return Err(Error::<T>::TODO);
}

for freeze in account.freezes {
if let Err(e) = <T as pallet::Config>::Currency::set_freeze(
&T::RcToAhFreezeReason::convert(freeze.id),
&who,
freeze.amount,
) {
log::error!(target: LOG_TARGET, "Failed to freeze into account {}: {:?}", who.to_ss58check(), e);
return Err(Error::<T>::TODO);
}
}

for lock in account.locks {
<T as pallet::Config>::Currency::set_lock(
lock.id,
&who,
lock.amount,
types::map_lock_reason(lock.reasons),
);
}

log::debug!(
target: LOG_TARGET,
"Integrating account: {}", who.to_ss58check(),
);

// TODO run some post-migration sanity checks

// Apply all additional consumers that were excluded from the balance stuff above:
for _ in 0..account.consumers {
if let Err(e) = frame_system::Pallet::<T>::inc_consumers(&who) {
log::error!(target: LOG_TARGET, "Failed to inc consumers for account {}: {:?}", who.to_ss58check(), e);
return Err(Error::<T>::TODO);
}
}
for _ in 0..account.providers {
frame_system::Pallet::<T>::inc_providers(&who);
}

// TODO: publish event
Ok(())
}
}
Loading
Loading