solana_sdk/
recent_blockhashes_account.rs

1#[allow(deprecated)]
2use solana_program::sysvar::recent_blockhashes::{
3    IntoIterSorted, IterItem, RecentBlockhashes, MAX_ENTRIES,
4};
5use {
6    crate::{
7        account::{
8            create_account_shared_data_with_fields, to_account, AccountSharedData,
9            InheritableAccountFields, DUMMY_INHERITABLE_ACCOUNT_FIELDS,
10        },
11        clock::INITIAL_RENT_EPOCH,
12    },
13    std::{collections::BinaryHeap, iter::FromIterator},
14};
15
16#[deprecated(
17    since = "1.9.0",
18    note = "Please do not use, will no longer be available in the future"
19)]
20#[allow(deprecated)]
21pub fn update_account<'a, I>(
22    account: &mut AccountSharedData,
23    recent_blockhash_iter: I,
24) -> Option<()>
25where
26    I: IntoIterator<Item = IterItem<'a>>,
27{
28    let sorted = BinaryHeap::from_iter(recent_blockhash_iter);
29    #[allow(deprecated)]
30    let sorted_iter = IntoIterSorted::new(sorted);
31    #[allow(deprecated)]
32    let recent_blockhash_iter = sorted_iter.take(MAX_ENTRIES);
33    #[allow(deprecated)]
34    let recent_blockhashes: RecentBlockhashes = recent_blockhash_iter.collect();
35    to_account(&recent_blockhashes, account)
36}
37
38#[deprecated(
39    since = "1.5.17",
40    note = "Please use `create_account_with_data_for_test` instead"
41)]
42#[allow(deprecated)]
43pub fn create_account_with_data<'a, I>(lamports: u64, recent_blockhash_iter: I) -> AccountSharedData
44where
45    I: IntoIterator<Item = IterItem<'a>>,
46{
47    #[allow(deprecated)]
48    create_account_with_data_and_fields(recent_blockhash_iter, (lamports, INITIAL_RENT_EPOCH))
49}
50
51#[deprecated(
52    since = "1.9.0",
53    note = "Please do not use, will no longer be available in the future"
54)]
55#[allow(deprecated)]
56pub fn create_account_with_data_and_fields<'a, I>(
57    recent_blockhash_iter: I,
58    fields: InheritableAccountFields,
59) -> AccountSharedData
60where
61    I: IntoIterator<Item = IterItem<'a>>,
62{
63    let mut account = create_account_shared_data_with_fields::<RecentBlockhashes>(
64        &RecentBlockhashes::default(),
65        fields,
66    );
67    update_account(&mut account, recent_blockhash_iter).unwrap();
68    account
69}
70
71#[deprecated(
72    since = "1.9.0",
73    note = "Please do not use, will no longer be available in the future"
74)]
75#[allow(deprecated)]
76pub fn create_account_with_data_for_test<'a, I>(recent_blockhash_iter: I) -> AccountSharedData
77where
78    I: IntoIterator<Item = IterItem<'a>>,
79{
80    create_account_with_data_and_fields(recent_blockhash_iter, DUMMY_INHERITABLE_ACCOUNT_FIELDS)
81}
82
83#[cfg(test)]
84mod tests {
85    #![allow(deprecated)]
86    use {
87        super::*,
88        crate::account::from_account,
89        rand::{seq::SliceRandom, thread_rng},
90        solana_program::{
91            hash::{Hash, HASH_BYTES},
92            sysvar::recent_blockhashes::Entry,
93        },
94    };
95
96    #[test]
97    fn test_create_account_empty() {
98        let account = create_account_with_data_for_test(vec![].into_iter());
99        let recent_blockhashes = from_account::<RecentBlockhashes, _>(&account).unwrap();
100        assert_eq!(recent_blockhashes, RecentBlockhashes::default());
101    }
102
103    #[test]
104    fn test_create_account_full() {
105        let def_hash = Hash::default();
106        let def_lamports_per_signature = 0;
107        let account = create_account_with_data_for_test(
108            vec![IterItem(0u64, &def_hash, def_lamports_per_signature); MAX_ENTRIES].into_iter(),
109        );
110        let recent_blockhashes = from_account::<RecentBlockhashes, _>(&account).unwrap();
111        assert_eq!(recent_blockhashes.len(), MAX_ENTRIES);
112    }
113
114    #[test]
115    fn test_create_account_truncate() {
116        let def_hash = Hash::default();
117        let def_lamports_per_signature = 0;
118        let account = create_account_with_data_for_test(
119            vec![IterItem(0u64, &def_hash, def_lamports_per_signature); MAX_ENTRIES + 1]
120                .into_iter(),
121        );
122        let recent_blockhashes = from_account::<RecentBlockhashes, _>(&account).unwrap();
123        assert_eq!(recent_blockhashes.len(), MAX_ENTRIES);
124    }
125
126    #[test]
127    fn test_create_account_unsorted() {
128        let def_lamports_per_signature = 0;
129        let mut unsorted_blocks: Vec<_> = (0..MAX_ENTRIES)
130            .map(|i| {
131                (i as u64, {
132                    // create hash with visibly recognizable ordering
133                    let mut h = [0; HASH_BYTES];
134                    h[HASH_BYTES - 1] = i as u8;
135                    Hash::new(&h)
136                })
137            })
138            .collect();
139        unsorted_blocks.shuffle(&mut thread_rng());
140
141        let account = create_account_with_data_for_test(
142            unsorted_blocks
143                .iter()
144                .map(|(i, hash)| IterItem(*i, hash, def_lamports_per_signature)),
145        );
146        let recent_blockhashes = from_account::<RecentBlockhashes, _>(&account).unwrap();
147
148        let mut unsorted_recent_blockhashes: Vec<_> = unsorted_blocks
149            .iter()
150            .map(|(i, hash)| IterItem(*i, hash, def_lamports_per_signature))
151            .collect();
152        unsorted_recent_blockhashes.sort();
153        unsorted_recent_blockhashes.reverse();
154        let expected_recent_blockhashes: Vec<_> = (unsorted_recent_blockhashes
155            .into_iter()
156            .map(|IterItem(_, b, f)| Entry::new(b, f)))
157        .collect();
158
159        assert_eq!(*recent_blockhashes, expected_recent_blockhashes);
160    }
161}