referrerpolicy=no-referrer-when-downgrade

pallet_broker/
types.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use crate::{
19	Config, CoreAssignment, CoreIndex, CoreMask, CoretimeInterface, RCBlockNumberOf, TaskId,
20	CORE_MASK_BITS,
21};
22use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
23use frame_support::traits::fungible::Inspect;
24use frame_system::Config as SConfig;
25use scale_info::TypeInfo;
26use sp_arithmetic::Perbill;
27use sp_core::ConstU32;
28use sp_runtime::BoundedVec;
29
30pub type BalanceOf<T> = <<T as Config>::Currency as Inspect<<T as SConfig>::AccountId>>::Balance;
31pub type RelayBalanceOf<T> = <<T as Config>::Coretime as CoretimeInterface>::Balance;
32pub type RelayBlockNumberOf<T> = RCBlockNumberOf<<T as Config>::Coretime>;
33pub type RelayAccountIdOf<T> = <<T as Config>::Coretime as CoretimeInterface>::AccountId;
34
35/// Relay-chain block number with a fixed divisor of Config::TimeslicePeriod.
36pub type Timeslice = u32;
37/// Counter for the total number of set bits over every core's `CoreMask`. `u32` so we don't
38/// ever get an overflow. This is 1/80th of a Polkadot Core per timeslice. Assuming timeslices are
39/// 80 blocks, then this indicates usage of a single core one time over a timeslice.
40pub type CoreMaskBitCount = u32;
41/// The same as `CoreMaskBitCount` but signed.
42pub type SignedCoreMaskBitCount = i32;
43
44/// Whether a core assignment is revokable or not.
45#[derive(
46	Encode,
47	Decode,
48	DecodeWithMemTracking,
49	Copy,
50	Clone,
51	PartialEq,
52	Eq,
53	Debug,
54	TypeInfo,
55	MaxEncodedLen,
56)]
57pub enum Finality {
58	/// The region remains with the same owner allowing the assignment to be altered.
59	Provisional,
60	/// The region is removed; the assignment may be eligible for renewal.
61	Final,
62}
63
64/// Self-describing identity for a Region of Bulk Coretime.
65#[derive(
66	Encode,
67	Decode,
68	DecodeWithMemTracking,
69	Copy,
70	Clone,
71	PartialEq,
72	Eq,
73	Debug,
74	TypeInfo,
75	MaxEncodedLen,
76)]
77pub struct RegionId {
78	/// The timeslice at which this Region begins.
79	pub begin: Timeslice,
80	/// The index of the Polkadot Core on which this Region will be scheduled.
81	pub core: CoreIndex,
82	/// The regularity parts in which this Region will be scheduled.
83	pub mask: CoreMask,
84}
85impl From<u128> for RegionId {
86	fn from(x: u128) -> Self {
87		Self { begin: (x >> 96) as u32, core: (x >> 80) as u16, mask: x.into() }
88	}
89}
90impl From<RegionId> for u128 {
91	fn from(x: RegionId) -> Self {
92		((x.begin as u128) << 96) | ((x.core as u128) << 80) | u128::from(x.mask)
93	}
94}
95#[test]
96fn region_id_converts_u128() {
97	let r = RegionId { begin: 0x12345678u32, core: 0xabcdu16, mask: 0xdeadbeefcafef00d0123.into() };
98	let u = 0x12345678_abcd_deadbeefcafef00d0123u128;
99	assert_eq!(RegionId::from(u), r);
100	assert_eq!(u128::from(r), u);
101}
102
103/// The rest of the information describing a Region.
104#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen)]
105pub struct RegionRecord<AccountId, Balance> {
106	/// The end of the Region.
107	pub end: Timeslice,
108	/// The owner of the Region.
109	pub owner: Option<AccountId>,
110	/// The amount paid to Polkadot for this Region, or `None` if renewal is not allowed.
111	pub paid: Option<Balance>,
112}
113pub type RegionRecordOf<T> = RegionRecord<<T as SConfig>::AccountId, BalanceOf<T>>;
114
115/// An distinct item which can be scheduled on a Polkadot Core.
116#[derive(
117	Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen,
118)]
119pub struct ScheduleItem {
120	/// The regularity parts in which this Item will be scheduled on the Core.
121	pub mask: CoreMask,
122	/// The job that the Core should be doing.
123	pub assignment: CoreAssignment,
124}
125pub type Schedule = BoundedVec<ScheduleItem, ConstU32<{ CORE_MASK_BITS as u32 }>>;
126
127/// The record body of a Region which was contributed to the Instantaneous Coretime Pool. This helps
128/// with making pro rata payments to contributors.
129#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen)]
130pub struct ContributionRecord<AccountId> {
131	/// The end of the Region contributed.
132	pub length: Timeslice,
133	/// The identity of the contributor.
134	pub payee: AccountId,
135}
136pub type ContributionRecordOf<T> = ContributionRecord<<T as SConfig>::AccountId>;
137
138/// A per-timeslice bookkeeping record for tracking Instantaneous Coretime Pool activity and
139/// making proper payments to contributors.
140#[derive(Encode, Decode, Clone, Default, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen)]
141pub struct InstaPoolHistoryRecord<Balance> {
142	/// The total amount of Coretime (measured in Core Mask Bits minus any contributions which have
143	/// already been paid out.
144	pub private_contributions: CoreMaskBitCount,
145	/// The total amount of Coretime (measured in Core Mask Bits contributed by the Polkadot System
146	/// in this timeslice.
147	pub system_contributions: CoreMaskBitCount,
148	/// The payout remaining for the `private_contributions`, or `None` if the revenue is not yet
149	/// known.
150	pub maybe_payout: Option<Balance>,
151}
152pub type InstaPoolHistoryRecordOf<T> = InstaPoolHistoryRecord<BalanceOf<T>>;
153
154/// How much of a core has been assigned or, if completely assigned, the workload itself.
155#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen)]
156pub enum CompletionStatus {
157	/// The core is not fully assigned; the inner is the parts which have.
158	Partial(CoreMask),
159	/// The core is fully assigned; the inner is the workload which has been assigned.
160	Complete(Schedule),
161}
162impl CompletionStatus {
163	/// Return reference to the complete workload, or `None` if incomplete.
164	pub fn complete(&self) -> Option<&Schedule> {
165		match self {
166			Self::Complete(s) => Some(s),
167			Self::Partial(_) => None,
168		}
169	}
170	/// Return the complete workload, or `None` if incomplete.
171	pub fn drain_complete(self) -> Option<Schedule> {
172		match self {
173			Self::Complete(s) => Some(s),
174			Self::Partial(_) => None,
175		}
176	}
177}
178
179/// The identity of a possibly renewable Core workload.
180#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen)]
181pub struct PotentialRenewalId {
182	/// The core whose workload at the sale ending with `when` may be renewed to begin at `when`.
183	pub core: CoreIndex,
184	/// The point in time that the renewable workload on `core` ends and a fresh renewal may begin.
185	pub when: Timeslice,
186}
187
188/// A record of a potential renewal.
189///
190/// The renewal will only actually be allowed if `CompletionStatus` is `Complete` at the time of
191/// renewal.
192#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen)]
193pub struct PotentialRenewalRecord<Balance> {
194	/// The price for which the next renewal can be made.
195	pub price: Balance,
196	/// The workload which will be scheduled on the Core in the case a renewal is made, or if
197	/// incomplete, then the parts of the core which have been scheduled.
198	pub completion: CompletionStatus,
199}
200pub type PotentialRenewalRecordOf<T> = PotentialRenewalRecord<BalanceOf<T>>;
201
202/// General status of the system.
203#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen)]
204pub struct StatusRecord {
205	/// The total number of cores which can be assigned (one plus the maximum index which can
206	/// be used in `Coretime::assign`).
207	pub core_count: CoreIndex,
208	/// The current size of the Instantaneous Coretime Pool, measured in
209	/// Core Mask Bits.
210	pub private_pool_size: CoreMaskBitCount,
211	/// The current amount of the Instantaneous Coretime Pool which is provided by the Polkadot
212	/// System, rather than provided as a result of privately operated Coretime.
213	pub system_pool_size: CoreMaskBitCount,
214	/// The last (Relay-chain) timeslice which we committed to the Relay-chain.
215	pub last_committed_timeslice: Timeslice,
216	/// The timeslice of the last time we ticked.
217	pub last_timeslice: Timeslice,
218}
219
220/// A record of flux in the InstaPool.
221#[derive(Encode, Decode, Clone, Copy, Default, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen)]
222pub struct PoolIoRecord {
223	/// The total change of the portion of the pool supplied by purchased Bulk Coretime, measured
224	/// in Core Mask Bits.
225	pub private: SignedCoreMaskBitCount,
226	/// The total change of the portion of the pool supplied by the Polkadot System, measured in
227	/// Core Mask Bits.
228	pub system: SignedCoreMaskBitCount,
229}
230
231/// The status of a Bulk Coretime Sale.
232#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen)]
233pub struct SaleInfoRecord<Balance, RelayBlockNumber> {
234	/// The relay block number at which the sale will/did start.
235	pub sale_start: RelayBlockNumber,
236	/// The length in blocks of the Leadin Period (where the price is decreasing).
237	pub leadin_length: RelayBlockNumber,
238	/// The price of Bulk Coretime after the Leadin Period.
239	pub end_price: Balance,
240	/// The first timeslice of the Regions which are being sold in this sale.
241	pub region_begin: Timeslice,
242	/// The timeslice on which the Regions which are being sold in the sale terminate. (i.e. One
243	/// after the last timeslice which the Regions control.)
244	pub region_end: Timeslice,
245	/// The number of cores we want to sell, ideally. Selling this amount would result in no
246	/// change to the price for the next sale.
247	pub ideal_cores_sold: CoreIndex,
248	/// Number of cores which are/have been offered for sale.
249	pub cores_offered: CoreIndex,
250	/// The index of the first core which is for sale. Core of Regions which are sold have
251	/// incrementing indices from this.
252	pub first_core: CoreIndex,
253	/// The price at which cores have been sold out.
254	///
255	/// Will only be `None` if no core was offered for sale.
256	pub sellout_price: Option<Balance>,
257	/// Number of cores which have been sold; never more than cores_offered.
258	pub cores_sold: CoreIndex,
259}
260pub type SaleInfoRecordOf<T> = SaleInfoRecord<BalanceOf<T>, RelayBlockNumberOf<T>>;
261
262/// Record for Polkadot Core reservations (generally tasked with the maintenance of System
263/// Chains).
264pub type ReservationsRecord<Max> = BoundedVec<Schedule, Max>;
265pub type ReservationsRecordOf<T> = ReservationsRecord<<T as Config>::MaxReservedCores>;
266
267/// Information on a single legacy lease.
268#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen)]
269pub struct LeaseRecordItem {
270	/// The timeslice until the lease is valid.
271	pub until: Timeslice,
272	/// The task which the lease is for.
273	pub task: TaskId,
274}
275
276/// Record for Polkadot Core legacy leases.
277pub type LeasesRecord<Max> = BoundedVec<LeaseRecordItem, Max>;
278pub type LeasesRecordOf<T> = LeasesRecord<<T as Config>::MaxLeasedCores>;
279
280/// Record for On demand core sales.
281///
282/// The blocknumber is the relay chain block height `until` which the original request
283/// for revenue was made.
284#[derive(
285	Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen,
286)]
287pub struct OnDemandRevenueRecord<RelayBlockNumber, RelayBalance> {
288	/// The height of the Relay-chain at the time the revenue request was made.
289	pub until: RelayBlockNumber,
290	/// The accumulated balance of on demand sales made on the relay chain.
291	pub amount: RelayBalance,
292}
293
294pub type OnDemandRevenueRecordOf<T> =
295	OnDemandRevenueRecord<RelayBlockNumberOf<T>, RelayBalanceOf<T>>;
296
297/// Configuration of this pallet.
298#[derive(
299	Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen,
300)]
301pub struct ConfigRecord<RelayBlockNumber> {
302	/// The number of Relay-chain blocks in advance which scheduling should be fixed and the
303	/// `Coretime::assign` API used to inform the Relay-chain.
304	pub advance_notice: RelayBlockNumber,
305	/// The length in blocks of the Interlude Period for forthcoming sales.
306	pub interlude_length: RelayBlockNumber,
307	/// The length in blocks of the Leadin Period for forthcoming sales.
308	pub leadin_length: RelayBlockNumber,
309	/// The length in timeslices of Regions which are up for sale in forthcoming sales.
310	pub region_length: Timeslice,
311	/// The proportion of cores available for sale which should be sold.
312	///
313	/// If more cores are sold than this, then further sales will no longer be considered in
314	/// determining the sellout price. In other words the sellout price will be the last price
315	/// paid, without going over this limit.
316	pub ideal_bulk_proportion: Perbill,
317	/// An artificial limit to the number of cores which are allowed to be sold. If `Some` then
318	/// no more cores will be sold than this.
319	pub limit_cores_offered: Option<CoreIndex>,
320	/// The amount by which the renewal price increases each sale period.
321	pub renewal_bump: Perbill,
322	/// The duration by which rewards for contributions to the InstaPool must be collected.
323	pub contribution_timeout: Timeslice,
324}
325pub type ConfigRecordOf<T> = ConfigRecord<RelayBlockNumberOf<T>>;
326
327impl<RelayBlockNumber> ConfigRecord<RelayBlockNumber>
328where
329	RelayBlockNumber: sp_arithmetic::traits::Zero,
330{
331	/// Check the config for basic validity constraints.
332	pub(crate) fn validate(&self) -> Result<(), ()> {
333		if self.leadin_length.is_zero() {
334			return Err(())
335		}
336
337		Ok(())
338	}
339}
340
341/// A record containing information regarding auto-renewal for a specific core.
342#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen)]
343pub struct AutoRenewalRecord {
344	/// The core for which auto renewal is enabled.
345	pub core: CoreIndex,
346	/// The task assigned to the core. We keep track of it so we don't have to look it up when
347	/// performing auto-renewal.
348	pub task: TaskId,
349	/// Specifies when the upcoming renewal should be performed. This is used for lease holding
350	/// tasks to ensure that the renewal process does not begin until the lease expires.
351	pub next_renewal: Timeslice,
352}