jam_std_common/
state.rs

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