solana_sdk/
nonce_account.rs1use {
4 crate::{
5 account_utils::StateMut,
6 hash::Hash,
7 nonce::{
8 state::{Data, Versions},
9 State,
10 },
11 },
12 solana_account::{AccountSharedData, ReadableAccount},
13 std::cell::RefCell,
14};
15
16pub fn create_account(lamports: u64) -> RefCell<AccountSharedData> {
17 RefCell::new(
18 AccountSharedData::new_data_with_space(
19 lamports,
20 &Versions::new(State::Uninitialized),
21 State::size(),
22 &crate::system_program::id(),
23 )
24 .expect("nonce_account"),
25 )
26}
27
28pub fn verify_nonce_account(
31 account: &AccountSharedData,
32 recent_blockhash: &Hash, ) -> Option<Data> {
34 (account.owner() == &crate::system_program::id())
35 .then(|| {
36 StateMut::<Versions>::state(account)
37 .ok()?
38 .verify_recent_blockhash(recent_blockhash)
39 .cloned()
40 })
41 .flatten()
42}
43
44pub fn lamports_per_signature_of(account: &AccountSharedData) -> Option<u64> {
45 match StateMut::<Versions>::state(account).ok()?.state() {
46 State::Initialized(data) => Some(data.fee_calculator.lamports_per_signature),
47 State::Uninitialized => None,
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use {
54 super::*,
55 crate::{
56 fee_calculator::FeeCalculator,
57 nonce::state::{Data, DurableNonce},
58 pubkey::Pubkey,
59 system_program,
60 },
61 };
62
63 #[test]
64 fn test_verify_bad_account_owner_fails() {
65 let program_id = Pubkey::new_unique();
66 assert_ne!(program_id, crate::system_program::id());
67 let account = AccountSharedData::new_data_with_space(
68 42,
69 &Versions::new(State::Uninitialized),
70 State::size(),
71 &program_id,
72 )
73 .expect("nonce_account");
74 assert_eq!(verify_nonce_account(&account, &Hash::default()), None);
75 }
76
77 fn new_nonce_account(versions: Versions) -> AccountSharedData {
78 AccountSharedData::new_data(
79 1_000_000, &versions, &system_program::id(), )
83 .unwrap()
84 }
85
86 #[test]
87 fn test_verify_nonce_account() {
88 let blockhash = Hash::from([171; 32]);
89 let versions = Versions::Legacy(Box::new(State::Uninitialized));
90 let account = new_nonce_account(versions);
91 assert_eq!(verify_nonce_account(&account, &blockhash), None);
92 assert_eq!(verify_nonce_account(&account, &Hash::default()), None);
93 let versions = Versions::Current(Box::new(State::Uninitialized));
94 let account = new_nonce_account(versions);
95 assert_eq!(verify_nonce_account(&account, &blockhash), None);
96 assert_eq!(verify_nonce_account(&account, &Hash::default()), None);
97 let durable_nonce = DurableNonce::from_blockhash(&blockhash);
98 let data = Data {
99 authority: Pubkey::new_unique(),
100 durable_nonce,
101 fee_calculator: FeeCalculator {
102 lamports_per_signature: 2718,
103 },
104 };
105 let versions = Versions::Legacy(Box::new(State::Initialized(data.clone())));
106 let account = new_nonce_account(versions);
107 assert_eq!(verify_nonce_account(&account, &blockhash), None);
108 assert_eq!(verify_nonce_account(&account, &Hash::default()), None);
109 assert_eq!(verify_nonce_account(&account, &data.blockhash()), None);
110 assert_eq!(
111 verify_nonce_account(&account, durable_nonce.as_hash()),
112 None
113 );
114 let durable_nonce = DurableNonce::from_blockhash(durable_nonce.as_hash());
115 assert_ne!(data.durable_nonce, durable_nonce);
116 let data = Data {
117 durable_nonce,
118 ..data
119 };
120 let versions = Versions::Current(Box::new(State::Initialized(data.clone())));
121 let account = new_nonce_account(versions);
122 assert_eq!(verify_nonce_account(&account, &blockhash), None);
123 assert_eq!(verify_nonce_account(&account, &Hash::default()), None);
124 assert_eq!(
125 verify_nonce_account(&account, &data.blockhash()),
126 Some(data.clone())
127 );
128 assert_eq!(
129 verify_nonce_account(&account, durable_nonce.as_hash()),
130 Some(data)
131 );
132 }
133}