solana_runtime/
stake_history.rs1pub use solana_sysvar::stake_history::StakeHistoryGetEntry;
4use {
5 solana_clock::Epoch,
6 solana_sysvar::stake_history::{self, StakeHistoryEntry},
7 std::{
8 ops::{Deref, DerefMut},
9 sync::Arc,
10 },
11};
12
13#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
15#[derive(Default, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
16pub struct StakeHistory(Arc<StakeHistoryInner>);
17
18impl Deref for StakeHistory {
19 type Target = StakeHistoryInner;
20 fn deref(&self) -> &Self::Target {
21 &self.0
22 }
23}
24
25impl DerefMut for StakeHistory {
26 fn deref_mut(&mut self) -> &mut Self::Target {
27 Arc::make_mut(&mut self.0)
28 }
29}
30
31type StakeHistoryInner = stake_history::StakeHistory;
33
34impl StakeHistoryGetEntry for StakeHistory {
35 fn get_entry(&self, epoch: Epoch) -> Option<StakeHistoryEntry> {
36 self.0.get_entry(epoch)
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use {super::*, solana_sysvar::stake_history::StakeHistoryEntry};
43
44 fn rand_stake_history_entry() -> StakeHistoryEntry {
45 StakeHistoryEntry {
46 effective: rand::random(),
47 activating: rand::random(),
48 deactivating: rand::random(),
49 }
50 }
51
52 #[test]
54 fn test_stake_history_is_cow() {
55 let mut stake_history = StakeHistory::default();
56 (100..109).for_each(|epoch| {
57 let entry = rand_stake_history_entry();
58 stake_history.add(epoch, entry);
59 });
60
61 {
64 let stake_history2 = stake_history.clone();
65 assert_eq!(stake_history, stake_history2);
66 assert!(
67 Arc::ptr_eq(&stake_history.0, &stake_history2.0),
68 "Inner Arc must point to the same underlying instance"
69 );
70 assert!(
71 std::ptr::eq(stake_history.deref(), stake_history2.deref()),
72 "Deref must point to the same underlying instance"
73 );
74 }
75
76 {
79 let mut stake_history2 = stake_history.clone();
80 assert_eq!(stake_history, stake_history2);
81 (200..209).for_each(|epoch| {
82 let entry = rand_stake_history_entry();
83 stake_history2.add(epoch, entry);
84 });
85 assert_ne!(stake_history, stake_history2);
86 assert!(
87 !Arc::ptr_eq(&stake_history.0, &stake_history2.0),
88 "Inner Arc must point to a different underlying instance"
89 );
90 assert!(
91 !std::ptr::eq(stake_history.deref(), stake_history2.deref()),
92 "Deref must point to a different underlying instance"
93 );
94 }
95 }
96
97 #[test]
99 fn test_stake_history_serde() {
100 let mut stake_history_outer = StakeHistory::default();
101 let mut stake_history_inner = StakeHistoryInner::default();
102 (2134..).take(11).for_each(|epoch| {
103 let entry = rand_stake_history_entry();
104 stake_history_outer.add(epoch, entry.clone());
105 stake_history_inner.add(epoch, entry);
106 });
107
108 assert_eq!(
110 bincode::serialize(&stake_history_outer).unwrap(),
111 bincode::serialize(&stake_history_inner).unwrap(),
112 );
113
114 {
117 let data = bincode::serialize(&stake_history_outer).unwrap();
118 let deserialized_inner: StakeHistoryInner = bincode::deserialize(&data).unwrap();
119 assert_eq!(&deserialized_inner, stake_history_outer.deref());
120 }
121
122 {
125 let data = bincode::serialize(&stake_history_inner).unwrap();
126 let deserialized_outer: StakeHistory = bincode::deserialize(&data).unwrap();
127 assert_eq!(deserialized_outer.deref(), &stake_history_inner);
128 }
129 }
130}