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}