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