2022-12-22 00:58:06 -08:00
|
|
|
//! Helpers for the recent blockhashes sysvar.
|
|
|
|
|
2021-07-27 16:34:21 -07:00
|
|
|
#[allow(deprecated)]
|
2020-10-28 22:01:07 -07:00
|
|
|
use solana_program::sysvar::recent_blockhashes::{
|
|
|
|
IntoIterSorted, IterItem, RecentBlockhashes, MAX_ENTRIES,
|
|
|
|
};
|
2021-12-03 09:00:31 -08:00
|
|
|
use {
|
|
|
|
crate::{
|
|
|
|
account::{
|
|
|
|
create_account_shared_data_with_fields, to_account, AccountSharedData,
|
|
|
|
InheritableAccountFields, DUMMY_INHERITABLE_ACCOUNT_FIELDS,
|
|
|
|
},
|
|
|
|
clock::INITIAL_RENT_EPOCH,
|
|
|
|
},
|
|
|
|
std::{collections::BinaryHeap, iter::FromIterator},
|
|
|
|
};
|
2020-10-28 22:01:07 -07:00
|
|
|
|
2021-07-27 16:34:21 -07:00
|
|
|
#[deprecated(
|
2021-10-26 09:06:41 -07:00
|
|
|
since = "1.9.0",
|
2021-07-27 16:34:21 -07:00
|
|
|
note = "Please do not use, will no longer be available in the future"
|
|
|
|
)]
|
|
|
|
#[allow(deprecated)]
|
2021-03-09 13:06:07 -08:00
|
|
|
pub fn update_account<'a, I>(
|
|
|
|
account: &mut AccountSharedData,
|
|
|
|
recent_blockhash_iter: I,
|
|
|
|
) -> Option<()>
|
2020-10-28 22:01:07 -07:00
|
|
|
where
|
|
|
|
I: IntoIterator<Item = IterItem<'a>>,
|
|
|
|
{
|
|
|
|
let sorted = BinaryHeap::from_iter(recent_blockhash_iter);
|
2021-07-27 16:34:21 -07:00
|
|
|
#[allow(deprecated)]
|
2020-10-28 22:01:07 -07:00
|
|
|
let sorted_iter = IntoIterSorted::new(sorted);
|
2021-07-27 16:34:21 -07:00
|
|
|
#[allow(deprecated)]
|
2020-10-28 22:01:07 -07:00
|
|
|
let recent_blockhash_iter = sorted_iter.take(MAX_ENTRIES);
|
2021-07-27 16:34:21 -07:00
|
|
|
#[allow(deprecated)]
|
2020-12-13 17:26:34 -08:00
|
|
|
let recent_blockhashes: RecentBlockhashes = recent_blockhash_iter.collect();
|
2020-10-28 22:01:07 -07:00
|
|
|
to_account(&recent_blockhashes, account)
|
|
|
|
}
|
|
|
|
|
2021-03-24 23:23:20 -07:00
|
|
|
#[deprecated(
|
|
|
|
since = "1.5.17",
|
|
|
|
note = "Please use `create_account_with_data_for_test` instead"
|
|
|
|
)]
|
2021-07-27 16:34:21 -07:00
|
|
|
#[allow(deprecated)]
|
2021-03-09 13:06:07 -08:00
|
|
|
pub fn create_account_with_data<'a, I>(lamports: u64, recent_blockhash_iter: I) -> AccountSharedData
|
2020-10-28 22:01:07 -07:00
|
|
|
where
|
|
|
|
I: IntoIterator<Item = IterItem<'a>>,
|
|
|
|
{
|
2021-07-27 16:34:21 -07:00
|
|
|
#[allow(deprecated)]
|
2021-03-24 23:23:20 -07:00
|
|
|
create_account_with_data_and_fields(recent_blockhash_iter, (lamports, INITIAL_RENT_EPOCH))
|
|
|
|
}
|
|
|
|
|
2021-07-27 16:34:21 -07:00
|
|
|
#[deprecated(
|
2021-10-26 09:06:41 -07:00
|
|
|
since = "1.9.0",
|
2021-07-27 16:34:21 -07:00
|
|
|
note = "Please do not use, will no longer be available in the future"
|
|
|
|
)]
|
|
|
|
#[allow(deprecated)]
|
2021-03-24 23:23:20 -07:00
|
|
|
pub fn create_account_with_data_and_fields<'a, I>(
|
|
|
|
recent_blockhash_iter: I,
|
|
|
|
fields: InheritableAccountFields,
|
|
|
|
) -> AccountSharedData
|
|
|
|
where
|
|
|
|
I: IntoIterator<Item = IterItem<'a>>,
|
|
|
|
{
|
|
|
|
let mut account = create_account_shared_data_with_fields::<RecentBlockhashes>(
|
|
|
|
&RecentBlockhashes::default(),
|
|
|
|
fields,
|
|
|
|
);
|
2020-10-28 22:01:07 -07:00
|
|
|
update_account(&mut account, recent_blockhash_iter).unwrap();
|
|
|
|
account
|
|
|
|
}
|
|
|
|
|
2021-07-27 16:34:21 -07:00
|
|
|
#[deprecated(
|
2021-10-26 09:06:41 -07:00
|
|
|
since = "1.9.0",
|
2021-07-27 16:34:21 -07:00
|
|
|
note = "Please do not use, will no longer be available in the future"
|
|
|
|
)]
|
|
|
|
#[allow(deprecated)]
|
2021-03-24 23:23:20 -07:00
|
|
|
pub fn create_account_with_data_for_test<'a, I>(recent_blockhash_iter: I) -> AccountSharedData
|
|
|
|
where
|
|
|
|
I: IntoIterator<Item = IterItem<'a>>,
|
|
|
|
{
|
|
|
|
create_account_with_data_and_fields(recent_blockhash_iter, DUMMY_INHERITABLE_ACCOUNT_FIELDS)
|
|
|
|
}
|
|
|
|
|
2020-10-28 22:01:07 -07:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2021-07-27 16:34:21 -07:00
|
|
|
#![allow(deprecated)]
|
2021-12-03 09:00:31 -08:00
|
|
|
use {
|
|
|
|
super::*,
|
|
|
|
crate::account::from_account,
|
|
|
|
rand::{seq::SliceRandom, thread_rng},
|
|
|
|
solana_program::{
|
|
|
|
hash::{Hash, HASH_BYTES},
|
|
|
|
sysvar::recent_blockhashes::Entry,
|
|
|
|
},
|
2020-10-28 22:01:07 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_create_account_empty() {
|
2021-03-24 23:23:20 -07:00
|
|
|
let account = create_account_with_data_for_test(vec![].into_iter());
|
2021-03-09 13:06:07 -08:00
|
|
|
let recent_blockhashes = from_account::<RecentBlockhashes, _>(&account).unwrap();
|
2020-10-28 22:01:07 -07:00
|
|
|
assert_eq!(recent_blockhashes, RecentBlockhashes::default());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_create_account_full() {
|
|
|
|
let def_hash = Hash::default();
|
2021-10-22 14:32:40 -07:00
|
|
|
let def_lamports_per_signature = 0;
|
2021-03-24 23:23:20 -07:00
|
|
|
let account = create_account_with_data_for_test(
|
2021-10-22 14:32:40 -07:00
|
|
|
vec![IterItem(0u64, &def_hash, def_lamports_per_signature); MAX_ENTRIES].into_iter(),
|
2020-10-28 22:01:07 -07:00
|
|
|
);
|
2021-03-09 13:06:07 -08:00
|
|
|
let recent_blockhashes = from_account::<RecentBlockhashes, _>(&account).unwrap();
|
2020-10-28 22:01:07 -07:00
|
|
|
assert_eq!(recent_blockhashes.len(), MAX_ENTRIES);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_create_account_truncate() {
|
|
|
|
let def_hash = Hash::default();
|
2021-10-22 14:32:40 -07:00
|
|
|
let def_lamports_per_signature = 0;
|
2021-03-24 23:23:20 -07:00
|
|
|
let account = create_account_with_data_for_test(
|
2021-10-22 14:32:40 -07:00
|
|
|
vec![IterItem(0u64, &def_hash, def_lamports_per_signature); MAX_ENTRIES + 1]
|
|
|
|
.into_iter(),
|
2020-10-28 22:01:07 -07:00
|
|
|
);
|
2021-03-09 13:06:07 -08:00
|
|
|
let recent_blockhashes = from_account::<RecentBlockhashes, _>(&account).unwrap();
|
2020-10-28 22:01:07 -07:00
|
|
|
assert_eq!(recent_blockhashes.len(), MAX_ENTRIES);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_create_account_unsorted() {
|
2021-10-22 14:32:40 -07:00
|
|
|
let def_lamports_per_signature = 0;
|
2020-10-28 22:01:07 -07:00
|
|
|
let mut unsorted_blocks: Vec<_> = (0..MAX_ENTRIES)
|
|
|
|
.map(|i| {
|
|
|
|
(i as u64, {
|
|
|
|
// create hash with visibly recognizable ordering
|
|
|
|
let mut h = [0; HASH_BYTES];
|
|
|
|
h[HASH_BYTES - 1] = i as u8;
|
|
|
|
Hash::new(&h)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
unsorted_blocks.shuffle(&mut thread_rng());
|
|
|
|
|
2021-03-24 23:23:20 -07:00
|
|
|
let account = create_account_with_data_for_test(
|
2020-10-28 22:01:07 -07:00
|
|
|
unsorted_blocks
|
|
|
|
.iter()
|
2021-10-22 14:32:40 -07:00
|
|
|
.map(|(i, hash)| IterItem(*i, hash, def_lamports_per_signature)),
|
2020-10-28 22:01:07 -07:00
|
|
|
);
|
2021-03-09 13:06:07 -08:00
|
|
|
let recent_blockhashes = from_account::<RecentBlockhashes, _>(&account).unwrap();
|
2020-10-28 22:01:07 -07:00
|
|
|
|
|
|
|
let mut unsorted_recent_blockhashes: Vec<_> = unsorted_blocks
|
|
|
|
.iter()
|
2021-10-22 14:32:40 -07:00
|
|
|
.map(|(i, hash)| IterItem(*i, hash, def_lamports_per_signature))
|
2020-10-28 22:01:07 -07:00
|
|
|
.collect();
|
|
|
|
unsorted_recent_blockhashes.sort();
|
|
|
|
unsorted_recent_blockhashes.reverse();
|
|
|
|
let expected_recent_blockhashes: Vec<_> = (unsorted_recent_blockhashes
|
|
|
|
.into_iter()
|
|
|
|
.map(|IterItem(_, b, f)| Entry::new(b, f)))
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
assert_eq!(*recent_blockhashes, expected_recent_blockhashes);
|
|
|
|
}
|
|
|
|
}
|