mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 08:11:03 +00:00
Create Macro for Implementing SlotRange (#2788)
* Macro for generating `SlotRange` * remove test code * refactor slots into crate * add no_std flag * finish macro * make compile * fix copyright date * don't assume lease periods per slot * Update runtime/common/Cargo.toml * Apply suggestions from code review Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> * fixes * Update lib.rs * tests * Move consts into struct * docs * fix compile * Apply suggestions from code review Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update Cargo.lock * Update runtime/common/src/slot_range.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * fixes Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
Generated
+11
@@ -6261,6 +6261,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"slot-range-helper",
|
||||||
"sp-api",
|
"sp-api",
|
||||||
"sp-application-crypto",
|
"sp-application-crypto",
|
||||||
"sp-core",
|
"sp-core",
|
||||||
@@ -8732,6 +8733,16 @@ version = "0.4.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slot-range-helper"
|
||||||
|
version = "0.8.30"
|
||||||
|
dependencies = [
|
||||||
|
"parity-scale-codec",
|
||||||
|
"paste 1.0.4",
|
||||||
|
"sp-runtime",
|
||||||
|
"sp-std",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "0.6.13"
|
version = "0.6.13"
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ members = [
|
|||||||
"erasure-coding",
|
"erasure-coding",
|
||||||
"primitives",
|
"primitives",
|
||||||
"runtime/common",
|
"runtime/common",
|
||||||
|
"runtime/common/slot_range_helper",
|
||||||
"runtime/parachains",
|
"runtime/parachains",
|
||||||
"runtime/polkadot",
|
"runtime/polkadot",
|
||||||
"runtime/kusama",
|
"runtime/kusama",
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ primitives = { package = "polkadot-primitives", path = "../../primitives", defau
|
|||||||
libsecp256k1 = { version = "0.3.5", default-features = false }
|
libsecp256k1 = { version = "0.3.5", default-features = false }
|
||||||
runtime-parachains = { package = "polkadot-runtime-parachains", path = "../parachains", default-features = false }
|
runtime-parachains = { package = "polkadot-runtime-parachains", path = "../parachains", default-features = false }
|
||||||
|
|
||||||
|
slot-range-helper = { path = "slot_range_helper", default-features = false }
|
||||||
xcm = { path = "../../xcm", default-features = false }
|
xcm = { path = "../../xcm", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
@@ -91,6 +92,7 @@ std = [
|
|||||||
"pallet-vesting/std",
|
"pallet-vesting/std",
|
||||||
"pallet-transaction-payment/std",
|
"pallet-transaction-payment/std",
|
||||||
"pallet-treasury/std",
|
"pallet-treasury/std",
|
||||||
|
"slot-range-helper/std",
|
||||||
"sp-runtime/std",
|
"sp-runtime/std",
|
||||||
"sp-session/std",
|
"sp-session/std",
|
||||||
"sp-staking/std",
|
"sp-staking/std",
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
[package]
|
||||||
|
name = "slot-range-helper"
|
||||||
|
version = "0.8.30"
|
||||||
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
paste = "1.0"
|
||||||
|
parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] }
|
||||||
|
sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
|
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["std"]
|
||||||
|
std = [
|
||||||
|
"sp-std/std",
|
||||||
|
"parity-scale-codec/std",
|
||||||
|
"sp-runtime/std",
|
||||||
|
]
|
||||||
@@ -0,0 +1,289 @@
|
|||||||
|
// Copyright 2021 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Polkadot.
|
||||||
|
|
||||||
|
// Polkadot is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Polkadot is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! A helper macro for generating SlotRange enum.
|
||||||
|
|
||||||
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
|
pub use sp_std::{result, ops::Add, convert::TryInto};
|
||||||
|
pub use sp_runtime::traits::CheckedSub;
|
||||||
|
pub use parity_scale_codec::{Encode, Decode};
|
||||||
|
pub use paste;
|
||||||
|
|
||||||
|
/// This macro generates a `SlotRange` enum of arbitrary length for use in the Slot Auction
|
||||||
|
/// mechanism on Polkadot.
|
||||||
|
///
|
||||||
|
/// Usage:
|
||||||
|
/// ```
|
||||||
|
/// slot_range_helper::generate_slot_range!(Zero(0), One(1), Two(2), Three(3));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// To extend the usage, continue to add `Identifier(value)` items to the macro.
|
||||||
|
///
|
||||||
|
/// This will generate an enum `SlotRange` with the following properties:
|
||||||
|
///
|
||||||
|
/// * Enum variants will range from all consecutive combinations of inputs, i.e.
|
||||||
|
/// `ZeroZero`, `ZeroOne`, `ZeroTwo`, `ZeroThree`, `OneOne`, `OneTwo`, `OneThree`...
|
||||||
|
/// * A constant `LEASE_PERIODS_PER_SLOT` will count the number of lease periods.
|
||||||
|
/// * A constant `SLOT_RANGE_COUNT` will count the total number of enum variants.
|
||||||
|
/// * A function `as_pair` will return a tuple representation of the `SlotRange`.
|
||||||
|
/// * A function `intersects` will tell you if two slot ranges intersect with one another.
|
||||||
|
/// * A function `len` will tell you the length of occupying a `SlotRange`.
|
||||||
|
/// * A function `new_bounded` will generate a `SlotRange` from an input of the current
|
||||||
|
/// lease period, the starting lease period, and the final lease period.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! generate_slot_range{
|
||||||
|
// Entry point
|
||||||
|
($( $x:ident ( $e:expr ) ),*) => {
|
||||||
|
$crate::generate_lease_period_per_slot!( $( $x )* );
|
||||||
|
$crate::generate_slot_range!(@inner
|
||||||
|
{ }
|
||||||
|
$( $x ( $e ) )*
|
||||||
|
);
|
||||||
|
};
|
||||||
|
// Does the magic...
|
||||||
|
(@inner
|
||||||
|
{ $( $parsed:ident ( $t1:expr, $t2:expr ) )* }
|
||||||
|
$current:ident ( $ce:expr )
|
||||||
|
$( $remaining:ident ( $re:expr ) )*
|
||||||
|
) => {
|
||||||
|
$crate::paste::paste! {
|
||||||
|
$crate::generate_slot_range!(@inner
|
||||||
|
{
|
||||||
|
$( $parsed ( $t1, $t2 ) )*
|
||||||
|
[< $current $current >] ( $ce, $ce )
|
||||||
|
$( [< $current $remaining >] ($ce, $re) )*
|
||||||
|
}
|
||||||
|
$( $remaining ( $re ) )*
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(@inner
|
||||||
|
{ $( $parsed:ident ( $t1:expr, $t2:expr ) )* }
|
||||||
|
) => {
|
||||||
|
$crate::generate_slot_range_enum!(@inner $( $parsed )* );
|
||||||
|
|
||||||
|
$crate::generate_slot_range_count!( $( $parsed )* );
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl std::fmt::Debug for SlotRange {
|
||||||
|
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
let p = self.as_pair();
|
||||||
|
write!(fmt, "[{}..{}]", p.0, p.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SlotRange {
|
||||||
|
pub const LEASE_PERIODS_PER_SLOT: usize = LEASE_PERIODS_PER_SLOT;
|
||||||
|
pub const SLOT_RANGE_COUNT: usize = SLOT_RANGE_COUNT;
|
||||||
|
|
||||||
|
$crate::generate_slot_range_as_pair!(@inner $( $parsed ( $t1, $t2 ) )* );
|
||||||
|
|
||||||
|
$crate::generate_slot_range_len!(@inner $( $parsed ( $t1, $t2 ) )* );
|
||||||
|
|
||||||
|
$crate::generate_slot_range_new_bounded!(@inner $( $parsed ( $t1, $t2 ) )* );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! generate_slot_range_enum {
|
||||||
|
(@inner
|
||||||
|
$( $parsed:ident )*
|
||||||
|
) => {
|
||||||
|
/// A compactly represented sub-range from the series.
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, $crate::Encode, $crate::Decode)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum SlotRange { $( $parsed ),* }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! generate_slot_range_as_pair {
|
||||||
|
(@inner
|
||||||
|
$( $parsed:ident ( $t1:expr, $t2:expr ) )*
|
||||||
|
) => {
|
||||||
|
/// Return true if two `SlotRange` intersect in their lease periods.
|
||||||
|
pub fn intersects(&self, other: SlotRange) -> bool {
|
||||||
|
let a = self.as_pair();
|
||||||
|
let b = other.as_pair();
|
||||||
|
b.0 <= a.1 && a.0 <= b.1
|
||||||
|
// == !(b.0 > a.1 || a.0 > b.1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a tuple representation of the `SlotRange`.
|
||||||
|
///
|
||||||
|
/// Example:`SlotRange::OneTwo.as_pair() == (1, 2)`
|
||||||
|
pub fn as_pair(&self) -> (u8, u8) {
|
||||||
|
match self {
|
||||||
|
$( SlotRange::$parsed => { ($t1, $t2) } )*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! generate_slot_range_len {
|
||||||
|
// Use evaluated length in function.
|
||||||
|
(@inner
|
||||||
|
$( $parsed:ident ( $t1:expr, $t2:expr ) )*
|
||||||
|
) => {
|
||||||
|
/// Return the length of occupying a `SlotRange`.
|
||||||
|
///
|
||||||
|
/// Example:`SlotRange::OneTwo.len() == 2`
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
// len (0, 2) = 2 - 0 + 1 = 3
|
||||||
|
$( SlotRange::$parsed => { ( $t2 - $t1 + 1) } )*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! generate_slot_range_new_bounded {
|
||||||
|
(@inner
|
||||||
|
$( $parsed:ident ( $t1:expr, $t2:expr ) )*
|
||||||
|
) => {
|
||||||
|
/// Construct a `SlotRange` from the current lease period, the first lease period of the range,
|
||||||
|
/// and the last lease period of the range.
|
||||||
|
///
|
||||||
|
/// For example: `SlotRange::new_bounded(1, 2, 3) == SlotRange::OneTwo`.
|
||||||
|
pub fn new_bounded<
|
||||||
|
Index: $crate::Add<Output=Index> + $crate::CheckedSub + Copy + Ord + From<u32> + $crate::TryInto<u32>
|
||||||
|
>(
|
||||||
|
current: Index,
|
||||||
|
first: Index,
|
||||||
|
last: Index
|
||||||
|
) -> $crate::result::Result<Self, &'static str> {
|
||||||
|
if first > last || first < current || last >= current + (LEASE_PERIODS_PER_SLOT as u32).into() {
|
||||||
|
return Err("Invalid range for this auction")
|
||||||
|
}
|
||||||
|
let count: u32 = last.checked_sub(&first)
|
||||||
|
.ok_or("range ends before it begins")?
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| "range too big")?;
|
||||||
|
let first: u32 = first.checked_sub(¤t)
|
||||||
|
.ok_or("range begins too early")?
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| "start too far")?;
|
||||||
|
match (first, first + count) {
|
||||||
|
$( ($t1, $t2) => { Ok(SlotRange::$parsed) })*
|
||||||
|
_ => Err("bad range"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! generate_slot_range_count {
|
||||||
|
(
|
||||||
|
$start:ident $( $rest:ident )*
|
||||||
|
) => {
|
||||||
|
$crate::generate_slot_range_count!(@inner 1; $( $rest )*);
|
||||||
|
};
|
||||||
|
(@inner
|
||||||
|
$count:expr;
|
||||||
|
$start:ident $( $rest:ident )*
|
||||||
|
) => {
|
||||||
|
$crate::generate_slot_range_count!(@inner $count + 1; $( $rest )*);
|
||||||
|
};
|
||||||
|
(@inner
|
||||||
|
$count:expr;
|
||||||
|
) => {
|
||||||
|
const SLOT_RANGE_COUNT: usize = $count;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[doc(hidden)]
|
||||||
|
macro_rules! generate_lease_period_per_slot {
|
||||||
|
(
|
||||||
|
$start:ident $( $rest:ident )*
|
||||||
|
) => {
|
||||||
|
$crate::generate_lease_period_per_slot!(@inner 1; $( $rest )*);
|
||||||
|
};
|
||||||
|
(@inner
|
||||||
|
$count:expr;
|
||||||
|
$start:ident $( $rest:ident )*
|
||||||
|
) => {
|
||||||
|
$crate::generate_lease_period_per_slot!(@inner $count + 1; $( $rest )*);
|
||||||
|
};
|
||||||
|
(@inner
|
||||||
|
$count:expr;
|
||||||
|
) => {
|
||||||
|
const LEASE_PERIODS_PER_SLOT: usize = $count;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn slot_range_4_works() {
|
||||||
|
generate_slot_range!(Zero(0), One(1), Two(2), Three(3));
|
||||||
|
|
||||||
|
assert_eq!(SlotRange::LEASE_PERIODS_PER_SLOT, 4);
|
||||||
|
// Sum over n from 0 - 4
|
||||||
|
assert_eq!(SlotRange::SLOT_RANGE_COUNT, 10);
|
||||||
|
assert_eq!(SlotRange::new_bounded(0u32, 1u32, 2u32).unwrap(), SlotRange::OneTwo);
|
||||||
|
assert_eq!(SlotRange::new_bounded(5u32, 6u32, 7u32).unwrap(), SlotRange::OneTwo);
|
||||||
|
assert!(SlotRange::new_bounded(10u32, 6u32, 7u32).is_err());
|
||||||
|
assert!(SlotRange::new_bounded(10u32, 16u32, 17u32).is_err());
|
||||||
|
assert!(SlotRange::new_bounded(10u32, 11u32, 10u32).is_err());
|
||||||
|
assert_eq!(SlotRange::TwoTwo.len(), 1);
|
||||||
|
assert_eq!(SlotRange::OneTwo.len(), 2);
|
||||||
|
assert_eq!(SlotRange::ZeroThree.len(), 4);
|
||||||
|
assert!(SlotRange::ZeroOne.intersects(SlotRange::OneThree));
|
||||||
|
assert!(!SlotRange::ZeroOne.intersects(SlotRange::TwoThree));
|
||||||
|
assert_eq!(SlotRange::ZeroZero.as_pair(), (0, 0));
|
||||||
|
assert_eq!(SlotRange::OneThree.as_pair(), (1, 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn slot_range_8_works() {
|
||||||
|
generate_slot_range!(Zero(0), One(1), Two(2), Three(3), Four(4), Five(5), Six(6), Seven(7));
|
||||||
|
|
||||||
|
assert_eq!(SlotRange::LEASE_PERIODS_PER_SLOT, 8);
|
||||||
|
// Sum over n from 0 to 8
|
||||||
|
assert_eq!(SlotRange::SLOT_RANGE_COUNT, 36);
|
||||||
|
assert_eq!(SlotRange::new_bounded(0u32, 1u32, 2u32).unwrap(), SlotRange::OneTwo);
|
||||||
|
assert_eq!(SlotRange::new_bounded(5u32, 6u32, 7u32).unwrap(), SlotRange::OneTwo);
|
||||||
|
assert!(SlotRange::new_bounded(10u32, 6u32, 7u32).is_err());
|
||||||
|
// This one passes with slot range 8
|
||||||
|
assert_eq!(SlotRange::new_bounded(10u32, 16u32, 17u32).unwrap(), SlotRange::SixSeven);
|
||||||
|
assert!(SlotRange::new_bounded(10u32, 17u32, 18u32).is_err());
|
||||||
|
assert!(SlotRange::new_bounded(10u32, 20u32, 21u32).is_err());
|
||||||
|
assert!(SlotRange::new_bounded(10u32, 11u32, 10u32).is_err());
|
||||||
|
assert_eq!(SlotRange::TwoTwo.len(), 1);
|
||||||
|
assert_eq!(SlotRange::OneTwo.len(), 2);
|
||||||
|
assert_eq!(SlotRange::ZeroThree.len(), 4);
|
||||||
|
assert_eq!(SlotRange::ZeroSeven.len(), 8);
|
||||||
|
assert!(SlotRange::ZeroOne.intersects(SlotRange::OneThree));
|
||||||
|
assert!(!SlotRange::ZeroOne.intersects(SlotRange::TwoThree));
|
||||||
|
assert!(SlotRange::FiveSix.intersects(SlotRange::SixSeven));
|
||||||
|
assert!(!SlotRange::ThreeFive.intersects(SlotRange::SixSeven));
|
||||||
|
assert_eq!(SlotRange::ZeroZero.as_pair(), (0, 0));
|
||||||
|
assert_eq!(SlotRange::OneThree.as_pair(), (1, 3));
|
||||||
|
assert_eq!(SlotRange::SixSeven.as_pair(), (6, 7));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,12 +27,13 @@ use frame_support::{
|
|||||||
};
|
};
|
||||||
use primitives::v1::Id as ParaId;
|
use primitives::v1::Id as ParaId;
|
||||||
use frame_system::{ensure_signed, ensure_root};
|
use frame_system::{ensure_signed, ensure_root};
|
||||||
use crate::slot_range::{SlotRange, SLOT_RANGE_COUNT};
|
use crate::slot_range::SlotRange;
|
||||||
use crate::traits::{Leaser, LeaseError, Auctioneer, Registrar};
|
use crate::traits::{Leaser, LeaseError, Auctioneer, Registrar};
|
||||||
use parity_scale_codec::Decode;
|
use parity_scale_codec::Decode;
|
||||||
|
|
||||||
type CurrencyOf<T> = <<T as Config>::Leaser as Leaser>::Currency;
|
type CurrencyOf<T> = <<T as Config>::Leaser as Leaser>::Currency;
|
||||||
type BalanceOf<T> = <<<T as Config>::Leaser as Leaser>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
|
type BalanceOf<T> =
|
||||||
|
<<<T as Config>::Leaser as Leaser>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
|
||||||
|
|
||||||
pub trait WeightInfo {
|
pub trait WeightInfo {
|
||||||
fn new_auction() -> Weight;
|
fn new_auction() -> Weight;
|
||||||
@@ -84,7 +85,7 @@ pub type AuctionIndex = u32;
|
|||||||
type LeasePeriodOf<T> = <<T as Config>::Leaser as Leaser>::LeasePeriod;
|
type LeasePeriodOf<T> = <<T as Config>::Leaser as Leaser>::LeasePeriod;
|
||||||
// Winning data type. This encodes the top bidders of each range together with their bid.
|
// Winning data type. This encodes the top bidders of each range together with their bid.
|
||||||
type WinningData<T> =
|
type WinningData<T> =
|
||||||
[Option<(<T as frame_system::Config>::AccountId, ParaId, BalanceOf<T>)>; SLOT_RANGE_COUNT];
|
[Option<(<T as frame_system::Config>::AccountId, ParaId, BalanceOf<T>)>; SlotRange::SLOT_RANGE_COUNT];
|
||||||
// Winners data type. This encodes each of the final winners of a parachain auction, the parachain
|
// Winners data type. This encodes each of the final winners of a parachain auction, the parachain
|
||||||
// index assigned to them, their winning bid and the range that they won.
|
// index assigned to them, their winning bid and the range that they won.
|
||||||
type WinnersData<T> = Vec<(<T as frame_system::Config>::AccountId, ParaId, BalanceOf<T>, SlotRange)>;
|
type WinnersData<T> = Vec<(<T as frame_system::Config>::AccountId, ParaId, BalanceOf<T>, SlotRange)>;
|
||||||
@@ -563,19 +564,19 @@ impl<T: Config> Module<T> {
|
|||||||
) -> WinnersData<T> {
|
) -> WinnersData<T> {
|
||||||
let winning_ranges = {
|
let winning_ranges = {
|
||||||
let mut best_winners_ending_at:
|
let mut best_winners_ending_at:
|
||||||
[(Vec<SlotRange>, BalanceOf<T>); 4] = Default::default();
|
[(Vec<SlotRange>, BalanceOf<T>); SlotRange::LEASE_PERIODS_PER_SLOT] = Default::default();
|
||||||
let best_bid = |range: SlotRange| {
|
let best_bid = |range: SlotRange| {
|
||||||
winning[range as u8 as usize].as_ref()
|
winning[range as u8 as usize].as_ref()
|
||||||
.map(|(_, _, amount)| *amount * (range.len() as u32).into())
|
.map(|(_, _, amount)| *amount * (range.len() as u32).into())
|
||||||
};
|
};
|
||||||
for i in 0..4 {
|
for i in 0..SlotRange::LEASE_PERIODS_PER_SLOT {
|
||||||
let r = SlotRange::new_bounded(0, 0, i as u32).expect("`i < 4`; qed");
|
let r = SlotRange::new_bounded(0, 0, i as u32).expect("`i < 4`; qed");
|
||||||
if let Some(bid) = best_bid(r) {
|
if let Some(bid) = best_bid(r) {
|
||||||
best_winners_ending_at[i] = (vec![r], bid);
|
best_winners_ending_at[i] = (vec![r], bid);
|
||||||
}
|
}
|
||||||
for j in 0..i {
|
for j in 0..i {
|
||||||
let r = SlotRange::new_bounded(0, j as u32 + 1, i as u32)
|
let r = SlotRange::new_bounded(0, j as u32 + 1, i as u32)
|
||||||
.expect("`i < 4`; `j < i`; `j + 1 < 4`; qed");
|
.expect("`i < LPPS`; `j < i`; `j + 1 < LPPS`; qed");
|
||||||
if let Some(mut bid) = best_bid(r) {
|
if let Some(mut bid) = best_bid(r) {
|
||||||
bid += best_winners_ending_at[j].1;
|
bid += best_winners_ending_at[j].1;
|
||||||
if bid > best_winners_ending_at[i].1 {
|
if bid > best_winners_ending_at[i].1 {
|
||||||
@@ -590,8 +591,7 @@ impl<T: Config> Module<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let [_, _, _, (winning_ranges, _)] = best_winners_ending_at;
|
best_winners_ending_at[SlotRange::LEASE_PERIODS_PER_SLOT - 1].0.clone()
|
||||||
winning_ranges
|
|
||||||
};
|
};
|
||||||
|
|
||||||
winning_ranges.into_iter().map(|range| {
|
winning_ranges.into_iter().map(|range| {
|
||||||
@@ -722,7 +722,10 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
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().iter()
|
leases().iter()
|
||||||
.filter_map(|((id, _period), data)|
|
.filter_map(|((id, _period), data)|
|
||||||
if id == ¶ && &data.leaser == leaser { Some(data.amount) } else { None }
|
if id == ¶ && &data.leaser == leaser { Some(data.amount) } else { None }
|
||||||
@@ -1546,7 +1549,7 @@ mod benchmarking {
|
|||||||
let auction_index = AuctionCounter::get();
|
let auction_index = AuctionCounter::get();
|
||||||
let minimum_balance = CurrencyOf::<T>::minimum_balance();
|
let minimum_balance = CurrencyOf::<T>::minimum_balance();
|
||||||
|
|
||||||
for n in 1 ..= SLOT_RANGE_COUNT as u32 {
|
for n in 1 ..= SlotRange::SLOT_RANGE_COUNT as u32 {
|
||||||
let owner = account("owner", n, 0);
|
let owner = account("owner", n, 0);
|
||||||
let worst_validation_code = T::Registrar::worst_validation_code();
|
let worst_validation_code = T::Registrar::worst_validation_code();
|
||||||
let worst_head_data = T::Registrar::worst_head_data();
|
let worst_head_data = T::Registrar::worst_head_data();
|
||||||
@@ -1562,7 +1565,7 @@ mod benchmarking {
|
|||||||
|
|
||||||
T::Registrar::execute_pending_transitions();
|
T::Registrar::execute_pending_transitions();
|
||||||
|
|
||||||
for n in 1 ..= SLOT_RANGE_COUNT as u32 {
|
for n in 1 ..= SlotRange::SLOT_RANGE_COUNT as u32 {
|
||||||
let bidder = account("bidder", n, 0);
|
let bidder = account("bidder", n, 0);
|
||||||
CurrencyOf::<T>::make_free_balance_be(&bidder, BalanceOf::<T>::max_value());
|
CurrencyOf::<T>::make_free_balance_be(&bidder, BalanceOf::<T>::max_value());
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ use sp_runtime::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use crate::traits::{Registrar, Auctioneer};
|
use crate::traits::{Registrar, Auctioneer};
|
||||||
|
use crate::slot_range::SlotRange;
|
||||||
use parity_scale_codec::{Encode, Decode};
|
use parity_scale_codec::{Encode, Decode};
|
||||||
use sp_std::vec::Vec;
|
use sp_std::vec::Vec;
|
||||||
use primitives::v1::Id as ParaId;
|
use primitives::v1::Id as ParaId;
|
||||||
@@ -318,7 +319,9 @@ decl_module! {
|
|||||||
let depositor = ensure_signed(origin)?;
|
let depositor = ensure_signed(origin)?;
|
||||||
|
|
||||||
ensure!(first_period <= last_period, Error::<T>::LastPeriodBeforeFirstPeriod);
|
ensure!(first_period <= last_period, Error::<T>::LastPeriodBeforeFirstPeriod);
|
||||||
let last_period_limit = first_period.checked_add(&3u32.into()).ok_or(Error::<T>::FirstPeriodTooFarInFuture)?;
|
let last_period_limit = first_period
|
||||||
|
.checked_add(&((SlotRange::LEASE_PERIODS_PER_SLOT as u32) - 1).into())
|
||||||
|
.ok_or(Error::<T>::FirstPeriodTooFarInFuture)?;
|
||||||
ensure!(last_period <= last_period_limit, Error::<T>::LastPeriodTooFarInFuture);
|
ensure!(last_period <= last_period_limit, Error::<T>::LastPeriodTooFarInFuture);
|
||||||
ensure!(end > <frame_system::Pallet<T>>::block_number(), Error::<T>::CannotEndInPast);
|
ensure!(end > <frame_system::Pallet<T>>::block_number(), Error::<T>::CannotEndInPast);
|
||||||
let last_possible_win_date = (first_period.saturating_add(One::one())).saturating_mul(T::Auctioneer::lease_period());
|
let last_possible_win_date = (first_period.saturating_add(One::one())).saturating_mul(T::Auctioneer::lease_period());
|
||||||
@@ -1475,7 +1478,7 @@ mod benchmarking {
|
|||||||
let cap = BalanceOf::<T>::max_value();
|
let cap = BalanceOf::<T>::max_value();
|
||||||
let lease_period_index = T::Auctioneer::lease_period_index();
|
let lease_period_index = T::Auctioneer::lease_period_index();
|
||||||
let first_period = lease_period_index;
|
let first_period = lease_period_index;
|
||||||
let last_period = lease_period_index + 3u32.into();
|
let last_period = lease_period_index + ((SlotRange::LEASE_PERIODS_PER_SLOT as u32) - 1).into();
|
||||||
let para_id = id.into();
|
let para_id = id.into();
|
||||||
|
|
||||||
let caller = account("fund_creator", id, 0);
|
let caller = account("fund_creator", id, 0);
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
pub mod claims;
|
pub mod claims;
|
||||||
pub mod slot_range;
|
|
||||||
pub mod slots;
|
pub mod slots;
|
||||||
pub mod auctions;
|
pub mod auctions;
|
||||||
pub mod crowdloan;
|
pub mod crowdloan;
|
||||||
@@ -28,6 +27,7 @@ pub mod impls;
|
|||||||
pub mod mmr;
|
pub mod mmr;
|
||||||
pub mod paras_sudo_wrapper;
|
pub mod paras_sudo_wrapper;
|
||||||
pub mod paras_registrar;
|
pub mod paras_registrar;
|
||||||
|
pub mod slot_range;
|
||||||
pub mod traits;
|
pub mod traits;
|
||||||
pub mod xcm_sender;
|
pub mod xcm_sender;
|
||||||
|
|
||||||
|
|||||||
@@ -17,139 +17,4 @@
|
|||||||
//! The SlotRange struct which succinctly handles the ten values that
|
//! The SlotRange struct which succinctly handles the ten values that
|
||||||
//! represent all sub ranges between 0 and 3 inclusive.
|
//! represent all sub ranges between 0 and 3 inclusive.
|
||||||
|
|
||||||
use sp_std::{result, ops::Add, convert::{TryFrom, TryInto}};
|
slot_range_helper::generate_slot_range!(Zero(0), One(1), Two(2), Three(3));
|
||||||
use sp_runtime::traits::CheckedSub;
|
|
||||||
use parity_scale_codec::{Encode, Decode};
|
|
||||||
|
|
||||||
/// Total number of possible sub ranges of slots.
|
|
||||||
pub const SLOT_RANGE_COUNT: usize = 10;
|
|
||||||
|
|
||||||
/// A compactly represented sub-range from the series (0, 1, 2, 3).
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode)]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum SlotRange {
|
|
||||||
/// Sub range from index 0 to index 0 inclusive.
|
|
||||||
ZeroZero = 0,
|
|
||||||
/// Sub range from index 0 to index 1 inclusive.
|
|
||||||
ZeroOne = 1,
|
|
||||||
/// Sub range from index 0 to index 2 inclusive.
|
|
||||||
ZeroTwo = 2,
|
|
||||||
/// Sub range from index 0 to index 3 inclusive.
|
|
||||||
ZeroThree = 3,
|
|
||||||
/// Sub range from index 1 to index 1 inclusive.
|
|
||||||
OneOne = 4,
|
|
||||||
/// Sub range from index 1 to index 2 inclusive.
|
|
||||||
OneTwo = 5,
|
|
||||||
/// Sub range from index 1 to index 3 inclusive.
|
|
||||||
OneThree = 6,
|
|
||||||
/// Sub range from index 2 to index 2 inclusive.
|
|
||||||
TwoTwo = 7,
|
|
||||||
/// Sub range from index 2 to index 3 inclusive.
|
|
||||||
TwoThree = 8,
|
|
||||||
/// Sub range from index 3 to index 3 inclusive.
|
|
||||||
ThreeThree = 9, // == SLOT_RANGE_COUNT - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
impl std::fmt::Debug for SlotRange {
|
|
||||||
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
let p = self.as_pair();
|
|
||||||
write!(fmt, "[{}..{}]", p.0, p.1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SlotRange {
|
|
||||||
pub fn new_bounded<
|
|
||||||
Index: Add<Output=Index> + CheckedSub + Copy + Ord + From<u32> + TryInto<u32>
|
|
||||||
>(
|
|
||||||
initial: Index,
|
|
||||||
first: Index,
|
|
||||||
last: Index
|
|
||||||
) -> result::Result<Self, &'static str> {
|
|
||||||
if first > last || first < initial || last > initial + 3.into() {
|
|
||||||
return Err("Invalid range for this auction")
|
|
||||||
}
|
|
||||||
let count: u32 = last.checked_sub(&first)
|
|
||||||
.ok_or("range ends before it begins")?
|
|
||||||
.try_into()
|
|
||||||
.map_err(|_| "range too big")?;
|
|
||||||
let first: u32 = first.checked_sub(&initial)
|
|
||||||
.ok_or("range begins too early")?
|
|
||||||
.try_into()
|
|
||||||
.map_err(|_| "start too far")?;
|
|
||||||
match first {
|
|
||||||
0 => match count {
|
|
||||||
0 => Some(SlotRange::ZeroZero),
|
|
||||||
1 => Some(SlotRange::ZeroOne),
|
|
||||||
2 => Some(SlotRange::ZeroTwo),
|
|
||||||
3 => Some(SlotRange::ZeroThree),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
1 => match count {
|
|
||||||
0 => Some(SlotRange::OneOne),
|
|
||||||
1 => Some(SlotRange::OneTwo),
|
|
||||||
2 => Some(SlotRange::OneThree),
|
|
||||||
_ => None
|
|
||||||
},
|
|
||||||
2 => match count { 0 => Some(SlotRange::TwoTwo), 1 => Some(SlotRange::TwoThree), _ => None },
|
|
||||||
3 => match count { 0 => Some(SlotRange::ThreeThree), _ => None },
|
|
||||||
_ => return Err("range begins too late"),
|
|
||||||
}.ok_or("range ends too late")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_pair(&self) -> (u8, u8) {
|
|
||||||
match self {
|
|
||||||
SlotRange::ZeroZero => (0, 0),
|
|
||||||
SlotRange::ZeroOne => (0, 1),
|
|
||||||
SlotRange::ZeroTwo => (0, 2),
|
|
||||||
SlotRange::ZeroThree => (0, 3),
|
|
||||||
SlotRange::OneOne => (1, 1),
|
|
||||||
SlotRange::OneTwo => (1, 2),
|
|
||||||
SlotRange::OneThree => (1, 3),
|
|
||||||
SlotRange::TwoTwo => (2, 2),
|
|
||||||
SlotRange::TwoThree => (2, 3),
|
|
||||||
SlotRange::ThreeThree => (3, 3),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn intersects(&self, other: SlotRange) -> bool {
|
|
||||||
let a = self.as_pair();
|
|
||||||
let b = other.as_pair();
|
|
||||||
b.0 <= a.1 && a.0 <= b.1
|
|
||||||
// == !(b.0 > a.1 || a.0 > b.1)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
match self {
|
|
||||||
SlotRange::ZeroZero => 1,
|
|
||||||
SlotRange::ZeroOne => 2,
|
|
||||||
SlotRange::ZeroTwo => 3,
|
|
||||||
SlotRange::ZeroThree => 4,
|
|
||||||
SlotRange::OneOne => 1,
|
|
||||||
SlotRange::OneTwo => 2,
|
|
||||||
SlotRange::OneThree => 3,
|
|
||||||
SlotRange::TwoTwo => 1,
|
|
||||||
SlotRange::TwoThree => 2,
|
|
||||||
SlotRange::ThreeThree => 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<usize> for SlotRange {
|
|
||||||
type Error = ();
|
|
||||||
fn try_from(x: usize) -> Result<SlotRange, ()> {
|
|
||||||
Ok(match x {
|
|
||||||
0 => SlotRange::ZeroZero,
|
|
||||||
1 => SlotRange::ZeroOne,
|
|
||||||
2 => SlotRange::ZeroTwo,
|
|
||||||
3 => SlotRange::ZeroThree,
|
|
||||||
4 => SlotRange::OneOne,
|
|
||||||
5 => SlotRange::OneTwo,
|
|
||||||
6 => SlotRange::OneThree,
|
|
||||||
7 => SlotRange::TwoTwo,
|
|
||||||
8 => SlotRange::TwoThree,
|
|
||||||
9 => SlotRange::ThreeThree,
|
|
||||||
_ => return Err(()),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user