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}