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;