solana_slot_hashes/
lib.rs1#[cfg(feature = "sysvar")]
10pub mod sysvar;
11
12use {
13 solana_hash::Hash,
14 std::{
15 iter::FromIterator,
16 ops::Deref,
17 sync::atomic::{AtomicUsize, Ordering},
18 },
19};
20
21pub const MAX_ENTRIES: usize = 512; static NUM_ENTRIES: AtomicUsize = AtomicUsize::new(MAX_ENTRIES);
26
27pub fn get_entries() -> usize {
28 NUM_ENTRIES.load(Ordering::Relaxed)
29}
30
31pub fn set_entries_for_tests_only(entries: usize) {
32 NUM_ENTRIES.store(entries, Ordering::Relaxed);
33}
34
35pub type SlotHash = (u64, Hash);
36
37#[repr(C)]
38#[cfg_attr(
39 feature = "serde",
40 derive(serde_derive::Deserialize, serde_derive::Serialize)
41)]
42#[derive(PartialEq, Eq, Debug, Default)]
43pub struct SlotHashes(Vec<SlotHash>);
44
45impl SlotHashes {
46 pub fn add(&mut self, slot: u64, hash: Hash) {
47 match self.binary_search_by(|(probe, _)| slot.cmp(probe)) {
48 Ok(index) => (self.0)[index] = (slot, hash),
49 Err(index) => (self.0).insert(index, (slot, hash)),
50 }
51 (self.0).truncate(get_entries());
52 }
53 pub fn position(&self, slot: &u64) -> Option<usize> {
54 self.binary_search_by(|(probe, _)| slot.cmp(probe)).ok()
55 }
56 #[allow(clippy::trivially_copy_pass_by_ref)]
57 pub fn get(&self, slot: &u64) -> Option<&Hash> {
58 self.binary_search_by(|(probe, _)| slot.cmp(probe))
59 .ok()
60 .map(|index| &self[index].1)
61 }
62 pub fn new(slot_hashes: &[SlotHash]) -> Self {
63 let mut slot_hashes = slot_hashes.to_vec();
64 slot_hashes.sort_by(|(a, _), (b, _)| b.cmp(a));
65 Self(slot_hashes)
66 }
67 pub fn slot_hashes(&self) -> &[SlotHash] {
68 &self.0
69 }
70}
71
72impl FromIterator<(u64, Hash)> for SlotHashes {
73 fn from_iter<I: IntoIterator<Item = (u64, Hash)>>(iter: I) -> Self {
74 Self(iter.into_iter().collect())
75 }
76}
77
78impl Deref for SlotHashes {
79 type Target = Vec<SlotHash>;
80 fn deref(&self) -> &Self::Target {
81 &self.0
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use {super::*, solana_sha256_hasher::hash};
88
89 #[test]
90 fn test() {
91 let mut slot_hashes = SlotHashes::new(&[(1, Hash::default()), (3, Hash::default())]);
92 slot_hashes.add(2, Hash::default());
93 assert_eq!(
94 slot_hashes,
95 SlotHashes(vec![
96 (3, Hash::default()),
97 (2, Hash::default()),
98 (1, Hash::default()),
99 ])
100 );
101
102 let mut slot_hashes = SlotHashes::new(&[]);
103 for i in 0..MAX_ENTRIES + 1 {
104 slot_hashes.add(
105 i as u64,
106 hash(&[(i >> 24) as u8, (i >> 16) as u8, (i >> 8) as u8, i as u8]),
107 );
108 }
109 for i in 0..MAX_ENTRIES {
110 assert_eq!(slot_hashes[i].0, (MAX_ENTRIES - i) as u64);
111 }
112
113 assert_eq!(slot_hashes.len(), MAX_ENTRIES);
114 }
115}