jam_types/
simple.rs

1#[allow(unused_imports)]
2use super::Authorizer;
3use crate::{chain_params, opaque, FixedVec};
4use bounded_collections::{BoundedVec, Get};
5use codec::{Decode, Encode, MaxEncodedLen};
6use core::sync::atomic::Ordering::Relaxed;
7
8/// Version of the Gray Paper implemented by this and dependent crates.
9pub const GP_VERSION: &str = "0.7.1";
10
11/// Beginning of the Jam "Common Era" (1200 UTC on January 1, 2025),
12/// as seconds after the Unix epoch, excluding leap seconds.
13pub const JAM_COMMON_ERA: u64 = 1_735_732_800;
14
15/// Length of a transfer memo in bytes.
16pub const MEMO_LEN: usize = 128;
17
18/// Maximum length of the preimage in the encoded form.
19#[doc(hidden)]
20// TODO @ivan This is temporary value. Replace with the one from the GP when it's updated.
21pub const MAX_PREIMAGE_LEN: usize = 4 * 1024 * 1024;
22
23/// Maximum length of the preimage blob.
24///
25/// Equals `MAX_PREIMAGE_LEN` minus the overhead.
26// TODO @ivan Unhide when the GP is updated.
27#[doc(hidden)]
28pub const MAX_PREIMAGE_BLOB_LEN: usize = MAX_PREIMAGE_LEN - 8;
29
30/// PolkaVM page size in bytes.
31pub const PAGE_SIZE: u32 = 4096;
32
33/// The maximum number of levels in the implicit tree derived from the segment hashes in a
34/// proof-page.
35pub const SUFFIX_SKIP_LEN: usize = 6;
36
37/// The maximum number of segments whose justification can be included in a single segment-sized
38/// proof-page. Basically just the highest power of 2 which when multiplied by 32 (the size of a
39/// hash) leaves enough room from 4104 (the size of a segment) to fit a partial Merkle proof of
40/// 6 branches (6 * 32 = 192) plus the overhead for storing the actual number of hashes (should be
41/// one byte for `PROVEN_PER_SEGMENT < 128`). It turns out that this is 2^6 = 64.
42///
43/// See `max_prefix_proof_len` for the actual formula.
44pub const PROVEN_PER_SEGMENT: usize = 1 << SUFFIX_SKIP_LEN;
45
46/// Index for an attempt at producing a ticket for the right to produce a block.
47pub type TicketAttempt = u8;
48
49const DEFAULT_PARAMS: ProtocolParameters = ProtocolParameters::full();
50
51chain_params! {
52	/// Total number of validators in the JAM.
53	static VAL_COUNT: _ = _(DEFAULT_PARAMS.val_count);
54	pub fn val_count() -> ValIndex;
55	pub struct ValCount; impl Get<_> for _ {}
56
57	/// Number of bytes in a basic EC piece.
58	static BASIC_PIECE_LEN: _ = _(DEFAULT_PARAMS.basic_piece_len as _);
59	pub fn basic_piece_len() -> usize;
60
61	/// Number EC pieces in a segment.
62	static SEGMENT_PIECE_COUNT: _ = _(DEFAULT_PARAMS.segment_piece_count as _);
63	pub fn segment_piece_count() -> usize;
64
65	/// Number of authorizations in a queue allocated to a core.
66	static AUTH_QUEUE_LEN: _ = _(DEFAULT_PARAMS.auth_queue_len as _);
67	pub fn auth_queue_len() -> usize;
68	pub struct AuthQueueLen; impl Get<_> for _ {}
69
70	/// Minimum period in blocks between going from becoming `Available` to `Zombie`, and then
71	/// again from `Zombie` to non-existent.
72	///
73	/// This ensures firstly that any data added and referenced in a Work Report's lookup anchor
74	/// block will remain on-chain right up until the latest possible time a dispute might
75	/// conclude. Secondly, it ensure that we only need to record one "flip-flop" of the data's
76	/// availability in order to be able to determine whether it's available or not at any block
77	/// within this period.
78	static MIN_TURNAROUND_PERIOD: _ = _(DEFAULT_PARAMS.min_turnaround_period);
79	pub fn min_turnaround_period() -> Slot;
80
81	/// Maximum number of Work Items in a Work Package.
82	static MAX_WORK_ITEMS: _ = _(DEFAULT_PARAMS.max_work_items as _);
83	pub fn max_work_items() -> usize;
84	pub struct MaxWorkItems; impl Get<_> for _ {}
85
86	/// Maximum number of imports in a Work Package.
87	static MAX_IMPORTS: _ = _(DEFAULT_PARAMS.max_imports);
88	pub fn max_imports() -> u32;
89	pub struct MaxImports; impl Get<_> for _ {}
90
91	/// Maximum number of exports in a Work Package.
92	static MAX_EXPORTS: _ = _(DEFAULT_PARAMS.max_exports);
93	pub fn max_exports() -> u32;
94
95	/// Maximum number of extrinsics in a Work Package.
96	static MAX_EXTRINSICS: _ = _(DEFAULT_PARAMS.max_extrinsics as _);
97	pub fn max_extrinsics() -> u32;
98	pub struct MaxExtrinsics; impl Get<_> for _ {}
99
100	/// Maximum number of dependencies (total of prerequisites and SR lookup entries).
101	static MAX_DEPENDENCIES: _ = _(DEFAULT_PARAMS.max_dependencies as _);
102	pub fn max_dependencies() -> usize;
103	pub struct MaxDependencies; impl Get<_> for _ {}
104
105	/// Maximum size of a Work Package together with all extrinsic data and imported segments.
106	static MAX_INPUT: _ = _(DEFAULT_PARAMS.max_input);
107	pub fn max_input() -> u32;
108	pub struct MaxInput; impl Get<_> for _ {}
109
110	/// Returns the number of bytes in a segment slice.
111	pub fn segment_slice_len() -> usize {
112		segment_len() / basic_piece_points()
113	}
114	pub struct SegmentSliceLen; impl Get<_> for _ {}
115
116	/// Number of bytes in a segment. This is fixed.
117	pub const SEGMENT_LEN: _ = (DEFAULT_PARAMS.basic_piece_len * DEFAULT_PARAMS.segment_piece_count) as usize;
118	pub fn segment_len() -> usize;
119	pub struct SegmentLen; impl Get<_> for _ {}
120
121	/// Number of seconds in a time slot.
122	static SLOT_PERIOD_SEC : _ = _(DEFAULT_PARAMS.slot_period_sec as _);
123	pub fn slot_period_sec() -> u64;
124
125	/// The rotation period, defined in number of slots.
126	static ROTATION_PERIOD: _ = _(DEFAULT_PARAMS.rotation_period as _);
127	pub fn rotation_period() -> Slot;
128
129	/// The epoch period, defined in number of slots.
130	static EPOCH_PERIOD: _ = _(DEFAULT_PARAMS.epoch_period);
131	pub fn epoch_period() -> Slot;
132	pub struct EpochPeriod; impl Get<_> for _ {}
133
134	/// The length of the contest, defined in number of slots.
135	static EPOCH_TAIL_START: _ = _(DEFAULT_PARAMS.epoch_tail_start);
136	pub fn epoch_tail_start() -> Slot;
137
138	/// Max tickets allowed to be embedded in each block extrinsic.
139	static MAX_TICKETS_PER_BLOCK: _ = _(DEFAULT_PARAMS.max_tickets_per_block as _);
140	pub fn max_tickets_per_block() -> usize;
141	pub struct MaxTicketsPerBlock; impl Get<_> for _ {}
142
143	/// Maximum number of tickets which each validator may create.
144	///
145	/// Influences the anonymity of block producers. As all published tickets have a public
146	/// attempt number less than `attempts_number` if two tickets share an attempt number
147	/// then they must belong to two different validators, which reduces anonymity late as
148	/// we approach the epoch tail.
149	static TICKETS_ATTEMPTS_NUMBER: _ = _(DEFAULT_PARAMS.tickets_attempts_number as _);
150	pub fn tickets_attempts_number() -> TicketAttempt;
151	pub struct TicketsAttemptsNumber; impl Get<_> for _ {}
152
153	static DEPOSIT_PER_ACCOUNT: _ = _(DEFAULT_PARAMS.deposit_per_account);
154	pub fn deposit_per_account() -> Balance;
155
156	static DEPOSIT_PER_ITEM: _ = _(DEFAULT_PARAMS.deposit_per_item);
157	pub fn deposit_per_item() -> Balance;
158
159	static DEPOSIT_PER_BYTE: _ = _(DEFAULT_PARAMS.deposit_per_byte);
160	pub fn deposit_per_byte() -> Balance;
161
162	/// The maximum gas which may be used in a single block. At present this is just the product of
163	/// the maximum gas per work-report and the number of cores. In the future it should probably be
164	/// more to account for the possibility of always-accumulate services.
165	static BLOCK_GAS_LIMIT: _ = _(DEFAULT_PARAMS.block_gas_limit);
166	pub fn block_gas_limit() -> UnsignedGas;
167
168	/// Maximum gas which may be used to Authorize a single work-package.
169	static MAX_IS_AUTHORIZED_GAS: _ = _(DEFAULT_PARAMS.max_is_authorized_gas);
170	pub fn max_is_authorized_gas() -> UnsignedGas;
171
172	/// Maximum gas which may be used to Refine a single work-report.
173	static MAX_REFINE_GAS: _ = _(DEFAULT_PARAMS.max_refine_gas);
174	pub fn max_refine_gas() -> UnsignedGas;
175
176	/// Maximum gas which may be used to Accumulate a single work-report.
177	static MAX_ACCUMULATE_GAS: _ = _(DEFAULT_PARAMS.max_accumulate_gas);
178	pub fn max_accumulate_gas() -> UnsignedGas;
179
180	static MAX_SERVICE_CODE_SIZE: _ = _(DEFAULT_PARAMS.max_service_code_size as _);
181	pub fn max_service_code_size() -> usize;
182
183	static MAX_AUTHORIZER_CODE_SIZE: _ = _(DEFAULT_PARAMS.max_authorizer_code_size as _);
184	pub fn max_authorizer_code_size() -> usize;
185
186	/// The number of blocks which are kept in the recent block cache. We use a `u8` to index into
187	/// this and therefore it may be no larger than 255.
188	static RECENT_BLOCK_COUNT: _ = _(DEFAULT_PARAMS.recent_block_count as _);
189	pub fn recent_block_count() -> Slot;
190	pub struct RecentBlockCount; impl Get<_> for _ {}
191
192	/// The number of validators on each core.
193	pub const VALS_PER_CORE: _ = 3;
194	pub fn _vals_per_core() -> usize;
195	pub struct _ValsPerCore; impl Get<_> for _ {}
196
197	/// Number of cores in the JAM.
198	pub fn core_count() -> CoreIndex {
199		(val_count() as usize / VALS_PER_CORE) as CoreIndex
200	}
201	pub struct CoreCount; impl Get<_> for _ {}
202
203	/// Maximum number of DA segments that a Work Package can produce.
204	pub fn max_export_segments() -> u32 {
205		max_exports() + max_exports().div_ceil(PROVEN_PER_SEGMENT as u32)
206	}
207	pub struct MaxExportSegments; impl Get<_> for _ {}
208
209	/// Maximum number of DA segments that a Work Package can require as imports. This is twice the
210	/// maximum number of imports because each import may require a proof segment.
211	pub fn max_import_segments() -> u32 { max_imports() * 2 }
212	pub struct MaxImportSegments; impl Get<_> for _ {}
213
214	/// The period in timeslots after which reported but unavailable work may be replaced.
215	static AVAILABILITY_TIMEOUT: _ = _(DEFAULT_PARAMS.availability_timeout as _);
216	pub fn availability_timeout() -> Slot;
217
218	/// Number of items in the authorization window.
219	static AUTH_WINDOW: _ = _(DEFAULT_PARAMS.auth_window as _);
220	pub fn auth_window() -> usize;
221	pub struct AuthWindow; impl Get<_> for _ {}
222
223	/// Maximum age, in blocks, that the lookup anchor may be, taken from the regular anchor.
224	static MAX_LOOKUP_ANCHOR_AGE: _ = _(DEFAULT_PARAMS.max_lookup_anchor_age);
225	pub fn max_lookup_anchor_age() -> Slot;
226
227	/// The maximum total size of all unbounded blobs in a work-report.
228	/// Maximum age, in blocks, that the lookup anchor may be, taken from the regular anchor.
229	static MAX_REPORT_ELECTIVE_DATA: _ = _(DEFAULT_PARAMS.max_report_elective_data);
230	pub fn max_report_elective_data() -> u32;
231	pub struct MaxReportElectiveData; impl Get<_> for _ {}
232}
233
234/// Number of points in a piece.
235pub fn basic_piece_points() -> usize {
236	basic_piece_len() / POINT_LEN
237}
238
239/// Returns the number of pieces in a segment.
240pub fn pieces_per_segment() -> usize {
241	SEGMENT_LEN / basic_piece_len()
242}
243
244/// Baseline parameters for the JAM protocol.
245#[derive(Copy, Clone, Eq, PartialEq, Debug, Encode, Decode, MaxEncodedLen)]
246#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
247pub struct ProtocolParameters {
248	/// (Bi) The additional deposit required for each preimage or storage item in an account.
249	pub deposit_per_item: Balance,
250	/// (Bl) The additional deposit required for each byte of each storage item in an account and
251	/// preimage of an account.
252	pub deposit_per_byte: Balance,
253	/// (Bs) The base deposit required to retain an account.
254	pub deposit_per_account: Balance,
255	/// (C) Number of JAM cores.
256	pub core_count: CoreIndex,
257	/// (D) The period in timeslots after which an unreferenced preimage may be expunged.
258	pub min_turnaround_period: Slot,
259	/// (E) The epoch period, defined in number of slots.
260	pub epoch_period: Slot,
261	/// (Ga) Maximum gas which may be used to Accumulate a single work-report.
262	pub max_accumulate_gas: UnsignedGas,
263	/// (Gi) Maximum gas which may be used to Authorize a single work-package.
264	pub max_is_authorized_gas: UnsignedGas,
265	/// (Gr) Maximum gas which may be used to Refine a single work-report.
266	pub max_refine_gas: UnsignedGas,
267	/// (Gt) Maximum gas which can be processed in a single block.
268	pub block_gas_limit: UnsignedGas,
269	/// (H) The number of blocks which are kept in the recent block cache.
270	pub recent_block_count: u16,
271	/// (I) Maximum number of Work Items in a Work Package.
272	pub max_work_items: u16,
273	/// (J) Maximum number of dependencies (total of prerequisites and SR lookup entries).
274	pub max_dependencies: u16,
275	/// (K) Max tickets allowed to be embedded in each block extrinsic.
276	pub max_tickets_per_block: u16,
277	/// (L) Maximum age, in blocks, that the lookup anchor may be, taken from the regular anchor.
278	pub max_lookup_anchor_age: Slot,
279	/// (N) The number of distinct tickets which may be created and submitted by each validator on
280	/// each epoch.
281	pub tickets_attempts_number: u16,
282	/// (O) Number of items in the authorization window.
283	pub auth_window: u16,
284	/// (P) The period for each JAM time slot, defined in seconds.
285	pub slot_period_sec: u16,
286	/// (Q) Number of authorizations in a queue allocated to a core.
287	pub auth_queue_len: u16,
288	/// (R) The rotation period, defined in number of slots.
289	pub rotation_period: u16,
290	/// (T) Maximum number of extrinsics in a Work Package.
291	pub max_extrinsics: u16,
292	/// (U) The period in timeslots after which reported but unavailable work may be replaced.
293	pub availability_timeout: u16,
294	/// (V) Total number of validators. Must by divisible by guarantor group size (3).
295	pub val_count: ValIndex,
296	/// (Wa) The maximum size of authorizer code (used by Is-Authorized procedure).
297	pub max_authorizer_code_size: u32,
298	/// (Wb) Maximum size of a Work Package together with all extrinsic data and imported segments.
299	pub max_input: u32,
300	/// (Wc) The maximum size of service code (used by Refine/Accumulate/OnTransfer procedures).
301	pub max_service_code_size: u32,
302	/// (We) Number of octets in a basic piece. Must be even and divide into segment length
303	/// (4,104).
304	pub basic_piece_len: u32,
305	/// (Wm) Maximum number of imports in a Work Package.
306	pub max_imports: u32,
307	/// (Wp) The number of erasure-coded pieces in a segment.
308	pub segment_piece_count: u32,
309	/// (Wr) The maximum total size of all unbounded blobs in a work-report, in octets.
310	pub max_report_elective_data: u32,
311	/// (Wt) The size of a transfer memo in octets. The size of a transfer memo in octets.
312	pub transfer_memo_size: u32,
313	/// (Wx) Maximum number of exports in a Work Package.
314	pub max_exports: u32,
315	/// (Y) The length of the contest, defined in number of slots.
316	pub epoch_tail_start: Slot,
317}
318
319impl ProtocolParameters {
320	pub const fn full() -> Self {
321		Self {
322			val_count: 1023,
323			core_count: 341,
324			basic_piece_len: 684,
325			auth_queue_len: 80,
326			min_turnaround_period: 19_200,
327			max_work_items: 16,
328			max_imports: 3072,
329			max_exports: 3072,
330			max_extrinsics: 128,
331			max_dependencies: 8,
332			max_input: 13_794_305,
333			slot_period_sec: 6,
334			epoch_period: 600,
335			epoch_tail_start: 500,
336			rotation_period: 10,
337			block_gas_limit: 3_500_000_000,
338			recent_block_count: 8,
339			max_tickets_per_block: 16,
340			tickets_attempts_number: 2,
341			deposit_per_account: 100,
342			deposit_per_item: 10,
343			deposit_per_byte: 1,
344			max_is_authorized_gas: 50_000_000,
345			max_refine_gas: 5_000_000_000,
346			max_accumulate_gas: 10_000_000,
347			max_service_code_size: 4_000_000,
348			max_authorizer_code_size: 64_000,
349			availability_timeout: 5,
350			auth_window: 8,
351			max_lookup_anchor_age: 24 * 600,
352			max_report_elective_data: 48 * 1024,
353			segment_piece_count: 6,
354			transfer_memo_size: 128,
355		}
356	}
357	pub const fn tiny() -> Self {
358		let mut params = Self::full();
359		params.val_count = 6;
360		params.core_count = 2;
361		params.basic_piece_len = 4;
362		params.epoch_period = 12;
363		params.epoch_tail_start = 10;
364		params.rotation_period = 4;
365		params.block_gas_limit = 20_000_000;
366		params.max_tickets_per_block = 3;
367		params.tickets_attempts_number = 3;
368		params.max_refine_gas = 1_000_000_000;
369		params.segment_piece_count = 1026;
370		// Remove unreferenced preimages after 32 slots.
371		// The short retention period simplifies testing with test vectors and fuzzing.
372		params.min_turnaround_period = 32;
373		// Same reasoning as `min_turnaround_period`
374		params.max_lookup_anchor_age = 24;
375		params
376	}
377
378	pub fn get() -> Self {
379		Self {
380			deposit_per_item: deposit_per_item(),
381			deposit_per_byte: deposit_per_byte(),
382			deposit_per_account: deposit_per_account(),
383			core_count: core_count(),
384			min_turnaround_period: min_turnaround_period(),
385			epoch_period: epoch_period(),
386			max_accumulate_gas: max_accumulate_gas(),
387			max_is_authorized_gas: max_is_authorized_gas(),
388			max_refine_gas: max_refine_gas(),
389			block_gas_limit: block_gas_limit(),
390			recent_block_count: recent_block_count() as _,
391			max_work_items: max_work_items() as _,
392			max_dependencies: max_dependencies() as _,
393			max_tickets_per_block: max_tickets_per_block() as _,
394			max_lookup_anchor_age: max_lookup_anchor_age(),
395			tickets_attempts_number: tickets_attempts_number() as _,
396			auth_window: auth_window() as _,
397			slot_period_sec: slot_period_sec() as _,
398			auth_queue_len: auth_queue_len() as _,
399			rotation_period: rotation_period() as _,
400			max_extrinsics: max_extrinsics() as _,
401			availability_timeout: availability_timeout() as _,
402			val_count: val_count(),
403			max_authorizer_code_size: max_authorizer_code_size() as _,
404			max_input: max_input(),
405			max_service_code_size: max_service_code_size() as _,
406			basic_piece_len: basic_piece_len() as _,
407			max_imports: max_imports() as _,
408			segment_piece_count: segment_piece_count() as _,
409			max_report_elective_data: max_report_elective_data(),
410			transfer_memo_size: MEMO_LEN as _,
411			max_exports: max_exports(),
412			epoch_tail_start: epoch_tail_start(),
413		}
414	}
415	pub fn validate(&self) -> Result<(), &'static str> {
416		if !self.basic_piece_len.is_multiple_of(2) {
417			return Err("`basic_piece_len` is not even")
418		}
419		if !SEGMENT_LEN.is_multiple_of(self.basic_piece_len as usize) {
420			return Err("`basic_piece_len` does not divide into `SEGMENT_LEN` (4,104)")
421		}
422		if !self.epoch_period.is_multiple_of(self.rotation_period as Slot) {
423			return Err("`rotation_period` does not divide into `epoch_period`")
424		}
425		if self.epoch_tail_start >= self.epoch_period {
426			return Err("`epoch_tail_start` must be less than `epoch_period`")
427		}
428		if !(self.val_count as usize).is_multiple_of(VALS_PER_CORE) {
429			return Err("`val_count` does not divide by `VALS_PER_CORE` (3)")
430		}
431		if self.val_count != self.core_count * VALS_PER_CORE as u16 {
432			return Err("`val_count != core_count * VALS_PER_CORE` (3)")
433		}
434		if self.transfer_memo_size != MEMO_LEN as u32 {
435			return Err("`transfer_memo_size` must be equal tor `MEMO_LEN` (128)")
436		}
437		if recent_block_count() > 255 {
438			return Err("`recent_block_count` may be no larger than `BlockIndex::MAX` (255)")
439		}
440		Ok(())
441	}
442	pub fn apply(self) -> Result<(), &'static str> {
443		self.validate()?;
444		DEPOSIT_PER_ITEM.store(self.deposit_per_item, Relaxed);
445		DEPOSIT_PER_BYTE.store(self.deposit_per_byte, Relaxed);
446		DEPOSIT_PER_ACCOUNT.store(self.deposit_per_account, Relaxed);
447		MIN_TURNAROUND_PERIOD.store(self.min_turnaround_period, Relaxed);
448		EPOCH_PERIOD.store(self.epoch_period, Relaxed);
449		MAX_ACCUMULATE_GAS.store(self.max_accumulate_gas, Relaxed);
450		MAX_IS_AUTHORIZED_GAS.store(self.max_is_authorized_gas, Relaxed);
451		MAX_REFINE_GAS.store(self.max_refine_gas, Relaxed);
452		BLOCK_GAS_LIMIT.store(self.block_gas_limit, Relaxed);
453		RECENT_BLOCK_COUNT.store(self.recent_block_count as _, Relaxed);
454		MAX_WORK_ITEMS.store(self.max_work_items as _, Relaxed);
455		MAX_DEPENDENCIES.store(self.max_dependencies as _, Relaxed);
456		MAX_TICKETS_PER_BLOCK.store(self.max_tickets_per_block as _, Relaxed);
457		MAX_LOOKUP_ANCHOR_AGE.store(self.max_lookup_anchor_age as _, Relaxed);
458		TICKETS_ATTEMPTS_NUMBER.store(self.tickets_attempts_number as _, Relaxed);
459		AUTH_WINDOW.store(self.auth_window as _, Relaxed);
460		SLOT_PERIOD_SEC.store(self.slot_period_sec as _, Relaxed);
461		AUTH_QUEUE_LEN.store(self.auth_queue_len as _, Relaxed);
462		ROTATION_PERIOD.store(self.rotation_period as _, Relaxed);
463		MAX_EXTRINSICS.store(self.max_extrinsics as _, Relaxed);
464		AVAILABILITY_TIMEOUT.store(self.availability_timeout as _, Relaxed);
465		VAL_COUNT.store(self.val_count, Relaxed);
466		MAX_AUTHORIZER_CODE_SIZE.store(self.max_authorizer_code_size as _, Relaxed);
467		MAX_INPUT.store(self.max_input, Relaxed);
468		MAX_SERVICE_CODE_SIZE.store(self.max_service_code_size as _, Relaxed);
469		BASIC_PIECE_LEN.store(self.basic_piece_len as _, Relaxed);
470		MAX_IMPORTS.store(self.max_imports, Relaxed);
471		SEGMENT_PIECE_COUNT.store(self.segment_piece_count as _, Relaxed);
472		MAX_REPORT_ELECTIVE_DATA.store(self.max_report_elective_data, Relaxed);
473		MAX_EXPORTS.store(self.max_exports, Relaxed);
474		EPOCH_TAIL_START.store(self.epoch_tail_start, Relaxed);
475		Ok(())
476	}
477}
478
479/// Number of bytes in an erasure-coding point.
480pub const POINT_LEN: usize = 2;
481
482/// Validators super-majority.
483#[doc(hidden)]
484#[derive(Copy, Clone, Eq, PartialEq, Default, Debug)]
485pub struct ValSuperMajority;
486impl Get<u32> for ValSuperMajority {
487	fn get() -> u32 {
488		val_count() as u32 / 3 * 2 + 1
489	}
490}
491
492/// Type that represents a time slot of six seconds.
493///
494/// This can be either in a relative sense or as a period which has elapsed from the Polkadot
495/// Common Era, beginning 1200 UTC, 1 January 2025.
496pub type Slot = u32;
497/// Type to represent the index of a validator.
498pub type ValIndex = u16;
499/// Type to represent the index of a compute core.
500pub type CoreIndex = u16;
501/// Type to represent the index of a service.
502pub type ServiceId = u32;
503/// Type to represent a balance.
504pub type Balance = u64;
505/// Type which is double the length of Balance, for non-overflowing multiplies.
506pub type DoubleBalance = u128;
507/// Type to represent some gas which may be below zero. This is used primarily for the `invoke`
508/// hostcall API which must be able to return a negative gas amount in case of a gas overrun.
509pub type SignedGas = i64;
510/// Type to represent some gas which must be at least zero.
511pub type UnsignedGas = u64;
512/// Type which is double the length of Gas, for non-overflowing multiplies.
513pub type DoubleGas = u128;
514
515/// A basic 256-bit data value.
516///
517/// This should generally not be used directly in the rich data types, but instead one of the
518/// rich opaque hash types to avoid accidental misuse and provide pretty-print facilities.
519pub type Hash = [u8; 32];
520
521opaque! {
522	/// Hash of an encoded block header.
523	pub struct HeaderHash(pub [u8; 32]);
524
525	/// Hash of PVM program code.
526	pub struct CodeHash(pub [u8; 32]);
527
528	/// Hash of an encoded Work Package.
529	pub struct WorkPackageHash(pub [u8; 32]);
530
531	/// Hash of an encoded Work Report.
532	pub struct WorkReportHash(pub [u8; 32]);
533
534	/// Hash of a Work Item's [WorkPayload].
535	pub struct PayloadHash(pub [u8; 32]);
536
537	/// Hash of the JAM state root.
538	pub struct StateRootHash(pub [u8; 32]);
539
540	/// Hash of an MMR peak.
541	pub struct MmrPeakHash(pub [u8; 32]);
542
543	/// Hash of an accumulation tree root node.
544	pub struct AccumulateRootHash(pub [u8; 32]);
545
546	/// Hash of a piece of extrinsic data.
547	pub struct ExtrinsicHash(pub [u8; 32]);
548
549	/// Hash of an encoded [Authorizer] value.
550	pub struct AuthorizerHash(pub [u8; 32]);
551
552	/// Hash of a segment tree root node.
553	pub struct SegmentTreeRoot(pub [u8; 32]);
554
555	/// Hash of a [Segment] value.
556	pub struct SegmentHash(pub [u8; 32]);
557
558	/// Hash of a Merkle tree node.
559	pub struct MerkleNodeHash(pub [u8; 32]);
560
561	/// Non usage-specific hash.
562	///
563	/// This can be useful for pretty-printing [type@Hash] values.
564	pub struct AnyHash(pub [u8; 32]);
565
566	/// Transfer memo data, included with balance transfers between services.
567	pub struct Memo(pub [u8; MEMO_LEN]);
568
569	/// Data constituting the Authorization Token in a Work Package.
570	pub struct Authorization(pub Vec<u8>);
571
572	/// PVM Program code.
573	pub struct Code(pub Vec<u8>);
574
575	/// Payload data defining a Work Item.
576	pub struct WorkPayload(pub Vec<u8>);
577
578	/// Authorization parameter.
579	pub struct AuthConfig(pub Vec<u8>);
580
581	/// Non usage-specific data.
582	///
583	/// This can be useful for pretty-printing `Vec<u8>` values.
584	pub struct AnyVec(pub Vec<u8>);
585
586	/// A wrapper for a segment of data.
587	///
588	/// This can be useful for pretty-printing `Segment` values or encoding them as BASE64.
589	pub struct WrappedSegment(pub FixedVec<u8, SegmentLen>);
590
591	/// Output data of Refinement operation, passed into Accumulation.
592	pub struct WorkOutput(pub Vec<u8>);
593
594	/// Output data of Is Authorized operation, passed into both Refinement and Accumulation.
595	pub struct AuthTrace(pub Vec<u8>);
596
597	/// Plain-old-data struct of the same length as an encoded Ed25519 public key.
598	///
599	/// This has no cryptographic functionality or dependencies.
600	pub struct OpaqueEd25519Public(pub [u8; 32]);
601
602	/// Plain-old-data struct of the same length as an encoded Bandersnatch public key.
603	///
604	/// This has no cryptographic functionality or dependencies.
605	pub struct OpaqueBandersnatchPublic(pub [u8; 32]);
606
607	/// Plain-old-data struct of the same length as an encoded BLS public key.
608	///
609	/// This has no cryptographic functionality or dependencies.
610	pub struct OpaqueBlsPublic(pub [u8; 144]);
611
612	/// Additional information on a validator, opaque to the actual usage.
613	pub struct OpaqueValidatorMetadata(pub [u8; 128]);
614}
615
616#[cfg(feature = "bytes")]
617opaque! {
618	/// Non usage-specific data.
619	///
620	/// This can be useful for pretty-printing `Bytes` values.
621	pub struct AnyBytes(pub Bytes);
622}
623
624/// A queue of [AuthorizerHash]s, each of which will be rotated into the authorizer pool for a core.
625pub type AuthQueue = FixedVec<AuthorizerHash, AuthQueueLen>;
626
627/// A segment of data.
628pub type Segment = FixedVec<u8, SegmentLen>;
629// TODO: ^^^ Measure performance penalty for this not being 4096.
630
631pub trait ToAny {
632	type Any;
633	fn any(&self) -> Self::Any;
634	fn into_any(self) -> Self::Any;
635}
636
637impl ToAny for [u8; 32] {
638	type Any = AnyHash;
639	fn any(&self) -> Self::Any {
640		AnyHash(*self)
641	}
642	fn into_any(self) -> Self::Any {
643		AnyHash(self)
644	}
645}
646
647impl ToAny for alloc::vec::Vec<u8> {
648	type Any = AnyVec;
649	fn any(&self) -> Self::Any {
650		AnyVec(self.clone())
651	}
652	fn into_any(self) -> Self::Any {
653		AnyVec(self)
654	}
655}
656
657impl ToAny for &[u8] {
658	type Any = AnyVec;
659	fn any(&self) -> Self::Any {
660		AnyVec(self.to_vec())
661	}
662	fn into_any(self) -> Self::Any {
663		AnyVec(self.to_vec())
664	}
665}
666
667impl MaxEncodedLen for Authorization {
668	fn max_encoded_len() -> usize {
669		BoundedVec::<u8, MaxInput>::max_encoded_len()
670	}
671}
672
673impl MaxEncodedLen for WorkPayload {
674	fn max_encoded_len() -> usize {
675		BoundedVec::<u8, MaxInput>::max_encoded_len()
676	}
677}
678
679impl MaxEncodedLen for AuthConfig {
680	fn max_encoded_len() -> usize {
681		BoundedVec::<u8, MaxInput>::max_encoded_len()
682	}
683}
684
685impl MaxEncodedLen for AuthTrace {
686	fn max_encoded_len() -> usize {
687		BoundedVec::<u8, MaxReportElectiveData>::max_encoded_len()
688	}
689}
690
691impl AuthTrace {
692	pub fn leak(self) -> &'static [u8] {
693		self.0.leak()
694	}
695}
696
697impl MaxEncodedLen for WorkOutput {
698	fn max_encoded_len() -> usize {
699		BoundedVec::<u8, MaxReportElectiveData>::max_encoded_len()
700	}
701}
702
703impl WorkOutput {
704	pub fn leak(self) -> &'static [u8] {
705		self.0.leak()
706	}
707}