1#![cfg(feature = "full")]
5
6use {
7 byteorder::{ByteOrder, LittleEndian},
8 solana_sdk::clock::Slot,
9};
10
11#[derive(Default, Clone, Debug, Deserialize, Serialize, AbiExample, PartialEq, Eq)]
12pub struct HardForks {
13 hard_forks: Vec<(Slot, usize)>,
14}
15impl HardForks {
16 pub fn register(&mut self, new_slot: Slot) {
18 if let Some(i) = self
19 .hard_forks
20 .iter()
21 .position(|(slot, _)| *slot == new_slot)
22 {
23 self.hard_forks[i] = (new_slot, self.hard_forks[i].1.saturating_add(1));
24 } else {
25 self.hard_forks.push((new_slot, 1));
26 }
27 #[allow(clippy::stable_sort_primitive)]
28 self.hard_forks.sort();
29 }
30
31 pub fn iter(&self) -> std::slice::Iter<(Slot, usize)> {
33 self.hard_forks.iter()
34 }
35
36 pub fn get_hash_data(&self, slot: Slot, parent_slot: Slot) -> Option<[u8; 8]> {
38 let fork_count: usize = self
42 .hard_forks
43 .iter()
44 .map(|(fork_slot, fork_count)| {
45 if parent_slot < *fork_slot && slot >= *fork_slot {
46 *fork_count
47 } else {
48 0
49 }
50 })
51 .sum();
52
53 if fork_count > 0 {
54 let mut buf = [0u8; 8];
55 LittleEndian::write_u64(&mut buf[..], fork_count as u64);
56 Some(buf)
57 } else {
58 None
59 }
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66
67 #[test]
68 fn iter_is_sorted() {
69 let mut hf = HardForks::default();
70 hf.register(30);
71 hf.register(20);
72 hf.register(10);
73 hf.register(20);
74
75 assert_eq!(hf.hard_forks, vec![(10, 1), (20, 2), (30, 1)]);
76 }
77
78 #[test]
79 fn multiple_hard_forks_since_parent() {
80 let mut hf = HardForks::default();
81 hf.register(10);
82 hf.register(20);
83
84 assert_eq!(hf.get_hash_data(9, 0), None);
85 assert_eq!(hf.get_hash_data(10, 0), Some([1, 0, 0, 0, 0, 0, 0, 0,]));
86 assert_eq!(hf.get_hash_data(19, 0), Some([1, 0, 0, 0, 0, 0, 0, 0,]));
87 assert_eq!(hf.get_hash_data(20, 0), Some([2, 0, 0, 0, 0, 0, 0, 0,]));
88 assert_eq!(hf.get_hash_data(20, 10), Some([1, 0, 0, 0, 0, 0, 0, 0,]));
89 assert_eq!(hf.get_hash_data(20, 11), Some([1, 0, 0, 0, 0, 0, 0, 0,]));
90 assert_eq!(hf.get_hash_data(21, 11), Some([1, 0, 0, 0, 0, 0, 0, 0,]));
91 assert_eq!(hf.get_hash_data(21, 20), None);
92 }
93}