jam_std_common/
simple.rs

1use super::{Extrinsic, Header};
2use codec::{Decode, Encode, MaxEncodedLen};
3use jam_types::{
4	max_export_segments, max_imports, opaque, segment_len, segment_slice_len, slot_period_sec,
5	Segment, WorkPackage, PROVEN_PER_SEGMENT, VALS_PER_CORE,
6};
7use std::time::Duration;
8
9/// Duration of a time slot, as a Rust-native `Duration`.
10pub fn slot_duration() -> Duration {
11	Duration::from_secs(slot_period_sec())
12}
13
14pub fn max_import_proof_size() -> usize {
15	// 6 hashes of page proof path + 6 hashes or segment tree path + 1 byte for size encoding
16	(PROVEN_PER_SEGMENT.next_power_of_two().ilog2() +
17		(max_imports() as usize)
18			.div_ceil(PROVEN_PER_SEGMENT)
19			.next_power_of_two()
20			.ilog2()) as usize *
21		32 + 1
22}
23
24/// The conservative maximum size of a Work Package Bundle.
25pub fn max_bundle_size() -> usize {
26	// Note that WorkPackage::max_encoded_len() includes max_input() so we don't need to explicitly
27	// include it here. This assumes a somewhat naive WorkPackage::max_encoded_len implementation,
28	// that doesn't eg account for the fact that if there are many import specs, some of the
29	// max_input() allowance will be used up by the imported segments. If
30	// WorkPackage::max_encoded_len is made less conservative, this function may need to be
31	// updated.
32	WorkPackage::max_encoded_len() + max_import_proof_size() * max_imports() as usize
33}
34
35/// Maximum basic size of a Work Package that we accept.
36/// This should be at least ImportSpec::encoded_fixed_size() * max_imports()
37pub const SANE_MAX_PACKAGE_SIZE: usize = 200 * 1024;
38
39/// The min. no. of signatures required for a guarantee to be valid.
40///
41/// Equals 2/3 of guarantors assigned to a core.
42pub const GUARANTEE_MIN_SIGNATURES: usize = (VALS_PER_CORE * 2).div_ceil(3);
43
44// Entropy required by some protocol's operations.
45opaque! { pub struct Entropy(pub [u8; 32]); }
46
47#[derive(Clone, Encode, Decode, Debug)]
48pub struct Block {
49	pub header: Header,
50	pub extrinsic: Extrinsic,
51}
52
53/// Type to represent the index of a tranche.
54pub type TrancheIndex = u8;
55
56/// Maximum size in bytes for a work package segments shard
57pub fn max_segment_slice_vec_bytes() -> u32 {
58	segment_slice_len() as u32 * max_export_segments()
59}
60
61/// Maximum size in bytes for a work package exported segments
62pub fn max_segment_vec_bytes() -> u32 {
63	segment_len() as u32 * max_export_segments()
64}
65
66/// Segment shard vector. Size is bound by the maximum number of segments a work package may
67/// export.
68#[derive(Clone, Debug, Default, Eq, PartialEq)]
69pub struct SegmentSliceVec(Vec<u8>);
70
71impl SegmentSliceVec {
72	/// Get raw byte buffer that contains all segments.
73	pub fn raw(&self) -> &[u8] {
74		&self.0
75	}
76
77	/// Get the underlying `Vec`.
78	pub fn into_inner(self) -> Vec<u8> {
79		self.0
80	}
81
82	/// Creates a slice vec from serialized bytes. Returns `None` if the size is incorrect.
83	pub fn from_bytes(data: Vec<u8>) -> Option<Self> {
84		if data.len() > segment_slice_len() * max_export_segments() as usize {
85			return None
86		}
87		if !data.len().is_multiple_of(segment_slice_len()) {
88			return None
89		}
90		Some(Self(data))
91	}
92
93	/// Preallocates a vec for the given number of slices
94	pub fn with_capacity(capacity: usize) -> Self {
95		Self(Vec::with_capacity(capacity * segment_slice_len()))
96	}
97
98	/// Returns the number of slices.
99	pub fn len(&self) -> usize {
100		self.0.len() / segment_slice_len()
101	}
102
103	/// Check if the vec is empty.
104	pub fn is_empty(&self) -> bool {
105		self.0.is_empty()
106	}
107
108	/// Appends a slice to this vec. Returns an error is the slice size is incorrect or if the vec
109	/// overflows
110	pub fn push(&mut self, slice: &[u8]) -> Result<(), &'static str> {
111		if slice.len() != segment_slice_len() {
112			return Err("Slice length does not match segment slice length")
113		}
114		if slice.len() + self.0.len() > max_segment_slice_vec_bytes() as usize {
115			return Err("Exceeded maximum segment slice vector size")
116		}
117		self.0.extend_from_slice(slice);
118		Ok(())
119	}
120
121	/// Adds a new empty slice to the vec and returns a reference to it. Produces an error if the
122	/// vec overflows.
123	pub fn push_default(&mut self) -> Result<&mut [u8], &'static str> {
124		if segment_slice_len() + self.0.len() > max_segment_slice_vec_bytes() as usize {
125			return Err("Exceeded maximum segment slice vector size")
126		}
127		let len = self.0.len();
128		self.0.resize(len + segment_slice_len(), 0u8);
129		Ok(&mut self.0[len..])
130	}
131}
132
133impl std::ops::Index<usize> for SegmentSliceVec {
134	type Output = [u8];
135	fn index(&self, index: usize) -> &Self::Output {
136		&self.0[index * segment_slice_len()..(index + 1) * segment_slice_len()]
137	}
138}
139
140pub type SegmentVec = Vec<Segment>;