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] Cleanup and add Preimage doc #543

Merged
merged 4 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ substrate.code-workspace
target/
**/__pycache__/
*.snap
*.json
1 change: 1 addition & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion integration-tests/ahm/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ async fn account_migration_works() {
let Some((mut rc, mut ah)) = load_externalities().await else { return };
let para_id = ParaId::from(1000);

// Simulate 10 relay blocks and grab the DMP messages
// Simulate relay blocks and grab the DMP messages
let dmp_messages = rc.execute_with(|| {
let mut dmps = Vec::new();

Expand Down
6 changes: 4 additions & 2 deletions pallets/ah-migrator/src/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ impl<T: Config> Pallet<T> {
let Ok(proxy_type) = T::RcToProxyType::try_convert(p.proxy_type) else {
// This is fine, eg. `Auction` proxy is not supported on AH
log::warn!(target: LOG_TARGET, "Dropping unsupported proxy at index {} for {}", i, proxy.delegator.to_ss58check());
// TODO unreserve deposit
return None;
};

Expand Down Expand Up @@ -89,7 +90,7 @@ impl<T: Config> Pallet<T> {
});

let (mut count_good, mut count_bad) = (0, 0);
log::info!(target: LOG_TARGET, "Integrating {} proxy announcements", announcements.len());
log::info!(target: LOG_TARGET, "Unreserving deposits for {} proxy announcements", announcements.len());

for announcement in announcements {
match Self::do_receive_proxy_announcement(announcement) {
Expand All @@ -109,13 +110,14 @@ impl<T: Config> Pallet<T> {
pub fn do_receive_proxy_announcement(
announcement: RcProxyAnnouncementOf<T>,
) -> Result<(), Error<T>> {
let before = frame_system::Account::<T>::get(&announcement.depositor);
let missing = <T as pallet_proxy::Config>::Currency::unreserve(
&announcement.depositor,
announcement.deposit,
);

if !missing.is_zero() {
log::warn!(target: LOG_TARGET, "Could not unreserve full proxy announcement deposit for {}, missing {:?}", announcement.depositor.to_ss58check(), missing);
log::warn!(target: LOG_TARGET, "Could not unreserve full proxy announcement deposit for {}, missing {:?}, before {:?}", announcement.depositor.to_ss58check(), missing, before);
}

Ok(())
Expand Down
2 changes: 1 addition & 1 deletion pallets/rc-migrator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pallet-multisig = { workspace = true }
polkadot-runtime-common = { workspace = true }
runtime-parachains = { workspace = true }
polkadot-parachain-primitives = { workspace = true }

hex-literal = { workspace = true }
xcm = { workspace = true }

[features]
Expand Down
30 changes: 7 additions & 23 deletions pallets/rc-migrator/src/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,27 +219,11 @@ impl<T: Config> Pallet<T> {
}
};

let call = types::AssetHubPalletConfig::<T>::AhmController(
types::AhMigratorCall::<T>::ReceiveAccounts { accounts: package },
);

let message = Xcm(vec![
Instruction::UnpaidExecution {
weight_limit: WeightLimit::Unlimited,
check_origin: None,
},
Instruction::Transact {
origin_kind: OriginKind::Superuser,
require_weight_at_most: Weight::from_all(1), // TODO
call: call.encode().into(),
},
]);

if let Err(_err) =
send_xcm::<T::SendXcm>(Location::new(0, [Junction::Parachain(1000)]), message.clone())
{
return Err(Error::TODO);
};
if !package.is_empty() {
Pallet::<T>::send_chunked_xcm(package, |package| {
types::AhMigratorCall::<T>::ReceiveAccounts { accounts: package }
})?;
}

Ok(maybe_last_key)
}
Expand Down Expand Up @@ -402,7 +386,7 @@ impl<T: Config> Pallet<T> {
/// Since the `reserved` and `frozen` balances will be known on a receiving side (AH) they will
/// be calculated there.
pub fn get_consumer_count(_who: &T::AccountId, _info: &AccountInfoFor<T>) -> u8 {
// TODO: check the pallets for provider references on Relay Chain.
// TODO: check the pallets for consumer references on Relay Chain.

// The following pallets increase consumers and are deployed on (Polkadot, Kusama, Westend):
// - `balances`: (P/K/W)
Expand All @@ -427,7 +411,7 @@ impl<T: Config> Pallet<T> {
pub fn get_provider_count(_who: &T::AccountId, _info: &AccountInfoFor<T>) -> u8 {
// TODO: check the pallets for provider references on Relay Chain.

// The following pallets increase consumers and are deployed on (Polkadot, Kusama, Westend):
// The following pallets increase provider and are deployed on (Polkadot, Kusama, Westend):
// - `crowdloan`: (P/K/W) https://github.com/paritytech/polkadot-sdk/blob/master/polkadot/runtime/common/src/crowdloan/mod.rs#L416
// - `parachains_on_demand`: (P/K/W) https://github.com/paritytech/polkadot-sdk/blob/master/polkadot/runtime/parachains/src/on_demand/mod.rs#L407
// - `balances`: (P/K/W) https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/balances/src/lib.rs#L1026
Expand Down
79 changes: 69 additions & 10 deletions pallets/rc-migrator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ pub enum MigrationStage<AccountId> {
/// easier to swap out what stage should run next for testing.
AccountsMigrationDone,
MultisigMigrationInit,
MultiSigMigrationOngoing {
MultisigMigrationOngoing {
/// Last migrated key of the `Multisigs` double map.
last_key: Option<(AccountId, [u8; 32])>,
},
Expand Down Expand Up @@ -158,10 +158,15 @@ pub mod pallet {
}

#[pallet::event]
//#[pallet::generate_deposit(pub(crate) fn deposit_event)]
#[pallet::generate_deposit(pub(crate) fn deposit_event)]
pub enum Event<T: Config> {
/// TODO
TODO,
/// A stage transition has occurred.
StageTransition {
/// The old stage before the transition.
old: MigrationStage<T::AccountId>,
/// The new stage after the transition.
new: MigrationStage<T::AccountId>,
},
}

/// The Relay Chain migration state.
Expand Down Expand Up @@ -267,9 +272,9 @@ pub mod pallet {
Self::transition(MigrationStage::MultisigMigrationInit);
},
MigrationStage::MultisigMigrationInit => {
Self::transition(MigrationStage::MultiSigMigrationOngoing { last_key: None });
Self::transition(MigrationStage::MultisigMigrationOngoing { last_key: None });
},
MigrationStage::MultiSigMigrationOngoing { last_key } => {
MigrationStage::MultisigMigrationOngoing { last_key } => {
let res = with_transaction_opaque_err::<Option<_>, Error<T>, _>(|| {
TransactionOutcome::Commit(MultisigMigrator::<T>::migrate_many(
last_key,
Expand All @@ -287,7 +292,7 @@ pub mod pallet {
Ok(Some(last_key)) => {
// multisig migration continues with the next block
// TODO publish event
Self::transition(MigrationStage::MultiSigMigrationOngoing {
Self::transition(MigrationStage::MultisigMigrationOngoing {
last_key: Some(last_key),
});
},
Expand Down Expand Up @@ -364,10 +369,64 @@ pub mod pallet {

impl<T: Config> Pallet<T> {
/// Execute a stage transition and log it.
fn transition(new_stage: MigrationStage<T::AccountId>) {
fn transition(new: MigrationStage<T::AccountId>) {
let old = RcMigrationStage::<T>::get();
RcMigrationStage::<T>::put(&new_stage);
log::info!(target: LOG_TARGET, "[Block {:?}] Stage transition: {:?} -> {:?}", frame_system::Pallet::<T>::block_number(), old, new_stage);
RcMigrationStage::<T>::put(&new);
log::info!(target: LOG_TARGET, "[Block {:?}] Stage transition: {:?} -> {:?}", frame_system::Pallet::<T>::block_number(), &old, &new);
Self::deposit_event(Event::StageTransition { old, new });
}

/// Split up the items into chunks of `MAX_MSG_SIZE` and send them as separate XCM
/// transacts.
///
/// This is done to avoid exceeding the XCM message size limit.
ggwpez marked this conversation as resolved.
Show resolved Hide resolved
pub fn send_chunked_xcm<E: Encode>(
mut items: Vec<E>,
create_call: impl Fn(Vec<E>) -> types::AhMigratorCall<T>,
) -> Result<(), Error<T>> {
const MAX_MSG_SIZE: u32 = 50_000; // Soft message size limit. Hard limit is about 64KiB

while !items.is_empty() {
let mut remaining_size: u32 = MAX_MSG_SIZE;
let mut batch = Vec::new();

while !items.is_empty() {
// Order does not matter, so we take from the back as optimization
ggwpez marked this conversation as resolved.
Show resolved Hide resolved
let item = items.last().unwrap(); // FAIL-CI no unwrap
let msg_size = item.encoded_size() as u32;
if msg_size > remaining_size {
break;
}
remaining_size -= msg_size;

batch.push(items.pop().unwrap()); // FAIL-CI no unwrap
}

log::info!(target: LOG_TARGET, "Sending batch of {} proxies", batch.len());
let call = types::AssetHubPalletConfig::<T>::AhmController(create_call(batch));

let message = Xcm(vec![
Instruction::UnpaidExecution {
weight_limit: WeightLimit::Unlimited,
check_origin: None,
},
Instruction::Transact {
origin_kind: OriginKind::Superuser,
require_weight_at_most: Weight::from_all(1), // TODO
call: call.encode().into(),
},
]);

if let Err(err) = send_xcm::<T::SendXcm>(
Location::new(0, [Junction::Parachain(1000)]),
message.clone(),
) {
log::error!(target: LOG_TARGET, "Error while sending XCM message: {:?}", err);
return Err(Error::TODO);
};
}

Ok(())
}
}
}
4 changes: 4 additions & 0 deletions pallets/rc-migrator/src/multisig.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ change the existing one. Both probably not worth it for us now.

The only thing that we should do is to unlock the deposits on the AH since they were migrated to AH
with the account state.

## TODO
- Think about what if one of the multisig members' accounts are inaccessible? Like they lost their key or something. Will this impact the possibility of the remaining multisig members to re-create the same multisig on AH?
- I think it does not impact it, as the [as_multi call](https://github.com/paritytech/polkadot-sdk/blob/9cdd1178f9e8da9f08a334a8cbbda435d1ffd9dd/substrate/frame/multisig/src/lib.rs#L358-L361) just accepts Account IDs as input that do not need to be accessible.
31 changes: 3 additions & 28 deletions pallets/rc-migrator/src/multisig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,9 @@ impl<T: Config> PalletMigration for MultisigMigrator<T> {
}

if !batch.is_empty() {
Self::send_batch_xcm(batch)?;
Pallet::<T>::send_chunked_xcm(batch, |batch| {
types::AhMigratorCall::<T>::ReceiveMultisigs { multisigs: batch }
})?;
}

Ok(last_key)
Expand All @@ -170,31 +172,4 @@ impl<T: Config> MultisigMigrator<T> {

Ok(RcMultisig { creator: ms.depositor, deposit: ms.deposit, details: Some(k1) })
}

/// Storage changes must be rolled back on error.
fn send_batch_xcm(multisigs: Vec<RcMultisigOf<T>>) -> Result<(), Error<T>> {
let call = types::AssetHubPalletConfig::<T>::AhmController(
types::AhMigratorCall::<T>::ReceiveMultisigs { multisigs },
);

let message = Xcm(vec![
Instruction::UnpaidExecution {
weight_limit: WeightLimit::Unlimited,
check_origin: None,
},
Instruction::Transact {
origin_kind: OriginKind::Superuser,
require_weight_at_most: Weight::from_all(1), // TODO
call: call.encode().into(),
},
]);

if let Err(_err) =
send_xcm::<T::SendXcm>(Location::new(0, [Junction::Parachain(1000)]), message.clone())
{
return Err(Error::TODO);
};

Ok(())
}
}
Loading
Loading