jam_std_common/
state.rs

1use crate::{
2	deposit_per_account, deposit_per_byte, deposit_per_item, hash_encoded, hash_raw_concat,
3	simple::AuthWindow, CoreCount, Entropy, EpochPeriod, Mmr, RecentBlockCount, WorkReport,
4};
5use bounded_collections::ConstU32;
6use codec::{Decode, Encode};
7use jam_types::{
8	opaque, AuthQueue, AuthorizerHash, Balance, BoundedVec, CodeHash, FixedVec, HeaderHash,
9	SegmentTreeRoot, ServiceId, ServiceInfo, Slot, StateRootHash, UnsignedGas, VecMap, VecSet,
10	WorkPackageHash, WorkReportHash,
11};
12
13opaque! {
14	pub struct StorageKey(pub [u8; 31]);
15}
16
17#[derive(Debug, Encode, Decode, Copy, Clone, Eq, PartialEq)]
18pub enum SystemKey {
19	Reserved0 = 0,
20	AuthPools = 1,
21	AuthQueues = 2,
22	RecentBlocks = 3,
23	Safrole = 4,
24	Disputes = 5,
25	Entropy = 6,
26	Designates = 7,
27	Validators = 8,
28	PrevValidators = 9,
29	Availability = 10,
30	CurrentTime = 11,
31	Privileges = 12,
32	Statistics = 13,
33	ReadyQueue = 14,
34	Accumulated = 15,
35}
36
37impl From<SystemKey> for StorageKey {
38	fn from(value: SystemKey) -> Self {
39		let k = value.encode();
40		let mut r = [0; StorageKey::LEN];
41		r[..k.len()].copy_from_slice(&k[..]);
42		r.into()
43	}
44}
45
46impl IntoStorageKey for SystemKey {}
47
48impl IntoStorageKey for StorageKey {}
49
50#[derive(Clone)]
51pub enum ServiceKey<'a> {
52	Info { id: ServiceId },
53	Value { id: ServiceId, key: &'a [u8] },
54	Request { id: ServiceId, len: u32, hash: [u8; 32] },
55	Preimage { id: ServiceId, hash: [u8; 32] },
56}
57
58pub trait IntoStorageKey: Into<StorageKey> {
59	fn service_id(&self) -> Option<ServiceId> {
60		None
61	}
62}
63
64impl IntoStorageKey for ServiceKey<'_> {
65	fn service_id(&self) -> Option<ServiceId> {
66		Some(match self {
67			Self::Info { id, .. } |
68			Self::Value { id, .. } |
69			Self::Request { id, .. } |
70			Self::Preimage { id, .. } => *id,
71		})
72	}
73}
74
75impl<'a> From<ServiceKey<'a>> for StorageKey {
76	fn from(k: ServiceKey<'a>) -> Self {
77		use ServiceKey::*;
78		let id = match k {
79			Info { id } | Value { id, .. } | Request { id, .. } | Preimage { id, .. } => id,
80		}
81		.to_le_bytes();
82		let mut r = [0; StorageKey::LEN];
83		let hash = match k {
84			Info { .. } => {
85				r[0] = 255;
86				r[1] = id[0];
87				r[3] = id[1];
88				r[5] = id[2];
89				r[7] = id[3];
90				return r.into();
91			},
92			Value { id, key } => {
93				let mut hash = hash_raw_concat([&id.to_le_bytes()[..], key]);
94				hash.copy_within(0..28, 4);
95				hash[..4].copy_from_slice(&[0xff, 0xff, 0xff, 0xff]);
96				hash
97			},
98			Preimage { mut hash, .. } => {
99				hash.copy_within(1..29, 4);
100				hash[..4].copy_from_slice(&[0xfe, 0xff, 0xff, 0xff]);
101				hash
102			},
103			Request { len, hash, .. } => {
104				let mut hash = hash_encoded(&hash);
105				hash.copy_within(2..30, 4);
106				hash[..4].copy_from_slice(&len.to_le_bytes());
107				hash
108			},
109		};
110		r[..8].copy_from_slice(&[id[0], hash[0], id[1], hash[1], id[2], hash[2], id[3], hash[3]]);
111		r[8..].copy_from_slice(&hash[4..27]);
112		r.into()
113	}
114}
115
116#[derive(Debug, Clone, Encode, Decode)]
117pub struct Service {
118	/// The hash of the code of the service.
119	pub code_hash: CodeHash,
120	/// The existing balance of the service.
121	pub balance: Balance,
122	/// The minimum amount of gas which must be provided to this service's `accumulate` for each
123	/// work item it must process.
124	pub min_item_gas: UnsignedGas,
125	/// The minimum amount of gas which must be provided to this service's `on_transfer` for each
126	/// memo (i.e. transfer receipt) it must process.
127	pub min_memo_gas: UnsignedGas,
128	/// The total number of bytes used for data electively held for this service on-chain.
129	pub bytes: u64,
130	/// The total number of items of data electively held for this service on-chain.
131	pub items: u32,
132}
133
134impl From<Service> for ServiceInfo {
135	fn from(service: Service) -> Self {
136		ServiceInfo {
137			code_hash: service.code_hash,
138			balance: service.balance,
139			min_item_gas: service.min_item_gas,
140			min_memo_gas: service.min_memo_gas,
141			bytes: service.bytes,
142			items: service.items,
143			threshold: service.threshold(),
144		}
145	}
146}
147
148impl Service {
149	pub fn threshold(&self) -> Balance {
150		Self::deposit_required(self.items, self.bytes)
151	}
152	pub fn free(&self) -> Balance {
153		self.balance.saturating_sub(self.threshold())
154	}
155	pub fn deposit_required(items: u32, bytes: u64) -> u64 {
156		items as u64 * deposit_per_item() + bytes * deposit_per_byte() + deposit_per_account()
157	}
158}
159
160pub type AuthPool = BoundedVec<AuthorizerHash, AuthWindow>;
161pub type AuthPools = FixedVec<AuthPool, CoreCount>;
162pub type AuthQueues = FixedVec<AuthQueue, CoreCount>;
163
164/// Block information.
165#[derive(Debug, Encode, Decode, Eq, PartialEq, Clone)]
166pub struct BlockInfo {
167	/// Header hash.
168	pub hash: HeaderHash,
169	/// Accumulation result MMR.
170	pub beefy_mmr: Mmr,
171	/// Posterior state root.
172	pub state_root: StateRootHash,
173	/// Hash of each work report made into the block which is no more than the
174	/// number of cores.
175	pub reported: VecMap<WorkPackageHash, SegmentTreeRoot>,
176}
177
178#[derive(Debug, Encode, Decode, Eq, PartialEq, Clone)]
179pub struct AvailabilityAssignment {
180	/// Work report.
181	pub report: WorkReport,
182	/// Timeslot when `report` has been reported.
183	pub report_slot: Slot,
184}
185
186#[derive(Clone, Encode, Decode, Debug, Eq, PartialEq, Default)]
187pub struct Privileges {
188	/// The service index with the ability to alter the privileges.
189	pub bless: ServiceId,
190	/// The service index with the ability to assign authorizors to cores.
191	pub assign: ServiceId,
192	/// The service index with the ability to set the validator keys.
193	pub designate: ServiceId,
194	/// The services which always accumulate, together with their free gas.
195	pub always_acc: VecMap<ServiceId, UnsignedGas>,
196}
197
198#[derive(Clone, Encode, Decode, Debug, Eq, PartialEq, Default)]
199pub struct Disputes {
200	/// The allow-set of work-reports, these are known to be good.
201	pub good: VecSet<WorkReportHash>,
202	/// The corrupt-set of work-reports, these are known to be bad.
203	pub bad: VecSet<WorkReportHash>,
204	/// The ban-set of work-reports, these have been determined of uncertain validity.
205	pub wonky: VecSet<WorkReportHash>,
206	/// The offenders' Ed25519 keys, these are known to have incorrectly judged a work-report's
207	/// validity.
208	pub offenders: VecSet<super::ed25519::Public>,
209}
210
211#[derive(Clone, Encode, Decode, Debug, Eq, PartialEq, Default)]
212pub struct ValActivityRecord {
213	// The number of blocks produced by the validator.
214	pub blocks: u32,
215	// The number of tickets introduced by the validator.
216	pub tickets: u32,
217	// The number of preimages introduced by the validator.
218	pub preimages: u32,
219	// The total number of octets across all preimages introduced by the validator.
220	pub preimages_size: u32,
221	// The number of reports guaranteed by the validator.
222	pub guarantees: u32,
223	// The number of availability assurances made by the validator.
224	pub assurances: u32,
225}
226
227#[derive(Clone, Encode, Decode, Debug, Eq, PartialEq, Default)]
228pub struct ServiceActivityRecord {
229	/// Number of preimages provided to this service.
230	#[codec(compact)]
231	pub provided_count: u16,
232	/// Total size of preimages provided to this service.
233	#[codec(compact)]
234	pub provided_size: u32,
235	/// Number of work-items refined by service for reported work.
236	#[codec(compact)]
237	pub refinement_count: u32,
238	/// Amount of gas used for refinement by service for reported work.
239	#[codec(compact)]
240	pub refinement_gas_used: UnsignedGas,
241	/// Number of segments imported from the DL by service for reported work.
242	#[codec(compact)]
243	pub imports: u32,
244	/// Number of segments exported into the DL by service for reported work.
245	#[codec(compact)]
246	pub exports: u32,
247	/// Total size of extrinsics used by service for reported work.
248	#[codec(compact)]
249	pub extrinsic_size: u32,
250	/// Total number of extrinsics used by service for reported work.
251	#[codec(compact)]
252	pub extrinsic_count: u32,
253	/// Number of work-items accumulated by service.
254	#[codec(compact)]
255	pub accumulate_count: u32,
256	/// Amount of gas used for accumulation by service.
257	#[codec(compact)]
258	pub accumulate_gas_used: UnsignedGas,
259	/// Number of transfers processed by service.
260	#[codec(compact)]
261	pub on_transfers_count: u32,
262	/// Amount of gas used for processing transfers by service.
263	#[codec(compact)]
264	pub on_transfers_gas_used: UnsignedGas,
265}
266
267#[derive(Clone, Encode, Decode, Debug, Eq, PartialEq, Default)]
268pub struct CoreActivityRecord {
269	// Assurances coming in from general validators (but ultimately provided by guarantors)
270	/// Amount of bytes which are placed into either Audits or Segments DA.
271	/// This includes the work-bundle (including all extrinsics and imports) as well as all
272	/// (exported) segments.
273	#[codec(compact)]
274	pub da_load: u32,
275	/// Number of validators which formed super-majority for assurance.
276	#[codec(compact)]
277	pub popularity: u16,
278	/// Number of segments imported from DA made by core for reported work.
279	#[codec(compact)]
280	pub imports: u16,
281	/// Number of segments exported into DA made by core for reported work.
282	#[codec(compact)]
283	pub exports: u16,
284	/// Total size of extrinsics used by core for reported work.
285	#[codec(compact)]
286	pub extrinsic_size: u32,
287	/// Total number of extrinsics used by core for reported work.
288	#[codec(compact)]
289	pub extrinsic_count: u16,
290	/// The work-bundle size. This is the size of data being placed into Audits DA by the core.
291	#[codec(compact)]
292	pub bundle_size: u32,
293	// Reports coming in from guarantors
294	/// Total gas consumed by core for reported work. Includes all refinement and authorizations.
295	#[codec(compact)]
296	pub gas_used: UnsignedGas,
297}
298
299pub type ValidatorsStats = FixedVec<ValActivityRecord, jam_types::ValCount>;
300pub type CoresStats = FixedVec<CoreActivityRecord, CoreCount>;
301pub type ServicesStats = VecMap<ServiceId, ServiceActivityRecord>;
302
303#[derive(Clone, Encode, Decode, Debug, Eq, PartialEq, Default)]
304pub struct Statistics {
305	pub vals_curr: ValidatorsStats,
306	pub vals_last: ValidatorsStats,
307	pub cores: CoresStats,
308	pub services: ServicesStats,
309}
310
311impl Statistics {
312	/// Reset the two accumulators.
313	pub fn reset(&mut self) {
314		self.cores = Default::default();
315		self.services = Default::default();
316	}
317}
318
319/// Entries relative to epoch `N`
320/// `[0]`: epoch `N` entropy accumulator. Updated on each block with fresh entropy.
321/// `[i]`, for 1 ≤ i ≤ 3: accumulator snapshot at the begin of epoch  `N-i+1`.
322/// If `N-i+1 < 0` then the corresponding entry is set to some fixed default value.
323pub type EntropyBuffer = FixedVec<Entropy, ConstU32<4>>;
324
325pub type RecentBlocks = BoundedVec<BlockInfo, RecentBlockCount>;
326
327pub type AvailabilityAssignments = FixedVec<Option<AvailabilityAssignment>, CoreCount>;
328
329#[derive(Clone, Encode, Decode, Debug, Eq, PartialEq)]
330pub struct ReadyRecord {
331	pub report: WorkReport,
332	pub deps: VecSet<WorkPackageHash>,
333}
334pub type ReadyQueue = FixedVec<Vec<ReadyRecord>, EpochPeriod>;
335pub type Accumulated = FixedVec<Vec<WorkPackageHash>, EpochPeriod>;