1use super::{Extrinsic, Header};
2use codec::{Decode, Encode};
3use core::fmt;
4use jam_types::{
5 chain_params, max_exports, max_imports, max_input, opaque, val_count, Balance, CoreIndex,
6 FixedVec, SegmentSliceLen, Slot, UnsignedGas, ValIndex,
7};
8use std::{sync::atomic::Ordering::Relaxed, time::Duration};
9
10pub fn slot_duration() -> Duration {
12 Duration::from_nanos(slot_period_ns())
13}
14
15pub type TicketAttempt = u8;
17
18#[cfg(feature = "tiny")]
19mod defaults {
20 use super::{Slot, TicketAttempt};
21 pub(super) const EPOCH_PERIOD: Slot = 12;
22 pub(super) const EPOCH_TAIL_START: Slot = 10;
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 EPOCH_TAIL_START: Slot = 500;
32 pub(super) const ROTATION_PERIOD: Slot = 10;
33 pub(super) const MAX_TICKETS_PER_BLOCK: usize = 16;
34 pub(super) const TICKETS_ATTEMPTS_NUMBER: TicketAttempt = 2;
35}
36
37chain_params! {
38 static SLOT_PERIOD_NS : _ = _(6_000_000_000);
40 pub fn slot_period_ns() -> u64;
41
42 static ROTATION_PERIOD: _ = _(defaults::ROTATION_PERIOD);
44 pub fn rotation_period() -> Slot;
45 pub struct RotationPeriod; impl Get<_> for _ {}
46
47 static EPOCH_PERIOD: _ = _(defaults::EPOCH_PERIOD);
49 pub fn epoch_period() -> Slot;
50 pub struct EpochPeriod; impl Get<_> for _ {}
51
52 static EPOCH_TAIL_START: _ = _(defaults::EPOCH_TAIL_START);
54 pub fn epoch_tail_start() -> Slot;
55
56 static MAX_TICKETS_PER_BLOCK: _ = _(defaults::MAX_TICKETS_PER_BLOCK);
58 pub fn max_tickets_per_block() -> usize;
59 pub struct MaxTicketsPerBlock; impl Get<_> for _ {}
60
61 static TICKETS_ATTEMPTS_NUMBER: _ = _(defaults::TICKETS_ATTEMPTS_NUMBER);
68 pub fn tickets_attempts_number() -> TicketAttempt;
69
70 static DEPOSIT_PER_ACCOUNT: _ = _(100);
71 pub fn deposit_per_account() -> Balance;
72
73 static DEPOSIT_PER_ITEM: _ = _(10);
74 pub fn deposit_per_item() -> Balance;
75
76 static DEPOSIT_PER_BYTE: _ = _(1);
77 pub fn deposit_per_byte() -> Balance;
78
79 static BLOCK_GAS_LIMIT: _ = _(3_500_000_000);
83 pub fn block_gas_limit() -> UnsignedGas;
84
85 static MAX_IS_AUTHORIZED_GAS: _ = _(50_000_000);
87 pub fn max_is_authorized_gas() -> UnsignedGas;
88
89 static MAX_REFINE_GAS: _ = _(5_000_000_000);
91 pub fn max_refine_gas() -> UnsignedGas;
92
93 static MAX_ACCUMULATE_GAS: _ = _(10_000_000);
95 pub fn max_accumulate_gas() -> UnsignedGas;
96
97 static MAX_SERVICE_CODE_SIZE: _ = _(4_000_000);
98 pub fn max_service_code_size() -> usize;
99
100 static MAX_AUTHORIZER_CODE_SIZE: _ = _(64_000);
101 pub fn max_authorizer_code_size() -> usize;
102
103 static MAX_REFINE_MEMORY: _ = _(1024 * 1024 * 1024);
104 pub fn max_refine_memory() -> usize;
105
106 static MAX_IS_AUTHORIZED_MEMORY: _ = _(256 * 1024);
107 pub fn max_is_authorized_memory() -> usize;
108
109 static RECENT_BLOCK_COUNT: _ = _(8);
112 pub fn recent_block_count() -> Slot;
113 pub struct RecentBlockCount; impl Get<_> for _ {}
114
115 pub const VALS_PER_CORE: _ = 3;
117 pub fn vals_per_core() -> usize;
118 pub struct ValsPerCore; impl Get<_> for _ {}
119
120 pub fn core_count() -> CoreIndex {
122 (val_count() as usize / VALS_PER_CORE) as CoreIndex
123 }
124 pub struct CoreCount; impl Get<_> for _ {}
125
126 pub fn max_export_segments() -> u32 {
128 max_exports() + max_exports().div_ceil(PROVEN_PER_SEGMENT as u32)
129 }
130 pub struct MaxExportSegments; impl Get<_> for _ {}
131
132 pub fn max_import_segments() -> u32 { max_imports() * 2 }
135 pub struct MaxImportSegments; impl Get<_> for _ {}
136
137 static AVAILABILITY_TIMEOUT: _ = _(5);
139 pub fn availability_timeout() -> Slot;
140
141 static AUTH_WINDOW: _ = _(8);
143 pub fn auth_window() -> usize;
144 pub struct AuthWindow; impl Get<_> for _ {}
145
146 static MAX_LOOKUP_ANCHOR_AGE: _ = _(24 * 600);
148 pub fn max_lookup_anchor_age() -> Slot;
149}
150
151pub fn max_import_proof_size() -> usize {
152 (PROVEN_PER_SEGMENT.next_power_of_two().ilog2() +
154 (max_imports() as usize)
155 .div_ceil(PROVEN_PER_SEGMENT)
156 .next_power_of_two()
157 .ilog2()) as usize *
158 32 + 1
159}
160
161pub fn max_bundle_size() -> usize {
164 max_input() as usize + max_import_proof_size() * max_imports() as usize
165}
166
167#[derive(
169 Copy, Clone, Eq, PartialEq, Debug, Encode, Decode, serde::Serialize, serde::Deserialize,
170)]
171pub struct Parameters {
172 pub val_count: ValIndex,
174 pub basic_piece_len: u32,
176 pub auth_queue_len: u32,
178 pub min_turnaround_period: Slot,
181 pub max_work_items: u32,
183 pub max_imports: u32,
185 pub max_exports: u32,
187 pub max_extrinsics: u32,
189 pub max_dependencies: u32,
191 pub max_input: u32,
193
194 pub slot_period_ns: u64,
196 pub epoch_period: Slot,
198 pub epoch_tail_start: Slot,
200 pub rotation_period: Slot,
202 pub block_gas_limit: UnsignedGas,
204 pub recent_block_count: Slot,
206 pub max_tickets_per_block: u32,
208 pub tickets_attempts_number: TicketAttempt,
211 pub deposit_per_account: Balance,
213 pub deposit_per_item: Balance,
215 pub deposit_per_byte: Balance,
218 pub max_is_authorized_gas: UnsignedGas,
220 pub max_refine_gas: UnsignedGas,
222 pub max_accumulate_gas: UnsignedGas,
224 pub max_service_code_size: u32,
226 pub max_authorizer_code_size: u32,
228 pub max_refine_memory: u32,
230 pub max_is_authorized_memory: u32,
232 pub availability_timeout: Slot,
234 pub auth_window: u32,
236 pub max_lookup_anchor_age: Slot,
238}
239impl fmt::Display for Parameters {
240 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
241 write!(
242 f,
243 "\n\
244 val_count: {}\n\
245 basic_piece_len: {}\n\
246 auth_queue_len: {}\n\
247 min_turnaround_period: {}\n\
248 max_work_items: {}\n\
249 max_imports: {}\n\
250 max_exports: {}\n\
251 max_extrinsics: {}\n\
252 max_dependencies: {}\n\
253 max_input: {}\n\
254 slot_period_ns: {}\n\
255 epoch_period: {}\n\
256 epoch_tail_start: {}\n\
257 rotation_period: {}\n\
258 block_gas_limit: {}\n\
259 recent_block_count: {}\n\
260 max_tickets_per_block: {}\n\
261 tickets_attempts_number: {}\n\
262 deposit_per_account: {}\n\
263 deposit_per_item: {}\n\
264 deposit_per_byte: {}\n\
265 max_is_authorized_gas: {}\n\
266 max_refine_gas: {}\n\
267 max_accumulate_gas: {}\n\
268 max_service_code_size: {}\n\
269 max_authorizer_code_size: {}\n\
270 max_refine_memory: {}\n\
271 max_is_authorized_memory: {}\n\
272 availability_timeout: {}\n\
273 auth_window: {}\n\
274 max_lookup_anchor_age: {}\n\
275 ",
276 self.val_count,
277 self.basic_piece_len,
278 self.auth_queue_len,
279 self.min_turnaround_period,
280 self.max_work_items,
281 self.max_imports,
282 self.max_exports,
283 self.max_extrinsics,
284 self.max_dependencies,
285 self.max_input,
286 self.slot_period_ns,
287 self.epoch_period,
288 self.epoch_tail_start,
289 self.rotation_period,
290 self.block_gas_limit,
291 self.recent_block_count,
292 self.max_tickets_per_block,
293 self.tickets_attempts_number,
294 self.deposit_per_account,
295 self.deposit_per_item,
296 self.deposit_per_byte,
297 self.max_is_authorized_gas,
298 self.max_refine_gas,
299 self.max_accumulate_gas,
300 self.max_service_code_size,
301 self.max_authorizer_code_size,
302 self.max_refine_memory,
303 self.max_is_authorized_memory,
304 self.availability_timeout,
305 self.auth_window,
306 self.max_lookup_anchor_age,
307 )
308 }
309}
310
311impl Parameters {
312 pub fn tiny() -> Self {
313 Self {
314 val_count: 6,
315 basic_piece_len: 4,
316 auth_queue_len: 80,
317 min_turnaround_period: 28_800,
318 max_work_items: 16,
319 max_imports: 3072,
320 max_exports: 3072,
321 max_extrinsics: 128,
322 max_dependencies: 8,
323 max_input: 12 * 1024 * 1024,
324 slot_period_ns: 6_000_000_000,
325 epoch_period: 12,
326 epoch_tail_start: 10,
327 rotation_period: 4,
328 block_gas_limit: 20_000_000,
329 recent_block_count: 8,
330 max_tickets_per_block: 3,
331 tickets_attempts_number: 3,
332 deposit_per_account: 100,
333 deposit_per_item: 10,
334 deposit_per_byte: 1,
335 max_is_authorized_gas: 50_000_000,
336 max_refine_gas: 1_000_000_000,
337 max_accumulate_gas: 10_000_000,
338 max_service_code_size: 4_000_000,
339 max_authorizer_code_size: 64_000,
340 max_refine_memory: 1024 * 1024 * 1024,
341 max_is_authorized_memory: 256 * 1024,
342 availability_timeout: 5,
343 auth_window: 8,
344 max_lookup_anchor_age: 24 * 600,
345 }
346 }
347 pub fn full() -> Self {
348 Self {
349 val_count: 1023,
350 basic_piece_len: 684,
351 auth_queue_len: 80,
352 min_turnaround_period: 28_800,
353 max_work_items: 16,
354 max_imports: 3072,
355 max_exports: 3072,
356 max_extrinsics: 128,
357 max_dependencies: 8,
358 max_input: 12 * 1024 * 1024,
359 slot_period_ns: 6_000_000_000,
360 epoch_period: 600,
361 epoch_tail_start: 500,
362 rotation_period: 10,
363 block_gas_limit: 3_500_000_000,
364 recent_block_count: 8,
365 max_tickets_per_block: 16,
366 tickets_attempts_number: 2,
367 deposit_per_account: 100,
368 deposit_per_item: 10,
369 deposit_per_byte: 1,
370 max_is_authorized_gas: 50_000_000,
371 max_refine_gas: 5_000_000_000,
372 max_accumulate_gas: 10_000_000,
373 max_service_code_size: 4_000_000,
374 max_authorizer_code_size: 64_000,
375 max_refine_memory: 1024 * 1024 * 1024,
376 max_is_authorized_memory: 256 * 1024,
377 availability_timeout: 5,
378 auth_window: 8,
379 max_lookup_anchor_age: 24 * 600,
380 }
381 }
382 pub fn get() -> Self {
383 let jam_types::Parameters {
384 val_count,
385 basic_piece_len,
386 auth_queue_len,
387 min_turnaround_period,
388 max_work_items,
389 max_imports,
390 max_exports,
391 max_extrinsics,
392 max_dependencies,
393 max_input,
394 } = jam_types::Parameters::get();
395 Self {
396 val_count,
397 basic_piece_len,
398 auth_queue_len,
399 min_turnaround_period,
400 max_work_items,
401 max_imports,
402 max_exports,
403 max_extrinsics,
404 max_dependencies,
405 max_input,
406 slot_period_ns: SLOT_PERIOD_NS.load(Relaxed),
407 epoch_period: EPOCH_PERIOD.load(Relaxed),
408 epoch_tail_start: EPOCH_TAIL_START.load(Relaxed),
409 rotation_period: ROTATION_PERIOD.load(Relaxed),
410 block_gas_limit: BLOCK_GAS_LIMIT.load(Relaxed),
411 recent_block_count: RECENT_BLOCK_COUNT.load(Relaxed),
412 max_tickets_per_block: MAX_TICKETS_PER_BLOCK.load(Relaxed) as _,
413 tickets_attempts_number: TICKETS_ATTEMPTS_NUMBER.load(Relaxed),
414 deposit_per_account: DEPOSIT_PER_ACCOUNT.load(Relaxed),
415 deposit_per_item: DEPOSIT_PER_ITEM.load(Relaxed),
416 deposit_per_byte: DEPOSIT_PER_BYTE.load(Relaxed),
417 max_is_authorized_gas: MAX_IS_AUTHORIZED_GAS.load(Relaxed),
418 max_refine_gas: MAX_REFINE_GAS.load(Relaxed),
419 max_accumulate_gas: MAX_ACCUMULATE_GAS.load(Relaxed),
420 max_service_code_size: MAX_SERVICE_CODE_SIZE.load(Relaxed) as _,
421 max_authorizer_code_size: MAX_AUTHORIZER_CODE_SIZE.load(Relaxed) as _,
422 max_refine_memory: MAX_REFINE_MEMORY.load(Relaxed) as _,
423 max_is_authorized_memory: MAX_IS_AUTHORIZED_MEMORY.load(Relaxed) as _,
424 availability_timeout: AVAILABILITY_TIMEOUT.load(Relaxed),
425 auth_window: AUTH_WINDOW.load(Relaxed) as _,
426 max_lookup_anchor_age: MAX_LOOKUP_ANCHOR_AGE.load(Relaxed),
427 }
428 }
429 pub fn validate(self) -> Result<jam_types::Parameters, &'static str> {
430 let r = jam_types::Parameters {
431 val_count: self.val_count,
432 basic_piece_len: self.basic_piece_len,
433 auth_queue_len: self.auth_queue_len,
434 min_turnaround_period: self.min_turnaround_period,
435 max_work_items: self.max_work_items,
436 max_imports: self.max_imports,
437 max_exports: self.max_exports,
438 max_extrinsics: self.max_extrinsics,
439 max_dependencies: self.max_dependencies,
440 max_input: self.max_input,
441 };
442 r.validate()?;
443 if self.epoch_period % self.rotation_period != 0 {
444 return Err("`rotation_period` does not divide into `epoch_period`")
445 }
446 if self.epoch_tail_start >= self.epoch_period {
447 return Err("`epoch_tail_start` must be less than `epoch_period`")
448 }
449 if self.val_count as usize % VALS_PER_CORE != 0 {
450 return Err("`val_count` does not divide by `VALS_PER_CORE` (3)")
451 }
452 if recent_block_count() > 255 {
453 return Err("`recent_block_count` may be no larger than `BlockIndex::MAX` (255)")
454 }
455 Ok(r)
456 }
457 pub fn apply(self) -> Result<(), &'static str> {
458 let base = self.validate()?;
459 base.apply()?;
460 EPOCH_PERIOD.store(self.epoch_period, Relaxed);
461 EPOCH_TAIL_START.store(self.epoch_tail_start, Relaxed);
462 ROTATION_PERIOD.store(self.rotation_period, Relaxed);
463 BLOCK_GAS_LIMIT.store(self.block_gas_limit, Relaxed);
464 RECENT_BLOCK_COUNT.store(self.recent_block_count, Relaxed);
465 MAX_TICKETS_PER_BLOCK.store(self.max_tickets_per_block as _, Relaxed);
466 TICKETS_ATTEMPTS_NUMBER.store(self.tickets_attempts_number, Relaxed);
467 DEPOSIT_PER_ACCOUNT.store(self.deposit_per_account, Relaxed);
468 DEPOSIT_PER_ITEM.store(self.deposit_per_item, Relaxed);
469 DEPOSIT_PER_BYTE.store(self.deposit_per_byte, Relaxed);
470 MAX_IS_AUTHORIZED_GAS.store(self.max_is_authorized_gas, Relaxed);
471 MAX_REFINE_GAS.store(self.max_refine_gas, Relaxed);
472 MAX_ACCUMULATE_GAS.store(self.max_accumulate_gas, Relaxed);
473 MAX_SERVICE_CODE_SIZE.store(self.max_service_code_size as _, Relaxed);
474 MAX_AUTHORIZER_CODE_SIZE.store(self.max_authorizer_code_size as _, Relaxed);
475 MAX_REFINE_MEMORY.store(self.max_refine_memory as _, Relaxed);
476 MAX_IS_AUTHORIZED_MEMORY.store(self.max_is_authorized_memory as _, Relaxed);
477 RECENT_BLOCK_COUNT.store(self.recent_block_count, Relaxed);
478 AVAILABILITY_TIMEOUT.store(self.availability_timeout, Relaxed);
479 AUTH_WINDOW.store(self.auth_window as _, Relaxed);
480 MAX_LOOKUP_ANCHOR_AGE.store(self.max_lookup_anchor_age, Relaxed);
481 Ok(())
482 }
483}
484
485pub const SANE_MAX_PACKAGE_SIZE: usize = 200 * 1024;
488
489pub const MAX_REPORT_ELECTIVE_DATA: usize = 48 * 1024;
493
494pub const GUARANTEE_MIN_SIGNATURES: usize = (VALS_PER_CORE * 2).div_ceil(3);
498
499opaque! { pub struct Entropy(pub [u8; 32]); }
501
502#[derive(Clone, Encode, Decode, Debug)]
503pub struct Block {
504 pub header: Header,
505 pub extrinsic: Extrinsic,
506}
507
508pub const SUFFIX_SKIP_LEN: usize = 6;
512
513pub const PROVEN_PER_SEGMENT: usize = 1 << SUFFIX_SKIP_LEN;
521
522pub type SegmentSlice = FixedVec<u8, SegmentSliceLen>;
523
524pub type TrancheIndex = u8;