yellowstone_block_machine/event.rs
1use {solana_clock::Slot, solana_hash::HASH_BYTES};
2
3///
4/// The lifecycle/commitment status of a slot, independent of any specific Geyser wire format.
5///
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum SlotStatusKind {
8 FirstShredReceived,
9 Completed,
10 CreatedBank,
11 Dead,
12 Processed,
13 Confirmed,
14 Finalized,
15 ///
16 /// Any status not recognized by this crate. Keeps the abstraction forward-compatible with
17 /// new statuses introduced by a Geyser wire format without requiring a breaking change here.
18 ///
19 Other,
20}
21
22///
23/// A borrowed view over a slot lifecycle/commitment update.
24///
25#[derive(Debug, Clone, Copy)]
26pub struct SlotUpdateEvInfo {
27 pub slot: Slot,
28 pub parent: Option<Slot>,
29 pub status: SlotStatusKind,
30 pub dead_error: bool,
31}
32
33///
34/// A borrowed view over a block metadata (summary) update.
35///
36#[derive(Debug, Clone, Copy)]
37pub struct BlockMetaEvInfo {
38 pub slot: Slot,
39 pub parent_slot: Slot,
40 pub entries_count: u64,
41 pub executed_transaction_count: u64,
42 pub blockhash: [u8; HASH_BYTES],
43}
44
45///
46/// A borrowed view over a block entry update.
47///
48#[derive(Debug, Clone, Copy)]
49pub struct EntryEvInfo {
50 pub slot: Slot,
51 pub index: u64,
52 pub starting_transaction_index: u64,
53 pub executed_transaction_count: u64,
54 pub hash: [u8; HASH_BYTES],
55}
56
57///
58/// A borrowed, wire-format-agnostic view over a single Geyser event, produced by a
59/// [`GeyserEventAdapter`].
60///
61/// This is the abstraction boundary that lets [`crate::wrapper::BlocksStateMachineWrapper`]
62/// and [`crate::stream::BlockStream`] operate over any event source, not just a specific version
63/// of `yellowstone_grpc_proto`.
64///
65#[derive(Debug, Clone)]
66pub enum GeyserEventInfo {
67 Slot(SlotUpdateEvInfo),
68 BlockMeta(BlockMetaEvInfo),
69 Entry(EntryEvInfo),
70 Transaction {
71 slot: Slot,
72 },
73 Account {
74 slot: Slot,
75 },
76 ///
77 /// Any event kind not used by block reconstruction (or not recognized by this crate).
78 ///
79 Other {
80 slot: Slot,
81 },
82}
83
84impl GeyserEventInfo {
85 pub fn slot(&self) -> Slot {
86 match self {
87 GeyserEventInfo::Slot(ev) => ev.slot,
88 GeyserEventInfo::BlockMeta(ev) => ev.slot,
89 GeyserEventInfo::Entry(ev) => ev.slot,
90 GeyserEventInfo::Transaction { slot } => *slot,
91 GeyserEventInfo::Account { slot } => *slot,
92 GeyserEventInfo::Other { slot } => *slot,
93 }
94 }
95}
96
97///
98/// Adapts a raw Geyser event (of type [`EventT`](GeyserEventAdapter::EventT)) into a
99/// [`GeyserEventInfo`], abstracted away from any specific wire format.
100///
101/// The implementing type does not have to be [`EventT`](GeyserEventAdapter::EventT) itself — it is
102/// only the adapter that knows how to view it. This lets you bridge a Geyser event type you don't
103/// own (e.g. `yellowstone_grpc_proto::geyser::SubscribeUpdate` from a version pinned by another
104/// crate) by implementing this trait on a small local marker type instead, with `EventT` set to
105/// that foreign type. That satisfies Rust's orphan rules, since only the implementing type — not
106/// `EventT` — needs to be local to your crate.
107///
108pub trait GeyserEventAdapter {
109 ///
110 /// The raw Geyser event type this adapter knows how to view.
111 ///
112 type EventT;
113
114 ///
115 /// Extracts a normalized event view for the state machine, or returns `None` if the event
116 /// cannot be represented by this crate's abstraction.
117 ///
118 fn extract_geyser_ev_info(event: &Self::EventT) -> Option<GeyserEventInfo>;
119}