waffles_solana_program/sysvar/
stake_history.rs

1//! History of stake activations and de-activations.
2//!
3//! The _stake history sysvar_ provides access to the [`StakeHistory`] type.
4//!
5//! The [`Sysvar::get`] method always returns
6//! [`ProgramError::UnsupportedSysvar`], and in practice the data size of this
7//! sysvar is too large to process on chain. One can still use the
8//! [`SysvarId::id`], [`SysvarId::check_id`] and [`Sysvar::size_of`] methods in
9//! an on-chain program, and it can be accessed off-chain through RPC.
10//!
11//! [`ProgramError::UnsupportedSysvar`]: crate::program_error::ProgramError::UnsupportedSysvar
12//! [`SysvarId::id`]: crate::sysvar::SysvarId::id
13//! [`SysvarId::check_id`]: crate::sysvar::SysvarId::check_id
14//!
15//! # Examples
16//!
17//! Calling via the RPC client:
18//!
19//! ```
20//! # use solana_program::example_mocks::solana_sdk;
21//! # use solana_program::example_mocks::solana_rpc_client;
22//! # use solana_sdk::account::Account;
23//! # use solana_rpc_client::rpc_client::RpcClient;
24//! # use solana_sdk::sysvar::stake_history::{self, StakeHistory};
25//! # use anyhow::Result;
26//! #
27//! fn print_sysvar_stake_history(client: &RpcClient) -> Result<()> {
28//! #   client.set_get_account_response(stake_history::ID, Account {
29//! #       lamports: 114979200,
30//! #       data: vec![0, 0, 0, 0, 0, 0, 0, 0],
31//! #       owner: solana_sdk::system_program::ID,
32//! #       executable: false,
33//! #       rent_epoch: 307,
34//! #   });
35//! #
36//!     let stake_history = client.get_account(&stake_history::ID)?;
37//!     let data: StakeHistory = bincode::deserialize(&stake_history.data)?;
38//!
39//!     Ok(())
40//! }
41//! #
42//! # let client = RpcClient::new(String::new());
43//! # print_sysvar_stake_history(&client)?;
44//! #
45//! # Ok::<(), anyhow::Error>(())
46//! ```
47
48pub use crate::stake_history::StakeHistory;
49use crate::sysvar::Sysvar;
50
51crate::declare_sysvar_id!("SysvarStakeHistory1111111111111111111111111", StakeHistory);
52
53impl Sysvar for StakeHistory {
54    // override
55    fn size_of() -> usize {
56        // hard-coded so that we don't have to construct an empty
57        16392 // golden, update if MAX_ENTRIES changes
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use {super::*, crate::stake_history::*};
64
65    #[test]
66    fn test_size_of() {
67        let mut stake_history = StakeHistory::default();
68        for i in 0..MAX_ENTRIES as u64 {
69            stake_history.add(
70                i,
71                StakeHistoryEntry {
72                    activating: i,
73                    ..StakeHistoryEntry::default()
74                },
75            );
76        }
77
78        assert_eq!(
79            bincode::serialized_size(&stake_history).unwrap() as usize,
80            StakeHistory::size_of()
81        );
82    }
83
84    #[test]
85    fn test_create_account() {
86        let mut stake_history = StakeHistory::default();
87        for i in 0..MAX_ENTRIES as u64 + 1 {
88            stake_history.add(
89                i,
90                StakeHistoryEntry {
91                    activating: i,
92                    ..StakeHistoryEntry::default()
93                },
94            );
95        }
96        assert_eq!(stake_history.len(), MAX_ENTRIES);
97        assert_eq!(stake_history.iter().map(|entry| entry.0).min().unwrap(), 1);
98        assert_eq!(stake_history.get(0), None);
99        assert_eq!(
100            stake_history.get(1),
101            Some(&StakeHistoryEntry {
102                activating: 1,
103                ..StakeHistoryEntry::default()
104            })
105        );
106    }
107}