mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-19 06:31:03 +00:00
Migrate slots pallet to pallet attribute macro. (#3218)
Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
@@ -28,7 +28,6 @@ use sp_keystore::{KeystoreExt, testing::KeyStore};
|
|||||||
use primitives::v1::{BlockNumber, Header, Id as ParaId, ValidationCode, HeadData, LOWEST_PUBLIC_ID};
|
use primitives::v1::{BlockNumber, Header, Id as ParaId, ValidationCode, HeadData, LOWEST_PUBLIC_ID};
|
||||||
use frame_support::{
|
use frame_support::{
|
||||||
parameter_types, assert_ok, assert_noop, PalletId,
|
parameter_types, assert_ok, assert_noop, PalletId,
|
||||||
storage::StorageMap,
|
|
||||||
traits::{Currency, OnInitialize, OnFinalize, KeyOwnerProofSystem},
|
traits::{Currency, OnInitialize, OnFinalize, KeyOwnerProofSystem},
|
||||||
};
|
};
|
||||||
use frame_system::EnsureRoot;
|
use frame_system::EnsureRoot;
|
||||||
|
|||||||
@@ -21,17 +21,20 @@
|
|||||||
//! This doesn't handle the mechanics of determining which para ID actually ends up with a parachain lease. This
|
//! This doesn't handle the mechanics of determining which para ID actually ends up with a parachain lease. This
|
||||||
//! must handled by a separately, through the trait interface that this pallet provides or the root dispatchables.
|
//! must handled by a separately, through the trait interface that this pallet provides or the root dispatchables.
|
||||||
|
|
||||||
use sp_std::prelude::*;
|
use crate::traits::{LeaseError, Leaser, Registrar};
|
||||||
use sp_runtime::traits::{CheckedSub, Zero, CheckedConversion, Saturating};
|
|
||||||
use frame_support::{
|
use frame_support::{
|
||||||
decl_module, decl_storage, decl_event, decl_error, dispatch::DispatchResult,
|
pallet_prelude::*,
|
||||||
traits::{Currency, ReservableCurrency, Get}, weights::Weight,
|
traits::{Currency, ReservableCurrency},
|
||||||
|
weights::Weight,
|
||||||
};
|
};
|
||||||
|
use frame_system::pallet_prelude::*;
|
||||||
|
pub use pallet::*;
|
||||||
use primitives::v1::Id as ParaId;
|
use primitives::v1::Id as ParaId;
|
||||||
use frame_system::{ensure_signed, ensure_root};
|
use sp_runtime::traits::{CheckedConversion, CheckedSub, Saturating, Zero};
|
||||||
use crate::traits::{Leaser, LeaseError, Registrar};
|
use sp_std::prelude::*;
|
||||||
|
|
||||||
type BalanceOf<T> = <<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
|
type BalanceOf<T> =
|
||||||
|
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
|
||||||
type LeasePeriodOf<T> = <T as frame_system::Config>::BlockNumber;
|
type LeasePeriodOf<T> = <T as frame_system::Config>::BlockNumber;
|
||||||
|
|
||||||
pub trait WeightInfo {
|
pub trait WeightInfo {
|
||||||
@@ -43,87 +46,102 @@ pub trait WeightInfo {
|
|||||||
|
|
||||||
pub struct TestWeightInfo;
|
pub struct TestWeightInfo;
|
||||||
impl WeightInfo for TestWeightInfo {
|
impl WeightInfo for TestWeightInfo {
|
||||||
fn force_lease() -> Weight { 0 }
|
fn force_lease() -> Weight {
|
||||||
fn manage_lease_period_start(_c: u32, _t:u32) -> Weight { 0 }
|
0
|
||||||
fn clear_all_leases() -> Weight { 0 }
|
}
|
||||||
fn trigger_onboard() -> Weight { 0 }
|
fn manage_lease_period_start(_c: u32, _t: u32) -> Weight {
|
||||||
}
|
0
|
||||||
|
}
|
||||||
/// The module's configuration trait.
|
fn clear_all_leases() -> Weight {
|
||||||
pub trait Config: frame_system::Config {
|
0
|
||||||
/// The overarching event type.
|
}
|
||||||
type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;
|
fn trigger_onboard() -> Weight {
|
||||||
|
0
|
||||||
/// The currency type used for bidding.
|
|
||||||
type Currency: ReservableCurrency<Self::AccountId>;
|
|
||||||
|
|
||||||
/// The parachain registrar type.
|
|
||||||
type Registrar: Registrar<AccountId=Self::AccountId>;
|
|
||||||
|
|
||||||
/// The number of blocks over which a single period lasts.
|
|
||||||
type LeasePeriod: Get<Self::BlockNumber>;
|
|
||||||
|
|
||||||
/// Weight Information for the Extrinsics in the Pallet
|
|
||||||
type WeightInfo: WeightInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This module's storage items.
|
|
||||||
decl_storage! {
|
|
||||||
trait Store for Module<T: Config> as Slots {
|
|
||||||
/// Amounts held on deposit for each (possibly future) leased parachain.
|
|
||||||
///
|
|
||||||
/// The actual amount locked on its behalf by any account at any time is the maximum of the second values
|
|
||||||
/// of the items in this list whose first value is the account.
|
|
||||||
///
|
|
||||||
/// The first item in the list is the amount locked for the current Lease Period. Following
|
|
||||||
/// items are for the subsequent lease periods.
|
|
||||||
///
|
|
||||||
/// The default value (an empty list) implies that the parachain no longer exists (or never
|
|
||||||
/// existed) as far as this module is concerned.
|
|
||||||
///
|
|
||||||
/// If a parachain doesn't exist *yet* but is scheduled to exist in the future, then it
|
|
||||||
/// will be left-padded with one or more `None`s to denote the fact that nothing is held on
|
|
||||||
/// deposit for the non-existent chain currently, but is held at some point in the future.
|
|
||||||
///
|
|
||||||
/// It is illegal for a `None` value to trail in the list.
|
|
||||||
pub Leases get(fn lease): map hasher(twox_64_concat) ParaId => Vec<Option<(T::AccountId, BalanceOf<T>)>>;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
decl_event!(
|
#[frame_support::pallet]
|
||||||
pub enum Event<T> where
|
pub mod pallet {
|
||||||
AccountId = <T as frame_system::Config>::AccountId,
|
use super::*;
|
||||||
LeasePeriod = LeasePeriodOf<T>,
|
|
||||||
ParaId = ParaId,
|
#[pallet::pallet]
|
||||||
Balance = BalanceOf<T>,
|
#[pallet::generate_store(pub(super) trait Store)]
|
||||||
{
|
pub struct Pallet<T>(_);
|
||||||
|
|
||||||
|
#[pallet::config]
|
||||||
|
pub trait Config: frame_system::Config {
|
||||||
|
/// The overarching event type.
|
||||||
|
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
|
||||||
|
|
||||||
|
/// The currency type used for bidding.
|
||||||
|
type Currency: ReservableCurrency<Self::AccountId>;
|
||||||
|
|
||||||
|
/// The parachain registrar type.
|
||||||
|
type Registrar: Registrar<AccountId = Self::AccountId>;
|
||||||
|
|
||||||
|
/// The number of blocks over which a single period lasts.
|
||||||
|
#[pallet::constant]
|
||||||
|
type LeasePeriod: Get<Self::BlockNumber>;
|
||||||
|
|
||||||
|
/// Weight Information for the Extrinsics in the Pallet
|
||||||
|
type WeightInfo: WeightInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Amounts held on deposit for each (possibly future) leased parachain.
|
||||||
|
///
|
||||||
|
/// The actual amount locked on its behalf by any account at any time is the maximum of the second values
|
||||||
|
/// of the items in this list whose first value is the account.
|
||||||
|
///
|
||||||
|
/// The first item in the list is the amount locked for the current Lease Period. Following
|
||||||
|
/// items are for the subsequent lease periods.
|
||||||
|
///
|
||||||
|
/// The default value (an empty list) implies that the parachain no longer exists (or never
|
||||||
|
/// existed) as far as this pallet is concerned.
|
||||||
|
///
|
||||||
|
/// If a parachain doesn't exist *yet* but is scheduled to exist in the future, then it
|
||||||
|
/// will be left-padded with one or more `None`s to denote the fact that nothing is held on
|
||||||
|
/// deposit for the non-existent chain currently, but is held at some point in the future.
|
||||||
|
///
|
||||||
|
/// It is illegal for a `None` value to trail in the list.
|
||||||
|
#[pallet::storage]
|
||||||
|
#[pallet::getter(fn lease)]
|
||||||
|
pub type Leases<T: Config> =
|
||||||
|
StorageMap<_, Twox64Concat, ParaId, Vec<Option<(T::AccountId, BalanceOf<T>)>>, ValueQuery>;
|
||||||
|
|
||||||
|
#[pallet::event]
|
||||||
|
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||||
|
#[pallet::metadata(
|
||||||
|
T::AccountId = "AccountId",
|
||||||
|
LeasePeriodOf<T> = "LeasePeriod",
|
||||||
|
BalanceOf<T> = "Balance",
|
||||||
|
)]
|
||||||
|
pub enum Event<T: Config> {
|
||||||
/// A new `[lease_period]` is beginning.
|
/// A new `[lease_period]` is beginning.
|
||||||
NewLeasePeriod(LeasePeriod),
|
NewLeasePeriod(LeasePeriodOf<T>),
|
||||||
/// A para has won the right to a continuous set of lease periods as a parachain.
|
/// A para has won the right to a continuous set of lease periods as a parachain.
|
||||||
/// First balance is any extra amount reserved on top of the para's existing deposit.
|
/// First balance is any extra amount reserved on top of the para's existing deposit.
|
||||||
/// Second balance is the total amount reserved.
|
/// Second balance is the total amount reserved.
|
||||||
/// `[parachain_id, leaser, period_begin, period_count, extra_reserved, total_amount]`
|
/// `[parachain_id, leaser, period_begin, period_count, extra_reserved, total_amount]`
|
||||||
Leased(ParaId, AccountId, LeasePeriod, LeasePeriod, Balance, Balance),
|
Leased(
|
||||||
|
ParaId,
|
||||||
|
T::AccountId,
|
||||||
|
LeasePeriodOf<T>,
|
||||||
|
LeasePeriodOf<T>,
|
||||||
|
BalanceOf<T>,
|
||||||
|
BalanceOf<T>,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
decl_error! {
|
#[pallet::error]
|
||||||
pub enum Error for Module<T: Config> {
|
pub enum Error<T> {
|
||||||
/// The parachain ID is not onboarding.
|
/// The parachain ID is not onboarding.
|
||||||
ParaNotOnboarding,
|
ParaNotOnboarding,
|
||||||
/// There was an error with the lease.
|
/// There was an error with the lease.
|
||||||
LeaseError,
|
LeaseError,
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
decl_module! {
|
|
||||||
pub struct Module<T: Config> for enum Call where origin: T::Origin {
|
|
||||||
type Error = Error<T>;
|
|
||||||
|
|
||||||
const LeasePeriod: T::BlockNumber = T::LeasePeriod::get();
|
|
||||||
|
|
||||||
fn deposit_event() = default;
|
|
||||||
|
|
||||||
|
#[pallet::hooks]
|
||||||
|
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
|
||||||
fn on_initialize(n: T::BlockNumber) -> Weight {
|
fn on_initialize(n: T::BlockNumber) -> Weight {
|
||||||
// If we're beginning a new lease period then handle that.
|
// If we're beginning a new lease period then handle that.
|
||||||
let lease_period = T::LeasePeriod::get();
|
let lease_period = T::LeasePeriod::get();
|
||||||
@@ -134,13 +152,17 @@ decl_module! {
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Just a connect to the `lease_out` call, in case Root wants to force some lease to happen
|
#[pallet::call]
|
||||||
|
impl<T: Config> Pallet<T> {
|
||||||
|
/// Just a connect into the `lease_out` call, in case Root wants to force some lease to happen
|
||||||
/// independently of any other on-chain mechanism to use it.
|
/// independently of any other on-chain mechanism to use it.
|
||||||
///
|
///
|
||||||
/// Can only be called by the Root origin.
|
/// Can only be called by the Root origin.
|
||||||
#[weight = T::WeightInfo::force_lease()]
|
#[pallet::weight(T::WeightInfo::force_lease())]
|
||||||
pub fn force_lease(origin,
|
pub fn force_lease(
|
||||||
|
origin: OriginFor<T>,
|
||||||
para: ParaId,
|
para: ParaId,
|
||||||
leaser: T::AccountId,
|
leaser: T::AccountId,
|
||||||
amount: BalanceOf<T>,
|
amount: BalanceOf<T>,
|
||||||
@@ -156,8 +178,8 @@ decl_module! {
|
|||||||
/// Clear all leases for a Para Id, refunding any deposits back to the original owners.
|
/// Clear all leases for a Para Id, refunding any deposits back to the original owners.
|
||||||
///
|
///
|
||||||
/// Can only be called by the Root origin.
|
/// Can only be called by the Root origin.
|
||||||
#[weight = T::WeightInfo::clear_all_leases()]
|
#[pallet::weight(T::WeightInfo::clear_all_leases())]
|
||||||
pub fn clear_all_leases(origin, para: ParaId) -> DispatchResult {
|
pub fn clear_all_leases(origin: OriginFor<T>, para: ParaId) -> DispatchResult {
|
||||||
ensure_root(origin)?;
|
ensure_root(origin)?;
|
||||||
let deposits = Self::all_deposits_held(para);
|
let deposits = Self::all_deposits_held(para);
|
||||||
|
|
||||||
@@ -178,16 +200,14 @@ decl_module! {
|
|||||||
/// let them onboard from here.
|
/// let them onboard from here.
|
||||||
///
|
///
|
||||||
/// Origin must be signed, but can be called by anyone.
|
/// Origin must be signed, but can be called by anyone.
|
||||||
#[weight = T::WeightInfo::trigger_onboard()]
|
#[pallet::weight(T::WeightInfo::trigger_onboard())]
|
||||||
pub fn trigger_onboard(origin, para: ParaId) -> DispatchResult {
|
pub fn trigger_onboard(origin: OriginFor<T>, para: ParaId) -> DispatchResult {
|
||||||
let _ = ensure_signed(origin)?;
|
let _ = ensure_signed(origin)?;
|
||||||
let leases = Leases::<T>::get(para);
|
let leases = Leases::<T>::get(para);
|
||||||
match leases.first() {
|
match leases.first() {
|
||||||
// If the first element in leases is present, then it has a lease!
|
// If the first element in leases is present, then it has a lease!
|
||||||
// We can try to onboard it.
|
// We can try to onboard it.
|
||||||
Some(Some(_lease_info)) => {
|
Some(Some(_lease_info)) => T::Registrar::make_parachain(para)?,
|
||||||
T::Registrar::make_parachain(para)?
|
|
||||||
},
|
|
||||||
// Otherwise, it does not have a lease.
|
// Otherwise, it does not have a lease.
|
||||||
Some(None) | None => {
|
Some(None) | None => {
|
||||||
return Err(Error::<T>::ParaNotOnboarding.into());
|
return Err(Error::<T>::ParaNotOnboarding.into());
|
||||||
@@ -198,20 +218,22 @@ decl_module! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Config> Module<T> {
|
impl<T: Config> Pallet<T> {
|
||||||
/// A new lease period is beginning. We're at the start of the first block of it.
|
/// A new lease period is beginning. We're at the start of the first block of it.
|
||||||
///
|
///
|
||||||
/// We need to on-board and off-board parachains as needed. We should also handle reducing/
|
/// We need to on-board and off-board parachains as needed. We should also handle reducing/
|
||||||
/// returning deposits.
|
/// returning deposits.
|
||||||
fn manage_lease_period_start(lease_period_index: LeasePeriodOf<T>) -> Weight {
|
fn manage_lease_period_start(lease_period_index: LeasePeriodOf<T>) -> Weight {
|
||||||
Self::deposit_event(RawEvent::NewLeasePeriod(lease_period_index));
|
Self::deposit_event(Event::<T>::NewLeasePeriod(lease_period_index));
|
||||||
|
|
||||||
let old_parachains = T::Registrar::parachains();
|
let old_parachains = T::Registrar::parachains();
|
||||||
|
|
||||||
// Figure out what chains need bringing on.
|
// Figure out what chains need bringing on.
|
||||||
let mut parachains = Vec::new();
|
let mut parachains = Vec::new();
|
||||||
for (para, mut lease_periods) in Leases::<T>::iter() {
|
for (para, mut lease_periods) in Leases::<T>::iter() {
|
||||||
if lease_periods.is_empty() { continue }
|
if lease_periods.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// ^^ should never be empty since we would have deleted the entry otherwise.
|
// ^^ should never be empty since we would have deleted the entry otherwise.
|
||||||
|
|
||||||
if lease_periods.len() == 1 {
|
if lease_periods.len() == 1 {
|
||||||
@@ -283,41 +305,31 @@ impl<T: Config> Module<T> {
|
|||||||
// you all the balances you need to unreserve.
|
// you all the balances you need to unreserve.
|
||||||
fn all_deposits_held(para: ParaId) -> Vec<(T::AccountId, BalanceOf<T>)> {
|
fn all_deposits_held(para: ParaId) -> Vec<(T::AccountId, BalanceOf<T>)> {
|
||||||
let mut tracker = sp_std::collections::btree_map::BTreeMap::new();
|
let mut tracker = sp_std::collections::btree_map::BTreeMap::new();
|
||||||
Leases::<T>::get(para)
|
Leases::<T>::get(para).into_iter().for_each(|lease| match lease {
|
||||||
.into_iter()
|
Some((who, amount)) => match tracker.get(&who) {
|
||||||
.for_each(|lease| {
|
Some(prev_amount) => {
|
||||||
match lease {
|
if amount > *prev_amount {
|
||||||
Some((who, amount)) => {
|
tracker.insert(who, amount);
|
||||||
match tracker.get(&who) {
|
}
|
||||||
Some(prev_amount) => {
|
|
||||||
if amount > *prev_amount {
|
|
||||||
tracker.insert(who, amount);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
tracker.insert(who, amount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {},
|
|
||||||
}
|
}
|
||||||
});
|
None => {
|
||||||
|
tracker.insert(who, amount);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {}
|
||||||
|
});
|
||||||
|
|
||||||
tracker.into_iter().collect()
|
tracker.into_iter().collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Config> crate::traits::OnSwap for Module<T> {
|
impl<T: Config> crate::traits::OnSwap for Pallet<T> {
|
||||||
fn on_swap(one: ParaId, other: ParaId) {
|
fn on_swap(one: ParaId, other: ParaId) {
|
||||||
Leases::<T>::mutate(one, |x|
|
Leases::<T>::mutate(one, |x| Leases::<T>::mutate(other, |y| sp_std::mem::swap(x, y)))
|
||||||
Leases::<T>::mutate(other, |y|
|
|
||||||
sp_std::mem::swap(x, y)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Config> Leaser for Module<T> {
|
impl<T: Config> Leaser for Pallet<T> {
|
||||||
type AccountId = T::AccountId;
|
type AccountId = T::AccountId;
|
||||||
type LeasePeriod = T::BlockNumber;
|
type LeasePeriod = T::BlockNumber;
|
||||||
type Currency = T::Currency;
|
type Currency = T::Currency;
|
||||||
@@ -347,12 +359,12 @@ impl<T: Config> Leaser for Module<T> {
|
|||||||
Leases::<T>::try_mutate(para, |d| {
|
Leases::<T>::try_mutate(para, |d| {
|
||||||
// Left-pad with `None`s as necessary.
|
// Left-pad with `None`s as necessary.
|
||||||
if d.len() < offset {
|
if d.len() < offset {
|
||||||
d.resize_with(offset, || { None });
|
d.resize_with(offset, || None);
|
||||||
}
|
}
|
||||||
let period_count_usize = period_count.checked_into::<usize>()
|
let period_count_usize =
|
||||||
.ok_or(LeaseError::AlreadyEnded)?;
|
period_count.checked_into::<usize>().ok_or(LeaseError::AlreadyEnded)?;
|
||||||
// Then place the deposit values for as long as the chain should exist.
|
// Then place the deposit values for as long as the chain should exist.
|
||||||
for i in offset .. (offset + period_count_usize) {
|
for i in offset..(offset + period_count_usize) {
|
||||||
if d.len() > i {
|
if d.len() > i {
|
||||||
// Already exists but it's `None`. That means a later slot was already leased.
|
// Already exists but it's `None`. That means a later slot was already leased.
|
||||||
// No problem.
|
// No problem.
|
||||||
@@ -391,24 +403,34 @@ impl<T: Config> Leaser for Module<T> {
|
|||||||
let _ = T::Registrar::make_parachain(para);
|
let _ = T::Registrar::make_parachain(para);
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::deposit_event(
|
Self::deposit_event(Event::<T>::Leased(
|
||||||
RawEvent::Leased(para, leaser.clone(), period_begin, period_count, reserved, amount)
|
para,
|
||||||
);
|
leaser.clone(),
|
||||||
|
period_begin,
|
||||||
|
period_count,
|
||||||
|
reserved,
|
||||||
|
amount,
|
||||||
|
));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deposit_held(para: ParaId, leaser: &Self::AccountId) -> <Self::Currency as Currency<Self::AccountId>>::Balance {
|
fn deposit_held(
|
||||||
|
para: ParaId,
|
||||||
|
leaser: &Self::AccountId,
|
||||||
|
) -> <Self::Currency as Currency<Self::AccountId>>::Balance {
|
||||||
Leases::<T>::get(para)
|
Leases::<T>::get(para)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|lease| {
|
.map(|lease| match lease {
|
||||||
match lease {
|
Some((who, amount)) => {
|
||||||
Some((who, amount)) => {
|
if &who == leaser {
|
||||||
if &who == leaser { amount } else { Zero::zero() }
|
amount
|
||||||
},
|
} else {
|
||||||
None => Zero::zero(),
|
Zero::zero()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
None => Zero::zero(),
|
||||||
})
|
})
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or_else(Zero::zero)
|
.unwrap_or_else(Zero::zero)
|
||||||
@@ -446,10 +468,10 @@ impl<T: Config> Leaser for Module<T> {
|
|||||||
|
|
||||||
// Get the leases, and check each item in the vec which is part of the range we are checking.
|
// Get the leases, and check each item in the vec which is part of the range we are checking.
|
||||||
let leases = Leases::<T>::get(para_id);
|
let leases = Leases::<T>::get(para_id);
|
||||||
for slot in offset ..= offset + period_count {
|
for slot in offset..=offset + period_count {
|
||||||
if let Some(Some(_)) = leases.get(slot) {
|
if let Some(Some(_)) = leases.get(slot) {
|
||||||
// If there exists any lease period, we exit early and return true.
|
// If there exists any lease period, we exit early and return true.
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,21 +480,17 @@ impl<T: Config> Leaser for Module<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// tests for this pallet
|
||||||
/// tests for this module
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use sp_core::H256;
|
use crate::{mock::TestRegistrar, slots};
|
||||||
use sp_runtime::traits::{BlakeTwo256, IdentityLookup};
|
use frame_support::{assert_noop, assert_ok, parameter_types};
|
||||||
use frame_support::{
|
|
||||||
parameter_types, assert_ok, assert_noop,
|
|
||||||
traits::{OnInitialize, OnFinalize}
|
|
||||||
};
|
|
||||||
use pallet_balances;
|
use pallet_balances;
|
||||||
use primitives::v1::{BlockNumber, Header};
|
use primitives::v1::{BlockNumber, Header};
|
||||||
use crate::{slots, mock::TestRegistrar};
|
use sp_core::H256;
|
||||||
|
use sp_runtime::traits::{BlakeTwo256, IdentityLookup};
|
||||||
|
|
||||||
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
|
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
|
||||||
type Block = frame_system::mocking::MockBlock<Test>;
|
type Block = frame_system::mocking::MockBlock<Test>;
|
||||||
@@ -553,7 +571,9 @@ mod tests {
|
|||||||
let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
|
let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
|
||||||
pallet_balances::GenesisConfig::<Test> {
|
pallet_balances::GenesisConfig::<Test> {
|
||||||
balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)],
|
balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)],
|
||||||
}.assimilate_storage(&mut t).unwrap();
|
}
|
||||||
|
.assimilate_storage(&mut t)
|
||||||
|
.unwrap();
|
||||||
t.into()
|
t.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -587,7 +607,12 @@ mod tests {
|
|||||||
new_test_ext().execute_with(|| {
|
new_test_ext().execute_with(|| {
|
||||||
run_to_block(1);
|
run_to_block(1);
|
||||||
|
|
||||||
assert_ok!(TestRegistrar::<Test>::register(1, ParaId::from(1), Default::default(), Default::default()));
|
assert_ok!(TestRegistrar::<Test>::register(
|
||||||
|
1,
|
||||||
|
ParaId::from(1),
|
||||||
|
Default::default(),
|
||||||
|
Default::default()
|
||||||
|
));
|
||||||
|
|
||||||
assert_ok!(Slots::lease_out(1.into(), &1, 1, 1, 1));
|
assert_ok!(Slots::lease_out(1.into(), &1, 1, 1, 1));
|
||||||
assert_eq!(Slots::deposit_held(1.into(), &1), 1);
|
assert_eq!(Slots::deposit_held(1.into(), &1), 1);
|
||||||
@@ -601,10 +626,10 @@ mod tests {
|
|||||||
assert_eq!(Slots::deposit_held(1.into(), &1), 0);
|
assert_eq!(Slots::deposit_held(1.into(), &1), 0);
|
||||||
assert_eq!(Balances::reserved_balance(1), 0);
|
assert_eq!(Balances::reserved_balance(1), 0);
|
||||||
|
|
||||||
assert_eq!(TestRegistrar::<Test>::operations(), vec![
|
assert_eq!(
|
||||||
(1.into(), 10, true),
|
TestRegistrar::<Test>::operations(),
|
||||||
(1.into(), 20, false),
|
vec![(1.into(), 10, true), (1.into(), 20, false),]
|
||||||
]);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,7 +638,12 @@ mod tests {
|
|||||||
new_test_ext().execute_with(|| {
|
new_test_ext().execute_with(|| {
|
||||||
run_to_block(1);
|
run_to_block(1);
|
||||||
|
|
||||||
assert_ok!(TestRegistrar::<Test>::register(1, ParaId::from(1), Default::default(), Default::default()));
|
assert_ok!(TestRegistrar::<Test>::register(
|
||||||
|
1,
|
||||||
|
ParaId::from(1),
|
||||||
|
Default::default(),
|
||||||
|
Default::default()
|
||||||
|
));
|
||||||
|
|
||||||
assert_ok!(Slots::lease_out(1.into(), &1, 6, 1, 1));
|
assert_ok!(Slots::lease_out(1.into(), &1, 6, 1, 1));
|
||||||
assert_ok!(Slots::lease_out(1.into(), &1, 4, 3, 1));
|
assert_ok!(Slots::lease_out(1.into(), &1, 4, 3, 1));
|
||||||
@@ -634,12 +664,15 @@ mod tests {
|
|||||||
assert_eq!(Slots::deposit_held(1.into(), &1), 0);
|
assert_eq!(Slots::deposit_held(1.into(), &1), 0);
|
||||||
assert_eq!(Balances::reserved_balance(1), 0);
|
assert_eq!(Balances::reserved_balance(1), 0);
|
||||||
|
|
||||||
assert_eq!(TestRegistrar::<Test>::operations(), vec![
|
assert_eq!(
|
||||||
(1.into(), 10, true),
|
TestRegistrar::<Test>::operations(),
|
||||||
(1.into(), 20, false),
|
vec![
|
||||||
(1.into(), 30, true),
|
(1.into(), 10, true),
|
||||||
(1.into(), 40, false),
|
(1.into(), 20, false),
|
||||||
]);
|
(1.into(), 30, true),
|
||||||
|
(1.into(), 40, false),
|
||||||
|
]
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -648,7 +681,12 @@ mod tests {
|
|||||||
new_test_ext().execute_with(|| {
|
new_test_ext().execute_with(|| {
|
||||||
run_to_block(1);
|
run_to_block(1);
|
||||||
|
|
||||||
assert_ok!(TestRegistrar::<Test>::register(1, ParaId::from(1), Default::default(), Default::default()));
|
assert_ok!(TestRegistrar::<Test>::register(
|
||||||
|
1,
|
||||||
|
ParaId::from(1),
|
||||||
|
Default::default(),
|
||||||
|
Default::default()
|
||||||
|
));
|
||||||
|
|
||||||
assert!(Slots::lease_out(1.into(), &1, 6, 1, 1).is_ok());
|
assert!(Slots::lease_out(1.into(), &1, 6, 1, 1).is_ok());
|
||||||
assert!(Slots::lease_out(1.into(), &2, 4, 2, 1).is_ok());
|
assert!(Slots::lease_out(1.into(), &2, 4, 2, 1).is_ok());
|
||||||
@@ -681,10 +719,10 @@ mod tests {
|
|||||||
assert_eq!(Slots::deposit_held(1.into(), &2), 0);
|
assert_eq!(Slots::deposit_held(1.into(), &2), 0);
|
||||||
assert_eq!(Balances::reserved_balance(2), 0);
|
assert_eq!(Balances::reserved_balance(2), 0);
|
||||||
|
|
||||||
assert_eq!(TestRegistrar::<Test>::operations(), vec![
|
assert_eq!(
|
||||||
(1.into(), 10, true),
|
TestRegistrar::<Test>::operations(),
|
||||||
(1.into(), 30, false),
|
vec![(1.into(), 10, true), (1.into(), 30, false),]
|
||||||
]);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -693,7 +731,12 @@ mod tests {
|
|||||||
new_test_ext().execute_with(|| {
|
new_test_ext().execute_with(|| {
|
||||||
run_to_block(1);
|
run_to_block(1);
|
||||||
|
|
||||||
assert_ok!(TestRegistrar::<Test>::register(1, ParaId::from(1), Default::default(), Default::default()));
|
assert_ok!(TestRegistrar::<Test>::register(
|
||||||
|
1,
|
||||||
|
ParaId::from(1),
|
||||||
|
Default::default(),
|
||||||
|
Default::default()
|
||||||
|
));
|
||||||
|
|
||||||
assert!(Slots::lease_out(1.into(), &1, 4, 1, 1).is_ok());
|
assert!(Slots::lease_out(1.into(), &1, 4, 1, 1).is_ok());
|
||||||
assert_eq!(Slots::deposit_held(1.into(), &1), 4);
|
assert_eq!(Slots::deposit_held(1.into(), &1), 4);
|
||||||
@@ -711,10 +754,10 @@ mod tests {
|
|||||||
assert_eq!(Slots::deposit_held(1.into(), &1), 0);
|
assert_eq!(Slots::deposit_held(1.into(), &1), 0);
|
||||||
assert_eq!(Balances::reserved_balance(1), 0);
|
assert_eq!(Balances::reserved_balance(1), 0);
|
||||||
|
|
||||||
assert_eq!(TestRegistrar::<Test>::operations(), vec![
|
assert_eq!(
|
||||||
(1.into(), 10, true),
|
TestRegistrar::<Test>::operations(),
|
||||||
(1.into(), 30, false),
|
vec![(1.into(), 10, true), (1.into(), 30, false),]
|
||||||
]);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -723,7 +766,12 @@ mod tests {
|
|||||||
new_test_ext().execute_with(|| {
|
new_test_ext().execute_with(|| {
|
||||||
run_to_block(1);
|
run_to_block(1);
|
||||||
|
|
||||||
assert_ok!(TestRegistrar::<Test>::register(1, ParaId::from(1), Default::default(), Default::default()));
|
assert_ok!(TestRegistrar::<Test>::register(
|
||||||
|
1,
|
||||||
|
ParaId::from(1),
|
||||||
|
Default::default(),
|
||||||
|
Default::default()
|
||||||
|
));
|
||||||
|
|
||||||
assert!(Slots::lease_out(1.into(), &1, 6, 1, 1).is_ok());
|
assert!(Slots::lease_out(1.into(), &1, 6, 1, 1).is_ok());
|
||||||
assert_eq!(Slots::deposit_held(1.into(), &1), 6);
|
assert_eq!(Slots::deposit_held(1.into(), &1), 6);
|
||||||
@@ -749,10 +797,10 @@ mod tests {
|
|||||||
assert_eq!(Slots::deposit_held(1.into(), &1), 0);
|
assert_eq!(Slots::deposit_held(1.into(), &1), 0);
|
||||||
assert_eq!(Balances::reserved_balance(1), 0);
|
assert_eq!(Balances::reserved_balance(1), 0);
|
||||||
|
|
||||||
assert_eq!(TestRegistrar::<Test>::operations(), vec![
|
assert_eq!(
|
||||||
(1.into(), 10, true),
|
TestRegistrar::<Test>::operations(),
|
||||||
(1.into(), 30, false),
|
vec![(1.into(), 10, true), (1.into(), 30, false),]
|
||||||
]);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -761,12 +809,17 @@ mod tests {
|
|||||||
new_test_ext().execute_with(|| {
|
new_test_ext().execute_with(|| {
|
||||||
run_to_block(1);
|
run_to_block(1);
|
||||||
|
|
||||||
assert_ok!(TestRegistrar::<Test>::register(1, ParaId::from(1), Default::default(), Default::default()));
|
assert_ok!(TestRegistrar::<Test>::register(
|
||||||
|
1,
|
||||||
|
ParaId::from(1),
|
||||||
|
Default::default(),
|
||||||
|
Default::default()
|
||||||
|
));
|
||||||
|
|
||||||
let max_num = 5u32;
|
let max_num = 5u32;
|
||||||
|
|
||||||
// max_num different people are reserved for leases to Para ID 1
|
// max_num different people are reserved for leases to Para ID 1
|
||||||
for i in 1u32 ..= max_num {
|
for i in 1u32..=max_num {
|
||||||
let j: u64 = i.into();
|
let j: u64 = i.into();
|
||||||
assert_ok!(Slots::lease_out(1.into(), &j, j * 10, i * i, i));
|
assert_ok!(Slots::lease_out(1.into(), &j, j * 10, i * i, i));
|
||||||
assert_eq!(Slots::deposit_held(1.into(), &j), j * 10);
|
assert_eq!(Slots::deposit_held(1.into(), &j), j * 10);
|
||||||
@@ -776,7 +829,7 @@ mod tests {
|
|||||||
assert_ok!(Slots::clear_all_leases(Origin::root(), 1.into()));
|
assert_ok!(Slots::clear_all_leases(Origin::root(), 1.into()));
|
||||||
|
|
||||||
// Balances cleaned up correctly
|
// Balances cleaned up correctly
|
||||||
for i in 1u32 ..= max_num {
|
for i in 1u32..=max_num {
|
||||||
let j: u64 = i.into();
|
let j: u64 = i.into();
|
||||||
assert_eq!(Slots::deposit_held(1.into(), &j), 0);
|
assert_eq!(Slots::deposit_held(1.into(), &j), 0);
|
||||||
assert_eq!(Balances::reserved_balance(j), 0);
|
assert_eq!(Balances::reserved_balance(j), 0);
|
||||||
@@ -792,8 +845,18 @@ mod tests {
|
|||||||
new_test_ext().execute_with(|| {
|
new_test_ext().execute_with(|| {
|
||||||
run_to_block(1);
|
run_to_block(1);
|
||||||
|
|
||||||
assert_ok!(TestRegistrar::<Test>::register(1, ParaId::from(1), Default::default(), Default::default()));
|
assert_ok!(TestRegistrar::<Test>::register(
|
||||||
assert_ok!(TestRegistrar::<Test>::register(1, ParaId::from(2), Default::default(), Default::default()));
|
1,
|
||||||
|
ParaId::from(1),
|
||||||
|
Default::default(),
|
||||||
|
Default::default()
|
||||||
|
));
|
||||||
|
assert_ok!(TestRegistrar::<Test>::register(
|
||||||
|
1,
|
||||||
|
ParaId::from(2),
|
||||||
|
Default::default(),
|
||||||
|
Default::default()
|
||||||
|
));
|
||||||
|
|
||||||
run_to_block(20);
|
run_to_block(20);
|
||||||
assert_eq!(Slots::lease_period_index(), 2);
|
assert_eq!(Slots::lease_period_index(), 2);
|
||||||
@@ -804,9 +867,7 @@ mod tests {
|
|||||||
// Lease in the future doesn't
|
// Lease in the future doesn't
|
||||||
assert_ok!(Slots::lease_out(2.into(), &1, 1, 3, 1));
|
assert_ok!(Slots::lease_out(2.into(), &1, 1, 3, 1));
|
||||||
|
|
||||||
assert_eq!(TestRegistrar::<Test>::operations(), vec![
|
assert_eq!(TestRegistrar::<Test>::operations(), vec![(1.into(), 20, true),]);
|
||||||
(1.into(), 20, true),
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -814,9 +875,24 @@ mod tests {
|
|||||||
fn trigger_onboard_works() {
|
fn trigger_onboard_works() {
|
||||||
new_test_ext().execute_with(|| {
|
new_test_ext().execute_with(|| {
|
||||||
run_to_block(1);
|
run_to_block(1);
|
||||||
assert_ok!(TestRegistrar::<Test>::register(1, ParaId::from(1), Default::default(), Default::default()));
|
assert_ok!(TestRegistrar::<Test>::register(
|
||||||
assert_ok!(TestRegistrar::<Test>::register(1, ParaId::from(2), Default::default(), Default::default()));
|
1,
|
||||||
assert_ok!(TestRegistrar::<Test>::register(1, ParaId::from(3), Default::default(), Default::default()));
|
ParaId::from(1),
|
||||||
|
Default::default(),
|
||||||
|
Default::default()
|
||||||
|
));
|
||||||
|
assert_ok!(TestRegistrar::<Test>::register(
|
||||||
|
1,
|
||||||
|
ParaId::from(2),
|
||||||
|
Default::default(),
|
||||||
|
Default::default()
|
||||||
|
));
|
||||||
|
assert_ok!(TestRegistrar::<Test>::register(
|
||||||
|
1,
|
||||||
|
ParaId::from(3),
|
||||||
|
Default::default(),
|
||||||
|
Default::default()
|
||||||
|
));
|
||||||
|
|
||||||
// We will directly manipulate leases to emulate some kind of failure in the system.
|
// We will directly manipulate leases to emulate some kind of failure in the system.
|
||||||
// Para 1 will have no leases
|
// Para 1 will have no leases
|
||||||
@@ -826,20 +902,24 @@ mod tests {
|
|||||||
Leases::<Test>::insert(ParaId::from(3), vec![None, None, Some((0, 0))]);
|
Leases::<Test>::insert(ParaId::from(3), vec![None, None, Some((0, 0))]);
|
||||||
|
|
||||||
// Para 1 should fail cause they don't have any leases
|
// Para 1 should fail cause they don't have any leases
|
||||||
assert_noop!(Slots::trigger_onboard(Origin::signed(1), 1.into()), Error::<Test>::ParaNotOnboarding);
|
assert_noop!(
|
||||||
|
Slots::trigger_onboard(Origin::signed(1), 1.into()),
|
||||||
|
Error::<Test>::ParaNotOnboarding
|
||||||
|
);
|
||||||
|
|
||||||
// Para 2 should succeed
|
// Para 2 should succeed
|
||||||
assert_ok!(Slots::trigger_onboard(Origin::signed(1), 2.into()));
|
assert_ok!(Slots::trigger_onboard(Origin::signed(1), 2.into()));
|
||||||
|
|
||||||
// Para 3 should fail cause their lease is in the future
|
// Para 3 should fail cause their lease is in the future
|
||||||
assert_noop!(Slots::trigger_onboard(Origin::signed(1), 3.into()), Error::<Test>::ParaNotOnboarding);
|
assert_noop!(
|
||||||
|
Slots::trigger_onboard(Origin::signed(1), 3.into()),
|
||||||
|
Error::<Test>::ParaNotOnboarding
|
||||||
|
);
|
||||||
|
|
||||||
// Trying Para 2 again should fail cause they are not currently a parathread
|
// Trying Para 2 again should fail cause they are not currently a parathread
|
||||||
assert!(Slots::trigger_onboard(Origin::signed(1), 2.into()).is_err());
|
assert!(Slots::trigger_onboard(Origin::signed(1), 2.into()).is_err());
|
||||||
|
|
||||||
assert_eq!(TestRegistrar::<Test>::operations(), vec![
|
assert_eq!(TestRegistrar::<Test>::operations(), vec![(2.into(), 1, true),]);
|
||||||
(2.into(), 1, true),
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -847,13 +927,13 @@ mod tests {
|
|||||||
#[cfg(feature = "runtime-benchmarks")]
|
#[cfg(feature = "runtime-benchmarks")]
|
||||||
mod benchmarking {
|
mod benchmarking {
|
||||||
use super::*;
|
use super::*;
|
||||||
use frame_system::RawOrigin;
|
|
||||||
use frame_support::assert_ok;
|
use frame_support::assert_ok;
|
||||||
|
use frame_system::RawOrigin;
|
||||||
use sp_runtime::traits::Bounded;
|
use sp_runtime::traits::Bounded;
|
||||||
|
|
||||||
use frame_benchmarking::{benchmarks, account, whitelisted_caller, impl_benchmark_test_suite};
|
use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller};
|
||||||
|
|
||||||
use crate::slots::Module as Slots;
|
use crate::slots::Pallet as Slots;
|
||||||
|
|
||||||
fn assert_last_event<T: Config>(generic_event: <T as Config>::Event) {
|
fn assert_last_event<T: Config>(generic_event: <T as Config>::Event) {
|
||||||
let events = frame_system::Pallet::<T>::events();
|
let events = frame_system::Pallet::<T>::events();
|
||||||
@@ -870,7 +950,12 @@ mod benchmarking {
|
|||||||
let worst_head_data = T::Registrar::worst_head_data();
|
let worst_head_data = T::Registrar::worst_head_data();
|
||||||
let worst_validation_code = T::Registrar::worst_validation_code();
|
let worst_validation_code = T::Registrar::worst_validation_code();
|
||||||
|
|
||||||
assert_ok!(T::Registrar::register(leaser.clone(), para, worst_head_data, worst_validation_code));
|
assert_ok!(T::Registrar::register(
|
||||||
|
leaser.clone(),
|
||||||
|
para,
|
||||||
|
worst_head_data,
|
||||||
|
worst_validation_code
|
||||||
|
));
|
||||||
T::Registrar::execute_pending_transitions();
|
T::Registrar::execute_pending_transitions();
|
||||||
|
|
||||||
(para, leaser)
|
(para, leaser)
|
||||||
@@ -886,7 +971,7 @@ mod benchmarking {
|
|||||||
let period_count = 3u32.into();
|
let period_count = 3u32.into();
|
||||||
}: _(RawOrigin::Root, para, leaser.clone(), amount, period_begin, period_count)
|
}: _(RawOrigin::Root, para, leaser.clone(), amount, period_begin, period_count)
|
||||||
verify {
|
verify {
|
||||||
assert_last_event::<T>(RawEvent::Leased(para, leaser, period_begin, period_count, amount, amount).into());
|
assert_last_event::<T>(Event::<T>::Leased(para, leaser, period_begin, period_count, amount, amount).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Worst case scenario, T parathreads onboard, and C parachains offboard.
|
// Worst case scenario, T parathreads onboard, and C parachains offboard.
|
||||||
|
|||||||
Reference in New Issue
Block a user