Identity Deposits Relay to Parachain Migration (#1814)

The goal of this PR is to migrate Identity deposits from the Relay Chain
to a system parachain.

The problem I want to solve is that `IdentityOf` and `SubsOf` both store
an amount that's held in reserve as a storage deposit. When migrating to
a parachain, we can take a snapshot of the actual `IdentityInfo` and
sub-account mappings, but should migrate (off chain) the `deposit`s to
zero, since the chain (and by extension, accounts) won't have any funds
at genesis.

The good news is that we expect parachain deposits to be significantly
lower (possibly 100x) on the parachain. That is, a deposit of 21 DOT on
the Relay Chain would need 0.21 DOT on a parachain. This PR proposes to
migrate the deposits in the following way:

1. Introduces a new pallet with two extrinsics: 
- `reap_identity`: Has a configurable `ReapOrigin`, which would be set
to `EnsureSigned` on the Relay Chain (i.e. callable by anyone) and
`EnsureRoot` on the parachain (we don't want identities reaped from
there).
- `poke_deposit`: Checks what deposit the pallet holds (at genesis,
zero) and attempts to update the amount based on the calculated deposit
for storage data.
2. `reap_identity` clears all storage data for a `target` account and
unreserves their deposit.
3. A `ReapIdentityHandler` teleports the necessary DOT to the parachain
and calls `poke_deposit`. Since the parachain deposit is much lower, and
was just unreserved, we know we have enough.

One awkwardness I ran into was that the XCMv3 instruction set does not
provide a way for the system to teleport assets without a fee being
deducted on reception. Users shouldn't have to pay a fee for the system
to migrate their info to a more efficient location. So I wrote my own
program and did the `InitiateTeleport` accounting on my own to send a
program with `UnpaidExecution`. Have discussed an
`InitiateUnpaidTeleport` instruction with @franciscoaguirre . Obviously
any chain executing this would have to pass a `Barrier` for free
execution.

TODO:

- [x] Confirm People Chain ParaId
- [x] Confirm People Chain deposit rates (determined in
https://github.com/paritytech/polkadot-sdk/pull/2281)
- [x] Add pallet to Westend

---------

Co-authored-by: Bastian Köcher <git@kchr.de>
This commit is contained in:
joe petrowski
2023-11-15 15:22:28 +01:00
committed by GitHub
parent 5b0622bc4d
commit c79b234b3b
15 changed files with 1111 additions and 13 deletions
@@ -17,7 +17,7 @@
//! Mocking utilities for testing with real pallets.
use crate::{
auctions, crowdloan,
auctions, crowdloan, identity_migrator,
mock::{conclude_pvf_checking, validators_public_keys},
paras_registrar,
slot_range::SlotRange,
@@ -32,6 +32,7 @@ use frame_support::{
};
use frame_support_test::TestRandomness;
use frame_system::EnsureRoot;
use pallet_identity::{self, legacy::IdentityInfo};
use parity_scale_codec::Encode;
use primitives::{
BlockNumber, HeadData, Id as ParaId, SessionIndex, ValidationCode, LOWEST_PUBLIC_ID,
@@ -88,6 +89,10 @@ frame_support::construct_runtime!(
Auctions: auctions::{Pallet, Call, Storage, Event<T>},
Crowdloan: crowdloan::{Pallet, Call, Storage, Event<T>},
Slots: slots::{Pallet, Call, Storage, Event<T>},
// Migrators
Identity: pallet_identity::{Pallet, Call, Storage, Event<T>},
IdentityMigrator: identity_migrator::{Pallet, Call, Event<T>},
}
);
@@ -274,6 +279,28 @@ impl crowdloan::Config for Test {
type WeightInfo = crate::crowdloan::TestWeightInfo;
}
impl pallet_identity::Config for Test {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type Slashed = ();
type BasicDeposit = ConstU32<100>;
type ByteDeposit = ConstU32<10>;
type SubAccountDeposit = ConstU32<100>;
type MaxSubAccounts = ConstU32<2>;
type IdentityInformation = IdentityInfo<ConstU32<2>>;
type MaxRegistrars = ConstU32<20>;
type RegistrarOrigin = EnsureRoot<AccountId>;
type ForceOrigin = EnsureRoot<AccountId>;
type WeightInfo = ();
}
impl identity_migrator::Config for Test {
type RuntimeEvent = RuntimeEvent;
type Reaper = EnsureRoot<AccountId>;
type ReapIdentityHandler = ();
type WeightInfo = crate::identity_migrator::TestWeightInfo;
}
/// Create a new set of test externalities.
pub fn new_test_ext() -> TestExternalities {
let mut t = frame_system::GenesisConfig::<Test>::default().build_storage().unwrap();