agave_geyser_plugin_interface/geyser_plugin_interface.rs
1//! The interface for Geyser plugins. A plugin must implement
2//! the GeyserPlugin trait to work with the runtime.
3//! In addition, the dynamic library must export a "C" function _create_plugin which
4//! creates the implementation of the plugin.
5use {
6 solana_clock::{Slot, UnixTimestamp},
7 solana_hash::Hash,
8 solana_message::v0::LoadedAddresses,
9 solana_signature::Signature,
10 solana_transaction::{sanitized::SanitizedTransaction, versioned::VersionedTransaction},
11 solana_transaction_status::{Reward, RewardsAndNumPartitions, TransactionStatusMeta},
12 std::{any::Any, error, io, net::SocketAddr},
13 thiserror::Error,
14};
15#[derive(Debug, Clone, PartialEq, Eq)]
16#[repr(C)]
17/// Information about an account being updated
18pub struct ReplicaAccountInfo<'a> {
19 /// The Pubkey for the account
20 pub pubkey: &'a [u8],
21
22 /// The lamports for the account
23 pub lamports: u64,
24
25 /// The Pubkey of the owner program account
26 pub owner: &'a [u8],
27
28 /// This account's data contains a loaded program (and is now read-only)
29 pub executable: bool,
30
31 /// The epoch at which this account will next owe rent
32 pub rent_epoch: u64,
33
34 /// The data held in this account.
35 pub data: &'a [u8],
36
37 /// A global monotonically increasing atomic number, which can be used
38 /// to tell the order of the account update. For example, when an
39 /// account is updated in the same slot multiple times, the update
40 /// with higher write_version should supersede the one with lower
41 /// write_version.
42 pub write_version: u64,
43}
44
45#[derive(Debug, Clone, PartialEq, Eq)]
46#[repr(C)]
47/// Information about an account being updated
48/// (extended with transaction signature doing this update)
49pub struct ReplicaAccountInfoV2<'a> {
50 /// The Pubkey for the account
51 pub pubkey: &'a [u8],
52
53 /// The lamports for the account
54 pub lamports: u64,
55
56 /// The Pubkey of the owner program account
57 pub owner: &'a [u8],
58
59 /// This account's data contains a loaded program (and is now read-only)
60 pub executable: bool,
61
62 /// The epoch at which this account will next owe rent
63 pub rent_epoch: u64,
64
65 /// The data held in this account.
66 pub data: &'a [u8],
67
68 /// A global monotonically increasing atomic number, which can be used
69 /// to tell the order of the account update. For example, when an
70 /// account is updated in the same slot multiple times, the update
71 /// with higher write_version should supersede the one with lower
72 /// write_version.
73 pub write_version: u64,
74
75 /// First signature of the transaction caused this account modification
76 pub txn_signature: Option<&'a Signature>,
77}
78
79#[derive(Debug, Clone, PartialEq, Eq)]
80#[repr(C)]
81/// Information about an account being updated
82/// (extended with reference to transaction doing this update)
83pub struct ReplicaAccountInfoV3<'a> {
84 /// The Pubkey for the account
85 pub pubkey: &'a [u8],
86
87 /// The lamports for the account
88 pub lamports: u64,
89
90 /// The Pubkey of the owner program account
91 pub owner: &'a [u8],
92
93 /// This account's data contains a loaded program (and is now read-only)
94 pub executable: bool,
95
96 /// The epoch at which this account will next owe rent
97 pub rent_epoch: u64,
98
99 /// The data held in this account.
100 pub data: &'a [u8],
101
102 /// A global monotonically increasing atomic number, which can be used
103 /// to tell the order of the account update. For example, when an
104 /// account is updated in the same slot multiple times, the update
105 /// with higher write_version should supersede the one with lower
106 /// write_version.
107 pub write_version: u64,
108
109 /// Reference to transaction causing this account modification
110 pub txn: Option<&'a SanitizedTransaction>,
111}
112
113/// A wrapper to future-proof ReplicaAccountInfo handling.
114/// If there were a change to the structure of ReplicaAccountInfo,
115/// there would be new enum entry for the newer version, forcing
116/// plugin implementations to handle the change.
117#[repr(u32)]
118pub enum ReplicaAccountInfoVersions<'a> {
119 V0_0_1(&'a ReplicaAccountInfo<'a>),
120 V0_0_2(&'a ReplicaAccountInfoV2<'a>),
121 V0_0_3(&'a ReplicaAccountInfoV3<'a>),
122}
123
124/// Information about a transaction
125#[derive(Clone, Debug)]
126#[repr(C)]
127pub struct ReplicaTransactionInfo<'a> {
128 /// The first signature of the transaction, used for identifying the transaction.
129 pub signature: &'a Signature,
130
131 /// Indicates if the transaction is a simple vote transaction.
132 pub is_vote: bool,
133
134 /// The sanitized transaction.
135 pub transaction: &'a SanitizedTransaction,
136
137 /// Metadata of the transaction status.
138 pub transaction_status_meta: &'a TransactionStatusMeta,
139}
140
141/// Information about a transaction, including index in block
142#[derive(Clone, Debug)]
143#[repr(C)]
144pub struct ReplicaTransactionInfoV2<'a> {
145 /// The first signature of the transaction, used for identifying the transaction.
146 pub signature: &'a Signature,
147
148 /// Indicates if the transaction is a simple vote transaction.
149 pub is_vote: bool,
150
151 /// The sanitized transaction.
152 pub transaction: &'a SanitizedTransaction,
153
154 /// Metadata of the transaction status.
155 pub transaction_status_meta: &'a TransactionStatusMeta,
156
157 /// The transaction's index in the block
158 pub index: usize,
159}
160
161/// Information about a transaction, including index in block
162#[derive(Clone, Debug)]
163#[repr(C)]
164pub struct ReplicaTransactionInfoV3<'a> {
165 /// The transaction signature, used for identifying the transaction.
166 pub signature: &'a Signature,
167
168 /// The transaction message hash, used for identifying the transaction.
169 pub message_hash: &'a Hash,
170
171 /// Indicates if the transaction is a simple vote transaction.
172 pub is_vote: bool,
173
174 /// The versioned transaction.
175 pub transaction: &'a VersionedTransaction,
176
177 /// Metadata of the transaction status.
178 pub transaction_status_meta: &'a TransactionStatusMeta,
179
180 /// The transaction's index in the block
181 pub index: usize,
182}
183
184/// A wrapper to future-proof ReplicaTransactionInfo handling.
185/// If there were a change to the structure of ReplicaTransactionInfo,
186/// there would be new enum entry for the newer version, forcing
187/// plugin implementations to handle the change.
188#[repr(u32)]
189pub enum ReplicaTransactionInfoVersions<'a> {
190 V0_0_1(&'a ReplicaTransactionInfo<'a>),
191 V0_0_2(&'a ReplicaTransactionInfoV2<'a>),
192 V0_0_3(&'a ReplicaTransactionInfoV3<'a>),
193}
194
195/// Information about a transaction after deshredding (when entries are formed from shreds).
196/// This is sent before any execution occurs.
197/// Unlike ReplicaTransactionInfo, this does not include TransactionStatusMeta
198/// since execution has not happened yet.
199#[derive(Clone, Debug)]
200#[repr(C)]
201pub struct ReplicaDeshredTransactionInfo<'a> {
202 /// The transaction signature, used for identifying the transaction.
203 pub signature: &'a Signature,
204
205 /// Indicates if the transaction is a simple vote transaction.
206 pub is_vote: bool,
207
208 /// The versioned transaction.
209 pub transaction: &'a VersionedTransaction,
210
211 /// Addresses loaded from address lookup tables for V0 transactions.
212 /// Resolution uses the rooted bank, so address lookup tables created between
213 /// the root slot and the current slot will not resolve. This field is `None`
214 /// for legacy transactions, when the transaction has no address table lookups,
215 /// when ALT resolution is not enabled by the plugin, or when resolution fails
216 /// (e.g. the lookup table account does not exist at the root slot).
217 pub loaded_addresses: Option<&'a LoadedAddresses>,
218}
219
220/// Extends ReplicaDeshredTransactionInfo with metadata about the completed data set that
221/// produced the transaction.
222///
223/// A completed data set is a contiguous range of data shreds whose combined payload deserializes
224/// to a single `Vec<Entry>`. Multiple transactions can share the same completed-data-set range,
225/// and completed data sets for the same slot may be observed out of order. These fields describe
226/// the data-set container; they are not a block-wide transaction index.
227#[derive(Clone, Debug)]
228#[repr(C)]
229pub struct ReplicaDeshredTransactionInfoV2<'a> {
230 /// The transaction signature, used for identifying the transaction.
231 pub signature: &'a Signature,
232
233 /// Indicates if the transaction is a simple vote transaction.
234 pub is_vote: bool,
235
236 /// The versioned transaction.
237 pub transaction: &'a VersionedTransaction,
238
239 /// Addresses loaded from address lookup tables for V0 transactions.
240 pub loaded_addresses: Option<&'a LoadedAddresses>,
241
242 /// The inclusive starting shred index of the completed data set containing this transaction.
243 pub completed_data_set_starting_shred_index: u32,
244
245 /// The exclusive ending shred index of the completed data set containing this transaction.
246 pub completed_data_set_ending_shred_index_exclusive: u32,
247}
248
249/// A wrapper to future-proof ReplicaDeshredTransactionInfo handling.
250#[repr(u32)]
251pub enum ReplicaDeshredTransactionInfoVersions<'a> {
252 V0_0_1(&'a ReplicaDeshredTransactionInfo<'a>),
253 V0_0_2(&'a ReplicaDeshredTransactionInfoV2<'a>),
254}
255
256#[derive(Clone, Debug)]
257#[repr(C)]
258pub struct ReplicaEntryInfo<'a> {
259 /// The slot number of the block containing this Entry
260 pub slot: Slot,
261 /// The Entry's index in the block
262 pub index: usize,
263 /// The number of hashes since the previous Entry
264 pub num_hashes: u64,
265 /// The Entry's SHA-256 hash, generated from the previous Entry's hash with
266 /// `solana_entry::entry::next_hash()`
267 pub hash: &'a [u8],
268 /// The number of executed transactions in the Entry
269 pub executed_transaction_count: u64,
270}
271
272#[derive(Clone, Debug)]
273#[repr(C)]
274pub struct ReplicaEntryInfoV2<'a> {
275 /// The slot number of the block containing this Entry
276 pub slot: Slot,
277 /// The Entry's index in the block
278 pub index: usize,
279 /// The number of hashes since the previous Entry
280 pub num_hashes: u64,
281 /// The Entry's SHA-256 hash, generated from the previous Entry's hash with
282 /// `solana_entry::entry::next_hash()`
283 pub hash: &'a [u8],
284 /// The number of executed transactions in the Entry
285 pub executed_transaction_count: u64,
286 /// The index-in-block of the first executed transaction in this Entry
287 pub starting_transaction_index: usize,
288}
289
290/// A wrapper to future-proof ReplicaEntryInfo handling. To make a change to the structure of
291/// ReplicaEntryInfo, add an new enum variant wrapping a newer version, which will force plugin
292/// implementations to handle the change.
293#[repr(u32)]
294pub enum ReplicaEntryInfoVersions<'a> {
295 V0_0_1(&'a ReplicaEntryInfo<'a>),
296 V0_0_2(&'a ReplicaEntryInfoV2<'a>),
297}
298
299#[derive(Clone, Debug)]
300#[repr(C)]
301pub struct ReplicaBlockInfo<'a> {
302 pub slot: Slot,
303 pub blockhash: &'a str,
304 pub rewards: &'a [Reward],
305 pub block_time: Option<UnixTimestamp>,
306 pub block_height: Option<u64>,
307}
308
309/// Extending ReplicaBlockInfo by sending the executed_transaction_count.
310#[derive(Clone, Debug)]
311#[repr(C)]
312pub struct ReplicaBlockInfoV2<'a> {
313 pub parent_slot: Slot,
314 pub parent_blockhash: &'a str,
315 pub slot: Slot,
316 pub blockhash: &'a str,
317 pub rewards: &'a [Reward],
318 pub block_time: Option<UnixTimestamp>,
319 pub block_height: Option<u64>,
320 pub executed_transaction_count: u64,
321}
322
323/// Extending ReplicaBlockInfo by sending the entries_count.
324#[derive(Clone, Debug)]
325#[repr(C)]
326pub struct ReplicaBlockInfoV3<'a> {
327 pub parent_slot: Slot,
328 pub parent_blockhash: &'a str,
329 pub slot: Slot,
330 pub blockhash: &'a str,
331 pub rewards: &'a [Reward],
332 pub block_time: Option<UnixTimestamp>,
333 pub block_height: Option<u64>,
334 pub executed_transaction_count: u64,
335 pub entry_count: u64,
336}
337
338/// Extending ReplicaBlockInfo by sending RewardsAndNumPartitions.
339#[derive(Clone, Debug)]
340#[repr(C)]
341pub struct ReplicaBlockInfoV4<'a> {
342 pub parent_slot: Slot,
343 pub parent_blockhash: &'a str,
344 pub slot: Slot,
345 pub blockhash: &'a str,
346 pub rewards: &'a RewardsAndNumPartitions,
347 pub block_time: Option<UnixTimestamp>,
348 pub block_height: Option<u64>,
349 pub executed_transaction_count: u64,
350 pub entry_count: u64,
351}
352
353#[repr(u32)]
354pub enum ReplicaBlockInfoVersions<'a> {
355 V0_0_1(&'a ReplicaBlockInfo<'a>),
356 V0_0_2(&'a ReplicaBlockInfoV2<'a>),
357 V0_0_3(&'a ReplicaBlockInfoV3<'a>),
358 V0_0_4(&'a ReplicaBlockInfoV4<'a>),
359}
360
361/// A snapshot of a validator's gossip contact info at a point in time.
362///
363/// Delivered to plugins that opt into contact info notifications. Every
364/// field is an owned/borrowed plain value — no internal Agave types leak
365/// into the plugin ABI.
366///
367/// `pubkey` is the 32-byte validator identity. Socket fields are `None`
368/// when the validator has not advertised that endpoint.
369#[derive(Clone, Debug, PartialEq, Eq)]
370#[repr(C)]
371pub struct ReplicaContactInfoV0_0_1<'a> {
372 /// The 32-byte validator identity pubkey.
373 pub pubkey: &'a [u8],
374
375 /// Logical timestamp (milliseconds since UNIX epoch) advertised by the
376 /// validator. Advances on every contact info republish.
377 pub wallclock: u64,
378
379 /// The time (microseconds since UNIX epoch) at which this validator
380 /// instance was created. Combined with `wallclock`, forms the tuple
381 /// used by gossip to order contact info versions.
382 pub outset: u64,
383
384 /// Cluster shred version the validator is running.
385 pub shred_version: u16,
386
387 /// Major component of the validator's software version (e.g. `1` in
388 /// `1.18.25`). Plain integers are used rather than a formatted string
389 /// so that the dispatch path is allocation-free; consumers can
390 /// `format!("{}.{}.{}", major, minor, patch)` if they want a string.
391 pub version_major: u16,
392
393 /// Minor component of the validator's software version.
394 pub version_minor: u16,
395
396 /// Patch component of the validator's software version.
397 pub version_patch: u16,
398
399 /// First four bytes of the build commit hash advertised by the
400 /// validator (`0` when unset).
401 pub version_commit: u32,
402
403 /// Active feature set (gossip-advertised). Used by consumers to
404 /// determine which protocol features the validator supports without
405 /// querying RPC.
406 pub version_feature_set: u32,
407
408 /// Client identifier as defined by `solana_version::ClientId`'s
409 /// `u16` encoding (0 = SolanaLabs, 3 = Agave, 5 = Firedancer, ...).
410 /// Consumers should treat unknown values as opaque.
411 pub version_client_id: u16,
412
413 /// Gossip endpoint.
414 pub gossip: Option<SocketAddr>,
415
416 /// TPU QUIC endpoint (where clients send transactions).
417 pub tpu_quic: Option<SocketAddr>,
418
419 /// TPU forwards QUIC endpoint.
420 pub tpu_forwards_quic: Option<SocketAddr>,
421
422 /// TPU vote UDP endpoint.
423 pub tpu_vote_udp: Option<SocketAddr>,
424
425 /// TPU vote QUIC endpoint.
426 pub tpu_vote_quic: Option<SocketAddr>,
427
428 /// TVU UDP endpoint.
429 pub tvu_udp: Option<SocketAddr>,
430
431 /// TVU QUIC endpoint.
432 pub tvu_quic: Option<SocketAddr>,
433
434 /// Serve-repair UDP endpoint.
435 pub serve_repair_udp: Option<SocketAddr>,
436
437 /// Serve-repair QUIC endpoint.
438 pub serve_repair_quic: Option<SocketAddr>,
439
440 /// JSON-RPC endpoint, if advertised.
441 pub rpc: Option<SocketAddr>,
442
443 /// JSON-RPC pubsub (websocket) endpoint, if advertised.
444 pub rpc_pubsub: Option<SocketAddr>,
445
446 /// Alpenglow consensus endpoint, if advertised.
447 pub alpenglow: Option<SocketAddr>,
448}
449
450/// A wrapper to future-proof ReplicaContactInfo handling.
451/// If there were a change to the structure of ReplicaContactInfo,
452/// there would be a new enum entry for the newer version, forcing
453/// plugin implementations to handle the change.
454#[repr(u32)]
455pub enum ReplicaContactInfoVersions<'a> {
456 V0_0_1(&'a ReplicaContactInfoV0_0_1<'a>),
457}
458
459/// Errors returned by plugin calls
460#[derive(Error, Debug)]
461#[repr(u32)]
462pub enum GeyserPluginError {
463 /// Error opening the configuration file; for example, when the file
464 /// is not found or when the validator process has no permission to read it.
465 #[error("Error opening config file. Error detail: ({0}).")]
466 ConfigFileOpenError(#[from] io::Error),
467
468 /// Error in reading the content of the config file or the content
469 /// is not in the expected format.
470 #[error("Error reading config file. Error message: ({msg})")]
471 ConfigFileReadError { msg: String },
472
473 /// Error when updating the account.
474 #[error("Error updating account. Error message: ({msg})")]
475 AccountsUpdateError { msg: String },
476
477 /// Error when updating the slot status
478 #[error("Error updating slot status. Error message: ({msg})")]
479 SlotStatusUpdateError { msg: String },
480
481 /// Any custom error defined by the plugin.
482 #[error("Plugin-defined custom error. Error message: ({0})")]
483 Custom(Box<dyn error::Error + Send + Sync>),
484
485 /// Error when updating the transaction.
486 #[error("Error updating transaction. Error message: ({msg})")]
487 TransactionUpdateError { msg: String },
488}
489
490/// The current status of a slot
491#[derive(Debug, Clone, PartialEq, Eq)]
492#[repr(u32)]
493pub enum SlotStatus {
494 /// The highest slot of the heaviest fork processed by the node. Ledger state at this slot is
495 /// not derived from a confirmed or finalized block, but if multiple forks are present, is from
496 /// the fork the validator believes is most likely to finalize.
497 Processed,
498
499 /// The highest slot having reached max vote lockout.
500 Rooted,
501
502 /// The highest slot that has been voted on by supermajority of the cluster, ie. is confirmed.
503 Confirmed,
504
505 /// First Shred Received
506 FirstShredReceived,
507
508 /// All shreds for the slot have been received.
509 Completed,
510
511 /// A new bank fork is created with the slot
512 CreatedBank,
513
514 /// A slot is marked dead
515 Dead(String),
516}
517
518impl SlotStatus {
519 pub fn as_str(&self) -> &'static str {
520 match self {
521 SlotStatus::Confirmed => "confirmed",
522 SlotStatus::Processed => "processed",
523 SlotStatus::Rooted => "rooted",
524 SlotStatus::FirstShredReceived => "first_shred_received",
525 SlotStatus::Completed => "completed",
526 SlotStatus::CreatedBank => "created_bank",
527 SlotStatus::Dead(_error) => "dead",
528 }
529 }
530}
531
532pub type Result<T> = std::result::Result<T, GeyserPluginError>;
533
534/// Defines a Geyser plugin, to stream data from the runtime.
535/// Geyser plugins must describe desired behavior for load and unload,
536/// as well as how they will handle streamed data.
537pub trait GeyserPlugin: Any + Send + Sync + std::fmt::Debug {
538 /// The callback to allow the plugin to setup the logging configuration using the logger
539 /// and log level specified by the validator. Will be called first on load/reload, before any other
540 /// callback, and only called once.
541 /// # Examples
542 ///
543 /// ```
544 /// use agave_geyser_plugin_interface::geyser_plugin_interface::{GeyserPlugin,
545 /// GeyserPluginError, Result};
546 ///
547 /// #[derive(Debug)]
548 /// struct SamplePlugin;
549 /// impl GeyserPlugin for SamplePlugin {
550 /// fn setup_logger(&self, logger: &'static dyn log::Log, level: log::LevelFilter) -> Result<()> {
551 /// log::set_max_level(level);
552 /// if let Err(err) = log::set_logger(logger) {
553 /// return Err(GeyserPluginError::Custom(Box::new(err)));
554 /// }
555 /// Ok(())
556 /// }
557 /// fn name(&self) -> &'static str {
558 /// &"sample"
559 /// }
560 /// }
561 /// ```
562 #[allow(unused_variables)]
563 fn setup_logger(&self, logger: &'static dyn log::Log, level: log::LevelFilter) -> Result<()> {
564 Ok(())
565 }
566
567 fn name(&self) -> &'static str;
568
569 /// The callback called when a plugin is loaded by the system,
570 /// used for doing whatever initialization is required by the plugin.
571 /// The _config_file contains the name of the
572 /// of the config file. The config must be in JSON format and
573 /// include a field "libpath" indicating the full path
574 /// name of the shared library implementing this interface.
575 fn on_load(&mut self, _config_file: &str, _is_reload: bool) -> Result<()> {
576 Ok(())
577 }
578
579 /// The callback called right before a plugin is unloaded by the system
580 /// Used for doing cleanup before unload.
581 fn on_unload(&mut self) {}
582
583 /// Called when an account is updated at a slot.
584 /// When `is_startup` is true, it indicates the account is loaded from
585 /// snapshots when the validator starts up. When `is_startup` is false,
586 /// the account is updated during transaction processing.
587 #[allow(unused_variables)]
588 fn update_account(
589 &self,
590 account: ReplicaAccountInfoVersions,
591 slot: Slot,
592 is_startup: bool,
593 ) -> Result<()> {
594 Ok(())
595 }
596
597 /// Called when all accounts are notified of during startup.
598 fn notify_end_of_startup(&self) -> Result<()> {
599 Ok(())
600 }
601
602 /// Called when a slot status is updated
603 #[allow(unused_variables)]
604 fn update_slot_status(
605 &self,
606 slot: Slot,
607 parent: Option<u64>,
608 status: &SlotStatus,
609 ) -> Result<()> {
610 Ok(())
611 }
612
613 /// Called when a transaction is processed in a slot.
614 #[allow(unused_variables)]
615 fn notify_transaction(
616 &self,
617 transaction: ReplicaTransactionInfoVersions,
618 slot: Slot,
619 ) -> Result<()> {
620 Ok(())
621 }
622
623 /// Called when an entry is executed.
624 #[allow(unused_variables)]
625 fn notify_entry(&self, entry: ReplicaEntryInfoVersions) -> Result<()> {
626 Ok(())
627 }
628
629 /// Called when block's metadata is updated.
630 #[allow(unused_variables)]
631 fn notify_block_metadata(&self, blockinfo: ReplicaBlockInfoVersions) -> Result<()> {
632 Ok(())
633 }
634
635 /// Called when a validator's gossip contact info is learned or updated.
636 ///
637 /// `is_startup` is true when this call is part of the initial state
638 /// dump delivered synchronously after the plugin is loaded (every
639 /// currently-known validator's latest contact info is delivered once
640 /// with `is_startup=true` before any live updates). Subsequent live
641 /// updates driven by gossip activity are delivered with `is_startup=false`.
642 ///
643 /// Delivery is best-effort: under extreme load, updates may be dropped
644 /// to keep the gossip subsystem unaffected. Contact info is rebroadcast
645 /// on a multi-second cadence by validators, so consumers self-heal on
646 /// the next republish.
647 ///
648 /// Only called when `contact_info_notifications_enabled()` returns true.
649 #[allow(unused_variables)]
650 fn notify_contact_info(
651 &self,
652 info: ReplicaContactInfoVersions,
653 is_startup: bool,
654 ) -> Result<()> {
655 Ok(())
656 }
657
658 /// Called when a validator's gossip contact info is removed from CRDS.
659 /// Plugins that maintain a cache keyed on validator identity should
660 /// invalidate the entry for `pubkey` on receipt of this notification.
661 ///
662 /// Fires for both timeout-based purges (the validator stopped
663 /// gossiping; their entry aged out per stake-aware CRDS timeouts) and
664 /// size-based trims (CRDS exceeded its capacity and evicted older
665 /// entries). The pubkey is the 32-byte validator identity that was
666 /// last seen via `notify_contact_info`.
667 ///
668 /// Like `notify_contact_info`, this is best-effort: under extreme
669 /// load a removal event may be dropped (the `gossip_contact_info_dropped`
670 /// counter is bumped when this happens). Consumers that need strict
671 /// liveness guarantees should pair this notification with their own
672 /// wallclock-staleness check on cached entries.
673 ///
674 /// Only called when `contact_info_notifications_enabled()` returns true.
675 #[allow(unused_variables)]
676 fn notify_contact_info_removed(&self, pubkey: &[u8]) -> Result<()> {
677 Ok(())
678 }
679
680 /// Check if the plugin is interested in account data
681 /// Default is true -- if the plugin is not interested in
682 /// account data, please return false.
683 fn account_data_notifications_enabled(&self) -> bool {
684 true
685 }
686
687 /// Check if the plugin is interested in account data from snapshot
688 /// Default is true -- if the plugin is not interested in
689 /// account data snapshot, please return false because startup would be
690 /// improved significantly.
691 fn account_data_snapshot_notifications_enabled(&self) -> bool {
692 true
693 }
694
695 /// Check if the plugin is interested in transaction data
696 /// Default is false -- if the plugin is interested in
697 /// transaction data, please return true.
698 fn transaction_notifications_enabled(&self) -> bool {
699 false
700 }
701
702 /// Check if the plugin is interested in entry data
703 /// Default is false -- if the plugin is interested in
704 /// entry data, return true.
705 fn entry_notifications_enabled(&self) -> bool {
706 false
707 }
708
709 /// Check if the plugin is interested in validator contact info updates
710 /// sourced from gossip. Default is false — if the plugin wants contact
711 /// info notifications, return true. When no loaded plugin returns true,
712 /// the validator bypasses all contact-info notification machinery
713 /// (no dispatch thread, no channel, zero hot-path overhead).
714 fn contact_info_notifications_enabled(&self) -> bool {
715 false
716 }
717
718 /// Called when a transaction is deshredded (entries formed from shreds).
719 /// This is triggered before any execution occurs. Unlike notify_transaction,
720 /// this does not include execution metadata (TransactionStatusMeta).
721 #[allow(unused_variables)]
722 fn notify_deshred_transaction(
723 &self,
724 transaction: ReplicaDeshredTransactionInfoVersions,
725 slot: Slot,
726 ) -> Result<()> {
727 Ok(())
728 }
729
730 /// Check if the plugin is interested in deshred transaction data.
731 /// Default is false -- if the plugin is interested in receiving
732 /// transactions when they are deshredded, return true.
733 fn deshred_transaction_notifications_enabled(&self) -> bool {
734 false
735 }
736
737 /// Check if the plugin wants address lookup table (ALT) resolution for
738 /// deshred transactions. Default is false. When true, the validator will
739 /// resolve V0 transaction address lookups using the rooted bank and
740 /// populate `loaded_addresses` in `ReplicaDeshredTransactionInfo`.
741 /// This adds accounts DB I/O on the shred insertion path, so plugins
742 /// that only need the raw transaction should leave this disabled.
743 fn deshred_transaction_alt_resolution_enabled(&self) -> bool {
744 false
745 }
746}