1use super::{Extrinsic, Header};
2use core::fmt;
3use jam_types::{
4	chain_params, max_exports, max_imports, max_input, opaque, val_count, Balance, CoreIndex,
5	FixedVec, SegmentSliceLen, Slot, UnsignedGas, ValIndex,
6};
7use scale::{Decode, Encode};
8use std::{sync::atomic::Ordering::Relaxed, time::Duration};
9
10pub const SLOT_PERIOD_IN_NS: u64 = 6_000_000_000;
12
13pub const SLOT_PERIOD: Duration = Duration::from_nanos(SLOT_PERIOD_IN_NS);
15
16pub type TicketAttempt = u8;
18
19#[cfg(feature = "tiny")]
20mod defaults {
21	use super::{Slot, TicketAttempt};
22	pub(super) const EPOCH_PERIOD: Slot = 12;
23	pub(super) const ROTATION_PERIOD: Slot = 4;
24	pub(super) const MAX_TICKETS_PER_BLOCK: usize = 3;
25	pub(super) const TICKETS_ATTEMPTS_NUMBER: TicketAttempt = 3;
26}
27#[cfg(not(feature = "tiny"))]
28mod defaults {
29	use super::{Slot, TicketAttempt};
30	pub(super) const EPOCH_PERIOD: Slot = 600;
31	pub(super) const ROTATION_PERIOD: Slot = 10;
32	pub(super) const MAX_TICKETS_PER_BLOCK: usize = 16;
33	pub(super) const TICKETS_ATTEMPTS_NUMBER: TicketAttempt = 2;
34}
35
36chain_params! {
37	static ROTATION_PERIOD: _ = _(defaults::ROTATION_PERIOD);
39	pub fn rotation_period() -> Slot;
40	pub struct RotationPeriod; impl Get<_> for _ {}
41
42	static EPOCH_PERIOD: _ = _(defaults::EPOCH_PERIOD);
44	pub fn epoch_period() -> Slot;
45	pub struct EpochPeriod; impl Get<_> for _ {}
46
47	static MAX_TICKETS_PER_BLOCK: _ = _(defaults::MAX_TICKETS_PER_BLOCK);
49	pub fn max_tickets_per_block() -> usize;
50	pub struct MaxTicketsPerBlock; impl Get<_> for _ {}
51
52	static TICKETS_ATTEMPTS_NUMBER: _ = _(defaults::TICKETS_ATTEMPTS_NUMBER);
59	pub fn tickets_attempts_number() -> TicketAttempt;
60
61	static DEPOSIT_PER_ACCOUNT: _ = _(100);
62	pub fn deposit_per_account() -> Balance;
63
64	static DEPOSIT_PER_ITEM: _ = _(10);
65	pub fn deposit_per_item() -> Balance;
66
67	static DEPOSIT_PER_BYTE: _ = _(1);
68	pub fn deposit_per_byte() -> Balance;
69
70	static BLOCK_GAS_LIMIT: _ = _(3_500_000_000);
74	pub fn block_gas_limit() -> UnsignedGas;
75
76	static MAX_IS_AUTHORIZED_GAS: _ = _(50_000_000);
78	pub fn max_is_authorized_gas() -> UnsignedGas;
79
80	static MAX_REFINE_GAS: _ = _(5_000_000_000);
82	pub fn max_refine_gas() -> UnsignedGas;
83
84	static MAX_ACCUMULATE_GAS: _ = _(10_000_000);
86	pub fn max_accumulate_gas() -> UnsignedGas;
87
88	static MAX_REFINE_CODE_SIZE: _ = _(10 * 1024 * 1024);
89	pub fn max_refine_code_size() -> usize;
90
91	static MAX_IS_AUTHORIZED_CODE_SIZE: _ = _(64 * 1024);
92	pub fn max_is_authorized_code_size() -> usize;
93
94	static MAX_REFINE_MEMORY: _ = _(1024 * 1024 * 1024);
95	pub fn max_refine_memory() -> usize;
96
97	static MAX_IS_AUTHORIZED_MEMORY: _ = _(256 * 1024);
98	pub fn max_is_authorized_memory() -> usize;
99
100	static RECENT_BLOCK_COUNT: _ = _(8);
103	pub fn recent_block_count() -> Slot;
104	pub struct RecentBlockCount; impl Get<_> for _ {}
105
106	pub const VALS_PER_CORE: _ = 3;
108	pub fn vals_per_core() -> usize;
109	pub struct ValsPerCore; impl Get<_> for _ {}
110
111	pub fn core_count() -> CoreIndex {
113		(val_count() as usize / VALS_PER_CORE) as CoreIndex
114	}
115	pub struct CoreCount; impl Get<_> for _ {}
116
117	pub fn max_export_segments() -> u32 {
119		max_exports() + max_exports().div_ceil(PROVEN_PER_SEGMENT as u32)
120	}
121	pub struct MaxExportSegments; impl Get<_> for _ {}
122
123	pub fn max_import_segments() -> u32 { max_imports() * 2 }
126	pub struct MaxImportSegments; impl Get<_> for _ {}
127
128	static AVAILABILITY_TIMEOUT: _ = _(5);
130	pub fn availability_timeout() -> Slot;
131
132	static AUTH_WINDOW: _ = _(8);
134	pub fn auth_window() -> usize;
135	pub struct AuthWindow; impl Get<_> for _ {}
136
137	static MAX_LOOKUP_ANCHOR_AGE: _ = _(24 * 600);
139	pub fn max_lookup_anchor_age() -> Slot;
140}
141
142pub fn max_bundle_size() -> usize {
145	max_input() as usize + 1024 * 1024
146}
147
148#[derive(
150	Copy, Clone, Eq, PartialEq, Debug, Encode, Decode, serde::Serialize, serde::Deserialize,
151)]
152pub struct Parameters {
153	pub val_count: ValIndex,
155	pub basic_piece_len: u32,
157	pub auth_queue_len: u32,
159	pub min_turnaround_period: Slot,
162	pub max_work_items: u32,
164	pub max_imports: u32,
166	pub max_exports: u32,
168	pub max_extrinsics: u32,
170	pub max_dependencies: u32,
172	pub max_input: u32,
174
175	pub epoch_period: Slot,
177	pub rotation_period: Slot,
179	pub block_gas_limit: UnsignedGas,
181	pub recent_block_count: Slot,
183	pub max_tickets_per_block: u32,
185	pub tickets_attempts_number: TicketAttempt,
188	pub deposit_per_account: Balance,
190	pub deposit_per_item: Balance,
192	pub deposit_per_byte: Balance,
195	pub max_is_authorized_gas: UnsignedGas,
197	pub max_refine_gas: UnsignedGas,
199	pub max_accumulate_gas: UnsignedGas,
201	pub max_refine_code_size: u32,
203	pub max_is_authorized_code_size: u32,
205	pub max_refine_memory: u32,
207	pub max_is_authorized_memory: u32,
209	pub availability_timeout: Slot,
211	pub auth_window: u32,
213	pub max_lookup_anchor_age: Slot,
215}
216impl fmt::Display for Parameters {
217	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218		write!(
219			f,
220			"\n\
221			val_count: {}\n\
222			basic_piece_len: {}\n\
223			auth_queue_len: {}\n\
224			min_turnaround_period: {}\n\
225			max_work_items: {}\n\
226			max_imports: {}\n\
227			max_exports: {}\n\
228			max_extrinsics: {}\n\
229			max_dependencies: {}\n\
230			max_input: {}\n\
231			epoch_period: {}\n\
232			rotation_period: {}\n\
233			block_gas_limit: {}\n\
234			recent_block_count: {}\n\
235			max_tickets_per_block: {}\n\
236			tickets_attempts_number: {}\n\
237			deposit_per_account: {}\n\
238			deposit_per_item: {}\n\
239			deposit_per_byte: {}\n\
240			max_is_authorized_gas: {}\n\
241			max_refine_gas: {}\n\
242			max_accumulate_gas: {}\n\
243			max_refine_code_size: {}\n\
244			max_is_authorized_code_size: {}\n\
245			max_refine_memory: {}\n\
246			max_is_authorized_memory: {}\n\
247			availability_timeout: {}\n\
248			auth_window: {}\n\
249			max_lookup_anchor_age: {}\n\
250			",
251			self.val_count,
252			self.basic_piece_len,
253			self.auth_queue_len,
254			self.min_turnaround_period,
255			self.max_work_items,
256			self.max_imports,
257			self.max_exports,
258			self.max_extrinsics,
259			self.max_dependencies,
260			self.max_input,
261			self.epoch_period,
262			self.rotation_period,
263			self.block_gas_limit,
264			self.recent_block_count,
265			self.max_tickets_per_block,
266			self.tickets_attempts_number,
267			self.deposit_per_account,
268			self.deposit_per_item,
269			self.deposit_per_byte,
270			self.max_is_authorized_gas,
271			self.max_refine_gas,
272			self.max_accumulate_gas,
273			self.max_refine_code_size,
274			self.max_is_authorized_code_size,
275			self.max_refine_memory,
276			self.max_is_authorized_memory,
277			self.availability_timeout,
278			self.auth_window,
279			self.max_lookup_anchor_age,
280		)
281	}
282}
283
284impl Parameters {
285	pub fn tiny() -> Self {
286		Self {
287			val_count: 6,
288			basic_piece_len: 4,
289			auth_queue_len: 80,
290			min_turnaround_period: 28_800,
291			max_work_items: 16,
292			max_imports: 3072,
293			max_exports: 3072,
294			max_extrinsics: 128,
295			max_dependencies: 8,
296			max_input: 12 * 1024 * 1024,
297			epoch_period: 12,
298			rotation_period: 4,
299			block_gas_limit: 20_000_000,
300			recent_block_count: 8,
301			max_tickets_per_block: 3,
302			tickets_attempts_number: 3,
303			deposit_per_account: 100,
304			deposit_per_item: 10,
305			deposit_per_byte: 1,
306			max_is_authorized_gas: 50_000_000,
307			max_refine_gas: 1_600_000_000,
308			max_accumulate_gas: 10_000_000,
309			max_refine_code_size: 10 * 1024 * 1024,
310			max_is_authorized_code_size: 64 * 1024,
311			max_refine_memory: 1024 * 1024 * 1024,
312			max_is_authorized_memory: 256 * 1024,
313			availability_timeout: 5,
314			auth_window: 8,
315			max_lookup_anchor_age: 24 * 600,
316		}
317	}
318	pub fn full() -> Self {
319		Self {
320			val_count: 1023,
321			basic_piece_len: 684,
322			auth_queue_len: 80,
323			min_turnaround_period: 28_800,
324			max_work_items: 16,
325			max_imports: 3072,
326			max_exports: 3072,
327			max_extrinsics: 128,
328			max_dependencies: 8,
329			max_input: 12 * 1024 * 1024,
330			epoch_period: 600,
331			rotation_period: 10,
332			block_gas_limit: 3_500_000_000,
333			recent_block_count: 8,
334			max_tickets_per_block: 16,
335			tickets_attempts_number: 2,
336			deposit_per_account: 100,
337			deposit_per_item: 10,
338			deposit_per_byte: 1,
339			max_is_authorized_gas: 50_000_000,
340			max_refine_gas: 5_000_000_000,
341			max_accumulate_gas: 10_000_000,
342			max_refine_code_size: 10 * 1024 * 1024,
343			max_is_authorized_code_size: 64 * 1024,
344			max_refine_memory: 1024 * 1024 * 1024,
345			max_is_authorized_memory: 256 * 1024,
346			availability_timeout: 5,
347			auth_window: 8,
348			max_lookup_anchor_age: 24 * 600,
349		}
350	}
351	pub fn get() -> Self {
352		let jam_types::Parameters {
353			val_count,
354			basic_piece_len,
355			auth_queue_len,
356			min_turnaround_period,
357			max_work_items,
358			max_imports,
359			max_exports,
360			max_extrinsics,
361			max_dependencies,
362			max_input,
363		} = jam_types::Parameters::get();
364		Self {
365			val_count,
366			basic_piece_len,
367			auth_queue_len,
368			min_turnaround_period,
369			max_work_items,
370			max_imports,
371			max_exports,
372			max_extrinsics,
373			max_dependencies,
374			max_input,
375			epoch_period: EPOCH_PERIOD.load(Relaxed),
376			rotation_period: ROTATION_PERIOD.load(Relaxed),
377			block_gas_limit: BLOCK_GAS_LIMIT.load(Relaxed),
378			recent_block_count: RECENT_BLOCK_COUNT.load(Relaxed),
379			max_tickets_per_block: MAX_TICKETS_PER_BLOCK.load(Relaxed) as _,
380			tickets_attempts_number: TICKETS_ATTEMPTS_NUMBER.load(Relaxed),
381			deposit_per_account: DEPOSIT_PER_ACCOUNT.load(Relaxed),
382			deposit_per_item: DEPOSIT_PER_ITEM.load(Relaxed),
383			deposit_per_byte: DEPOSIT_PER_BYTE.load(Relaxed),
384			max_is_authorized_gas: MAX_IS_AUTHORIZED_GAS.load(Relaxed),
385			max_refine_gas: MAX_REFINE_GAS.load(Relaxed),
386			max_accumulate_gas: MAX_ACCUMULATE_GAS.load(Relaxed),
387			max_refine_code_size: MAX_REFINE_CODE_SIZE.load(Relaxed) as _,
388			max_is_authorized_code_size: MAX_IS_AUTHORIZED_CODE_SIZE.load(Relaxed) as _,
389			max_refine_memory: MAX_REFINE_MEMORY.load(Relaxed) as _,
390			max_is_authorized_memory: MAX_IS_AUTHORIZED_MEMORY.load(Relaxed) as _,
391			availability_timeout: AVAILABILITY_TIMEOUT.load(Relaxed),
392			auth_window: AUTH_WINDOW.load(Relaxed) as _,
393			max_lookup_anchor_age: MAX_LOOKUP_ANCHOR_AGE.load(Relaxed),
394		}
395	}
396	pub fn validate(self) -> Result<jam_types::Parameters, &'static str> {
397		let r = jam_types::Parameters {
398			val_count: self.val_count,
399			basic_piece_len: self.basic_piece_len,
400			auth_queue_len: self.auth_queue_len,
401			min_turnaround_period: self.min_turnaround_period,
402			max_work_items: self.max_work_items,
403			max_imports: self.max_imports,
404			max_exports: self.max_exports,
405			max_extrinsics: self.max_extrinsics,
406			max_dependencies: self.max_dependencies,
407			max_input: self.max_input,
408		};
409		r.validate()?;
410		if self.epoch_period % self.rotation_period != 0 {
411			return Err("`rotation_period` does not divide into `epoch_period`")
412		}
413		if self.val_count as usize % VALS_PER_CORE != 0 {
414			return Err("`val_count` does not divide by `VALS_PER_CORE` (3)")
415		}
416		if recent_block_count() > 255 {
417			return Err("`recent_block_count` may be no larger than `BlockIndex::MAX` (255)")
418		}
419		Ok(r)
420	}
421	pub fn apply(self) -> Result<(), &'static str> {
422		let base = self.validate()?;
423		base.apply()?;
424		EPOCH_PERIOD.store(self.epoch_period, Relaxed);
425		ROTATION_PERIOD.store(self.rotation_period, Relaxed);
426		BLOCK_GAS_LIMIT.store(self.block_gas_limit, Relaxed);
427		RECENT_BLOCK_COUNT.store(self.recent_block_count, Relaxed);
428		MAX_TICKETS_PER_BLOCK.store(self.max_tickets_per_block as _, Relaxed);
429		TICKETS_ATTEMPTS_NUMBER.store(self.tickets_attempts_number, Relaxed);
430		DEPOSIT_PER_ACCOUNT.store(self.deposit_per_account, Relaxed);
431		DEPOSIT_PER_ITEM.store(self.deposit_per_item, Relaxed);
432		DEPOSIT_PER_BYTE.store(self.deposit_per_byte, Relaxed);
433		MAX_IS_AUTHORIZED_GAS.store(self.max_is_authorized_gas, Relaxed);
434		MAX_REFINE_GAS.store(self.max_refine_gas, Relaxed);
435		MAX_ACCUMULATE_GAS.store(self.max_accumulate_gas, Relaxed);
436		MAX_REFINE_CODE_SIZE.store(self.max_refine_code_size as _, Relaxed);
437		MAX_IS_AUTHORIZED_CODE_SIZE.store(self.max_is_authorized_code_size as _, Relaxed);
438		MAX_REFINE_MEMORY.store(self.max_refine_memory as _, Relaxed);
439		MAX_IS_AUTHORIZED_MEMORY.store(self.max_is_authorized_memory as _, Relaxed);
440		RECENT_BLOCK_COUNT.store(self.recent_block_count, Relaxed);
441		AVAILABILITY_TIMEOUT.store(self.availability_timeout, Relaxed);
442		AUTH_WINDOW.store(self.auth_window as _, Relaxed);
443		MAX_LOOKUP_ANCHOR_AGE.store(self.max_lookup_anchor_age, Relaxed);
444		Ok(())
445	}
446}
447
448pub const SANE_MAX_PACKAGE_SIZE: usize = 100 * 1024;
450
451pub const MAX_REPORT_ELECTIVE_DATA: usize = 48 * 1024;
455
456pub const GUARANTEE_MIN_SIGNATURES: usize = (VALS_PER_CORE * 2).div_ceil(3);
460
461opaque! { pub struct Entropy(pub [u8; 32]); }
463
464#[derive(Clone, Encode, Decode, Debug)]
465pub struct Block {
466	pub header: Header,
467	pub extrinsic: Extrinsic,
468}
469
470pub const SUFFIX_SKIP_LEN: usize = 6;
474
475pub const PROVEN_PER_SEGMENT: usize = 1 << SUFFIX_SKIP_LEN;
483
484pub type SegmentSlice = FixedVec<u8, SegmentSliceLen>;
485
486pub type TrancheIndex = u8;