Skip to main content

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}