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