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