Skip to main content

jam_std_common/
telemetry.rs

1use crate::{
2	AvailabilityStatement, Block, BoundedString, EpochIndex, ErasureRoot, ImmutableWorkPackage,
3	PeerAddr, PeerDetails, PeerId, ReportGuarantee, TicketId, WorkReport,
4};
5use bounded_collections::{BoundedVec, ConstU32, Get, TryCollect};
6use codec::{Decode, Encode, MaxEncodedLen};
7use jam_types::{
8	CoreCount, CoreIndex, FixedVec, Hash, HeaderHash, ImportSpec, JAM_COMMON_ERA, MIN_VAL_COUNT,
9	MaxDependencies, MaxImportSegments, MaxImports, MaxWorkItems, ProtocolParameters,
10	SegmentTreeRoot, ServiceId, Slot, TicketAttempt, UnsignedGas, VALS_PER_CORE, ValIndex,
11	WorkItem, WorkPackageHash, WorkReportHash, max_imports, max_work_items, tickets_per_validator,
12};
13use std::{
14	ops::AddAssign,
15	time::{Duration, SystemTime, UNIX_EPOCH},
16};
17
18/// Telemetry protocol version, should be incremented when the protocol changes.
19pub const PROTOCOL_VERSION: u8 = 1;
20
21pub type Reason = BoundedString<128>;
22
23/// Microseconds since the beginning of the Jam "Common Era".
24#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, MaxEncodedLen)]
25pub struct Timestamp(pub u64);
26
27impl Timestamp {
28	pub fn now() -> Self {
29		Self::from(SystemTime::now())
30	}
31}
32
33impl std::fmt::Debug for Timestamp {
34	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35		self.0.fmt(f)
36	}
37}
38
39impl From<SystemTime> for Timestamp {
40	fn from(time: SystemTime) -> Self {
41		let jam_ce = UNIX_EPOCH + Duration::from_secs(JAM_COMMON_ERA);
42		let since_jam_ce = time.duration_since(jam_ce).unwrap_or(Duration::ZERO);
43		Self(since_jam_ce.as_micros() as u64)
44	}
45}
46
47impl From<Timestamp> for SystemTime {
48	fn from(timestamp: Timestamp) -> Self {
49		let jam_ce = UNIX_EPOCH + Duration::from_secs(JAM_COMMON_ERA);
50		jam_ce + Duration::from_micros(timestamp.0)
51	}
52}
53
54/// Each event sent over a connection is implicitly given an ID:
55///
56/// - The first event is given ID 0.
57/// - The event immediately following an event E is given the ID of event E plus N, where N is the
58///   number of dropped events if E is a "dropped" event, or 1 otherwise.
59#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, MaxEncodedLen)]
60pub struct EventId(pub u64);
61
62impl std::fmt::Debug for EventId {
63	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64		self.0.fmt(f)
65	}
66}
67
68impl std::fmt::Display for EventId {
69	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70		self.0.fmt(f)
71	}
72}
73
74#[repr(u8)]
75#[derive(Clone, Copy, Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen)]
76pub enum ConnectionSide {
77	Local = 0,
78	Remote = 1,
79}
80
81pub type ShardIndex = u16;
82
83#[derive(Clone, Debug, Encode, Decode, MaxEncodedLen)]
84pub struct BlockOutline {
85	/// Size in bytes.
86	pub size: u32,
87	pub hash: HeaderHash,
88	pub num_tickets: u32,
89	pub num_preimages: u32,
90	/// Total size of preimages in bytes.
91	pub preimages_size: u32,
92	pub num_guarantees: u32,
93	pub num_assurances: u32,
94	pub num_dispute_verdicts: u32,
95}
96
97impl From<(&Block, HeaderHash)> for BlockOutline {
98	fn from((block, hash): (&Block, HeaderHash)) -> Self {
99		Self {
100			size: block.encoded_size() as u32,
101			hash,
102			num_tickets: block.extrinsic.tickets.len() as u32,
103			num_preimages: block.extrinsic.preimages.len() as u32,
104			preimages_size: block.extrinsic.preimages.iter().map(|p| p.blob().len() as u32).sum(),
105			num_guarantees: block.extrinsic.guarantees.len() as u32,
106			num_assurances: block.extrinsic.assurances.len() as u32,
107			num_dispute_verdicts: block.extrinsic.disputes.verdicts.len() as u32,
108		}
109	}
110}
111
112impl From<&Block> for BlockOutline {
113	fn from(block: &Block) -> Self {
114		(block, block.header.hash()).into()
115	}
116}
117
118#[repr(u8)]
119#[derive(Clone, Copy, Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen)]
120pub enum BlockRequestDirection {
121	AscendingExclusive = 0,
122	DescendingInclusive = 1,
123}
124
125#[derive(Clone, Debug, Default, Encode, Decode, MaxEncodedLen)]
126pub struct ExecCost {
127	pub gas: UnsignedGas,
128	/// Elapsed wall-clock time in nanoseconds.
129	pub ns: u64,
130}
131
132impl AddAssign for ExecCost {
133	fn add_assign(&mut self, rhs: Self) {
134		self.gas += rhs.gas;
135		self.ns += rhs.ns;
136	}
137}
138
139#[derive(Clone, Debug, Default, Encode, Decode, MaxEncodedLen)]
140pub struct IsAuthorizedCost {
141	pub total: ExecCost,
142	/// Time taken to load and compile the code, in nanoseconds.
143	///
144	/// Note that this is included in `total.ns`.
145	pub load_ns: u64,
146	/// Total cost of host calls.
147	pub host_call: ExecCost,
148}
149
150impl AddAssign for IsAuthorizedCost {
151	fn add_assign(&mut self, rhs: Self) {
152		self.total += rhs.total;
153		self.host_call += rhs.host_call;
154	}
155}
156
157#[derive(Clone, Debug, Default, Encode, Decode, MaxEncodedLen)]
158pub struct RefineHostCallCost {
159	/// Total cost of `historical_lookup` calls.
160	pub lookup: ExecCost,
161	/// Total cost of `machine`/`expunge` calls.
162	pub vm: ExecCost,
163	/// Total cost of `peek`/`poke`/`pages` calls.
164	pub mem: ExecCost,
165	/// Total cost of `invoke` calls.
166	pub invoke: ExecCost,
167	/// Total cost of all other host calls.
168	pub other: ExecCost,
169}
170
171impl AddAssign for RefineHostCallCost {
172	fn add_assign(&mut self, rhs: Self) {
173		self.lookup += rhs.lookup;
174		self.vm += rhs.vm;
175		self.mem += rhs.mem;
176		self.invoke += rhs.invoke;
177		self.other += rhs.other;
178	}
179}
180
181#[derive(Clone, Debug, Default, Encode, Decode, MaxEncodedLen)]
182pub struct RefineCost {
183	pub total: ExecCost,
184	/// Time taken to load and compile the code, in nanoseconds.
185	///
186	/// Note that this is included in `total.ns`.
187	pub load_ns: u64,
188	pub host_call: RefineHostCallCost,
189}
190
191impl AddAssign for RefineCost {
192	fn add_assign(&mut self, rhs: Self) {
193		self.total += rhs.total;
194		self.host_call += rhs.host_call;
195	}
196}
197
198pub type RefineCosts = BoundedVec<RefineCost, MaxWorkItems>;
199
200#[derive(Clone, Debug, Default, Encode, Decode, MaxEncodedLen)]
201pub struct AccumulateHostCallCost {
202	/// Total cost of `read`/`write` calls.
203	pub state: ExecCost,
204	/// Total cost of `lookup` calls.
205	pub lookup: ExecCost,
206	/// Total cost of `query`/`solicit`/`forget`/`provide` calls.
207	pub preimage: ExecCost,
208	/// Total cost of `info`/`new`/`upgrade`/`eject` calls.
209	pub service: ExecCost,
210	/// Total cost of `transfer` calls.
211	pub transfer: ExecCost,
212	/// Total gas charged for transfer processing by destination services.
213	pub transfer_dest_gas: UnsignedGas,
214	/// Total cost of all other host calls.
215	pub other: ExecCost,
216}
217
218impl AddAssign for AccumulateHostCallCost {
219	fn add_assign(&mut self, rhs: Self) {
220		self.state += rhs.state;
221		self.lookup += rhs.lookup;
222		self.preimage += rhs.preimage;
223		self.service += rhs.service;
224		self.transfer += rhs.transfer;
225		self.transfer_dest_gas += rhs.transfer_dest_gas;
226		self.other += rhs.other;
227	}
228}
229
230#[derive(Clone, Debug, Default, Encode, Decode, MaxEncodedLen)]
231pub struct AccumulateCost {
232	/// Number of `accumulate` calls.
233	pub num_calls: u32,
234	/// Number of transfers processed.
235	pub num_transfers: u32,
236	/// Number of work items accumulated.
237	pub num_items: u32,
238	pub total: ExecCost,
239	/// Time taken to load and compile the code, in nanoseconds.
240	///
241	/// Note that this is included in `total.ns`.
242	pub load_ns: u64,
243	pub host_call: AccumulateHostCallCost,
244}
245
246impl AddAssign for AccumulateCost {
247	fn add_assign(&mut self, rhs: Self) {
248		self.num_calls += rhs.num_calls;
249		self.num_transfers += rhs.num_transfers;
250		self.num_items += rhs.num_items;
251		self.total += rhs.total;
252		self.host_call += rhs.host_call;
253	}
254}
255
256pub type AccumulateCosts = BoundedVec<(ServiceId, AccumulateCost), ConstU32<500>>;
257
258/// Identifies a segment needed by a work-package.
259#[derive(Clone, Copy, Debug, PartialEq, Eq)]
260pub enum ImportSegmentId {
261	/// The segment with the given index in the overall list of imports.
262	Import(u16),
263	/// The proof page for the segment with the given index in the overall list of imports.
264	ProofPage(u16),
265}
266
267impl ImportSegmentId {
268	pub fn import(self) -> Option<u16> {
269		match self {
270			Self::Import(index) => Some(index),
271			Self::ProofPage(_) => None,
272		}
273	}
274}
275
276impl Encode for ImportSegmentId {
277	fn size_hint(&self) -> usize {
278		2
279	}
280
281	fn encode_to<O: codec::Output + ?Sized>(&self, output: &mut O) {
282		let index = match *self {
283			Self::Import(index) => {
284				debug_assert!(index < (1 << 15));
285				index
286			},
287			Self::ProofPage(index) => {
288				debug_assert!(index < (1 << 15));
289				index + (1 << 15)
290			},
291		};
292		index.encode_to(output);
293	}
294}
295
296impl Decode for ImportSegmentId {
297	fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
298		let index = u16::decode(input)?;
299		if (index & (1 << 15)) == 0 {
300			Ok(Self::Import(index))
301		} else {
302			Ok(Self::ProofPage(index & !(1 << 15)))
303		}
304	}
305
306	fn encoded_fixed_size() -> Option<usize> {
307		u16::encoded_fixed_size()
308	}
309}
310
311impl MaxEncodedLen for ImportSegmentId {
312	fn max_encoded_len() -> usize {
313		u16::max_encoded_len()
314	}
315}
316
317#[derive(Clone, Debug, Encode, Decode, MaxEncodedLen)]
318pub struct WorkItemOutline {
319	pub service: ServiceId,
320	pub payload_size: u32,
321	pub refine_gas_limit: UnsignedGas,
322	pub accumulate_gas_limit: UnsignedGas,
323	/// Sum of extrinsic lengths.
324	pub extrinsic_size: u32,
325	pub imports: BoundedVec<ImportSpec, MaxImports>,
326	pub num_exports: u16,
327}
328
329impl From<&WorkItem> for WorkItemOutline {
330	fn from(item: &WorkItem) -> Self {
331		Self {
332			service: item.service,
333			payload_size: item.payload.len() as u32,
334			refine_gas_limit: item.refine_gas_limit,
335			accumulate_gas_limit: item.accumulate_gas_limit,
336			extrinsic_size: item.extrinsic_size(),
337			imports: item.import_segments.clone(),
338			num_exports: item.export_count,
339		}
340	}
341}
342
343#[derive(Clone, Debug, Encode, Decode)]
344pub struct WorkPackageOutline {
345	/// Size in bytes, excluding extrinsic data.
346	pub size: u32,
347	pub hash: WorkPackageHash,
348	pub anchor: HeaderHash,
349	pub lookup_anchor_slot: Slot,
350	pub prerequisites: BoundedVec<WorkPackageHash, MaxDependencies>,
351	pub items: BoundedVec<WorkItemOutline, MaxWorkItems>,
352}
353
354impl From<&ImmutableWorkPackage> for WorkPackageOutline {
355	fn from(package: &ImmutableWorkPackage) -> Self {
356		Self {
357			size: package.encoded_len() as u32,
358			hash: package.hash(),
359			anchor: package.context.anchor,
360			lookup_anchor_slot: package.context.lookup_anchor_slot,
361			// package.context.prerequisites is an unbounded VecSet, but the package is invalid if
362			// it has more than max_dependencies() entries. So the truncation here _could_ result
363			// in an incorrect outline, but only in the case of an invalid package. I don't think
364			// it's worth doing anything about this.
365			prerequisites: BoundedVec::truncate_from(package.context.prerequisites.to_vec()),
366			items: package
367				.items
368				.iter()
369				.map(|item| (&**item).into())
370				.try_collect()
371				.expect("Output and input bounds are the same"),
372		}
373	}
374}
375
376impl MaxEncodedLen for WorkPackageOutline {
377	fn max_encoded_len() -> usize {
378		let mut max_len = u32::max_encoded_len() + // size
379			WorkPackageHash::max_encoded_len() + // hash
380			HeaderHash::max_encoded_len() + // anchor
381			Slot::max_encoded_len() + // lookup_anchor_slot
382			BoundedVec::<WorkPackageHash, MaxDependencies>::max_encoded_len() + // prerequisites
383			BoundedVec::<WorkItemOutline, MaxWorkItems>::max_encoded_len(); // items
384
385		if let Some(import_spec_size) = ImportSpec::encoded_fixed_size() {
386			// Import limit is per work-package, not per-item. We do not expect work-packages which
387			// violate basic validity requirements such as max number of imports to be emitted over
388			// telemetry.
389			max_len -= (max_work_items() - 1) * (max_imports() as usize) * import_spec_size;
390		}
391
392		max_len
393	}
394}
395
396#[derive(Clone, Debug, Encode, Decode, MaxEncodedLen)]
397pub struct WorkReportOutline {
398	pub hash: WorkReportHash,
399	/// Size of bundle in bytes.
400	pub bundle_size: u32,
401	pub erasure_root: ErasureRoot,
402	pub exports_root: SegmentTreeRoot,
403}
404
405impl From<&WorkReport> for WorkReportOutline {
406	fn from(report: &WorkReport) -> Self {
407		Self {
408			hash: report.hash(),
409			bundle_size: report.package_spec.len,
410			erasure_root: report.package_spec.erasure_root,
411			exports_root: report.package_spec.exports_root,
412		}
413	}
414}
415
416#[derive(Clone, Debug, Encode, Decode, MaxEncodedLen)]
417pub struct GuaranteeOutline {
418	pub report_hash: WorkReportHash,
419	pub slot: Slot,
420	pub guarantors: BoundedVec<ValIndex, ConstU32<{ VALS_PER_CORE as u32 }>>,
421}
422
423impl From<&ReportGuarantee> for GuaranteeOutline {
424	fn from(guarantee: &ReportGuarantee) -> Self {
425		Self {
426			report_hash: guarantee.report.hash(),
427			slot: guarantee.slot,
428			guarantors: guarantee
429				.signatures
430				.iter()
431				.map(|signature| signature.val_index)
432				.try_collect()
433				.expect("Output and input bounds are the same"),
434		}
435	}
436}
437
438#[repr(u8)]
439#[derive(Clone, Copy, Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen)]
440pub enum GuaranteeDiscardReason {
441	PackageReportedOnChain = 0,
442	Superseded = 1,
443	CannotReportOnChain = 2,
444	TooMany = 3,
445	Other = 4,
446}
447
448#[repr(u8)]
449#[derive(Clone, Copy, Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen)]
450pub enum ReconstructionKind {
451	/// A non-trivial reconstruction, involving at least some recovery shards.
452	NonTrivial,
453	/// A trivial reconstruction, using only original-data shards.
454	Trivial,
455}
456
457#[repr(u8)]
458#[derive(Clone, Copy, Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen)]
459pub enum AnnouncedPreimageForgetReason {
460	ProvidedOnChain = 0,
461	NotRequestedOnChain = 1,
462	FailedToAcquire = 2,
463	TooMany = 3,
464	BadLength = 4,
465	Other = 5,
466}
467
468#[repr(u8)]
469#[derive(Clone, Copy, Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen)]
470pub enum PreimageDiscardReason {
471	ProvidedOnChain = 0,
472	NotRequestedOnChain = 1,
473	TooMany = 2,
474	Other = 3,
475}
476
477/// `NodeInfo` flag indicating that the node uses a PVM recompiler rather than an interpreter.
478pub const NODE_USES_PVM_RECOMPILER: u32 = 1 << 0;
479
480#[derive(Clone, Debug, Encode, Decode, MaxEncodedLen)]
481pub struct NodeInfo {
482	/// Protocol parameters the node is using.
483	pub params: ProtocolParameters,
484	/// Genesis header hash.
485	pub genesis: HeaderHash,
486	/// Peer ID and external address of the node.
487	pub details: PeerDetails,
488	pub flags: u32,
489	/// Name of the node implementation, eg "PolkaJam".
490	pub impl_name: BoundedString<32>,
491	/// Version of the node implementation, eg "1.0".
492	pub impl_version: BoundedString<32>,
493	/// Gray Paper version implemented by the node, eg "0.7.1".
494	pub gp_version: BoundedString<16>,
495	/// Freeform note with additional information about the node.
496	pub note: BoundedString<512>,
497}
498
499macro_rules! event_struct {
500	($(#[$attr:meta])* $name:ident { $($(#[$field_attr:meta])* $field_name:ident: $field_type:ty,)+ }) => {
501		$(#[$attr])*
502		#[derive(Clone, Debug, Encode, Decode, MaxEncodedLen)]
503		pub struct $name {
504			$($(#[$field_attr])* pub $field_name: $field_type,)+
505		}
506	};
507}
508
509macro_rules! events {
510	($($(#[$attr:meta])* $name:ident = $discriminator:literal $fields:tt)+) => {
511		pub mod event {
512			use super::*;
513			$(event_struct! { $(#[$attr])* $name $fields })+
514		}
515
516		#[repr(u8)]
517		#[derive(Clone, Encode, Decode, MaxEncodedLen)]
518		pub enum Event {
519			$($name(event::$name) = $discriminator,)+
520		}
521
522		impl std::fmt::Debug for Event {
523			fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
524				match self {
525					$(Self::$name(event) => event.fmt(f),)+
526				}
527			}
528		}
529	};
530}
531
532/// Bound for `TicketsGenerated::ids`: the per-validator ticket allowance (`⌈2E/VāŒ‰`) at the
533/// minimum allowed set size, an upper bound over all sizes.
534#[derive(Copy, Clone, Eq, PartialEq, Default, Debug)]
535pub struct MaxTicketsPerValidator;
536impl Get<u32> for MaxTicketsPerValidator {
537	fn get() -> u32 {
538		tickets_per_validator(MIN_VAL_COUNT) as u32
539	}
540}
541
542events! {
543	Dropped = 0 {
544		/// Timestamp of the last dropped event.
545		last_timestamp: Timestamp,
546		/// Number of dropped events.
547		num: u64,
548	}
549
550	Status = 10 {
551		/// Total number of peers.
552		num_peers: u32,
553		/// Number of validator peers.
554		num_val_peers: u32,
555		/// Number of peers with a block announcement stream open.
556		num_sync_peers: u32,
557		/// Number of guarantees in pool, by core.
558		num_guarantees: FixedVec<u8, CoreCount>,
559		/// Number of shards in availability store.
560		num_shards: u32,
561		/// Total size of shards in availability store, in bytes.
562		shards_size: u64,
563		/// Number of preimages in the pool, ready to be included in a block.
564		num_preimages: u32,
565		/// Total size of preimages in the pool, in bytes.
566		preimages_size: u32,
567	}
568
569	BestBlockChanged = 11 {
570		slot: Slot,
571		hash: HeaderHash,
572	}
573
574	FinalizedBlockChanged = 12 {
575		slot: Slot,
576		hash: HeaderHash,
577	}
578
579	SyncStatusChanged = 13 {
580		synced: bool,
581	}
582
583	ConnectionRefused = 20 {
584		from: PeerAddr,
585	}
586
587	ConnectingIn = 21 {
588		from: PeerAddr,
589	}
590
591	ConnectInFailed = 22 {
592		connecting_id: EventId,
593		reason: Reason,
594	}
595
596	ConnectedIn = 23 {
597		connecting_id: EventId,
598		peer_id: PeerId,
599	}
600
601	ConnectingOut = 24 {
602		to: PeerDetails,
603	}
604
605	ConnectOutFailed = 25 {
606		connecting_id: EventId,
607		reason: Reason,
608	}
609
610	ConnectedOut = 26 {
611		connecting_id: EventId,
612	}
613
614	Disconnected = 27 {
615		peer: PeerId,
616		/// Which side terminated the connection? May be `None` in case of eg timeout.
617		terminator: Option<ConnectionSide>,
618		reason: Reason,
619	}
620
621	PeerMisbehaved = 28 {
622		peer: PeerId,
623		reason: Reason,
624	}
625
626	Authoring = 40 {
627		slot: Slot,
628		parent: HeaderHash,
629	}
630
631	AuthoringFailed = 41 {
632		authoring_id: EventId,
633		reason: Reason,
634	}
635
636	Authored = 42 {
637		authoring_id: EventId,
638		outline: BlockOutline,
639	}
640
641	Importing = 43 {
642		slot: Slot,
643		outline: BlockOutline,
644	}
645
646	BlockVerificationFailed = 44 {
647		importing_id: EventId,
648		reason: Reason,
649	}
650
651	BlockVerified = 45 {
652		importing_id: EventId,
653	}
654
655	BlockExecutionFailed = 46 {
656		authoring_or_importing_id: EventId,
657		reason: Reason,
658	}
659
660	BlockExecuted = 47 {
661		authoring_or_importing_id: EventId,
662		accumulate_costs: AccumulateCosts,
663	}
664
665	BlockAnnouncementStreamOpened = 60 {
666		peer: PeerId,
667		/// Which side opened the stream?
668		opener: ConnectionSide,
669	}
670
671	BlockAnnouncementStreamClosed = 61 {
672		opened_id: EventId,
673		/// Which side closed the stream?
674		closer: ConnectionSide,
675		reason: Reason,
676	}
677
678	BlockAnnounced = 62 {
679		peer: PeerId,
680		/// Which side announced the block?
681		announcer: ConnectionSide,
682		slot: Slot,
683		hash: HeaderHash,
684	}
685
686	SendingBlockRequest = 63 {
687		recipient: PeerId,
688		hash: HeaderHash,
689		direction: BlockRequestDirection,
690		max_blocks: u32,
691	}
692
693	ReceivingBlockRequest = 64 {
694		sender: PeerId,
695	}
696
697	BlockRequestFailed = 65 {
698		/// ID of the corresponding `SendingBlockRequest` or `ReceivingBlockRequest` event.
699		request_id: EventId,
700		reason: Reason,
701	}
702
703	BlockRequestSent = 66 {
704		/// ID of the corresponding `SendingBlockRequest`.
705		request_id: EventId,
706	}
707
708	BlockRequestReceived = 67 {
709		/// ID of the corresponding `ReceivingBlockRequest`.
710		request_id: EventId,
711		hash: HeaderHash,
712		direction: BlockRequestDirection,
713		max_blocks: u32,
714	}
715
716	BlockTransferred = 68 {
717		/// ID of the corresponding `SendingBlockRequest` or `ReceivingBlockRequest` event.
718		request_id: EventId,
719		slot: Slot,
720		outline: BlockOutline,
721		/// Was this the last block for the request?
722		last: bool,
723	}
724
725	GeneratingTickets = 80 {
726		epoch: EpochIndex,
727	}
728
729	TicketGenerationFailed = 81 {
730		/// ID of the corresponding `GeneratingTickets` event.
731		generating_id: EventId,
732		reason: Reason,
733	}
734
735	TicketsGenerated = 82 {
736		/// ID of the corresponding `GeneratingTickets` event.
737		generating_id: EventId,
738		/// VRF outputs.
739		ids: BoundedVec<TicketId, MaxTicketsPerValidator>,
740	}
741
742	TicketTransferFailed = 83 {
743		peer: PeerId,
744		/// Which side tried to send a ticket?
745		sender: ConnectionSide,
746		/// Was this a transfer from the proxy to a potential block author? If `false`, this was a
747		/// transfer from the ticket creator to the proxy.
748		from_proxy: bool,
749		reason: Reason,
750	}
751
752	TicketTransferred = 84 {
753		peer: PeerId,
754		/// Which side sent a ticket?
755		sender: ConnectionSide,
756		/// Was this a transfer from the proxy to a potential block author? If `false`, this was a
757		/// transfer from the ticket creator to the proxy.
758		from_proxy: bool,
759		/// The epoch the ticket is to be used in.
760		epoch: EpochIndex,
761		/// Ticket attempt number.
762		attempt: TicketAttempt,
763		/// VRF output.
764		id: TicketId,
765	}
766
767	WorkPackageSubmission = 90 {
768		builder: PeerId,
769		bundle: bool,
770	}
771
772	WorkPackageBeingShared = 91 {
773		primary: PeerId,
774	}
775
776	WorkPackageFailed = 92 {
777		/// ID of the corresponding `WorkPackageSubmission` or `WorkPackageBeingShared` event.
778		submission_or_share_id: EventId,
779		reason: Reason,
780	}
781
782	DuplicateWorkPackage = 93 {
783		/// ID of the corresponding `WorkPackageSubmission` or `WorkPackageBeingShared` event.
784		submission_or_share_id: EventId,
785		core: CoreIndex,
786		hash: WorkPackageHash,
787	}
788
789	WorkPackageReceived = 94 {
790		/// ID of the corresponding `WorkPackageSubmission` or `WorkPackageBeingShared` event.
791		submission_or_share_id: EventId,
792		core: CoreIndex,
793		outline: WorkPackageOutline,
794	}
795
796	Authorized = 95 {
797		/// ID of the corresponding `WorkPackageSubmission` or `WorkPackageBeingShared` event.
798		submission_or_share_id: EventId,
799		cost: IsAuthorizedCost,
800	}
801
802	ExtrinsicDataReceived = 96 {
803		/// ID of the corresponding `WorkPackageSubmission` or `WorkPackageBeingShared` event.
804		submission_or_share_id: EventId,
805	}
806
807	ImportsReceived = 97 {
808		/// ID of the corresponding `WorkPackageSubmission` or `WorkPackageBeingShared` event.
809		submission_or_share_id: EventId,
810	}
811
812	SharingWorkPackage = 98 {
813		/// ID of the corresponding `WorkPackageSubmission` event.
814		submission_id: EventId,
815		secondary: PeerId,
816	}
817
818	WorkPackageSharingFailed = 99 {
819		/// ID of the corresponding `WorkPackageSubmission` event.
820		submission_id: EventId,
821		secondary: PeerId,
822		reason: Reason,
823	}
824
825	BundleSent = 100 {
826		/// ID of the corresponding `WorkPackageSubmission` event.
827		submission_id: EventId,
828		secondary: PeerId,
829	}
830
831	Refined = 101 {
832		/// ID of the corresponding `WorkPackageSubmission` or `WorkPackageBeingShared` event.
833		submission_or_share_id: EventId,
834		/// Cost of `refine` call for each work item.
835		costs: RefineCosts,
836	}
837
838	WorkReportBuilt = 102 {
839		/// ID of the corresponding `WorkPackageSubmission` or `WorkPackageBeingShared` event.
840		submission_or_share_id: EventId,
841		outline: WorkReportOutline,
842	}
843
844	WorkReportSignatureSent = 103 {
845		/// ID of the corresponding `WorkPackageBeingShared` event.
846		share_id: EventId,
847	}
848
849	WorkReportSignatureReceived = 104 {
850		/// ID of the corresponding `WorkPackageSubmission` event.
851		submission_id: EventId,
852		secondary: PeerId,
853	}
854
855	GuaranteeBuilt = 105 {
856		/// ID of the corresponding `WorkPackageSubmission` event.
857		submission_id: EventId,
858		outline: GuaranteeOutline,
859	}
860
861	SendingGuarantee = 106 {
862		/// ID of the corresponding `GuaranteeBuilt` event.
863		built_id: EventId,
864		recipient: PeerId,
865	}
866
867	GuaranteeSendFailed = 107 {
868		sending_id: EventId,
869		reason: Reason,
870	}
871
872	GuaranteeSent = 108 {
873		sending_id: EventId,
874	}
875
876	GuaranteesDistributed = 109 {
877		/// ID of the corresponding `WorkPackageSubmission` event.
878		submission_id: EventId,
879	}
880
881	ReceivingGuarantee = 110 {
882		sender: PeerId,
883	}
884
885	GuaranteeReceiveFailed = 111 {
886		receiving_id: EventId,
887		reason: Reason,
888	}
889
890	GuaranteeReceived = 112 {
891		receiving_id: EventId,
892		outline: GuaranteeOutline,
893	}
894
895	GuaranteeDiscarded = 113 {
896		outline: GuaranteeOutline,
897		reason: GuaranteeDiscardReason,
898	}
899
900	SendingShardRequest = 120 {
901		guarantor: PeerId,
902		erasure_root: ErasureRoot,
903		shard: ShardIndex,
904	}
905
906	ReceivingShardRequest = 121 {
907		assurer: PeerId,
908	}
909
910	ShardRequestFailed = 122 {
911		/// ID of the corresponding `SendingShardRequest` or `ReceivingShardRequest` event.
912		request_id: EventId,
913		reason: Reason,
914	}
915
916	ShardRequestSent = 123 {
917		/// ID of the corresponding `SendingShardRequest`.
918		request_id: EventId,
919	}
920
921	ShardRequestReceived = 124 {
922		/// ID of the corresponding `ReceivingShardRequest`.
923		request_id: EventId,
924		erasure_root: ErasureRoot,
925		shard: ShardIndex,
926	}
927
928	ShardsTransferred = 125 {
929		/// ID of the corresponding `SendingShardRequest` or `ReceivingShardRequest` event.
930		request_id: EventId,
931	}
932
933	DistributingAssurance = 126 {
934		statement: AvailabilityStatement,
935	}
936
937	AssuranceSendFailed = 127 {
938		/// ID of the corresponding `DistributingAssurance` event.
939		distributing_id: EventId,
940		recipient: PeerId,
941		reason: Reason,
942	}
943
944	AssuranceSent = 128 {
945		/// ID of the corresponding `DistributingAssurance` event.
946		distributing_id: EventId,
947		recipient: PeerId,
948	}
949
950	AssuranceDistributed = 129 {
951		/// ID of the corresponding `DistributingAssurance` event.
952		distributing_id: EventId,
953	}
954
955	AssuranceReceiveFailed = 130 {
956		sender: PeerId,
957		reason: Reason,
958	}
959
960	AssuranceReceived = 131 {
961		sender: PeerId,
962		/// Assurance anchor.
963		anchor: HeaderHash,
964	}
965
966	SendingBundleShardRequest = 140 {
967		audit_id: EventId,
968		assurer: PeerId,
969		shard: ShardIndex,
970	}
971
972	ReceivingBundleShardRequest = 141 {
973		auditor: PeerId,
974	}
975
976	BundleShardRequestFailed = 142 {
977		/// ID of the corresponding `SendingBundleShardRequest` or `ReceivingBundleShardRequest`
978		/// event.
979		request_id: EventId,
980		reason: Reason,
981	}
982
983	BundleShardRequestSent = 143 {
984		/// ID of the corresponding `SendingBundleShardRequest`.
985		request_id: EventId,
986	}
987
988	BundleShardRequestReceived = 144 {
989		/// ID of the corresponding `ReceivingBundleShardRequest`.
990		request_id: EventId,
991		erasure_root: ErasureRoot,
992		shard: ShardIndex,
993	}
994
995	BundleShardTransferred = 145 {
996		/// ID of the corresponding `SendingBundleShardRequest` or `ReceivingBundleShardRequest`
997		/// event.
998		request_id: EventId,
999	}
1000
1001	ReconstructingBundle = 146 {
1002		audit_id: EventId,
1003		kind: ReconstructionKind,
1004	}
1005
1006	BundleReconstructed = 147 {
1007		audit_id: EventId,
1008	}
1009
1010	SendingBundleRequest = 148 {
1011		audit_id: EventId,
1012		guarantor: PeerId,
1013	}
1014
1015	ReceivingBundleRequest = 149 {
1016		auditor: PeerId,
1017	}
1018
1019	BundleRequestFailed = 150 {
1020		/// ID of the corresponding `SendingBundleRequest` or `ReceivingBundleRequest` event.
1021		request_id: EventId,
1022		reason: Reason,
1023	}
1024
1025	BundleRequestSent = 151 {
1026		/// ID of the corresponding `SendingBundleRequest` event.
1027		request_id: EventId,
1028	}
1029
1030	BundleRequestReceived = 152 {
1031		/// ID of the corresponding `ReceivingBundleRequest` event.
1032		request_id: EventId,
1033		erasure_root: ErasureRoot,
1034	}
1035
1036	BundleTransferred = 153 {
1037		/// ID of the corresponding `SendingBundleRequest` or `ReceivingBundleRequest` event.
1038		request_id: EventId,
1039	}
1040
1041	WorkPackageHashMapped = 160 {
1042		/// ID of the corresponding `WorkPackageSubmission` event.
1043		submission_id: EventId,
1044		work_package_hash: WorkPackageHash,
1045		segments_root: SegmentTreeRoot,
1046	}
1047
1048	SegmentsRootMapped = 161 {
1049		/// ID of the corresponding `WorkPackageSubmission` event.
1050		submission_id: EventId,
1051		segments_root: SegmentTreeRoot,
1052		erasure_root: ErasureRoot,
1053	}
1054
1055	SendingSegmentShardRequest = 162 {
1056		/// ID of the corresponding `WorkPackageSubmission` event.
1057		submission_id: EventId,
1058		assurer: PeerId,
1059		/// Are proofs of the segment shards being requested?
1060		proofs: bool,
1061		/// Segment shards being requested.
1062		shards: BoundedVec<(ImportSegmentId, ShardIndex), MaxImportSegments>,
1063	}
1064
1065	ReceivingSegmentShardRequest = 163 {
1066		sender: PeerId,
1067		/// Have proofs of the segment shards been requested?
1068		proofs: bool,
1069	}
1070
1071	SegmentShardRequestFailed = 164 {
1072		/// ID of the corresponding `SendingSegmentShardRequest` or `ReceivingSegmentShardRequest`
1073		/// event.
1074		request_id: EventId,
1075		reason: Reason,
1076	}
1077
1078	SegmentShardRequestSent = 165 {
1079		/// ID of the corresponding `SendingSegmentShardRequest` event.
1080		request_id: EventId,
1081	}
1082
1083	SegmentShardRequestReceived = 166 {
1084		/// ID of the corresponding `ReceivingSegmentShardRequest` event.
1085		request_id: EventId,
1086		/// Number of segment shards requested.
1087		num: u16,
1088	}
1089
1090	SegmentShardsTransferred = 167 {
1091		/// ID of the corresponding `SendingSegmentShardRequest` or `ReceivingSegmentShardRequest`
1092		/// event.
1093		request_id: EventId,
1094	}
1095
1096	ReconstructingSegments = 168 {
1097		/// ID of the corresponding `WorkPackageSubmission` event.
1098		submission_id: EventId,
1099		segments: BoundedVec<ImportSegmentId, MaxImportSegments>,
1100		kind: ReconstructionKind,
1101	}
1102
1103	SegmentReconstructionFailed = 169 {
1104		/// ID of the corresponding `ReconstructingSegments` event.
1105		reconstructing_id: EventId,
1106		reason: Reason,
1107	}
1108
1109	SegmentsReconstructed = 170 {
1110		/// ID of the corresponding `ReconstructingSegments` event.
1111		reconstructing_id: EventId,
1112	}
1113
1114	SegmentVerificationFailed = 171 {
1115		/// ID of the corresponding `WorkPackageSubmission` event.
1116		submission_id: EventId,
1117		segments: BoundedVec<u16, MaxImports>,
1118		reason: Reason,
1119	}
1120
1121	SegmentsVerified = 172 {
1122		/// ID of the corresponding `WorkPackageSubmission` event.
1123		submission_id: EventId,
1124		segments: BoundedVec<u16, MaxImports>,
1125	}
1126
1127	SendingSegmentRequest = 173 {
1128		/// ID of the corresponding `WorkPackageSubmission` event.
1129		submission_id: EventId,
1130		prev_guarantor: PeerId,
1131		segments: BoundedVec<u16, MaxImportSegments>,
1132	}
1133
1134	ReceivingSegmentRequest = 174 {
1135		guarantor: PeerId,
1136	}
1137
1138	SegmentRequestFailed = 175 {
1139		/// ID of the corresponding `SendingSegmentRequest` or `ReceivingSegmentRequest` event.
1140		request_id: EventId,
1141		reason: Reason,
1142	}
1143
1144	SegmentRequestSent = 176 {
1145		/// ID of the corresponding `SendingSegmentRequest` event.
1146		request_id: EventId,
1147	}
1148
1149	SegmentRequestReceived = 177 {
1150		/// ID of the corresponding `ReceivingSegmentRequest` event.
1151		request_id: EventId,
1152		/// Number of segments requested.
1153		num: u16,
1154	}
1155
1156	SegmentsTransferred = 178 {
1157		/// ID of the corresponding `SendingSegmentRequest` or `ReceivingSegmentRequest` event.
1158		request_id: EventId,
1159	}
1160
1161	PreimageAnnouncementFailed = 190 {
1162		peer: PeerId,
1163		/// Which side tried to announce a preimage?
1164		announcer: ConnectionSide,
1165		reason: Reason,
1166	}
1167
1168	PreimageAnnounced = 191 {
1169		peer: PeerId,
1170		/// Which side announced a preimage?
1171		announcer: ConnectionSide,
1172		/// ID of requesting service.
1173		service: ServiceId,
1174		hash: Hash,
1175		length: u32,
1176	}
1177
1178	AnnouncedPreimageForgotten = 192 {
1179		service: ServiceId,
1180		hash: Hash,
1181		length: u32,
1182		reason: AnnouncedPreimageForgetReason,
1183	}
1184
1185	SendingPreimageRequest = 193 {
1186		recipient: PeerId,
1187		hash: Hash,
1188	}
1189
1190	ReceivingPreimageRequest = 194 {
1191		sender: PeerId,
1192	}
1193
1194	PreimageRequestFailed = 195 {
1195		/// ID of the corresponding `SendingPreimageRequest` or `ReceivingPreimageRequest` event.
1196		request_id: EventId,
1197		reason: Reason,
1198	}
1199
1200	PreimageRequestSent = 196 {
1201		/// ID of the corresponding `SendingPreimageRequest`.
1202		request_id: EventId,
1203	}
1204
1205	PreimageRequestReceived = 197 {
1206		/// ID of the corresponding `ReceivingPreimageRequest`.
1207		request_id: EventId,
1208		hash: Hash,
1209	}
1210
1211	PreimageTransferred = 198 {
1212		/// ID of the corresponding `SendingPreimageRequest` or `ReceivingPreimageRequest` event.
1213		request_id: EventId,
1214		length: u32,
1215	}
1216
1217	PreimageDiscarded = 199 {
1218		hash: Hash,
1219		length: u32,
1220		reason: PreimageDiscardReason,
1221	}
1222}
1223
1224impl Event {
1225	/// Returns the ID of the following event.
1226	///
1227	/// `id` should be the ID of this event.
1228	pub fn next_id(&self, id: EventId) -> EventId {
1229		let inc = match self {
1230			Self::Dropped(dropped) => dropped.num,
1231			_ => 1,
1232		};
1233		EventId(id.0 + inc)
1234	}
1235}
1236
1237#[derive(Clone, Debug, Encode, Decode, MaxEncodedLen)]
1238pub struct TimestampedEvent {
1239	pub timestamp: Timestamp,
1240	pub event: Event,
1241}