4666047395
Updated 4763 files with dual copyright: - Parity Technologies (UK) Ltd. - Dijital Kurdistan Tech Institute
327 lines
11 KiB
Rust
327 lines
11 KiB
Rust
// Copyright (C) Parity Technologies (UK) Ltd. and Dijital Kurdistan Tech Institute
|
|
// 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.
|
|
|
|
//! This pezpallet is designed to go into a source chain and destination chain to migrate data. The
|
|
//! design motivations are:
|
|
//!
|
|
//! - Call some function on the source chain that executes some migration (clearing state,
|
|
//! forwarding an XCM program).
|
|
//! - Call some function (probably from an XCM program) on the destination chain.
|
|
//! - Avoid cluttering the source pezpallet with new dispatchables that are unrelated to its
|
|
//! functionality and only used for migration.
|
|
//!
|
|
//! After the migration is complete, the pezpallet may be removed from both chains' runtimes as well
|
|
//! as the `pezkuwi-runtime-common` crate.
|
|
|
|
use pezframe_support::{dispatch::DispatchResult, traits::Currency, weights::Weight};
|
|
pub use pezpallet::*;
|
|
use pezpallet_identity;
|
|
use pezsp_core::Get;
|
|
|
|
#[cfg(feature = "runtime-benchmarks")]
|
|
use pezframe_benchmarking::{account, v2::*, BenchmarkError};
|
|
|
|
pub trait WeightInfo {
|
|
fn reap_identity(r: u32, s: u32) -> Weight;
|
|
fn poke_deposit() -> Weight;
|
|
}
|
|
|
|
impl WeightInfo for () {
|
|
fn reap_identity(_r: u32, _s: u32) -> Weight {
|
|
Weight::MAX
|
|
}
|
|
fn poke_deposit() -> Weight {
|
|
Weight::MAX
|
|
}
|
|
}
|
|
|
|
pub struct TestWeightInfo;
|
|
impl WeightInfo for TestWeightInfo {
|
|
fn reap_identity(_r: u32, _s: u32) -> Weight {
|
|
Weight::zero()
|
|
}
|
|
fn poke_deposit() -> Weight {
|
|
Weight::zero()
|
|
}
|
|
}
|
|
|
|
// Must use the same `Balance` as `T`'s Identity pezpallet to handle deposits.
|
|
type BalanceOf<T> = <<T as pezpallet_identity::Config>::Currency as Currency<
|
|
<T as pezframe_system::Config>::AccountId,
|
|
>>::Balance;
|
|
|
|
#[pezframe_support::pezpallet]
|
|
pub mod pezpallet {
|
|
use super::*;
|
|
use pezframe_support::{
|
|
dispatch::{DispatchResultWithPostInfo, PostDispatchInfo},
|
|
pezpallet_prelude::*,
|
|
traits::EnsureOrigin,
|
|
};
|
|
use pezframe_system::pezpallet_prelude::*;
|
|
|
|
#[pezpallet::pezpallet]
|
|
pub struct Pezpallet<T>(_);
|
|
|
|
#[pezpallet::config]
|
|
pub trait Config: pezframe_system::Config + pezpallet_identity::Config {
|
|
/// Overarching event type.
|
|
#[allow(deprecated)]
|
|
type RuntimeEvent: From<Event<Self>>
|
|
+ IsType<<Self as pezframe_system::Config>::RuntimeEvent>;
|
|
|
|
/// The origin that can reap identities. Expected to be `EnsureSigned<AccountId>` on the
|
|
/// source chain such that anyone can all this function.
|
|
type Reaper: EnsureOrigin<Self::RuntimeOrigin>;
|
|
|
|
/// A handler for what to do when an identity is reaped.
|
|
type ReapIdentityHandler: OnReapIdentity<Self::AccountId>;
|
|
|
|
/// Weight information for the extrinsics in the pezpallet.
|
|
type WeightInfo: WeightInfo;
|
|
}
|
|
|
|
#[pezpallet::event]
|
|
#[pezpallet::generate_deposit(pub(super) fn deposit_event)]
|
|
pub enum Event<T: Config> {
|
|
/// The identity and all sub accounts were reaped for `who`.
|
|
IdentityReaped { who: T::AccountId },
|
|
/// The deposits held for `who` were updated. `identity` is the new deposit held for
|
|
/// identity info, and `subs` is the new deposit held for the sub-accounts.
|
|
DepositUpdated { who: T::AccountId, identity: BalanceOf<T>, subs: BalanceOf<T> },
|
|
}
|
|
|
|
#[pezpallet::call]
|
|
impl<T: Config> Pezpallet<T> {
|
|
/// Reap the `IdentityInfo` of `who` from the Identity pezpallet of `T`, unreserving any
|
|
/// deposits held and removing storage items associated with `who`.
|
|
#[pezpallet::call_index(0)]
|
|
#[pezpallet::weight(<T as pezpallet::Config>::WeightInfo::reap_identity(
|
|
T::MaxRegistrars::get(),
|
|
T::MaxSubAccounts::get()
|
|
))]
|
|
pub fn reap_identity(
|
|
origin: OriginFor<T>,
|
|
who: T::AccountId,
|
|
) -> DispatchResultWithPostInfo {
|
|
T::Reaper::ensure_origin(origin)?;
|
|
// - number of registrars (required to calculate weight)
|
|
// - byte size of `IdentityInfo` (required to calculate remote deposit)
|
|
// - number of sub accounts (required to calculate both weight and remote deposit)
|
|
let (registrars, bytes, subs) =
|
|
pezpallet_identity::Pezpallet::<T>::reap_identity(&who)?;
|
|
T::ReapIdentityHandler::on_reap_identity(&who, bytes, subs)?;
|
|
Self::deposit_event(Event::IdentityReaped { who });
|
|
let post = PostDispatchInfo {
|
|
actual_weight: Some(<T as pezpallet::Config>::WeightInfo::reap_identity(
|
|
registrars, subs,
|
|
)),
|
|
pays_fee: Pays::No,
|
|
};
|
|
Ok(post)
|
|
}
|
|
|
|
/// Update the deposit of `who`. Meant to be called by the system with an XCM `Transact`
|
|
/// Instruction.
|
|
#[pezpallet::call_index(1)]
|
|
#[pezpallet::weight(<T as pezpallet::Config>::WeightInfo::poke_deposit())]
|
|
pub fn poke_deposit(origin: OriginFor<T>, who: T::AccountId) -> DispatchResultWithPostInfo {
|
|
ensure_root(origin)?;
|
|
let (id_deposit, subs_deposit) =
|
|
pezpallet_identity::Pezpallet::<T>::poke_deposit(&who)?;
|
|
Self::deposit_event(Event::DepositUpdated {
|
|
who,
|
|
identity: id_deposit,
|
|
subs: subs_deposit,
|
|
});
|
|
Ok(Pays::No.into())
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Trait to handle reaping identity from state.
|
|
pub trait OnReapIdentity<AccountId> {
|
|
/// What to do when an identity is reaped. For example, the implementation could send an XCM
|
|
/// program to another chain. Concretely, a type implementing this trait in the Pezkuwi
|
|
/// runtime would teleport enough HEZ to the People Chain to cover the Identity deposit there.
|
|
///
|
|
/// This could also directly include `Transact { poke_deposit(..), ..}`.
|
|
///
|
|
/// Inputs
|
|
/// - `who`: Whose identity was reaped.
|
|
/// - `bytes`: The byte size of `IdentityInfo`.
|
|
/// - `subs`: The number of sub-accounts they had.
|
|
fn on_reap_identity(who: &AccountId, bytes: u32, subs: u32) -> DispatchResult;
|
|
|
|
/// Ensure that identity reaping will be succesful in benchmarking.
|
|
///
|
|
/// Should setup the state in a way that the same call ot `[Self::on_reap_identity]` will be
|
|
/// successful.
|
|
#[cfg(feature = "runtime-benchmarks")]
|
|
fn ensure_successful_identity_reaping(who: &AccountId, bytes: u32, subs: u32);
|
|
}
|
|
|
|
impl<AccountId> OnReapIdentity<AccountId> for () {
|
|
fn on_reap_identity(_who: &AccountId, _bytes: u32, _subs: u32) -> DispatchResult {
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(feature = "runtime-benchmarks")]
|
|
fn ensure_successful_identity_reaping(_: &AccountId, _: u32, _: u32) {}
|
|
}
|
|
|
|
#[cfg(feature = "runtime-benchmarks")]
|
|
#[benchmarks]
|
|
mod benchmarks {
|
|
use super::*;
|
|
use alloc::{boxed::Box, vec, vec::Vec};
|
|
use codec::Encode;
|
|
use pezframe_support::traits::EnsureOrigin;
|
|
use pezframe_system::RawOrigin;
|
|
use pezpallet_identity::{Data, IdentityInformationProvider, Judgement, Pezpallet as Identity};
|
|
use pezsp_runtime::{
|
|
traits::{Bounded, Hash, StaticLookup},
|
|
Saturating,
|
|
};
|
|
|
|
const SEED: u32 = 0;
|
|
|
|
fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
|
|
let events = pezframe_system::Pezpallet::<T>::events();
|
|
let system_event: <T as pezframe_system::Config>::RuntimeEvent = generic_event.into();
|
|
let pezframe_system::EventRecord { event, .. } = &events[events.len() - 1];
|
|
assert_eq!(event, &system_event);
|
|
}
|
|
|
|
#[benchmark]
|
|
fn reap_identity(
|
|
r: Linear<0, { T::MaxRegistrars::get() }>,
|
|
s: Linear<0, { T::MaxSubAccounts::get() }>,
|
|
) -> Result<(), BenchmarkError> {
|
|
// set up target
|
|
let target: T::AccountId = account("target", 0, SEED);
|
|
let target_origin =
|
|
<T as pezframe_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(target.clone()));
|
|
let target_lookup = T::Lookup::unlookup(target.clone());
|
|
let _ = T::Currency::make_free_balance_be(&target, BalanceOf::<T>::max_value());
|
|
|
|
// set identity
|
|
let info = <T as pezpallet_identity::Config>::IdentityInformation::create_identity_info();
|
|
Identity::<T>::set_identity(
|
|
RawOrigin::Signed(target.clone()).into(),
|
|
Box::new(info.clone()),
|
|
)?;
|
|
|
|
// create and set subs
|
|
let mut subs = Vec::new();
|
|
let data = Data::Raw(vec![0; 32].try_into().unwrap());
|
|
for ii in 0..s {
|
|
let sub_account = account("sub", ii, SEED);
|
|
subs.push((sub_account, data.clone()));
|
|
}
|
|
Identity::<T>::set_subs(target_origin.clone(), subs.clone())?;
|
|
|
|
T::ReapIdentityHandler::ensure_successful_identity_reaping(
|
|
&target,
|
|
info.encoded_size() as u32,
|
|
subs.len() as u32,
|
|
);
|
|
|
|
// add registrars and provide judgements
|
|
let registrar_origin = T::RegistrarOrigin::try_successful_origin()
|
|
.expect("RegistrarOrigin has no successful origin required for the benchmark");
|
|
for ii in 0..r {
|
|
// registrar account
|
|
let registrar: T::AccountId = account("registrar", ii, SEED);
|
|
let registrar_lookup = T::Lookup::unlookup(registrar.clone());
|
|
let _ = <T as pezpallet_identity::Config>::Currency::make_free_balance_be(
|
|
®istrar,
|
|
<T as pezpallet_identity::Config>::Currency::minimum_balance(),
|
|
);
|
|
|
|
// add registrar
|
|
Identity::<T>::add_registrar(registrar_origin.clone(), registrar_lookup)?;
|
|
Identity::<T>::set_fee(RawOrigin::Signed(registrar.clone()).into(), ii, 10u32.into())?;
|
|
let fields = <T as pezpallet_identity::Config>::IdentityInformation::all_fields();
|
|
Identity::<T>::set_fields(RawOrigin::Signed(registrar.clone()).into(), ii, fields)?;
|
|
|
|
// request and provide judgement
|
|
Identity::<T>::request_judgement(target_origin.clone(), ii, 10u32.into())?;
|
|
Identity::<T>::provide_judgement(
|
|
RawOrigin::Signed(registrar).into(),
|
|
ii,
|
|
target_lookup.clone(),
|
|
Judgement::Reasonable,
|
|
<T as pezframe_system::Config>::Hashing::hash_of(&info),
|
|
)?;
|
|
}
|
|
|
|
let origin = T::Reaper::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
|
|
|
|
#[extrinsic_call]
|
|
_(origin as T::RuntimeOrigin, target.clone());
|
|
|
|
assert_last_event::<T>(Event::<T>::IdentityReaped { who: target.clone() }.into());
|
|
|
|
let fields = <T as pezpallet_identity::Config>::IdentityInformation::all_fields();
|
|
assert!(!Identity::<T>::has_identity(&target, fields));
|
|
assert_eq!(Identity::<T>::subs(&target).len(), 0);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[benchmark]
|
|
fn poke_deposit() -> Result<(), BenchmarkError> {
|
|
let target: T::AccountId = account("target", 0, SEED);
|
|
let _ = T::Currency::make_free_balance_be(&target, BalanceOf::<T>::max_value());
|
|
let info = <T as pezpallet_identity::Config>::IdentityInformation::create_identity_info();
|
|
|
|
let _ = Identity::<T>::set_identity_no_deposit(&target, info.clone());
|
|
|
|
let sub_account: T::AccountId = account("sub", 0, SEED);
|
|
let name = Data::Raw(b"benchsub".to_vec().try_into().unwrap());
|
|
let _ = Identity::<T>::set_subs_no_deposit(&target, vec![(sub_account.clone(), name)]);
|
|
|
|
// expected deposits
|
|
let expected_id_deposit = <T as pezpallet_identity::Config>::BasicDeposit::get()
|
|
.saturating_add(
|
|
<T as pezpallet_identity::Config>::ByteDeposit::get()
|
|
.saturating_mul(<BalanceOf<T>>::from(info.encoded_size() as u32)),
|
|
);
|
|
// only 1 sub
|
|
let expected_sub_deposit = <T as pezpallet_identity::Config>::SubAccountDeposit::get();
|
|
|
|
#[extrinsic_call]
|
|
_(RawOrigin::Root, target.clone());
|
|
|
|
assert_last_event::<T>(
|
|
Event::<T>::DepositUpdated {
|
|
who: target,
|
|
identity: expected_id_deposit,
|
|
subs: expected_sub_deposit,
|
|
}
|
|
.into(),
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
impl_benchmark_test_suite!(
|
|
Pezpallet,
|
|
crate::integration_tests::new_test_ext(),
|
|
crate::integration_tests::Test,
|
|
);
|
|
}
|