1use {
2 crate::{
3 account_overrides::AccountOverrides,
4 account_rent_state::{check_rent_state_with_account, RentState},
5 accounts_db::{
6 AccountShrinkThreshold, AccountsAddRootTiming, AccountsDb, AccountsDbConfig,
7 BankHashInfo, LoadHint, LoadZeroLamports, LoadedAccount, ScanStorageResult,
8 ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS, ACCOUNTS_DB_CONFIG_FOR_TESTING,
9 },
10 accounts_index::{
11 AccountSecondaryIndexes, IndexKey, ScanConfig, ScanError, ScanResult, ZeroLamport,
12 },
13 accounts_update_notifier_interface::AccountsUpdateNotifier,
14 ancestors::Ancestors,
15 bank::{
16 Bank, NonceFull, NonceInfo, RentDebits, Rewrites, TransactionCheckResult,
17 TransactionExecutionResult,
18 },
19 blockhash_queue::BlockhashQueue,
20 rent_collector::RentCollector,
21 storable_accounts::StorableAccounts,
22 system_instruction_processor::{get_system_account_kind, SystemAccountKind},
23 transaction_error_metrics::TransactionErrorMetrics,
24 },
25 dashmap::{
26 mapref::entry::Entry::{Occupied, Vacant},
27 DashMap,
28 },
29 log::*,
30 rand::{thread_rng, Rng},
31 solana_address_lookup_table_program::{error::AddressLookupError, state::AddressLookupTable},
32 solana_sdk::{
33 account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
34 account_utils::StateMut,
35 bpf_loader_upgradeable::{self, UpgradeableLoaderState},
36 clock::{BankId, Slot, INITIAL_RENT_EPOCH},
37 feature_set::{
38 self, add_set_compute_unit_price_ix, enable_request_heap_frame_ix,
39 return_none_for_zero_lamport_accounts, use_default_units_in_fee_calculation,
40 FeatureSet,
41 },
42 fee::FeeStructure,
43 genesis_config::ClusterType,
44 hash::Hash,
45 message::{
46 v0::{LoadedAddresses, MessageAddressTableLookup},
47 SanitizedMessage,
48 },
49 native_loader,
50 nonce::{
51 state::{DurableNonce, Versions as NonceVersions},
52 State as NonceState,
53 },
54 pubkey::Pubkey,
55 signature::Signature,
56 slot_hashes::SlotHashes,
57 system_program,
58 sysvar::{self, epoch_schedule::EpochSchedule, instructions::construct_instructions_data},
59 transaction::{Result, SanitizedTransaction, TransactionAccountLocks, TransactionError},
60 transaction_context::TransactionAccount,
61 },
62 std::{
63 cmp::Reverse,
64 collections::{hash_map, BinaryHeap, HashMap, HashSet},
65 ops::RangeBounds,
66 path::PathBuf,
67 sync::{
68 atomic::{AtomicUsize, Ordering},
69 Arc, Mutex,
70 },
71 },
72};
73
74pub type PubkeyAccountSlot = (Pubkey, AccountSharedData, Slot);
75
76#[derive(Debug, Default, AbiExample)]
77pub struct AccountLocks {
78 write_locks: HashSet<Pubkey>,
79 readonly_locks: HashMap<Pubkey, u64>,
80}
81
82impl AccountLocks {
83 fn is_locked_readonly(&self, key: &Pubkey) -> bool {
84 self.readonly_locks
85 .get(key)
86 .map_or(false, |count| *count > 0)
87 }
88
89 fn is_locked_write(&self, key: &Pubkey) -> bool {
90 self.write_locks.contains(key)
91 }
92
93 fn insert_new_readonly(&mut self, key: &Pubkey) {
94 assert!(self.readonly_locks.insert(*key, 1).is_none());
95 }
96
97 fn lock_readonly(&mut self, key: &Pubkey) -> bool {
98 self.readonly_locks.get_mut(key).map_or(false, |count| {
99 *count += 1;
100 true
101 })
102 }
103
104 fn unlock_readonly(&mut self, key: &Pubkey) {
105 if let hash_map::Entry::Occupied(mut occupied_entry) = self.readonly_locks.entry(*key) {
106 let count = occupied_entry.get_mut();
107 *count -= 1;
108 if *count == 0 {
109 occupied_entry.remove_entry();
110 }
111 }
112 }
113
114 fn unlock_write(&mut self, key: &Pubkey) {
115 self.write_locks.remove(key);
116 }
117}
118
119#[derive(Debug, AbiExample)]
121pub struct Accounts {
122 pub accounts_db: Arc<AccountsDb>,
124
125 pub(crate) account_locks: Mutex<AccountLocks>,
128}
129
130pub type TransactionRent = u64;
132pub type TransactionProgramIndices = Vec<Vec<usize>>;
133#[derive(PartialEq, Eq, Debug, Clone)]
134pub struct LoadedTransaction {
135 pub accounts: Vec<TransactionAccount>,
136 pub program_indices: TransactionProgramIndices,
137 pub rent: TransactionRent,
138 pub rent_debits: RentDebits,
139}
140
141pub type TransactionLoadResult = (Result<LoadedTransaction>, Option<NonceFull>);
142
143pub enum AccountAddressFilter {
144 Exclude, Include, }
147
148impl Accounts {
149 pub fn default_for_tests() -> Self {
150 Self {
151 accounts_db: Arc::new(AccountsDb::default_for_tests()),
152 account_locks: Mutex::default(),
153 }
154 }
155
156 pub fn new_with_config_for_tests(
157 paths: Vec<PathBuf>,
158 cluster_type: &ClusterType,
159 account_indexes: AccountSecondaryIndexes,
160 caching_enabled: bool,
161 shrink_ratio: AccountShrinkThreshold,
162 ) -> Self {
163 Self::new_with_config(
164 paths,
165 cluster_type,
166 account_indexes,
167 caching_enabled,
168 shrink_ratio,
169 Some(ACCOUNTS_DB_CONFIG_FOR_TESTING),
170 None,
171 )
172 }
173
174 pub fn new_with_config_for_benches(
175 paths: Vec<PathBuf>,
176 cluster_type: &ClusterType,
177 account_indexes: AccountSecondaryIndexes,
178 caching_enabled: bool,
179 shrink_ratio: AccountShrinkThreshold,
180 ) -> Self {
181 Self::new_with_config(
182 paths,
183 cluster_type,
184 account_indexes,
185 caching_enabled,
186 shrink_ratio,
187 Some(ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS),
188 None,
189 )
190 }
191
192 pub fn new_with_config(
193 paths: Vec<PathBuf>,
194 cluster_type: &ClusterType,
195 account_indexes: AccountSecondaryIndexes,
196 caching_enabled: bool,
197 shrink_ratio: AccountShrinkThreshold,
198 accounts_db_config: Option<AccountsDbConfig>,
199 accounts_update_notifier: Option<AccountsUpdateNotifier>,
200 ) -> Self {
201 Self {
202 accounts_db: Arc::new(AccountsDb::new_with_config(
203 paths,
204 cluster_type,
205 account_indexes,
206 caching_enabled,
207 shrink_ratio,
208 accounts_db_config,
209 accounts_update_notifier,
210 )),
211 account_locks: Mutex::new(AccountLocks::default()),
212 }
213 }
214
215 pub fn new_from_parent(parent: &Accounts, slot: Slot, parent_slot: Slot) -> Self {
216 let accounts_db = parent.accounts_db.clone();
217 accounts_db.set_hash(slot, parent_slot);
218 Self {
219 accounts_db,
220 account_locks: Mutex::new(AccountLocks::default()),
221 }
222 }
223
224 pub(crate) fn new_empty(accounts_db: AccountsDb) -> Self {
225 Self {
226 accounts_db: Arc::new(accounts_db),
227 account_locks: Mutex::new(AccountLocks::default()),
228 }
229 }
230
231 fn construct_instructions_account(
232 message: &SanitizedMessage,
233 is_owned_by_sysvar: bool,
234 ) -> AccountSharedData {
235 let data = construct_instructions_data(&message.decompile_instructions());
236 let owner = if is_owned_by_sysvar {
237 sysvar::id()
238 } else {
239 system_program::id()
240 };
241 AccountSharedData::from(Account {
242 data,
243 owner,
244 ..Account::default()
245 })
246 }
247
248 fn load_transaction(
249 &self,
250 ancestors: &Ancestors,
251 tx: &SanitizedTransaction,
252 fee: u64,
253 error_counters: &mut TransactionErrorMetrics,
254 rent_collector: &RentCollector,
255 feature_set: &FeatureSet,
256 account_overrides: Option<&AccountOverrides>,
257 ) -> Result<LoadedTransaction> {
258 let load_zero_lamports =
259 if feature_set.is_active(&return_none_for_zero_lamport_accounts::id()) {
260 LoadZeroLamports::None
261 } else {
262 LoadZeroLamports::SomeWithZeroLamportAccount
263 };
264
265 let message = tx.message();
267 if tx.signatures().is_empty() && fee != 0 {
269 Err(TransactionError::MissingSignatureForFee)
270 } else {
271 let mut validated_fee_payer = false;
274 let mut tx_rent: TransactionRent = 0;
275 let account_keys = message.account_keys();
276 let mut accounts = Vec::with_capacity(account_keys.len());
277 let mut account_deps = Vec::with_capacity(account_keys.len());
278 let mut rent_debits = RentDebits::default();
279 let preserve_rent_epoch_for_rent_exempt_accounts = feature_set
280 .is_active(&feature_set::preserve_rent_epoch_for_rent_exempt_accounts::id());
281 for (i, key) in account_keys.iter().enumerate() {
282 let account = if !message.is_non_loader_key(i) {
283 AccountSharedData::default()
285 } else {
286 #[allow(clippy::collapsible_else_if)]
287 if solana_sdk::sysvar::instructions::check_id(key) {
288 Self::construct_instructions_account(
289 message,
290 feature_set
291 .is_active(&feature_set::instructions_sysvar_owned_by_sysvar::id()),
292 )
293 } else {
294 let (mut account, rent) = if let Some(account_override) =
295 account_overrides.and_then(|overrides| overrides.get(key))
296 {
297 (account_override.clone(), 0)
298 } else {
299 self.accounts_db
300 .load_with_fixed_root(ancestors, key, load_zero_lamports)
301 .map(|(mut account, _)| {
302 if message.is_writable(i) {
303 let rent_due = rent_collector
304 .collect_from_existing_account(
305 key,
306 &mut account,
307 self.accounts_db.filler_account_suffix.as_ref(),
308 preserve_rent_epoch_for_rent_exempt_accounts,
309 )
310 .rent_amount;
311 (account, rent_due)
312 } else {
313 (account, 0)
314 }
315 })
316 .unwrap_or_default()
317 };
318
319 if !validated_fee_payer {
320 if i != 0 {
321 warn!("Payer index should be 0! {:?}", tx);
322 }
323
324 Self::validate_fee_payer(
325 key,
326 &mut account,
327 i,
328 error_counters,
329 rent_collector,
330 feature_set,
331 fee,
332 )?;
333
334 validated_fee_payer = true;
335 }
336
337 if bpf_loader_upgradeable::check_id(account.owner()) {
338 if message.is_writable(i) && !message.is_upgradeable_loader_present() {
339 error_counters.invalid_writable_account += 1;
340 return Err(TransactionError::InvalidWritableAccount);
341 }
342
343 if account.executable() {
344 if let Ok(UpgradeableLoaderState::Program {
346 programdata_address,
347 }) = account.state()
348 {
349 if let Some((programdata_account, _)) =
350 self.accounts_db.load_with_fixed_root(
351 ancestors,
352 &programdata_address,
353 load_zero_lamports,
354 )
355 {
356 account_deps
357 .push((programdata_address, programdata_account));
358 } else {
359 error_counters.account_not_found += 1;
360 return Err(TransactionError::ProgramAccountNotFound);
361 }
362 } else {
363 error_counters.invalid_program_for_execution += 1;
364 return Err(TransactionError::InvalidProgramForExecution);
365 }
366 }
367 } else if account.executable() && message.is_writable(i) {
368 error_counters.invalid_writable_account += 1;
369 return Err(TransactionError::InvalidWritableAccount);
370 }
371
372 tx_rent += rent;
373 rent_debits.insert(key, rent, account.lamports());
374
375 account
376 }
377 };
378 accounts.push((*key, account));
379 }
380 debug_assert_eq!(accounts.len(), account_keys.len());
381 accounts.append(&mut account_deps);
387
388 if validated_fee_payer {
389 let program_indices = message
390 .instructions()
391 .iter()
392 .map(|instruction| {
393 self.load_executable_accounts(
394 ancestors,
395 &mut accounts,
396 instruction.program_id_index as usize,
397 error_counters,
398 load_zero_lamports,
399 )
400 })
401 .collect::<Result<Vec<Vec<usize>>>>()?;
402
403 Ok(LoadedTransaction {
404 accounts,
405 program_indices,
406 rent: tx_rent,
407 rent_debits,
408 })
409 } else {
410 error_counters.account_not_found += 1;
411 Err(TransactionError::AccountNotFound)
412 }
413 }
414 }
415
416 fn validate_fee_payer(
417 payer_address: &Pubkey,
418 payer_account: &mut AccountSharedData,
419 payer_index: usize,
420 error_counters: &mut TransactionErrorMetrics,
421 rent_collector: &RentCollector,
422 feature_set: &FeatureSet,
423 fee: u64,
424 ) -> Result<()> {
425 if payer_account.lamports() == 0 {
426 error_counters.account_not_found += 1;
427 return Err(TransactionError::AccountNotFound);
428 }
429 let min_balance = match get_system_account_kind(payer_account).ok_or_else(|| {
430 error_counters.invalid_account_for_fee += 1;
431 TransactionError::InvalidAccountForFee
432 })? {
433 SystemAccountKind::System => 0,
434 SystemAccountKind::Nonce => {
435 rent_collector.rent.minimum_balance(NonceState::size())
438 }
439 };
440
441 if payer_account.lamports() < fee + min_balance {
442 error_counters.insufficient_funds += 1;
443 return Err(TransactionError::InsufficientFundsForFee);
444 }
445 let payer_pre_rent_state = RentState::from_account(payer_account, &rent_collector.rent);
446 payer_account
447 .checked_sub_lamports(fee)
448 .map_err(|_| TransactionError::InsufficientFundsForFee)?;
449
450 let payer_post_rent_state = RentState::from_account(payer_account, &rent_collector.rent);
451 check_rent_state_with_account(
452 &payer_pre_rent_state,
453 &payer_post_rent_state,
454 payer_address,
455 payer_account,
456 feature_set
457 .is_active(&feature_set::include_account_index_in_rent_error::ID)
458 .then(|| payer_index),
459 feature_set
460 .is_active(&feature_set::prevent_crediting_accounts_that_end_rent_paying::id()),
461 )
462 }
463
464 fn load_executable_accounts(
465 &self,
466 ancestors: &Ancestors,
467 accounts: &mut Vec<TransactionAccount>,
468 mut program_account_index: usize,
469 error_counters: &mut TransactionErrorMetrics,
470 load_zero_lamports: LoadZeroLamports,
471 ) -> Result<Vec<usize>> {
472 let mut account_indices = Vec::new();
473 let mut program_id = match accounts.get(program_account_index) {
474 Some(program_account) => program_account.0,
475 None => {
476 error_counters.account_not_found += 1;
477 return Err(TransactionError::ProgramAccountNotFound);
478 }
479 };
480 let mut depth = 0;
481 while !native_loader::check_id(&program_id) {
482 if depth >= 5 {
483 error_counters.call_chain_too_deep += 1;
484 return Err(TransactionError::CallChainTooDeep);
485 }
486 depth += 1;
487
488 program_account_index = match self.accounts_db.load_with_fixed_root(
489 ancestors,
490 &program_id,
491 load_zero_lamports,
492 ) {
493 Some((program_account, _)) => {
494 let account_index = accounts.len();
495 accounts.push((program_id, program_account));
496 account_index
497 }
498 None => {
499 error_counters.account_not_found += 1;
500 return Err(TransactionError::ProgramAccountNotFound);
501 }
502 };
503 let program = &accounts[program_account_index].1;
504 if !program.executable() {
505 error_counters.invalid_program_for_execution += 1;
506 return Err(TransactionError::InvalidProgramForExecution);
507 }
508
509 let program_owner = *program.owner();
511 account_indices.insert(0, program_account_index);
512 if bpf_loader_upgradeable::check_id(&program_owner) {
513 if let Ok(UpgradeableLoaderState::Program {
515 programdata_address,
516 }) = program.state()
517 {
518 let programdata_account_index = match self.accounts_db.load_with_fixed_root(
519 ancestors,
520 &programdata_address,
521 load_zero_lamports,
522 ) {
523 Some((programdata_account, _)) => {
524 let account_index = accounts.len();
525 accounts.push((programdata_address, programdata_account));
526 account_index
527 }
528 None => {
529 error_counters.account_not_found += 1;
530 return Err(TransactionError::ProgramAccountNotFound);
531 }
532 };
533 account_indices.insert(0, programdata_account_index);
534 } else {
535 error_counters.invalid_program_for_execution += 1;
536 return Err(TransactionError::InvalidProgramForExecution);
537 }
538 }
539
540 program_id = program_owner;
541 }
542 Ok(account_indices)
543 }
544
545 #[allow(clippy::too_many_arguments)]
546 pub fn load_accounts(
547 &self,
548 ancestors: &Ancestors,
549 txs: &[SanitizedTransaction],
550 lock_results: Vec<TransactionCheckResult>,
551 hash_queue: &BlockhashQueue,
552 error_counters: &mut TransactionErrorMetrics,
553 rent_collector: &RentCollector,
554 feature_set: &FeatureSet,
555 fee_structure: &FeeStructure,
556 account_overrides: Option<&AccountOverrides>,
557 ) -> Vec<TransactionLoadResult> {
558 txs.iter()
559 .zip(lock_results)
560 .map(|etx| match etx {
561 (tx, (Ok(()), nonce)) => {
562 let lamports_per_signature = nonce
563 .as_ref()
564 .map(|nonce| nonce.lamports_per_signature())
565 .unwrap_or_else(|| {
566 hash_queue.get_lamports_per_signature(tx.message().recent_blockhash())
567 });
568 let fee = if let Some(lamports_per_signature) = lamports_per_signature {
569 Bank::calculate_fee(
570 tx.message(),
571 lamports_per_signature,
572 fee_structure,
573 feature_set.is_active(&add_set_compute_unit_price_ix::id()),
574 feature_set.is_active(&use_default_units_in_fee_calculation::id()),
575 feature_set.is_active(&enable_request_heap_frame_ix::id())
576 || self.accounts_db.expected_cluster_type()
577 != ClusterType::MainnetBeta,
578 )
579 } else {
580 return (Err(TransactionError::BlockhashNotFound), None);
581 };
582
583 let loaded_transaction = match self.load_transaction(
584 ancestors,
585 tx,
586 fee,
587 error_counters,
588 rent_collector,
589 feature_set,
590 account_overrides,
591 ) {
592 Ok(loaded_transaction) => loaded_transaction,
593 Err(e) => return (Err(e), None),
594 };
595
596 let nonce = if let Some(nonce) = nonce {
598 match NonceFull::from_partial(
599 nonce,
600 tx.message(),
601 &loaded_transaction.accounts,
602 &loaded_transaction.rent_debits,
603 ) {
604 Ok(nonce) => Some(nonce),
605 Err(e) => return (Err(e), None),
606 }
607 } else {
608 None
609 };
610
611 (Ok(loaded_transaction), nonce)
612 }
613 (_, (Err(e), _nonce)) => (Err(e), None),
614 })
615 .collect()
616 }
617
618 pub fn load_lookup_table_addresses(
619 &self,
620 ancestors: &Ancestors,
621 address_table_lookup: &MessageAddressTableLookup,
622 slot_hashes: &SlotHashes,
623 load_zero_lamports: LoadZeroLamports,
624 ) -> std::result::Result<LoadedAddresses, AddressLookupError> {
625 let table_account = self
626 .accounts_db
627 .load_with_fixed_root(
628 ancestors,
629 &address_table_lookup.account_key,
630 load_zero_lamports,
631 )
632 .map(|(account, _rent)| account)
633 .ok_or(AddressLookupError::LookupTableAccountNotFound)?;
634
635 if table_account.owner() == &solana_address_lookup_table_program::id() {
636 let current_slot = ancestors.max_slot();
637 let lookup_table = AddressLookupTable::deserialize(table_account.data())
638 .map_err(|_ix_err| AddressLookupError::InvalidAccountData)?;
639
640 Ok(LoadedAddresses {
641 writable: lookup_table.lookup(
642 current_slot,
643 &address_table_lookup.writable_indexes,
644 slot_hashes,
645 )?,
646 readonly: lookup_table.lookup(
647 current_slot,
648 &address_table_lookup.readonly_indexes,
649 slot_hashes,
650 )?,
651 })
652 } else {
653 Err(AddressLookupError::InvalidAccountOwner)
654 }
655 }
656
657 fn filter_zero_lamport_account(
658 account: AccountSharedData,
659 slot: Slot,
660 ) -> Option<(AccountSharedData, Slot)> {
661 if account.lamports() > 0 {
662 Some((account, slot))
663 } else {
664 None
665 }
666 }
667
668 fn load_slow(
670 &self,
671 ancestors: &Ancestors,
672 pubkey: &Pubkey,
673 load_hint: LoadHint,
674 ) -> Option<(AccountSharedData, Slot)> {
675 let (account, slot) = self.accounts_db.load(ancestors, pubkey, load_hint)?;
676 Self::filter_zero_lamport_account(account, slot)
677 }
678
679 pub fn load_with_fixed_root(
680 &self,
681 ancestors: &Ancestors,
682 pubkey: &Pubkey,
683 ) -> Option<(AccountSharedData, Slot)> {
684 self.load_slow(ancestors, pubkey, LoadHint::FixedMaxRoot)
685 }
686
687 pub fn load_without_fixed_root(
688 &self,
689 ancestors: &Ancestors,
690 pubkey: &Pubkey,
691 ) -> Option<(AccountSharedData, Slot)> {
692 self.load_slow(ancestors, pubkey, LoadHint::Unspecified)
693 }
694
695 pub fn scan_slot<F, B>(&self, slot: Slot, func: F) -> Vec<B>
699 where
700 F: Fn(LoadedAccount) -> Option<B> + Send + Sync,
701 B: Sync + Send + Default + std::cmp::Eq,
702 {
703 let scan_result = self.accounts_db.scan_account_storage(
704 slot,
705 |loaded_account: LoadedAccount| {
706 func(loaded_account)
708 },
709 |accum: &DashMap<Pubkey, (u64, B)>, loaded_account: LoadedAccount| {
710 let loaded_account_pubkey = *loaded_account.pubkey();
711 let loaded_write_version = loaded_account.write_version();
712 let should_insert = accum
713 .get(&loaded_account_pubkey)
714 .map(|existing_entry| loaded_write_version > existing_entry.value().0)
715 .unwrap_or(true);
716 if should_insert {
717 if let Some(val) = func(loaded_account) {
718 match accum.entry(loaded_account_pubkey) {
720 Occupied(mut occupied_entry) => {
722 if loaded_write_version > occupied_entry.get().0 {
723 occupied_entry.insert((loaded_write_version, val));
724 }
725 }
726
727 Vacant(vacant_entry) => {
728 vacant_entry.insert((loaded_write_version, val));
729 }
730 }
731 }
732 }
733 },
734 );
735
736 match scan_result {
737 ScanStorageResult::Cached(cached_result) => cached_result,
738 ScanStorageResult::Stored(stored_result) => stored_result
739 .into_iter()
740 .map(|(_pubkey, (_latest_write_version, val))| val)
741 .collect(),
742 }
743 }
744
745 pub fn load_by_program_slot(
746 &self,
747 slot: Slot,
748 program_id: Option<&Pubkey>,
749 ) -> Vec<TransactionAccount> {
750 self.scan_slot(slot, |stored_account| {
751 let hit = match program_id {
752 None => true,
753 Some(program_id) => stored_account.owner() == program_id,
754 };
755
756 if hit {
757 Some((*stored_account.pubkey(), stored_account.take_account()))
758 } else {
759 None
760 }
761 })
762 }
763
764 pub fn load_largest_accounts(
765 &self,
766 ancestors: &Ancestors,
767 bank_id: BankId,
768 num: usize,
769 filter_by_address: &HashSet<Pubkey>,
770 filter: AccountAddressFilter,
771 ) -> ScanResult<Vec<(Pubkey, u64)>> {
772 if num == 0 {
773 return Ok(vec![]);
774 }
775 let account_balances = self.accounts_db.scan_accounts(
776 ancestors,
777 bank_id,
778 |collector: &mut BinaryHeap<Reverse<(u64, Pubkey)>>, option| {
779 if let Some((pubkey, account, _slot)) = option {
780 if account.lamports() == 0 {
781 return;
782 }
783 let contains_address = filter_by_address.contains(pubkey);
784 let collect = match filter {
785 AccountAddressFilter::Exclude => !contains_address,
786 AccountAddressFilter::Include => contains_address,
787 };
788 if !collect {
789 return;
790 }
791 if collector.len() == num {
792 let Reverse(entry) = collector
793 .peek()
794 .expect("BinaryHeap::peek should succeed when len > 0");
795 if *entry >= (account.lamports(), *pubkey) {
796 return;
797 }
798 collector.pop();
799 }
800 collector.push(Reverse((account.lamports(), *pubkey)));
801 }
802 },
803 &ScanConfig::default(),
804 )?;
805 Ok(account_balances
806 .into_sorted_vec()
807 .into_iter()
808 .map(|Reverse((balance, pubkey))| (pubkey, balance))
809 .collect())
810 }
811
812 pub fn calculate_capitalization(
814 &self,
815 ancestors: &Ancestors,
816 slot: Slot,
817 can_cached_slot_be_unflushed: bool,
818 debug_verify: bool,
819 epoch_schedule: &EpochSchedule,
820 rent_collector: &RentCollector,
821 ) -> u64 {
822 let use_index = false;
823 let is_startup = true;
824 self.accounts_db
825 .update_accounts_hash_with_index_option(
826 use_index,
827 debug_verify,
828 slot,
829 ancestors,
830 None,
831 can_cached_slot_be_unflushed,
832 epoch_schedule,
833 rent_collector,
834 is_startup,
835 )
836 .1
837 }
838
839 #[must_use]
841 #[allow(clippy::too_many_arguments)]
842 pub fn verify_bank_hash_and_lamports(
843 &self,
844 slot: Slot,
845 ancestors: &Ancestors,
846 total_lamports: u64,
847 test_hash_calculation: bool,
848 epoch_schedule: &EpochSchedule,
849 rent_collector: &RentCollector,
850 can_cached_slot_be_unflushed: bool,
851 ignore_mismatch: bool,
852 store_detailed_debug_info: bool,
853 use_bg_thread_pool: bool,
854 ) -> bool {
855 if let Err(err) = self.accounts_db.verify_bank_hash_and_lamports_new(
856 slot,
857 ancestors,
858 total_lamports,
859 test_hash_calculation,
860 epoch_schedule,
861 rent_collector,
862 can_cached_slot_be_unflushed,
863 ignore_mismatch,
864 store_detailed_debug_info,
865 use_bg_thread_pool,
866 ) {
867 warn!("verify_bank_hash failed: {:?}, slot: {}", err, slot);
868 false
869 } else {
870 true
871 }
872 }
873
874 fn is_loadable(lamports: u64) -> bool {
875 lamports > 0
878 }
879
880 fn load_while_filtering<F: Fn(&AccountSharedData) -> bool>(
881 collector: &mut Vec<TransactionAccount>,
882 some_account_tuple: Option<(&Pubkey, AccountSharedData, Slot)>,
883 filter: F,
884 ) {
885 if let Some(mapped_account_tuple) = some_account_tuple
886 .filter(|(_, account, _)| Self::is_loadable(account.lamports()) && filter(account))
887 .map(|(pubkey, account, _slot)| (*pubkey, account))
888 {
889 collector.push(mapped_account_tuple)
890 }
891 }
892
893 fn load_with_slot(
894 collector: &mut Vec<PubkeyAccountSlot>,
895 some_account_tuple: Option<(&Pubkey, AccountSharedData, Slot)>,
896 ) {
897 if let Some(mapped_account_tuple) = some_account_tuple
898 .filter(|(_, account, _)| Self::is_loadable(account.lamports()))
899 .map(|(pubkey, account, slot)| (*pubkey, account, slot))
900 {
901 collector.push(mapped_account_tuple)
902 }
903 }
904
905 pub fn load_by_program(
906 &self,
907 ancestors: &Ancestors,
908 bank_id: BankId,
909 program_id: &Pubkey,
910 config: &ScanConfig,
911 ) -> ScanResult<Vec<TransactionAccount>> {
912 self.accounts_db.scan_accounts(
913 ancestors,
914 bank_id,
915 |collector: &mut Vec<TransactionAccount>, some_account_tuple| {
916 Self::load_while_filtering(collector, some_account_tuple, |account| {
917 account.owner() == program_id
918 })
919 },
920 config,
921 )
922 }
923
924 pub fn load_by_program_with_filter<F: Fn(&AccountSharedData) -> bool>(
925 &self,
926 ancestors: &Ancestors,
927 bank_id: BankId,
928 program_id: &Pubkey,
929 filter: F,
930 config: &ScanConfig,
931 ) -> ScanResult<Vec<TransactionAccount>> {
932 self.accounts_db.scan_accounts(
933 ancestors,
934 bank_id,
935 |collector: &mut Vec<TransactionAccount>, some_account_tuple| {
936 Self::load_while_filtering(collector, some_account_tuple, |account| {
937 account.owner() == program_id && filter(account)
938 })
939 },
940 config,
941 )
942 }
943
944 fn calc_scan_result_size(account: &AccountSharedData) -> usize {
945 account.data().len()
946 + std::mem::size_of::<AccountSharedData>()
947 + std::mem::size_of::<Pubkey>()
948 }
949
950 fn accumulate_and_check_scan_result_size(
953 sum: &AtomicUsize,
954 account: &AccountSharedData,
955 byte_limit_for_scan: &Option<usize>,
956 ) -> bool {
957 if let Some(byte_limit_for_scan) = byte_limit_for_scan.as_ref() {
958 let added = Self::calc_scan_result_size(account);
959 sum.fetch_add(added, Ordering::Relaxed)
960 .saturating_add(added)
961 > *byte_limit_for_scan
962 } else {
963 false
964 }
965 }
966
967 fn maybe_abort_scan(
968 result: ScanResult<Vec<TransactionAccount>>,
969 config: &ScanConfig,
970 ) -> ScanResult<Vec<TransactionAccount>> {
971 if config.is_aborted() {
972 ScanResult::Err(ScanError::Aborted(
973 "The accumulated scan results exceeded the limit".to_string(),
974 ))
975 } else {
976 result
977 }
978 }
979
980 pub fn load_by_index_key_with_filter<F: Fn(&AccountSharedData) -> bool>(
981 &self,
982 ancestors: &Ancestors,
983 bank_id: BankId,
984 index_key: &IndexKey,
985 filter: F,
986 config: &ScanConfig,
987 byte_limit_for_scan: Option<usize>,
988 ) -> ScanResult<Vec<TransactionAccount>> {
989 let sum = AtomicUsize::default();
990 let config = config.recreate_with_abort();
991 let result = self
992 .accounts_db
993 .index_scan_accounts(
994 ancestors,
995 bank_id,
996 *index_key,
997 |collector: &mut Vec<TransactionAccount>, some_account_tuple| {
998 Self::load_while_filtering(collector, some_account_tuple, |account| {
999 let use_account = filter(account);
1000 if use_account
1001 && Self::accumulate_and_check_scan_result_size(
1002 &sum,
1003 account,
1004 &byte_limit_for_scan,
1005 )
1006 {
1007 config.abort();
1009 }
1010 use_account
1011 });
1012 },
1013 &config,
1014 )
1015 .map(|result| result.0);
1016 Self::maybe_abort_scan(result, &config)
1017 }
1018
1019 pub fn account_indexes_include_key(&self, key: &Pubkey) -> bool {
1020 self.accounts_db.account_indexes.include_key(key)
1021 }
1022
1023 pub fn load_all(
1024 &self,
1025 ancestors: &Ancestors,
1026 bank_id: BankId,
1027 ) -> ScanResult<Vec<PubkeyAccountSlot>> {
1028 self.accounts_db.scan_accounts(
1029 ancestors,
1030 bank_id,
1031 |collector: &mut Vec<PubkeyAccountSlot>, some_account_tuple| {
1032 if let Some((pubkey, account, slot)) = some_account_tuple
1033 .filter(|(_, account, _)| Self::is_loadable(account.lamports()))
1034 {
1035 collector.push((*pubkey, account, slot))
1036 }
1037 },
1038 &ScanConfig::default(),
1039 )
1040 }
1041
1042 pub fn hold_range_in_memory<R>(
1043 &self,
1044 range: &R,
1045 start_holding: bool,
1046 thread_pool: &rayon::ThreadPool,
1047 ) where
1048 R: RangeBounds<Pubkey> + std::fmt::Debug + Sync,
1049 {
1050 self.accounts_db
1051 .accounts_index
1052 .hold_range_in_memory(range, start_holding, thread_pool)
1053 }
1054
1055 pub fn load_to_collect_rent_eagerly<R: RangeBounds<Pubkey> + std::fmt::Debug>(
1056 &self,
1057 ancestors: &Ancestors,
1058 range: R,
1059 ) -> Vec<PubkeyAccountSlot> {
1060 self.accounts_db.range_scan_accounts(
1061 "", ancestors,
1063 range,
1064 &ScanConfig::new(true),
1065 |collector: &mut Vec<PubkeyAccountSlot>, option| {
1066 Self::load_with_slot(collector, option)
1067 },
1068 )
1069 }
1070
1071 pub fn store_slow_uncached(&self, slot: Slot, pubkey: &Pubkey, account: &AccountSharedData) {
1075 self.accounts_db.store_uncached(slot, &[(pubkey, account)]);
1076 }
1077
1078 fn lock_account(
1079 &self,
1080 account_locks: &mut AccountLocks,
1081 writable_keys: Vec<&Pubkey>,
1082 readonly_keys: Vec<&Pubkey>,
1083 ) -> Result<()> {
1084 for k in writable_keys.iter() {
1085 if account_locks.is_locked_write(k) || account_locks.is_locked_readonly(k) {
1086 debug!("Writable account in use: {:?}", k);
1087 return Err(TransactionError::AccountInUse);
1088 }
1089 }
1090 for k in readonly_keys.iter() {
1091 if account_locks.is_locked_write(k) {
1092 debug!("Read-only account in use: {:?}", k);
1093 return Err(TransactionError::AccountInUse);
1094 }
1095 }
1096
1097 for k in writable_keys {
1098 account_locks.write_locks.insert(*k);
1099 }
1100
1101 for k in readonly_keys {
1102 if !account_locks.lock_readonly(k) {
1103 account_locks.insert_new_readonly(k);
1104 }
1105 }
1106
1107 Ok(())
1108 }
1109
1110 fn unlock_account(
1111 &self,
1112 account_locks: &mut AccountLocks,
1113 writable_keys: Vec<&Pubkey>,
1114 readonly_keys: Vec<&Pubkey>,
1115 ) {
1116 for k in writable_keys {
1117 account_locks.unlock_write(k);
1118 }
1119 for k in readonly_keys {
1120 account_locks.unlock_readonly(k);
1121 }
1122 }
1123
1124 pub fn bank_hash_at(&self, slot: Slot, rewrites: &Rewrites) -> Hash {
1125 self.bank_hash_info_at(slot, rewrites).hash
1126 }
1127
1128 pub fn bank_hash_info_at(&self, slot: Slot, rewrites: &Rewrites) -> BankHashInfo {
1129 let delta_hash = self
1130 .accounts_db
1131 .get_accounts_delta_hash_with_rewrites(slot, rewrites);
1132 let bank_hashes = self.accounts_db.bank_hashes.read().unwrap();
1133 let mut hash_info = bank_hashes
1134 .get(&slot)
1135 .expect("No bank hash was found for this bank, that should not be possible")
1136 .clone();
1137 hash_info.hash = delta_hash;
1138 hash_info
1139 }
1140
1141 #[must_use]
1144 #[allow(clippy::needless_collect)]
1145 pub fn lock_accounts<'a>(
1146 &self,
1147 txs: impl Iterator<Item = &'a SanitizedTransaction>,
1148 tx_account_lock_limit: usize,
1149 ) -> Vec<Result<()>> {
1150 let tx_account_locks_results: Vec<Result<_>> = txs
1151 .map(|tx| tx.get_account_locks(tx_account_lock_limit))
1152 .collect();
1153 self.lock_accounts_inner(tx_account_locks_results)
1154 }
1155
1156 #[must_use]
1157 #[allow(clippy::needless_collect)]
1158 pub fn lock_accounts_with_results<'a>(
1159 &self,
1160 txs: impl Iterator<Item = &'a SanitizedTransaction>,
1161 results: impl Iterator<Item = &'a Result<()>>,
1162 tx_account_lock_limit: usize,
1163 ) -> Vec<Result<()>> {
1164 let tx_account_locks_results: Vec<Result<_>> = txs
1165 .zip(results)
1166 .map(|(tx, result)| match result {
1167 Ok(()) => tx.get_account_locks(tx_account_lock_limit),
1168 Err(err) => Err(err.clone()),
1169 })
1170 .collect();
1171 self.lock_accounts_inner(tx_account_locks_results)
1172 }
1173
1174 #[must_use]
1175 fn lock_accounts_inner(
1176 &self,
1177 tx_account_locks_results: Vec<Result<TransactionAccountLocks>>,
1178 ) -> Vec<Result<()>> {
1179 let account_locks = &mut self.account_locks.lock().unwrap();
1180 tx_account_locks_results
1181 .into_iter()
1182 .map(|tx_account_locks_result| match tx_account_locks_result {
1183 Ok(tx_account_locks) => self.lock_account(
1184 account_locks,
1185 tx_account_locks.writable,
1186 tx_account_locks.readonly,
1187 ),
1188 Err(err) => Err(err),
1189 })
1190 .collect()
1191 }
1192
1193 #[allow(clippy::needless_collect)]
1195 pub fn unlock_accounts<'a>(
1196 &self,
1197 txs: impl Iterator<Item = &'a SanitizedTransaction>,
1198 results: &[Result<()>],
1199 ) {
1200 let keys: Vec<_> = txs
1201 .zip(results)
1202 .filter_map(|(tx, res)| match res {
1203 Err(TransactionError::AccountLoadedTwice)
1204 | Err(TransactionError::AccountInUse)
1205 | Err(TransactionError::SanitizeFailure)
1206 | Err(TransactionError::TooManyAccountLocks)
1207 | Err(TransactionError::WouldExceedMaxBlockCostLimit)
1208 | Err(TransactionError::WouldExceedMaxVoteCostLimit)
1209 | Err(TransactionError::WouldExceedMaxAccountCostLimit)
1210 | Err(TransactionError::WouldExceedAccountDataBlockLimit)
1211 | Err(TransactionError::WouldExceedAccountDataTotalLimit) => None,
1212 _ => Some(tx.get_account_locks_unchecked()),
1213 })
1214 .collect();
1215 let mut account_locks = self.account_locks.lock().unwrap();
1216 debug!("bank unlock accounts");
1217 keys.into_iter().for_each(|keys| {
1218 self.unlock_account(&mut account_locks, keys.writable, keys.readonly);
1219 });
1220 }
1221
1222 #[allow(clippy::too_many_arguments)]
1225 pub(crate) fn store_cached(
1226 &self,
1227 slot: Slot,
1228 txs: &[SanitizedTransaction],
1229 res: &[TransactionExecutionResult],
1230 loaded: &mut [TransactionLoadResult],
1231 rent_collector: &RentCollector,
1232 durable_nonce: &DurableNonce,
1233 lamports_per_signature: u64,
1234 preserve_rent_epoch_for_rent_exempt_accounts: bool,
1235 ) {
1236 let (accounts_to_store, txn_signatures) = self.collect_accounts_to_store(
1237 txs,
1238 res,
1239 loaded,
1240 rent_collector,
1241 durable_nonce,
1242 lamports_per_signature,
1243 preserve_rent_epoch_for_rent_exempt_accounts,
1244 );
1245 self.accounts_db
1246 .store_cached((slot, &accounts_to_store[..]), Some(&txn_signatures));
1247 }
1248
1249 pub fn store_accounts_cached<'a, T: ReadableAccount + Sync + ZeroLamport>(
1250 &self,
1251 accounts: impl StorableAccounts<'a, T>,
1252 ) {
1253 self.accounts_db.store_cached(accounts, None)
1254 }
1255
1256 pub fn add_root(&self, slot: Slot) -> AccountsAddRootTiming {
1258 self.accounts_db.add_root(slot)
1259 }
1260
1261 #[allow(clippy::too_many_arguments)]
1262 fn collect_accounts_to_store<'a>(
1263 &self,
1264 txs: &'a [SanitizedTransaction],
1265 execution_results: &'a [TransactionExecutionResult],
1266 load_results: &'a mut [TransactionLoadResult],
1267 rent_collector: &RentCollector,
1268 durable_nonce: &DurableNonce,
1269 lamports_per_signature: u64,
1270 preserve_rent_epoch_for_rent_exempt_accounts: bool,
1271 ) -> (
1272 Vec<(&'a Pubkey, &'a AccountSharedData)>,
1273 Vec<Option<&'a Signature>>,
1274 ) {
1275 let mut accounts = Vec::with_capacity(load_results.len());
1276 let mut signatures = Vec::with_capacity(load_results.len());
1277 for (i, ((tx_load_result, nonce), tx)) in load_results.iter_mut().zip(txs).enumerate() {
1278 if tx_load_result.is_err() {
1279 continue;
1281 }
1282
1283 let execution_status = match &execution_results[i] {
1284 TransactionExecutionResult::Executed { details, .. } => &details.status,
1285 TransactionExecutionResult::NotExecuted(_) => continue,
1287 };
1288
1289 let maybe_nonce = match (execution_status, &*nonce) {
1290 (Ok(_), _) => None, (Err(_), Some(nonce)) => {
1292 Some((nonce, true ))
1293 }
1294 (Err(_), None) => {
1295 continue;
1298 }
1299 };
1300
1301 let message = tx.message();
1302 let loaded_transaction = tx_load_result.as_mut().unwrap();
1303 let mut fee_payer_index = None;
1304 for (i, (address, account)) in (0..message.account_keys().len())
1305 .zip(loaded_transaction.accounts.iter_mut())
1306 .filter(|(i, _)| message.is_non_loader_key(*i))
1307 {
1308 if fee_payer_index.is_none() {
1309 fee_payer_index = Some(i);
1310 }
1311 let is_fee_payer = Some(i) == fee_payer_index;
1312 if message.is_writable(i) {
1313 let is_nonce_account = prepare_if_nonce_account(
1314 address,
1315 account,
1316 execution_status,
1317 is_fee_payer,
1318 maybe_nonce,
1319 durable_nonce,
1320 lamports_per_signature,
1321 );
1322
1323 if execution_status.is_ok() || is_nonce_account || is_fee_payer {
1324 if !preserve_rent_epoch_for_rent_exempt_accounts
1325 && account.rent_epoch() == INITIAL_RENT_EPOCH
1326 {
1327 let rent = rent_collector
1328 .collect_from_created_account(
1329 address,
1330 account,
1331 preserve_rent_epoch_for_rent_exempt_accounts,
1332 )
1333 .rent_amount;
1334 loaded_transaction.rent += rent;
1335 loaded_transaction.rent_debits.insert(
1336 address,
1337 rent,
1338 account.lamports(),
1339 );
1340 }
1341
1342 accounts.push((&*address, &*account));
1344 signatures.push(Some(tx.signature()));
1345 }
1346 }
1347 }
1348 }
1349 (accounts, signatures)
1350 }
1351}
1352
1353fn prepare_if_nonce_account<'a>(
1354 address: &Pubkey,
1355 account: &mut AccountSharedData,
1356 execution_result: &Result<()>,
1357 is_fee_payer: bool,
1358 maybe_nonce: Option<(&'a NonceFull, bool)>,
1359 &durable_nonce: &DurableNonce,
1360 lamports_per_signature: u64,
1361) -> bool {
1362 if let Some((nonce, rollback)) = maybe_nonce {
1363 if address == nonce.address() {
1364 if rollback {
1365 *account = nonce.account().clone();
1370 }
1371
1372 let nonce_versions = StateMut::<NonceVersions>::state(nonce.account()).unwrap();
1379 if let NonceState::Initialized(ref data) = nonce_versions.state() {
1380 let nonce_state = NonceState::new_initialized(
1381 &data.authority,
1382 durable_nonce,
1383 lamports_per_signature,
1384 );
1385 let nonce_versions = NonceVersions::new(nonce_state);
1386 account.set_state(&nonce_versions).unwrap();
1387 }
1388 true
1389 } else {
1390 if execution_result.is_err() && is_fee_payer {
1391 if let Some(fee_payer_account) = nonce.fee_payer_account() {
1392 *account = fee_payer_account.clone();
1396 }
1397 }
1398
1399 false
1400 }
1401 } else {
1402 false
1403 }
1404}
1405
1406pub mod test_utils {
1408 use super::*;
1409
1410 pub fn create_test_accounts(
1411 accounts: &Accounts,
1412 pubkeys: &mut Vec<Pubkey>,
1413 num: usize,
1414 slot: Slot,
1415 ) {
1416 for t in 0..num {
1417 let pubkey = solana_sdk::pubkey::new_rand();
1418 let account =
1419 AccountSharedData::new((t + 1) as u64, 0, AccountSharedData::default().owner());
1420 accounts.store_slow_uncached(slot, &pubkey, &account);
1421 pubkeys.push(pubkey);
1422 }
1423 }
1424
1425 pub fn update_accounts_bench(accounts: &Accounts, pubkeys: &[Pubkey], slot: u64) {
1428 for pubkey in pubkeys {
1429 let amount = thread_rng().gen_range(0, 10);
1430 let account = AccountSharedData::new(amount, 0, AccountSharedData::default().owner());
1431 accounts.store_slow_uncached(slot, pubkey, &account);
1432 }
1433 }
1434}
1435
1436#[cfg(test)]
1437mod tests {
1438 use {
1439 super::*,
1440 crate::{
1441 bank::{DurableNonceFee, TransactionExecutionDetails},
1442 rent_collector::RentCollector,
1443 },
1444 assert_matches::assert_matches,
1445 solana_address_lookup_table_program::state::LookupTableMeta,
1446 solana_program_runtime::executor_cache::Executors,
1447 solana_sdk::{
1448 account::{AccountSharedData, WritableAccount},
1449 epoch_schedule::EpochSchedule,
1450 genesis_config::ClusterType,
1451 hash::Hash,
1452 instruction::{CompiledInstruction, InstructionError},
1453 message::{Message, MessageHeader},
1454 nonce, nonce_account,
1455 rent::Rent,
1456 signature::{keypair_from_seed, signers::Signers, Keypair, Signer},
1457 system_instruction, system_program,
1458 transaction::{Transaction, MAX_TX_ACCOUNT_LOCKS},
1459 },
1460 std::{
1461 borrow::Cow,
1462 cell::RefCell,
1463 convert::TryFrom,
1464 rc::Rc,
1465 sync::atomic::{AtomicBool, AtomicU64, Ordering},
1466 thread, time,
1467 },
1468 };
1469
1470 fn new_sanitized_tx<T: Signers>(
1471 from_keypairs: &T,
1472 message: Message,
1473 recent_blockhash: Hash,
1474 ) -> SanitizedTransaction {
1475 SanitizedTransaction::from_transaction_for_tests(Transaction::new(
1476 from_keypairs,
1477 message,
1478 recent_blockhash,
1479 ))
1480 }
1481
1482 fn new_execution_result(
1483 status: Result<()>,
1484 nonce: Option<&NonceFull>,
1485 ) -> TransactionExecutionResult {
1486 TransactionExecutionResult::Executed {
1487 details: TransactionExecutionDetails {
1488 status,
1489 log_messages: None,
1490 inner_instructions: None,
1491 durable_nonce_fee: nonce.map(DurableNonceFee::from),
1492 return_data: None,
1493 executed_units: 0,
1494 accounts_data_len_delta: 0,
1495 },
1496 executors: Rc::new(RefCell::new(Executors::default())),
1497 }
1498 }
1499
1500 fn load_accounts_with_fee_and_rent(
1501 tx: Transaction,
1502 ka: &[TransactionAccount],
1503 lamports_per_signature: u64,
1504 rent_collector: &RentCollector,
1505 error_counters: &mut TransactionErrorMetrics,
1506 feature_set: &FeatureSet,
1507 fee_structure: &FeeStructure,
1508 ) -> Vec<TransactionLoadResult> {
1509 let mut hash_queue = BlockhashQueue::new(100);
1510 hash_queue.register_hash(&tx.message().recent_blockhash, lamports_per_signature);
1511 let accounts = Accounts::new_with_config_for_tests(
1512 Vec::new(),
1513 &ClusterType::Development,
1514 AccountSecondaryIndexes::default(),
1515 false,
1516 AccountShrinkThreshold::default(),
1517 );
1518 for ka in ka.iter() {
1519 accounts.store_slow_uncached(0, &ka.0, &ka.1);
1520 }
1521
1522 let ancestors = vec![(0, 0)].into_iter().collect();
1523 let sanitized_tx = SanitizedTransaction::from_transaction_for_tests(tx);
1524 accounts.load_accounts(
1525 &ancestors,
1526 &[sanitized_tx],
1527 vec![(Ok(()), None)],
1528 &hash_queue,
1529 error_counters,
1530 rent_collector,
1531 feature_set,
1532 fee_structure,
1533 None,
1534 )
1535 }
1536
1537 fn load_accounts_with_fee(
1538 tx: Transaction,
1539 ka: &[TransactionAccount],
1540 lamports_per_signature: u64,
1541 error_counters: &mut TransactionErrorMetrics,
1542 ) -> Vec<TransactionLoadResult> {
1543 load_accounts_with_fee_and_rent(
1544 tx,
1545 ka,
1546 lamports_per_signature,
1547 &RentCollector::default(),
1548 error_counters,
1549 &FeatureSet::all_enabled(),
1550 &FeeStructure::default(),
1551 )
1552 }
1553
1554 fn load_accounts(
1555 tx: Transaction,
1556 ka: &[TransactionAccount],
1557 error_counters: &mut TransactionErrorMetrics,
1558 ) -> Vec<TransactionLoadResult> {
1559 load_accounts_with_fee(tx, ka, 0, error_counters)
1560 }
1561
1562 #[test]
1563 fn test_hold_range_in_memory() {
1564 let accts = Accounts::default_for_tests();
1565 let range = Pubkey::from([0; 32])..=Pubkey::from([0xff; 32]);
1566 accts.hold_range_in_memory(&range, true, &test_thread_pool());
1567 accts.hold_range_in_memory(&range, false, &test_thread_pool());
1568 accts.hold_range_in_memory(&range, true, &test_thread_pool());
1569 accts.hold_range_in_memory(&range, true, &test_thread_pool());
1570 accts.hold_range_in_memory(&range, false, &test_thread_pool());
1571 accts.hold_range_in_memory(&range, false, &test_thread_pool());
1572 }
1573
1574 #[test]
1575 fn test_hold_range_in_memory2() {
1576 let accts = Accounts::default_for_tests();
1577 let range = Pubkey::from([0; 32])..=Pubkey::from([0xff; 32]);
1578 let idx = &accts.accounts_db.accounts_index;
1579 let bins = idx.account_maps.len();
1580 let bins_2 = bins * 2;
1582 let binner = crate::pubkey_bins::PubkeyBinCalculator24::new(bins_2);
1583 let range2 =
1584 binner.lowest_pubkey_from_bin(0, bins_2)..binner.lowest_pubkey_from_bin(1, bins_2);
1585 let range2_inclusive = range2.start..=range2.end;
1586 assert_eq!(0, idx.bin_calculator.bin_from_pubkey(&range2.start));
1587 assert_eq!(0, idx.bin_calculator.bin_from_pubkey(&range2.end));
1588 accts.hold_range_in_memory(&range, true, &test_thread_pool());
1589 idx.account_maps.iter().for_each(|map| {
1590 assert_eq!(
1591 map.cache_ranges_held.read().unwrap().to_vec(),
1592 vec![range.clone()]
1593 );
1594 });
1595 accts.hold_range_in_memory(&range2, true, &test_thread_pool());
1596 idx.account_maps.iter().enumerate().for_each(|(bin, map)| {
1597 let expected = if bin == 0 {
1598 vec![range.clone(), range2_inclusive.clone()]
1599 } else {
1600 vec![range.clone()]
1601 };
1602 assert_eq!(
1603 map.cache_ranges_held.read().unwrap().to_vec(),
1604 expected,
1605 "bin: {}",
1606 bin
1607 );
1608 });
1609 accts.hold_range_in_memory(&range, false, &test_thread_pool());
1610 accts.hold_range_in_memory(&range2, false, &test_thread_pool());
1611 }
1612
1613 fn test_thread_pool() -> rayon::ThreadPool {
1614 crate::accounts_db::make_min_priority_thread_pool()
1615 }
1616
1617 #[test]
1618 fn test_load_accounts_no_account_0_exists() {
1619 let accounts: Vec<TransactionAccount> = Vec::new();
1620 let mut error_counters = TransactionErrorMetrics::default();
1621
1622 let keypair = Keypair::new();
1623
1624 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1625 let tx = Transaction::new_with_compiled_instructions(
1626 &[&keypair],
1627 &[],
1628 Hash::default(),
1629 vec![native_loader::id()],
1630 instructions,
1631 );
1632
1633 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1634
1635 assert_eq!(error_counters.account_not_found, 1);
1636 assert_eq!(loaded_accounts.len(), 1);
1637 assert_eq!(
1638 loaded_accounts[0],
1639 (Err(TransactionError::AccountNotFound), None,),
1640 );
1641 }
1642
1643 #[test]
1644 fn test_load_accounts_unknown_program_id() {
1645 let mut accounts: Vec<TransactionAccount> = Vec::new();
1646 let mut error_counters = TransactionErrorMetrics::default();
1647
1648 let keypair = Keypair::new();
1649 let key0 = keypair.pubkey();
1650 let key1 = Pubkey::from([5u8; 32]);
1651
1652 let account = AccountSharedData::new(1, 0, &Pubkey::default());
1653 accounts.push((key0, account));
1654
1655 let account = AccountSharedData::new(2, 1, &Pubkey::default());
1656 accounts.push((key1, account));
1657
1658 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1659 let tx = Transaction::new_with_compiled_instructions(
1660 &[&keypair],
1661 &[],
1662 Hash::default(),
1663 vec![Pubkey::default()],
1664 instructions,
1665 );
1666
1667 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1668
1669 assert_eq!(error_counters.account_not_found, 1);
1670 assert_eq!(loaded_accounts.len(), 1);
1671 assert_eq!(
1672 loaded_accounts[0],
1673 (Err(TransactionError::ProgramAccountNotFound), None,)
1674 );
1675 }
1676
1677 #[test]
1678 fn test_load_accounts_insufficient_funds() {
1679 let lamports_per_signature = 5000;
1680 let mut accounts: Vec<TransactionAccount> = Vec::new();
1681 let mut error_counters = TransactionErrorMetrics::default();
1682
1683 let keypair = Keypair::new();
1684 let key0 = keypair.pubkey();
1685
1686 let account = AccountSharedData::new(1, 0, &Pubkey::default());
1687 accounts.push((key0, account));
1688
1689 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1690 let tx = Transaction::new_with_compiled_instructions(
1691 &[&keypair],
1692 &[],
1693 Hash::default(),
1694 vec![native_loader::id()],
1695 instructions,
1696 );
1697
1698 let fee = Bank::calculate_fee(
1699 &SanitizedMessage::try_from(tx.message().clone()).unwrap(),
1700 lamports_per_signature,
1701 &FeeStructure::default(),
1702 true,
1703 true,
1704 true,
1705 );
1706 assert_eq!(fee, lamports_per_signature);
1707
1708 let loaded_accounts =
1709 load_accounts_with_fee(tx, &accounts, lamports_per_signature, &mut error_counters);
1710
1711 assert_eq!(error_counters.insufficient_funds, 1);
1712 assert_eq!(loaded_accounts.len(), 1);
1713 assert_eq!(
1714 loaded_accounts[0].clone(),
1715 (Err(TransactionError::InsufficientFundsForFee), None,),
1716 );
1717 }
1718
1719 #[test]
1720 fn test_load_accounts_invalid_account_for_fee() {
1721 let mut accounts: Vec<TransactionAccount> = Vec::new();
1722 let mut error_counters = TransactionErrorMetrics::default();
1723
1724 let keypair = Keypair::new();
1725 let key0 = keypair.pubkey();
1726
1727 let account = AccountSharedData::new(1, 1, &solana_sdk::pubkey::new_rand()); accounts.push((key0, account));
1729
1730 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1731 let tx = Transaction::new_with_compiled_instructions(
1732 &[&keypair],
1733 &[],
1734 Hash::default(),
1735 vec![native_loader::id()],
1736 instructions,
1737 );
1738
1739 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1740
1741 assert_eq!(error_counters.invalid_account_for_fee, 1);
1742 assert_eq!(loaded_accounts.len(), 1);
1743 assert_eq!(
1744 loaded_accounts[0],
1745 (Err(TransactionError::InvalidAccountForFee), None,),
1746 );
1747 }
1748
1749 #[test]
1750 fn test_load_accounts_fee_payer_is_nonce() {
1751 let lamports_per_signature = 5000;
1752 let mut error_counters = TransactionErrorMetrics::default();
1753 let rent_collector = RentCollector::new(
1754 0,
1755 EpochSchedule::default(),
1756 500_000.0,
1757 Rent {
1758 lamports_per_byte_year: 42,
1759 ..Rent::default()
1760 },
1761 );
1762 let min_balance = rent_collector.rent.minimum_balance(NonceState::size());
1763 let nonce = Keypair::new();
1764 let mut accounts = vec![(
1765 nonce.pubkey(),
1766 AccountSharedData::new_data(
1767 min_balance + lamports_per_signature,
1768 &NonceVersions::new(NonceState::Initialized(nonce::state::Data::default())),
1769 &system_program::id(),
1770 )
1771 .unwrap(),
1772 )];
1773 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1774 let tx = Transaction::new_with_compiled_instructions(
1775 &[&nonce],
1776 &[],
1777 Hash::default(),
1778 vec![native_loader::id()],
1779 instructions,
1780 );
1781
1782 let loaded_accounts = load_accounts_with_fee_and_rent(
1784 tx.clone(),
1785 &accounts,
1786 lamports_per_signature,
1787 &rent_collector,
1788 &mut error_counters,
1789 &FeatureSet::all_enabled(),
1790 &FeeStructure::default(),
1791 );
1792 assert_eq!(loaded_accounts.len(), 1);
1793 let (load_res, _nonce) = &loaded_accounts[0];
1794 let loaded_transaction = load_res.as_ref().unwrap();
1795 assert_eq!(loaded_transaction.accounts[0].1.lamports(), min_balance);
1796
1797 accounts[0].1.set_lamports(lamports_per_signature);
1799 let loaded_accounts = load_accounts_with_fee_and_rent(
1800 tx.clone(),
1801 &accounts,
1802 lamports_per_signature,
1803 &rent_collector,
1804 &mut error_counters,
1805 &FeatureSet::all_enabled(),
1806 &FeeStructure::default(),
1807 );
1808 assert_eq!(loaded_accounts.len(), 1);
1809 let (load_res, _nonce) = &loaded_accounts[0];
1810 assert_eq!(*load_res, Err(TransactionError::InsufficientFundsForFee));
1811
1812 accounts[0]
1814 .1
1815 .set_lamports(lamports_per_signature + min_balance / 2);
1816 let loaded_accounts = load_accounts_with_fee_and_rent(
1817 tx,
1818 &accounts,
1819 lamports_per_signature,
1820 &rent_collector,
1821 &mut error_counters,
1822 &FeatureSet::all_enabled(),
1823 &FeeStructure::default(),
1824 );
1825 assert_eq!(loaded_accounts.len(), 1);
1826 let (load_res, _nonce) = &loaded_accounts[0];
1827 assert_eq!(*load_res, Err(TransactionError::InsufficientFundsForFee));
1828 }
1829
1830 #[test]
1831 fn test_load_accounts_no_loaders() {
1832 let mut accounts: Vec<TransactionAccount> = Vec::new();
1833 let mut error_counters = TransactionErrorMetrics::default();
1834
1835 let keypair = Keypair::new();
1836 let key0 = keypair.pubkey();
1837 let key1 = Pubkey::from([5u8; 32]);
1838
1839 let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
1840 account.set_rent_epoch(1);
1841 accounts.push((key0, account));
1842
1843 let mut account = AccountSharedData::new(2, 1, &Pubkey::default());
1844 account.set_rent_epoch(1);
1845 accounts.push((key1, account));
1846
1847 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
1848 let tx = Transaction::new_with_compiled_instructions(
1849 &[&keypair],
1850 &[key1],
1851 Hash::default(),
1852 vec![native_loader::id()],
1853 instructions,
1854 );
1855
1856 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1857
1858 assert_eq!(error_counters.account_not_found, 0);
1859 assert_eq!(loaded_accounts.len(), 1);
1860 match &loaded_accounts[0] {
1861 (Ok(loaded_transaction), _nonce) => {
1862 assert_eq!(loaded_transaction.accounts.len(), 3);
1863 assert_eq!(loaded_transaction.accounts[0].1, accounts[0].1);
1864 assert_eq!(loaded_transaction.program_indices.len(), 1);
1865 assert_eq!(loaded_transaction.program_indices[0].len(), 0);
1866 }
1867 (Err(e), _nonce) => Err(e).unwrap(),
1868 }
1869 }
1870
1871 #[test]
1872 fn test_load_accounts_max_call_depth() {
1873 let mut accounts: Vec<TransactionAccount> = Vec::new();
1874 let mut error_counters = TransactionErrorMetrics::default();
1875
1876 let keypair = Keypair::new();
1877 let key0 = keypair.pubkey();
1878 let key1 = Pubkey::from([5u8; 32]);
1879 let key2 = Pubkey::from([6u8; 32]);
1880 let key3 = Pubkey::from([7u8; 32]);
1881 let key4 = Pubkey::from([8u8; 32]);
1882 let key5 = Pubkey::from([9u8; 32]);
1883 let key6 = Pubkey::from([10u8; 32]);
1884
1885 let account = AccountSharedData::new(1, 0, &Pubkey::default());
1886 accounts.push((key0, account));
1887
1888 let mut account = AccountSharedData::new(40, 1, &Pubkey::default());
1889 account.set_executable(true);
1890 account.set_owner(native_loader::id());
1891 accounts.push((key1, account));
1892
1893 let mut account = AccountSharedData::new(41, 1, &Pubkey::default());
1894 account.set_executable(true);
1895 account.set_owner(key1);
1896 accounts.push((key2, account));
1897
1898 let mut account = AccountSharedData::new(42, 1, &Pubkey::default());
1899 account.set_executable(true);
1900 account.set_owner(key2);
1901 accounts.push((key3, account));
1902
1903 let mut account = AccountSharedData::new(43, 1, &Pubkey::default());
1904 account.set_executable(true);
1905 account.set_owner(key3);
1906 accounts.push((key4, account));
1907
1908 let mut account = AccountSharedData::new(44, 1, &Pubkey::default());
1909 account.set_executable(true);
1910 account.set_owner(key4);
1911 accounts.push((key5, account));
1912
1913 let mut account = AccountSharedData::new(45, 1, &Pubkey::default());
1914 account.set_executable(true);
1915 account.set_owner(key5);
1916 accounts.push((key6, account));
1917
1918 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1919 let tx = Transaction::new_with_compiled_instructions(
1920 &[&keypair],
1921 &[],
1922 Hash::default(),
1923 vec![key6],
1924 instructions,
1925 );
1926
1927 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1928
1929 assert_eq!(error_counters.call_chain_too_deep, 1);
1930 assert_eq!(loaded_accounts.len(), 1);
1931 assert_eq!(
1932 loaded_accounts[0],
1933 (Err(TransactionError::CallChainTooDeep), None,)
1934 );
1935 }
1936
1937 #[test]
1938 fn test_load_accounts_bad_owner() {
1939 let mut accounts: Vec<TransactionAccount> = Vec::new();
1940 let mut error_counters = TransactionErrorMetrics::default();
1941
1942 let keypair = Keypair::new();
1943 let key0 = keypair.pubkey();
1944 let key1 = Pubkey::from([5u8; 32]);
1945
1946 let account = AccountSharedData::new(1, 0, &Pubkey::default());
1947 accounts.push((key0, account));
1948
1949 let mut account = AccountSharedData::new(40, 1, &Pubkey::default());
1950 account.set_executable(true);
1951 accounts.push((key1, account));
1952
1953 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1954 let tx = Transaction::new_with_compiled_instructions(
1955 &[&keypair],
1956 &[],
1957 Hash::default(),
1958 vec![key1],
1959 instructions,
1960 );
1961
1962 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1963
1964 assert_eq!(error_counters.account_not_found, 1);
1965 assert_eq!(loaded_accounts.len(), 1);
1966 assert_eq!(
1967 loaded_accounts[0],
1968 (Err(TransactionError::ProgramAccountNotFound), None,)
1969 );
1970 }
1971
1972 #[test]
1973 fn test_load_accounts_not_executable() {
1974 let mut accounts: Vec<TransactionAccount> = Vec::new();
1975 let mut error_counters = TransactionErrorMetrics::default();
1976
1977 let keypair = Keypair::new();
1978 let key0 = keypair.pubkey();
1979 let key1 = Pubkey::from([5u8; 32]);
1980
1981 let account = AccountSharedData::new(1, 0, &Pubkey::default());
1982 accounts.push((key0, account));
1983
1984 let account = AccountSharedData::new(40, 1, &native_loader::id());
1985 accounts.push((key1, account));
1986
1987 let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
1988 let tx = Transaction::new_with_compiled_instructions(
1989 &[&keypair],
1990 &[],
1991 Hash::default(),
1992 vec![key1],
1993 instructions,
1994 );
1995
1996 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
1997
1998 assert_eq!(error_counters.invalid_program_for_execution, 1);
1999 assert_eq!(loaded_accounts.len(), 1);
2000 assert_eq!(
2001 loaded_accounts[0],
2002 (Err(TransactionError::InvalidProgramForExecution), None,)
2003 );
2004 }
2005
2006 #[test]
2007 fn test_load_accounts_multiple_loaders() {
2008 let mut accounts: Vec<TransactionAccount> = Vec::new();
2009 let mut error_counters = TransactionErrorMetrics::default();
2010
2011 let keypair = Keypair::new();
2012 let key0 = keypair.pubkey();
2013 let key1 = Pubkey::from([5u8; 32]);
2014 let key2 = Pubkey::from([6u8; 32]);
2015
2016 let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
2017 account.set_rent_epoch(1);
2018 accounts.push((key0, account));
2019
2020 let mut account = AccountSharedData::new(40, 1, &Pubkey::default());
2021 account.set_executable(true);
2022 account.set_rent_epoch(1);
2023 account.set_owner(native_loader::id());
2024 accounts.push((key1, account));
2025
2026 let mut account = AccountSharedData::new(41, 1, &Pubkey::default());
2027 account.set_executable(true);
2028 account.set_rent_epoch(1);
2029 account.set_owner(key1);
2030 accounts.push((key2, account));
2031
2032 let instructions = vec![
2033 CompiledInstruction::new(1, &(), vec![0]),
2034 CompiledInstruction::new(2, &(), vec![0]),
2035 ];
2036 let tx = Transaction::new_with_compiled_instructions(
2037 &[&keypair],
2038 &[],
2039 Hash::default(),
2040 vec![key1, key2],
2041 instructions,
2042 );
2043
2044 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
2045
2046 assert_eq!(error_counters.account_not_found, 0);
2047 assert_eq!(loaded_accounts.len(), 1);
2048 match &loaded_accounts[0] {
2049 (Ok(loaded_transaction), _nonce) => {
2050 assert_eq!(loaded_transaction.accounts.len(), 6);
2051 assert_eq!(loaded_transaction.accounts[0].1, accounts[0].1);
2052 assert_eq!(loaded_transaction.program_indices.len(), 2);
2053 assert_eq!(loaded_transaction.program_indices[0].len(), 1);
2054 assert_eq!(loaded_transaction.program_indices[1].len(), 2);
2055 for program_indices in loaded_transaction.program_indices.iter() {
2056 for (i, program_index) in program_indices.iter().enumerate() {
2057 assert_eq!(
2059 loaded_transaction.accounts[*program_index].0,
2060 accounts[i + 1].0
2061 );
2062 assert_eq!(
2063 loaded_transaction.accounts[*program_index].1,
2064 accounts[i + 1].1
2065 );
2066 }
2067 }
2068 }
2069 (Err(e), _nonce) => Err(e).unwrap(),
2070 }
2071 }
2072
2073 #[test]
2074 fn test_load_lookup_table_addresses_account_not_found() {
2075 let ancestors = vec![(0, 0)].into_iter().collect();
2076 let accounts = Accounts::new_with_config_for_tests(
2077 Vec::new(),
2078 &ClusterType::Development,
2079 AccountSecondaryIndexes::default(),
2080 false,
2081 AccountShrinkThreshold::default(),
2082 );
2083
2084 let invalid_table_key = Pubkey::new_unique();
2085 let address_table_lookup = MessageAddressTableLookup {
2086 account_key: invalid_table_key,
2087 writable_indexes: vec![],
2088 readonly_indexes: vec![],
2089 };
2090
2091 assert_eq!(
2092 accounts.load_lookup_table_addresses(
2093 &ancestors,
2094 &address_table_lookup,
2095 &SlotHashes::default(),
2096 LoadZeroLamports::SomeWithZeroLamportAccount,
2097 ),
2098 Err(AddressLookupError::LookupTableAccountNotFound),
2099 );
2100 }
2101
2102 #[test]
2103 fn test_load_lookup_table_addresses_invalid_account_owner() {
2104 let ancestors = vec![(0, 0)].into_iter().collect();
2105 let accounts = Accounts::new_with_config_for_tests(
2106 Vec::new(),
2107 &ClusterType::Development,
2108 AccountSecondaryIndexes::default(),
2109 false,
2110 AccountShrinkThreshold::default(),
2111 );
2112
2113 let invalid_table_key = Pubkey::new_unique();
2114 let mut invalid_table_account = AccountSharedData::default();
2115 invalid_table_account.set_lamports(1);
2116 accounts.store_slow_uncached(0, &invalid_table_key, &invalid_table_account);
2117
2118 let address_table_lookup = MessageAddressTableLookup {
2119 account_key: invalid_table_key,
2120 writable_indexes: vec![],
2121 readonly_indexes: vec![],
2122 };
2123
2124 assert_eq!(
2125 accounts.load_lookup_table_addresses(
2126 &ancestors,
2127 &address_table_lookup,
2128 &SlotHashes::default(),
2129 LoadZeroLamports::SomeWithZeroLamportAccount,
2130 ),
2131 Err(AddressLookupError::InvalidAccountOwner),
2132 );
2133 }
2134
2135 #[test]
2136 fn test_load_lookup_table_addresses_invalid_account_data() {
2137 let ancestors = vec![(0, 0)].into_iter().collect();
2138 let accounts = Accounts::new_with_config_for_tests(
2139 Vec::new(),
2140 &ClusterType::Development,
2141 AccountSecondaryIndexes::default(),
2142 false,
2143 AccountShrinkThreshold::default(),
2144 );
2145
2146 let invalid_table_key = Pubkey::new_unique();
2147 let invalid_table_account =
2148 AccountSharedData::new(1, 0, &solana_address_lookup_table_program::id());
2149 accounts.store_slow_uncached(0, &invalid_table_key, &invalid_table_account);
2150
2151 let address_table_lookup = MessageAddressTableLookup {
2152 account_key: invalid_table_key,
2153 writable_indexes: vec![],
2154 readonly_indexes: vec![],
2155 };
2156
2157 assert_eq!(
2158 accounts.load_lookup_table_addresses(
2159 &ancestors,
2160 &address_table_lookup,
2161 &SlotHashes::default(),
2162 LoadZeroLamports::SomeWithZeroLamportAccount,
2163 ),
2164 Err(AddressLookupError::InvalidAccountData),
2165 );
2166 }
2167
2168 #[test]
2169 fn test_load_lookup_table_addresses() {
2170 let ancestors = vec![(1, 1), (0, 0)].into_iter().collect();
2171 let accounts = Accounts::new_with_config_for_tests(
2172 Vec::new(),
2173 &ClusterType::Development,
2174 AccountSecondaryIndexes::default(),
2175 false,
2176 AccountShrinkThreshold::default(),
2177 );
2178
2179 let table_key = Pubkey::new_unique();
2180 let table_addresses = vec![Pubkey::new_unique(), Pubkey::new_unique()];
2181 let table_account = {
2182 let table_state = AddressLookupTable {
2183 meta: LookupTableMeta::default(),
2184 addresses: Cow::Owned(table_addresses.clone()),
2185 };
2186 AccountSharedData::create(
2187 1,
2188 table_state.serialize_for_tests().unwrap(),
2189 solana_address_lookup_table_program::id(),
2190 false,
2191 0,
2192 )
2193 };
2194 accounts.store_slow_uncached(0, &table_key, &table_account);
2195
2196 let address_table_lookup = MessageAddressTableLookup {
2197 account_key: table_key,
2198 writable_indexes: vec![0],
2199 readonly_indexes: vec![1],
2200 };
2201
2202 assert_eq!(
2203 accounts.load_lookup_table_addresses(
2204 &ancestors,
2205 &address_table_lookup,
2206 &SlotHashes::default(),
2207 LoadZeroLamports::SomeWithZeroLamportAccount,
2208 ),
2209 Ok(LoadedAddresses {
2210 writable: vec![table_addresses[0]],
2211 readonly: vec![table_addresses[1]],
2212 }),
2213 );
2214 }
2215
2216 #[test]
2217 fn test_load_by_program_slot() {
2218 let accounts = Accounts::new_with_config_for_tests(
2219 Vec::new(),
2220 &ClusterType::Development,
2221 AccountSecondaryIndexes::default(),
2222 false,
2223 AccountShrinkThreshold::default(),
2224 );
2225
2226 let pubkey0 = solana_sdk::pubkey::new_rand();
2228 let account0 = AccountSharedData::new(1, 0, &Pubkey::from([2; 32]));
2229 accounts.store_slow_uncached(0, &pubkey0, &account0);
2230 let pubkey1 = solana_sdk::pubkey::new_rand();
2231 let account1 = AccountSharedData::new(1, 0, &Pubkey::from([2; 32]));
2232 accounts.store_slow_uncached(0, &pubkey1, &account1);
2233 let pubkey2 = solana_sdk::pubkey::new_rand();
2234 let account2 = AccountSharedData::new(1, 0, &Pubkey::from([3; 32]));
2235 accounts.store_slow_uncached(0, &pubkey2, &account2);
2236
2237 let loaded = accounts.load_by_program_slot(0, Some(&Pubkey::from([2; 32])));
2238 assert_eq!(loaded.len(), 2);
2239 let loaded = accounts.load_by_program_slot(0, Some(&Pubkey::from([3; 32])));
2240 assert_eq!(loaded, vec![(pubkey2, account2)]);
2241 let loaded = accounts.load_by_program_slot(0, Some(&Pubkey::from([4; 32])));
2242 assert_eq!(loaded, vec![]);
2243 }
2244
2245 #[test]
2246 fn test_load_accounts_executable_with_write_lock() {
2247 let mut accounts: Vec<TransactionAccount> = Vec::new();
2248 let mut error_counters = TransactionErrorMetrics::default();
2249
2250 let keypair = Keypair::new();
2251 let key0 = keypair.pubkey();
2252 let key1 = Pubkey::from([5u8; 32]);
2253 let key2 = Pubkey::from([6u8; 32]);
2254
2255 let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
2256 account.set_rent_epoch(1);
2257 accounts.push((key0, account));
2258
2259 let mut account = AccountSharedData::new(40, 1, &native_loader::id());
2260 account.set_executable(true);
2261 account.set_rent_epoch(1);
2262 accounts.push((key1, account));
2263
2264 let mut account = AccountSharedData::new(40, 1, &native_loader::id());
2265 account.set_executable(true);
2266 account.set_rent_epoch(1);
2267 accounts.push((key2, account));
2268
2269 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2270 let mut message = Message::new_with_compiled_instructions(
2271 1,
2272 0,
2273 1, vec![key0, key1, key2],
2275 Hash::default(),
2276 instructions,
2277 );
2278 let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
2279 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
2280
2281 assert_eq!(error_counters.invalid_writable_account, 1);
2282 assert_eq!(loaded_accounts.len(), 1);
2283 assert_eq!(
2284 loaded_accounts[0],
2285 (Err(TransactionError::InvalidWritableAccount), None)
2286 );
2287
2288 message.account_keys = vec![key0, key1, key2]; message.header.num_readonly_unsigned_accounts = 2; let tx = Transaction::new(&[&keypair], message, Hash::default());
2292 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
2293
2294 assert_eq!(error_counters.invalid_writable_account, 1);
2295 assert_eq!(loaded_accounts.len(), 1);
2296 let result = loaded_accounts[0].0.as_ref().unwrap();
2297 assert_eq!(result.accounts[..2], accounts[..2]);
2298 assert_eq!(result.accounts[result.program_indices[0][0]], accounts[2]);
2299 }
2300
2301 #[test]
2302 fn test_load_accounts_upgradeable_with_write_lock() {
2303 let mut accounts: Vec<TransactionAccount> = Vec::new();
2304 let mut error_counters = TransactionErrorMetrics::default();
2305
2306 let keypair = Keypair::new();
2307 let key0 = keypair.pubkey();
2308 let key1 = Pubkey::from([5u8; 32]);
2309 let key2 = Pubkey::from([6u8; 32]);
2310 let programdata_key1 = Pubkey::from([7u8; 32]);
2311 let programdata_key2 = Pubkey::from([8u8; 32]);
2312
2313 let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
2314 account.set_rent_epoch(1);
2315 accounts.push((key0, account));
2316
2317 let program_data = UpgradeableLoaderState::ProgramData {
2318 slot: 42,
2319 upgrade_authority_address: None,
2320 };
2321
2322 let program = UpgradeableLoaderState::Program {
2323 programdata_address: programdata_key1,
2324 };
2325 let mut account =
2326 AccountSharedData::new_data(40, &program, &bpf_loader_upgradeable::id()).unwrap();
2327 account.set_executable(true);
2328 account.set_rent_epoch(1);
2329 accounts.push((key1, account));
2330 let mut account =
2331 AccountSharedData::new_data(40, &program_data, &bpf_loader_upgradeable::id()).unwrap();
2332 account.set_rent_epoch(1);
2333 accounts.push((programdata_key1, account));
2334
2335 let program = UpgradeableLoaderState::Program {
2336 programdata_address: programdata_key2,
2337 };
2338 let mut account =
2339 AccountSharedData::new_data(40, &program, &bpf_loader_upgradeable::id()).unwrap();
2340 account.set_executable(true);
2341 account.set_rent_epoch(1);
2342 accounts.push((key2, account));
2343 let mut account =
2344 AccountSharedData::new_data(40, &program_data, &bpf_loader_upgradeable::id()).unwrap();
2345 account.set_rent_epoch(1);
2346 accounts.push((programdata_key2, account));
2347
2348 let mut account = AccountSharedData::new(40, 1, &native_loader::id()); account.set_executable(true);
2350 account.set_rent_epoch(1);
2351 accounts.push((bpf_loader_upgradeable::id(), account));
2352
2353 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2354 let mut message = Message::new_with_compiled_instructions(
2355 1,
2356 0,
2357 1, vec![key0, key1, key2],
2359 Hash::default(),
2360 instructions,
2361 );
2362 let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
2363 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
2364
2365 assert_eq!(error_counters.invalid_writable_account, 1);
2366 assert_eq!(loaded_accounts.len(), 1);
2367 assert_eq!(
2368 loaded_accounts[0],
2369 (Err(TransactionError::InvalidWritableAccount), None)
2370 );
2371
2372 message.account_keys = vec![key0, key1, bpf_loader_upgradeable::id()];
2374 let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
2375 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
2376
2377 assert_eq!(error_counters.invalid_writable_account, 1);
2378 assert_eq!(loaded_accounts.len(), 1);
2379 let result = loaded_accounts[0].0.as_ref().unwrap();
2380 assert_eq!(result.accounts[..2], accounts[..2]);
2381 assert_eq!(result.accounts[result.program_indices[0][0]], accounts[5]);
2382
2383 message.account_keys = vec![key0, key1, key2]; message.header.num_readonly_unsigned_accounts = 2; let tx = Transaction::new(&[&keypair], message, Hash::default());
2387 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
2388
2389 assert_eq!(error_counters.invalid_writable_account, 1);
2390 assert_eq!(loaded_accounts.len(), 1);
2391 let result = loaded_accounts[0].0.as_ref().unwrap();
2392 assert_eq!(result.accounts[..2], accounts[..2]);
2393 assert_eq!(result.accounts[result.program_indices[0][0]], accounts[5]);
2394 assert_eq!(result.accounts[result.program_indices[0][1]], accounts[4]);
2395 assert_eq!(result.accounts[result.program_indices[0][2]], accounts[3]);
2396 }
2397
2398 #[test]
2399 fn test_load_accounts_programdata_with_write_lock() {
2400 let mut accounts: Vec<TransactionAccount> = Vec::new();
2401 let mut error_counters = TransactionErrorMetrics::default();
2402
2403 let keypair = Keypair::new();
2404 let key0 = keypair.pubkey();
2405 let key1 = Pubkey::from([5u8; 32]);
2406 let key2 = Pubkey::from([6u8; 32]);
2407
2408 let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
2409 account.set_rent_epoch(1);
2410 accounts.push((key0, account));
2411
2412 let program_data = UpgradeableLoaderState::ProgramData {
2413 slot: 42,
2414 upgrade_authority_address: None,
2415 };
2416 let mut account =
2417 AccountSharedData::new_data(40, &program_data, &bpf_loader_upgradeable::id()).unwrap();
2418 account.set_rent_epoch(1);
2419 accounts.push((key1, account));
2420
2421 let mut account = AccountSharedData::new(40, 1, &native_loader::id());
2422 account.set_executable(true);
2423 account.set_rent_epoch(1);
2424 accounts.push((key2, account));
2425
2426 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2427 let mut message = Message::new_with_compiled_instructions(
2428 1,
2429 0,
2430 1, vec![key0, key1, key2],
2432 Hash::default(),
2433 instructions,
2434 );
2435 let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
2436 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
2437
2438 assert_eq!(error_counters.invalid_writable_account, 1);
2439 assert_eq!(loaded_accounts.len(), 1);
2440 assert_eq!(
2441 loaded_accounts[0],
2442 (Err(TransactionError::InvalidWritableAccount), None)
2443 );
2444
2445 let mut account = AccountSharedData::new(40, 1, &native_loader::id()); account.set_executable(true);
2448 account.set_rent_epoch(1);
2449 let accounts_with_upgradeable_loader = vec![
2450 accounts[0].clone(),
2451 accounts[1].clone(),
2452 (bpf_loader_upgradeable::id(), account),
2453 ];
2454 message.account_keys = vec![key0, key1, bpf_loader_upgradeable::id()];
2455 let tx = Transaction::new(&[&keypair], message.clone(), Hash::default());
2456 let loaded_accounts =
2457 load_accounts(tx, &accounts_with_upgradeable_loader, &mut error_counters);
2458
2459 assert_eq!(error_counters.invalid_writable_account, 1);
2460 assert_eq!(loaded_accounts.len(), 1);
2461 let result = loaded_accounts[0].0.as_ref().unwrap();
2462 assert_eq!(result.accounts[..2], accounts_with_upgradeable_loader[..2]);
2463 assert_eq!(
2464 result.accounts[result.program_indices[0][0]],
2465 accounts_with_upgradeable_loader[2]
2466 );
2467
2468 message.account_keys = vec![key0, key1, key2]; message.header.num_readonly_unsigned_accounts = 2; let tx = Transaction::new(&[&keypair], message, Hash::default());
2472 let loaded_accounts = load_accounts(tx, &accounts, &mut error_counters);
2473
2474 assert_eq!(error_counters.invalid_writable_account, 1);
2475 assert_eq!(loaded_accounts.len(), 1);
2476 let result = loaded_accounts[0].0.as_ref().unwrap();
2477 assert_eq!(result.accounts[..2], accounts[..2]);
2478 assert_eq!(result.accounts[result.program_indices[0][0]], accounts[2]);
2479 }
2480
2481 #[test]
2482 fn test_accounts_account_not_found() {
2483 let accounts = Accounts::new_with_config_for_tests(
2484 Vec::new(),
2485 &ClusterType::Development,
2486 AccountSecondaryIndexes::default(),
2487 false,
2488 AccountShrinkThreshold::default(),
2489 );
2490 let mut error_counters = TransactionErrorMetrics::default();
2491 let ancestors = vec![(0, 0)].into_iter().collect();
2492
2493 let keypair = Keypair::new();
2494 let mut account = AccountSharedData::new(1, 0, &Pubkey::default());
2495 account.set_executable(true);
2496 accounts.store_slow_uncached(0, &keypair.pubkey(), &account);
2497
2498 assert_eq!(
2499 accounts.load_executable_accounts(
2500 &ancestors,
2501 &mut vec![(keypair.pubkey(), account)],
2502 0,
2503 &mut error_counters,
2504 LoadZeroLamports::SomeWithZeroLamportAccount,
2505 ),
2506 Err(TransactionError::ProgramAccountNotFound)
2507 );
2508 assert_eq!(error_counters.account_not_found, 1);
2509 }
2510
2511 #[test]
2512 #[should_panic]
2513 fn test_accounts_empty_bank_hash() {
2514 let accounts = Accounts::new_with_config_for_tests(
2515 Vec::new(),
2516 &ClusterType::Development,
2517 AccountSecondaryIndexes::default(),
2518 false,
2519 AccountShrinkThreshold::default(),
2520 );
2521 accounts.bank_hash_at(1, &Rewrites::default());
2522 }
2523
2524 #[test]
2525 fn test_lock_accounts_with_duplicates() {
2526 let accounts = Accounts::new_with_config_for_tests(
2527 Vec::new(),
2528 &ClusterType::Development,
2529 AccountSecondaryIndexes::default(),
2530 false,
2531 AccountShrinkThreshold::default(),
2532 );
2533
2534 let keypair = Keypair::new();
2535 let message = Message {
2536 header: MessageHeader {
2537 num_required_signatures: 1,
2538 ..MessageHeader::default()
2539 },
2540 account_keys: vec![keypair.pubkey(), keypair.pubkey()],
2541 ..Message::default()
2542 };
2543
2544 let tx = new_sanitized_tx(&[&keypair], message, Hash::default());
2545 let results = accounts.lock_accounts([tx].iter(), MAX_TX_ACCOUNT_LOCKS);
2546 assert_eq!(results[0], Err(TransactionError::AccountLoadedTwice));
2547 }
2548
2549 #[test]
2550 fn test_lock_accounts_with_too_many_accounts() {
2551 let accounts = Accounts::new_with_config_for_tests(
2552 Vec::new(),
2553 &ClusterType::Development,
2554 AccountSecondaryIndexes::default(),
2555 false,
2556 AccountShrinkThreshold::default(),
2557 );
2558
2559 let keypair = Keypair::new();
2560
2561 {
2563 let num_account_keys = MAX_TX_ACCOUNT_LOCKS;
2564 let mut account_keys: Vec<_> = (0..num_account_keys)
2565 .map(|_| Pubkey::new_unique())
2566 .collect();
2567 account_keys[0] = keypair.pubkey();
2568 let message = Message {
2569 header: MessageHeader {
2570 num_required_signatures: 1,
2571 ..MessageHeader::default()
2572 },
2573 account_keys,
2574 ..Message::default()
2575 };
2576
2577 let txs = vec![new_sanitized_tx(&[&keypair], message, Hash::default())];
2578 let results = accounts.lock_accounts(txs.iter(), MAX_TX_ACCOUNT_LOCKS);
2579 assert_eq!(results[0], Ok(()));
2580 accounts.unlock_accounts(txs.iter(), &results);
2581 }
2582
2583 {
2585 let num_account_keys = MAX_TX_ACCOUNT_LOCKS + 1;
2586 let mut account_keys: Vec<_> = (0..num_account_keys)
2587 .map(|_| Pubkey::new_unique())
2588 .collect();
2589 account_keys[0] = keypair.pubkey();
2590 let message = Message {
2591 header: MessageHeader {
2592 num_required_signatures: 1,
2593 ..MessageHeader::default()
2594 },
2595 account_keys,
2596 ..Message::default()
2597 };
2598
2599 let txs = vec![new_sanitized_tx(&[&keypair], message, Hash::default())];
2600 let results = accounts.lock_accounts(txs.iter(), MAX_TX_ACCOUNT_LOCKS);
2601 assert_eq!(results[0], Err(TransactionError::TooManyAccountLocks));
2602 }
2603 }
2604
2605 #[test]
2606 fn test_accounts_locks() {
2607 let keypair0 = Keypair::new();
2608 let keypair1 = Keypair::new();
2609 let keypair2 = Keypair::new();
2610 let keypair3 = Keypair::new();
2611
2612 let account0 = AccountSharedData::new(1, 0, &Pubkey::default());
2613 let account1 = AccountSharedData::new(2, 0, &Pubkey::default());
2614 let account2 = AccountSharedData::new(3, 0, &Pubkey::default());
2615 let account3 = AccountSharedData::new(4, 0, &Pubkey::default());
2616
2617 let accounts = Accounts::new_with_config_for_tests(
2618 Vec::new(),
2619 &ClusterType::Development,
2620 AccountSecondaryIndexes::default(),
2621 false,
2622 AccountShrinkThreshold::default(),
2623 );
2624 accounts.store_slow_uncached(0, &keypair0.pubkey(), &account0);
2625 accounts.store_slow_uncached(0, &keypair1.pubkey(), &account1);
2626 accounts.store_slow_uncached(0, &keypair2.pubkey(), &account2);
2627 accounts.store_slow_uncached(0, &keypair3.pubkey(), &account3);
2628
2629 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2630 let message = Message::new_with_compiled_instructions(
2631 1,
2632 0,
2633 2,
2634 vec![keypair0.pubkey(), keypair1.pubkey(), native_loader::id()],
2635 Hash::default(),
2636 instructions,
2637 );
2638 let tx = new_sanitized_tx(&[&keypair0], message, Hash::default());
2639 let results0 = accounts.lock_accounts([tx.clone()].iter(), MAX_TX_ACCOUNT_LOCKS);
2640
2641 assert!(results0[0].is_ok());
2642 assert_eq!(
2643 *accounts
2644 .account_locks
2645 .lock()
2646 .unwrap()
2647 .readonly_locks
2648 .get(&keypair1.pubkey())
2649 .unwrap(),
2650 1
2651 );
2652
2653 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2654 let message = Message::new_with_compiled_instructions(
2655 1,
2656 0,
2657 2,
2658 vec![keypair2.pubkey(), keypair1.pubkey(), native_loader::id()],
2659 Hash::default(),
2660 instructions,
2661 );
2662 let tx0 = new_sanitized_tx(&[&keypair2], message, Hash::default());
2663 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2664 let message = Message::new_with_compiled_instructions(
2665 1,
2666 0,
2667 2,
2668 vec![keypair1.pubkey(), keypair3.pubkey(), native_loader::id()],
2669 Hash::default(),
2670 instructions,
2671 );
2672 let tx1 = new_sanitized_tx(&[&keypair1], message, Hash::default());
2673 let txs = vec![tx0, tx1];
2674 let results1 = accounts.lock_accounts(txs.iter(), MAX_TX_ACCOUNT_LOCKS);
2675
2676 assert!(results1[0].is_ok()); assert!(results1[1].is_err()); assert_eq!(
2679 *accounts
2680 .account_locks
2681 .lock()
2682 .unwrap()
2683 .readonly_locks
2684 .get(&keypair1.pubkey())
2685 .unwrap(),
2686 2
2687 );
2688
2689 accounts.unlock_accounts([tx].iter(), &results0);
2690 accounts.unlock_accounts(txs.iter(), &results1);
2691 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2692 let message = Message::new_with_compiled_instructions(
2693 1,
2694 0,
2695 2,
2696 vec![keypair1.pubkey(), keypair3.pubkey(), native_loader::id()],
2697 Hash::default(),
2698 instructions,
2699 );
2700 let tx = new_sanitized_tx(&[&keypair1], message, Hash::default());
2701 let results2 = accounts.lock_accounts([tx].iter(), MAX_TX_ACCOUNT_LOCKS);
2702 assert!(results2[0].is_ok()); assert!(accounts
2706 .account_locks
2707 .lock()
2708 .unwrap()
2709 .readonly_locks
2710 .get(&keypair1.pubkey())
2711 .is_none());
2712 }
2713
2714 #[test]
2715 fn test_accounts_locks_multithreaded() {
2716 let counter = Arc::new(AtomicU64::new(0));
2717 let exit = Arc::new(AtomicBool::new(false));
2718
2719 let keypair0 = Keypair::new();
2720 let keypair1 = Keypair::new();
2721 let keypair2 = Keypair::new();
2722
2723 let account0 = AccountSharedData::new(1, 0, &Pubkey::default());
2724 let account1 = AccountSharedData::new(2, 0, &Pubkey::default());
2725 let account2 = AccountSharedData::new(3, 0, &Pubkey::default());
2726
2727 let accounts = Accounts::new_with_config_for_tests(
2728 Vec::new(),
2729 &ClusterType::Development,
2730 AccountSecondaryIndexes::default(),
2731 false,
2732 AccountShrinkThreshold::default(),
2733 );
2734 accounts.store_slow_uncached(0, &keypair0.pubkey(), &account0);
2735 accounts.store_slow_uncached(0, &keypair1.pubkey(), &account1);
2736 accounts.store_slow_uncached(0, &keypair2.pubkey(), &account2);
2737
2738 let accounts_arc = Arc::new(accounts);
2739
2740 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2741 let readonly_message = Message::new_with_compiled_instructions(
2742 1,
2743 0,
2744 2,
2745 vec![keypair0.pubkey(), keypair1.pubkey(), native_loader::id()],
2746 Hash::default(),
2747 instructions,
2748 );
2749 let readonly_tx = new_sanitized_tx(&[&keypair0], readonly_message, Hash::default());
2750
2751 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2752 let writable_message = Message::new_with_compiled_instructions(
2753 1,
2754 0,
2755 2,
2756 vec![keypair1.pubkey(), keypair2.pubkey(), native_loader::id()],
2757 Hash::default(),
2758 instructions,
2759 );
2760 let writable_tx = new_sanitized_tx(&[&keypair1], writable_message, Hash::default());
2761
2762 let counter_clone = counter.clone();
2763 let accounts_clone = accounts_arc.clone();
2764 let exit_clone = exit.clone();
2765 thread::spawn(move || {
2766 let counter_clone = counter_clone.clone();
2767 let exit_clone = exit_clone.clone();
2768 loop {
2769 let txs = vec![writable_tx.clone()];
2770 let results = accounts_clone
2771 .clone()
2772 .lock_accounts(txs.iter(), MAX_TX_ACCOUNT_LOCKS);
2773 for result in results.iter() {
2774 if result.is_ok() {
2775 counter_clone.clone().fetch_add(1, Ordering::SeqCst);
2776 }
2777 }
2778 accounts_clone.unlock_accounts(txs.iter(), &results);
2779 if exit_clone.clone().load(Ordering::Relaxed) {
2780 break;
2781 }
2782 }
2783 });
2784 let counter_clone = counter;
2785 for _ in 0..5 {
2786 let txs = vec![readonly_tx.clone()];
2787 let results = accounts_arc
2788 .clone()
2789 .lock_accounts(txs.iter(), MAX_TX_ACCOUNT_LOCKS);
2790 if results[0].is_ok() {
2791 let counter_value = counter_clone.clone().load(Ordering::SeqCst);
2792 thread::sleep(time::Duration::from_millis(50));
2793 assert_eq!(counter_value, counter_clone.clone().load(Ordering::SeqCst));
2794 }
2795 accounts_arc.unlock_accounts(txs.iter(), &results);
2796 thread::sleep(time::Duration::from_millis(50));
2797 }
2798 exit.store(true, Ordering::Relaxed);
2799 }
2800
2801 #[test]
2802 fn test_demote_program_write_locks() {
2803 let keypair0 = Keypair::new();
2804 let keypair1 = Keypair::new();
2805 let keypair2 = Keypair::new();
2806 let keypair3 = Keypair::new();
2807
2808 let account0 = AccountSharedData::new(1, 0, &Pubkey::default());
2809 let account1 = AccountSharedData::new(2, 0, &Pubkey::default());
2810 let account2 = AccountSharedData::new(3, 0, &Pubkey::default());
2811 let account3 = AccountSharedData::new(4, 0, &Pubkey::default());
2812
2813 let accounts = Accounts::new_with_config_for_tests(
2814 Vec::new(),
2815 &ClusterType::Development,
2816 AccountSecondaryIndexes::default(),
2817 false,
2818 AccountShrinkThreshold::default(),
2819 );
2820 accounts.store_slow_uncached(0, &keypair0.pubkey(), &account0);
2821 accounts.store_slow_uncached(0, &keypair1.pubkey(), &account1);
2822 accounts.store_slow_uncached(0, &keypair2.pubkey(), &account2);
2823 accounts.store_slow_uncached(0, &keypair3.pubkey(), &account3);
2824
2825 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2826 let message = Message::new_with_compiled_instructions(
2827 1,
2828 0,
2829 0, vec![keypair0.pubkey(), keypair1.pubkey(), native_loader::id()],
2831 Hash::default(),
2832 instructions,
2833 );
2834 let tx = new_sanitized_tx(&[&keypair0], message, Hash::default());
2835 let results0 = accounts.lock_accounts([tx].iter(), MAX_TX_ACCOUNT_LOCKS);
2836
2837 assert!(results0[0].is_ok());
2838 assert_eq!(
2840 *accounts
2841 .account_locks
2842 .lock()
2843 .unwrap()
2844 .readonly_locks
2845 .get(&native_loader::id())
2846 .unwrap(),
2847 1
2848 );
2849 assert!(accounts
2851 .account_locks
2852 .lock()
2853 .unwrap()
2854 .write_locks
2855 .contains(&keypair0.pubkey()));
2856 assert!(accounts
2857 .account_locks
2858 .lock()
2859 .unwrap()
2860 .write_locks
2861 .contains(&keypair1.pubkey()));
2862 }
2863
2864 #[test]
2865 fn test_accounts_locks_with_results() {
2866 let keypair0 = Keypair::new();
2867 let keypair1 = Keypair::new();
2868 let keypair2 = Keypair::new();
2869 let keypair3 = Keypair::new();
2870
2871 let account0 = AccountSharedData::new(1, 0, &Pubkey::default());
2872 let account1 = AccountSharedData::new(2, 0, &Pubkey::default());
2873 let account2 = AccountSharedData::new(3, 0, &Pubkey::default());
2874 let account3 = AccountSharedData::new(4, 0, &Pubkey::default());
2875
2876 let accounts = Accounts::new_with_config_for_tests(
2877 Vec::new(),
2878 &ClusterType::Development,
2879 AccountSecondaryIndexes::default(),
2880 false,
2881 AccountShrinkThreshold::default(),
2882 );
2883 accounts.store_slow_uncached(0, &keypair0.pubkey(), &account0);
2884 accounts.store_slow_uncached(0, &keypair1.pubkey(), &account1);
2885 accounts.store_slow_uncached(0, &keypair2.pubkey(), &account2);
2886 accounts.store_slow_uncached(0, &keypair3.pubkey(), &account3);
2887
2888 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2889 let message = Message::new_with_compiled_instructions(
2890 1,
2891 0,
2892 2,
2893 vec![keypair1.pubkey(), keypair0.pubkey(), native_loader::id()],
2894 Hash::default(),
2895 instructions,
2896 );
2897 let tx0 = new_sanitized_tx(&[&keypair1], message, Hash::default());
2898 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2899 let message = Message::new_with_compiled_instructions(
2900 1,
2901 0,
2902 2,
2903 vec![keypair2.pubkey(), keypair0.pubkey(), native_loader::id()],
2904 Hash::default(),
2905 instructions,
2906 );
2907 let tx1 = new_sanitized_tx(&[&keypair2], message, Hash::default());
2908 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2909 let message = Message::new_with_compiled_instructions(
2910 1,
2911 0,
2912 2,
2913 vec![keypair3.pubkey(), keypair0.pubkey(), native_loader::id()],
2914 Hash::default(),
2915 instructions,
2916 );
2917 let tx2 = new_sanitized_tx(&[&keypair3], message, Hash::default());
2918 let txs = vec![tx0, tx1, tx2];
2919
2920 let qos_results = vec![
2921 Ok(()),
2922 Err(TransactionError::WouldExceedMaxBlockCostLimit),
2923 Ok(()),
2924 ];
2925
2926 let results = accounts.lock_accounts_with_results(
2927 txs.iter(),
2928 qos_results.iter(),
2929 MAX_TX_ACCOUNT_LOCKS,
2930 );
2931
2932 assert!(results[0].is_ok()); assert!(results[1].is_err()); assert!(results[2].is_ok()); assert_eq!(
2938 *accounts
2939 .account_locks
2940 .lock()
2941 .unwrap()
2942 .readonly_locks
2943 .get(&keypair0.pubkey())
2944 .unwrap(),
2945 2
2946 );
2947 assert!(accounts
2949 .account_locks
2950 .lock()
2951 .unwrap()
2952 .write_locks
2953 .get(&keypair2.pubkey())
2954 .is_none());
2955
2956 accounts.unlock_accounts(txs.iter(), &results);
2957
2958 assert!(accounts
2960 .account_locks
2961 .lock()
2962 .unwrap()
2963 .readonly_locks
2964 .is_empty());
2965 assert!(accounts
2966 .account_locks
2967 .lock()
2968 .unwrap()
2969 .write_locks
2970 .is_empty());
2971 }
2972
2973 #[test]
2974 fn test_collect_accounts_to_store() {
2975 let keypair0 = Keypair::new();
2976 let keypair1 = Keypair::new();
2977 let pubkey = solana_sdk::pubkey::new_rand();
2978 let account0 = AccountSharedData::new(1, 0, &Pubkey::default());
2979 let account1 = AccountSharedData::new(2, 0, &Pubkey::default());
2980 let account2 = AccountSharedData::new(3, 0, &Pubkey::default());
2981
2982 let rent_collector = RentCollector::default();
2983
2984 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
2985 let message = Message::new_with_compiled_instructions(
2986 1,
2987 0,
2988 2,
2989 vec![keypair0.pubkey(), pubkey, native_loader::id()],
2990 Hash::default(),
2991 instructions,
2992 );
2993 let transaction_accounts0 = vec![
2994 (message.account_keys[0], account0),
2995 (message.account_keys[1], account2.clone()),
2996 ];
2997 let tx0 = new_sanitized_tx(&[&keypair0], message, Hash::default());
2998 let tx0_sign = *tx0.signature();
2999
3000 let instructions = vec![CompiledInstruction::new(2, &(), vec![0, 1])];
3001 let message = Message::new_with_compiled_instructions(
3002 1,
3003 0,
3004 2,
3005 vec![keypair1.pubkey(), pubkey, native_loader::id()],
3006 Hash::default(),
3007 instructions,
3008 );
3009 let transaction_accounts1 = vec![
3010 (message.account_keys[0], account1),
3011 (message.account_keys[1], account2),
3012 ];
3013 let tx1 = new_sanitized_tx(&[&keypair1], message, Hash::default());
3014 let tx1_sign = *tx1.signature();
3015
3016 let loaded0 = (
3017 Ok(LoadedTransaction {
3018 accounts: transaction_accounts0,
3019 program_indices: vec![],
3020 rent: 0,
3021 rent_debits: RentDebits::default(),
3022 }),
3023 None,
3024 );
3025
3026 let loaded1 = (
3027 Ok(LoadedTransaction {
3028 accounts: transaction_accounts1,
3029 program_indices: vec![],
3030 rent: 0,
3031 rent_debits: RentDebits::default(),
3032 }),
3033 None,
3034 );
3035
3036 let mut loaded = vec![loaded0, loaded1];
3037
3038 let accounts = Accounts::new_with_config_for_tests(
3039 Vec::new(),
3040 &ClusterType::Development,
3041 AccountSecondaryIndexes::default(),
3042 false,
3043 AccountShrinkThreshold::default(),
3044 );
3045 {
3046 accounts
3047 .account_locks
3048 .lock()
3049 .unwrap()
3050 .insert_new_readonly(&pubkey);
3051 }
3052 let txs = vec![tx0, tx1];
3053 let execution_results = vec![new_execution_result(Ok(()), None); 2];
3054 let (collected_accounts, txn_signatures) = accounts.collect_accounts_to_store(
3055 &txs,
3056 &execution_results,
3057 loaded.as_mut_slice(),
3058 &rent_collector,
3059 &DurableNonce::default(),
3060 0,
3061 true, );
3063 assert_eq!(collected_accounts.len(), 2);
3064 assert!(collected_accounts
3065 .iter()
3066 .any(|(pubkey, _account)| *pubkey == &keypair0.pubkey()));
3067 assert!(collected_accounts
3068 .iter()
3069 .any(|(pubkey, _account)| *pubkey == &keypair1.pubkey()));
3070
3071 assert_eq!(txn_signatures.len(), 2);
3072 assert!(txn_signatures
3073 .iter()
3074 .any(|signature| signature.unwrap().to_string().eq(&tx0_sign.to_string())));
3075 assert!(txn_signatures
3076 .iter()
3077 .any(|signature| signature.unwrap().to_string().eq(&tx1_sign.to_string())));
3078
3079 assert_eq!(
3081 *accounts
3082 .account_locks
3083 .lock()
3084 .unwrap()
3085 .readonly_locks
3086 .get(&pubkey)
3087 .unwrap(),
3088 1
3089 );
3090 }
3091
3092 #[test]
3093 fn huge_clean() {
3094 solana_logger::setup();
3095 let accounts = Accounts::new_with_config_for_tests(
3096 Vec::new(),
3097 &ClusterType::Development,
3098 AccountSecondaryIndexes::default(),
3099 false,
3100 AccountShrinkThreshold::default(),
3101 );
3102 let mut old_pubkey = Pubkey::default();
3103 let zero_account = AccountSharedData::new(0, 0, AccountSharedData::default().owner());
3104 info!("storing..");
3105 for i in 0..2_000 {
3106 let pubkey = solana_sdk::pubkey::new_rand();
3107 let account =
3108 AccountSharedData::new((i + 1) as u64, 0, AccountSharedData::default().owner());
3109 accounts.store_slow_uncached(i, &pubkey, &account);
3110 accounts.store_slow_uncached(i, &old_pubkey, &zero_account);
3111 old_pubkey = pubkey;
3112 accounts.add_root(i);
3113 if i % 1_000 == 0 {
3114 info!(" store {}", i);
3115 }
3116 }
3117 info!("done..cleaning..");
3118 accounts.accounts_db.clean_accounts(None, false, None);
3119 }
3120
3121 fn load_accounts_no_store(
3122 accounts: &Accounts,
3123 tx: Transaction,
3124 account_overrides: Option<&AccountOverrides>,
3125 ) -> Vec<TransactionLoadResult> {
3126 let tx = SanitizedTransaction::from_transaction_for_tests(tx);
3127 let rent_collector = RentCollector::default();
3128 let mut hash_queue = BlockhashQueue::new(100);
3129 hash_queue.register_hash(tx.message().recent_blockhash(), 10);
3130
3131 let ancestors = vec![(0, 0)].into_iter().collect();
3132 let mut error_counters = TransactionErrorMetrics::default();
3133 accounts.load_accounts(
3134 &ancestors,
3135 &[tx],
3136 vec![(Ok(()), None)],
3137 &hash_queue,
3138 &mut error_counters,
3139 &rent_collector,
3140 &FeatureSet::all_enabled(),
3141 &FeeStructure::default(),
3142 account_overrides,
3143 )
3144 }
3145
3146 #[test]
3147 fn test_instructions() {
3148 solana_logger::setup();
3149 let accounts = Accounts::new_with_config_for_tests(
3150 Vec::new(),
3151 &ClusterType::Development,
3152 AccountSecondaryIndexes::default(),
3153 false,
3154 AccountShrinkThreshold::default(),
3155 );
3156
3157 let instructions_key = solana_sdk::sysvar::instructions::id();
3158 let keypair = Keypair::new();
3159 let instructions = vec![CompiledInstruction::new(1, &(), vec![0, 1])];
3160 let tx = Transaction::new_with_compiled_instructions(
3161 &[&keypair],
3162 &[solana_sdk::pubkey::new_rand(), instructions_key],
3163 Hash::default(),
3164 vec![native_loader::id()],
3165 instructions,
3166 );
3167
3168 let loaded_accounts = load_accounts_no_store(&accounts, tx, None);
3169 assert_eq!(loaded_accounts.len(), 1);
3170 assert!(loaded_accounts[0].0.is_err());
3171 }
3172
3173 #[test]
3174 fn test_overrides() {
3175 solana_logger::setup();
3176 let accounts = Accounts::new_with_config_for_tests(
3177 Vec::new(),
3178 &ClusterType::Development,
3179 AccountSecondaryIndexes::default(),
3180 false,
3181 AccountShrinkThreshold::default(),
3182 );
3183 let mut account_overrides = AccountOverrides::default();
3184 let slot_history_id = sysvar::slot_history::id();
3185 let account = AccountSharedData::new(42, 0, &Pubkey::default());
3186 account_overrides.set_slot_history(Some(account));
3187
3188 let keypair = Keypair::new();
3189 let account = AccountSharedData::new(1_000_000, 0, &Pubkey::default());
3190 accounts.store_slow_uncached(0, &keypair.pubkey(), &account);
3191
3192 let instructions = vec![CompiledInstruction::new(2, &(), vec![0])];
3193 let tx = Transaction::new_with_compiled_instructions(
3194 &[&keypair],
3195 &[slot_history_id],
3196 Hash::default(),
3197 vec![native_loader::id()],
3198 instructions,
3199 );
3200
3201 let loaded_accounts = load_accounts_no_store(&accounts, tx, Some(&account_overrides));
3202 assert_eq!(loaded_accounts.len(), 1);
3203 let loaded_transaction = loaded_accounts[0].0.as_ref().unwrap();
3204 assert_eq!(loaded_transaction.accounts[0].0, keypair.pubkey());
3205 assert_eq!(loaded_transaction.accounts[1].0, slot_history_id);
3206 assert_eq!(loaded_transaction.accounts[1].1.lamports(), 42);
3207 }
3208
3209 fn create_accounts_prepare_if_nonce_account() -> (
3210 Pubkey,
3211 AccountSharedData,
3212 AccountSharedData,
3213 DurableNonce,
3214 u64,
3215 Option<AccountSharedData>,
3216 ) {
3217 let data = NonceVersions::new(NonceState::Initialized(nonce::state::Data::default()));
3218 let account = AccountSharedData::new_data(42, &data, &system_program::id()).unwrap();
3219 let mut pre_account = account.clone();
3220 pre_account.set_lamports(43);
3221 let durable_nonce = DurableNonce::from_blockhash(&Hash::new(&[1u8; 32]));
3222 (
3223 Pubkey::default(),
3224 pre_account,
3225 account,
3226 durable_nonce,
3227 1234,
3228 None,
3229 )
3230 }
3231
3232 fn run_prepare_if_nonce_account_test(
3233 account_address: &Pubkey,
3234 account: &mut AccountSharedData,
3235 tx_result: &Result<()>,
3236 is_fee_payer: bool,
3237 maybe_nonce: Option<(&NonceFull, bool)>,
3238 durable_nonce: &DurableNonce,
3239 lamports_per_signature: u64,
3240 expect_account: &AccountSharedData,
3241 ) -> bool {
3242 if !is_fee_payer {
3244 match maybe_nonce {
3245 Some((nonce, _)) if nonce.address() == account_address => {
3246 assert_ne!(expect_account, nonce.account())
3247 }
3248 _ => assert_eq!(expect_account, account),
3249 }
3250 }
3251
3252 prepare_if_nonce_account(
3253 account_address,
3254 account,
3255 tx_result,
3256 is_fee_payer,
3257 maybe_nonce,
3258 durable_nonce,
3259 lamports_per_signature,
3260 );
3261 assert_eq!(expect_account, account);
3262 expect_account == account
3263 }
3264
3265 #[test]
3266 fn test_prepare_if_nonce_account_expected() {
3267 let (
3268 pre_account_address,
3269 pre_account,
3270 mut post_account,
3271 blockhash,
3272 lamports_per_signature,
3273 maybe_fee_payer_account,
3274 ) = create_accounts_prepare_if_nonce_account();
3275 let post_account_address = pre_account_address;
3276 let nonce = NonceFull::new(
3277 pre_account_address,
3278 pre_account.clone(),
3279 maybe_fee_payer_account,
3280 );
3281
3282 let mut expect_account = pre_account;
3283 expect_account
3284 .set_state(&NonceVersions::new(NonceState::Initialized(
3285 nonce::state::Data::new(Pubkey::default(), blockhash, lamports_per_signature),
3286 )))
3287 .unwrap();
3288
3289 assert!(run_prepare_if_nonce_account_test(
3290 &post_account_address,
3291 &mut post_account,
3292 &Ok(()),
3293 false,
3294 Some((&nonce, true)),
3295 &blockhash,
3296 lamports_per_signature,
3297 &expect_account,
3298 ));
3299 }
3300
3301 #[test]
3302 fn test_prepare_if_nonce_account_not_nonce_tx() {
3303 let (
3304 pre_account_address,
3305 _pre_account,
3306 _post_account,
3307 blockhash,
3308 lamports_per_signature,
3309 _maybe_fee_payer_account,
3310 ) = create_accounts_prepare_if_nonce_account();
3311 let post_account_address = pre_account_address;
3312
3313 let mut post_account = AccountSharedData::default();
3314 let expect_account = post_account.clone();
3315 assert!(run_prepare_if_nonce_account_test(
3316 &post_account_address,
3317 &mut post_account,
3318 &Ok(()),
3319 false,
3320 None,
3321 &blockhash,
3322 lamports_per_signature,
3323 &expect_account,
3324 ));
3325 }
3326
3327 #[test]
3328 fn test_prepare_if_nonce_account_not_nonce_address() {
3329 let (
3330 pre_account_address,
3331 pre_account,
3332 mut post_account,
3333 blockhash,
3334 lamports_per_signature,
3335 maybe_fee_payer_account,
3336 ) = create_accounts_prepare_if_nonce_account();
3337
3338 let nonce = NonceFull::new(pre_account_address, pre_account, maybe_fee_payer_account);
3339
3340 let expect_account = post_account.clone();
3341 assert!(run_prepare_if_nonce_account_test(
3343 &Pubkey::from([1u8; 32]),
3344 &mut post_account,
3345 &Ok(()),
3346 false,
3347 Some((&nonce, true)),
3348 &blockhash,
3349 lamports_per_signature,
3350 &expect_account,
3351 ));
3352 }
3353
3354 #[test]
3355 fn test_prepare_if_nonce_account_tx_error() {
3356 let (
3357 pre_account_address,
3358 pre_account,
3359 mut post_account,
3360 blockhash,
3361 lamports_per_signature,
3362 maybe_fee_payer_account,
3363 ) = create_accounts_prepare_if_nonce_account();
3364 let post_account_address = pre_account_address;
3365 let mut expect_account = pre_account.clone();
3366
3367 let nonce = NonceFull::new(pre_account_address, pre_account, maybe_fee_payer_account);
3368
3369 expect_account
3370 .set_state(&NonceVersions::new(NonceState::Initialized(
3371 nonce::state::Data::new(Pubkey::default(), blockhash, lamports_per_signature),
3372 )))
3373 .unwrap();
3374
3375 assert!(run_prepare_if_nonce_account_test(
3376 &post_account_address,
3377 &mut post_account,
3378 &Err(TransactionError::InstructionError(
3379 0,
3380 InstructionError::InvalidArgument,
3381 )),
3382 false,
3383 Some((&nonce, true)),
3384 &blockhash,
3385 lamports_per_signature,
3386 &expect_account,
3387 ));
3388 }
3389
3390 #[test]
3391 fn test_rollback_nonce_fee_payer() {
3392 let nonce_account = AccountSharedData::new_data(1, &(), &system_program::id()).unwrap();
3393 let pre_fee_payer_account =
3394 AccountSharedData::new_data(42, &(), &system_program::id()).unwrap();
3395 let mut post_fee_payer_account =
3396 AccountSharedData::new_data(84, &[1, 2, 3, 4], &system_program::id()).unwrap();
3397 let nonce = NonceFull::new(
3398 Pubkey::new_unique(),
3399 nonce_account,
3400 Some(pre_fee_payer_account.clone()),
3401 );
3402
3403 assert!(run_prepare_if_nonce_account_test(
3404 &Pubkey::new_unique(),
3405 &mut post_fee_payer_account.clone(),
3406 &Err(TransactionError::InstructionError(
3407 0,
3408 InstructionError::InvalidArgument,
3409 )),
3410 false,
3411 Some((&nonce, true)),
3412 &DurableNonce::default(),
3413 1,
3414 &post_fee_payer_account.clone(),
3415 ));
3416
3417 assert!(run_prepare_if_nonce_account_test(
3418 &Pubkey::new_unique(),
3419 &mut post_fee_payer_account.clone(),
3420 &Ok(()),
3421 true,
3422 Some((&nonce, true)),
3423 &DurableNonce::default(),
3424 1,
3425 &post_fee_payer_account.clone(),
3426 ));
3427
3428 assert!(run_prepare_if_nonce_account_test(
3429 &Pubkey::new_unique(),
3430 &mut post_fee_payer_account.clone(),
3431 &Err(TransactionError::InstructionError(
3432 0,
3433 InstructionError::InvalidArgument,
3434 )),
3435 true,
3436 None,
3437 &DurableNonce::default(),
3438 1,
3439 &post_fee_payer_account.clone(),
3440 ));
3441
3442 assert!(run_prepare_if_nonce_account_test(
3443 &Pubkey::new_unique(),
3444 &mut post_fee_payer_account,
3445 &Err(TransactionError::InstructionError(
3446 0,
3447 InstructionError::InvalidArgument,
3448 )),
3449 true,
3450 Some((&nonce, true)),
3451 &DurableNonce::default(),
3452 1,
3453 &pre_fee_payer_account,
3454 ));
3455 }
3456
3457 #[test]
3458 fn test_nonced_failure_accounts_rollback_from_pays() {
3459 let rent_collector = RentCollector::default();
3460
3461 let nonce_address = Pubkey::new_unique();
3462 let nonce_authority = keypair_from_seed(&[0; 32]).unwrap();
3463 let from = keypair_from_seed(&[1; 32]).unwrap();
3464 let from_address = from.pubkey();
3465 let to_address = Pubkey::new_unique();
3466 let durable_nonce = DurableNonce::from_blockhash(&Hash::new_unique());
3467 let nonce_state = NonceVersions::new(NonceState::Initialized(nonce::state::Data::new(
3468 nonce_authority.pubkey(),
3469 durable_nonce,
3470 0,
3471 )));
3472 let nonce_account_post =
3473 AccountSharedData::new_data(43, &nonce_state, &system_program::id()).unwrap();
3474 let from_account_post = AccountSharedData::new(4199, 0, &Pubkey::default());
3475 let to_account = AccountSharedData::new(2, 0, &Pubkey::default());
3476 let nonce_authority_account = AccountSharedData::new(3, 0, &Pubkey::default());
3477 let recent_blockhashes_sysvar_account = AccountSharedData::new(4, 0, &Pubkey::default());
3478
3479 let instructions = vec![
3480 system_instruction::advance_nonce_account(&nonce_address, &nonce_authority.pubkey()),
3481 system_instruction::transfer(&from_address, &to_address, 42),
3482 ];
3483 let message = Message::new(&instructions, Some(&from_address));
3484 let blockhash = Hash::new_unique();
3485 let transaction_accounts = vec![
3486 (message.account_keys[0], from_account_post),
3487 (message.account_keys[1], nonce_authority_account),
3488 (message.account_keys[2], nonce_account_post),
3489 (message.account_keys[3], to_account),
3490 (message.account_keys[4], recent_blockhashes_sysvar_account),
3491 ];
3492 let tx = new_sanitized_tx(&[&nonce_authority, &from], message, blockhash);
3493
3494 let durable_nonce = DurableNonce::from_blockhash(&Hash::new_unique());
3495 let nonce_state = NonceVersions::new(NonceState::Initialized(nonce::state::Data::new(
3496 nonce_authority.pubkey(),
3497 durable_nonce,
3498 0,
3499 )));
3500 let nonce_account_pre =
3501 AccountSharedData::new_data(42, &nonce_state, &system_program::id()).unwrap();
3502 let from_account_pre = AccountSharedData::new(4242, 0, &Pubkey::default());
3503
3504 let nonce = Some(NonceFull::new(
3505 nonce_address,
3506 nonce_account_pre.clone(),
3507 Some(from_account_pre.clone()),
3508 ));
3509
3510 let loaded = (
3511 Ok(LoadedTransaction {
3512 accounts: transaction_accounts,
3513 program_indices: vec![],
3514 rent: 0,
3515 rent_debits: RentDebits::default(),
3516 }),
3517 nonce.clone(),
3518 );
3519
3520 let mut loaded = vec![loaded];
3521
3522 let durable_nonce = DurableNonce::from_blockhash(&Hash::new_unique());
3523 let accounts = Accounts::new_with_config_for_tests(
3524 Vec::new(),
3525 &ClusterType::Development,
3526 AccountSecondaryIndexes::default(),
3527 false,
3528 AccountShrinkThreshold::default(),
3529 );
3530 let txs = vec![tx];
3531 let execution_results = vec![new_execution_result(
3532 Err(TransactionError::InstructionError(
3533 1,
3534 InstructionError::InvalidArgument,
3535 )),
3536 nonce.as_ref(),
3537 )];
3538 let (collected_accounts, _) = accounts.collect_accounts_to_store(
3539 &txs,
3540 &execution_results,
3541 loaded.as_mut_slice(),
3542 &rent_collector,
3543 &durable_nonce,
3544 0,
3545 true, );
3547 assert_eq!(collected_accounts.len(), 2);
3548 assert_eq!(
3549 collected_accounts
3550 .iter()
3551 .find(|(pubkey, _account)| *pubkey == &from_address)
3552 .map(|(_pubkey, account)| *account)
3553 .cloned()
3554 .unwrap(),
3555 from_account_pre,
3556 );
3557 let collected_nonce_account = collected_accounts
3558 .iter()
3559 .find(|(pubkey, _account)| *pubkey == &nonce_address)
3560 .map(|(_pubkey, account)| *account)
3561 .cloned()
3562 .unwrap();
3563 assert_eq!(
3564 collected_nonce_account.lamports(),
3565 nonce_account_pre.lamports(),
3566 );
3567 assert_matches!(
3568 nonce_account::verify_nonce_account(&collected_nonce_account, durable_nonce.as_hash()),
3569 Some(_)
3570 );
3571 }
3572
3573 #[test]
3574 fn test_nonced_failure_accounts_rollback_nonce_pays() {
3575 let rent_collector = RentCollector::default();
3576
3577 let nonce_authority = keypair_from_seed(&[0; 32]).unwrap();
3578 let nonce_address = nonce_authority.pubkey();
3579 let from = keypair_from_seed(&[1; 32]).unwrap();
3580 let from_address = from.pubkey();
3581 let to_address = Pubkey::new_unique();
3582 let durable_nonce = DurableNonce::from_blockhash(&Hash::new_unique());
3583 let nonce_state = NonceVersions::new(NonceState::Initialized(nonce::state::Data::new(
3584 nonce_authority.pubkey(),
3585 durable_nonce,
3586 0,
3587 )));
3588 let nonce_account_post =
3589 AccountSharedData::new_data(43, &nonce_state, &system_program::id()).unwrap();
3590 let from_account_post = AccountSharedData::new(4200, 0, &Pubkey::default());
3591 let to_account = AccountSharedData::new(2, 0, &Pubkey::default());
3592 let nonce_authority_account = AccountSharedData::new(3, 0, &Pubkey::default());
3593 let recent_blockhashes_sysvar_account = AccountSharedData::new(4, 0, &Pubkey::default());
3594
3595 let instructions = vec![
3596 system_instruction::advance_nonce_account(&nonce_address, &nonce_authority.pubkey()),
3597 system_instruction::transfer(&from_address, &to_address, 42),
3598 ];
3599 let message = Message::new(&instructions, Some(&nonce_address));
3600 let blockhash = Hash::new_unique();
3601 let transaction_accounts = vec![
3602 (message.account_keys[0], from_account_post),
3603 (message.account_keys[1], nonce_authority_account),
3604 (message.account_keys[2], nonce_account_post),
3605 (message.account_keys[3], to_account),
3606 (message.account_keys[4], recent_blockhashes_sysvar_account),
3607 ];
3608 let tx = new_sanitized_tx(&[&nonce_authority, &from], message, blockhash);
3609
3610 let durable_nonce = DurableNonce::from_blockhash(&Hash::new_unique());
3611 let nonce_state = NonceVersions::new(NonceState::Initialized(nonce::state::Data::new(
3612 nonce_authority.pubkey(),
3613 durable_nonce,
3614 0,
3615 )));
3616 let nonce_account_pre =
3617 AccountSharedData::new_data(42, &nonce_state, &system_program::id()).unwrap();
3618
3619 let nonce = Some(NonceFull::new(
3620 nonce_address,
3621 nonce_account_pre.clone(),
3622 None,
3623 ));
3624
3625 let loaded = (
3626 Ok(LoadedTransaction {
3627 accounts: transaction_accounts,
3628 program_indices: vec![],
3629 rent: 0,
3630 rent_debits: RentDebits::default(),
3631 }),
3632 nonce.clone(),
3633 );
3634
3635 let mut loaded = vec![loaded];
3636
3637 let durable_nonce = DurableNonce::from_blockhash(&Hash::new_unique());
3638 let accounts = Accounts::new_with_config_for_tests(
3639 Vec::new(),
3640 &ClusterType::Development,
3641 AccountSecondaryIndexes::default(),
3642 false,
3643 AccountShrinkThreshold::default(),
3644 );
3645 let txs = vec![tx];
3646 let execution_results = vec![new_execution_result(
3647 Err(TransactionError::InstructionError(
3648 1,
3649 InstructionError::InvalidArgument,
3650 )),
3651 nonce.as_ref(),
3652 )];
3653 let (collected_accounts, _) = accounts.collect_accounts_to_store(
3654 &txs,
3655 &execution_results,
3656 loaded.as_mut_slice(),
3657 &rent_collector,
3658 &durable_nonce,
3659 0,
3660 true, );
3662 assert_eq!(collected_accounts.len(), 1);
3663 let collected_nonce_account = collected_accounts
3664 .iter()
3665 .find(|(pubkey, _account)| *pubkey == &nonce_address)
3666 .map(|(_pubkey, account)| *account)
3667 .cloned()
3668 .unwrap();
3669 assert_eq!(
3670 collected_nonce_account.lamports(),
3671 nonce_account_pre.lamports()
3672 );
3673 assert_matches!(
3674 nonce_account::verify_nonce_account(&collected_nonce_account, durable_nonce.as_hash()),
3675 Some(_)
3676 );
3677 }
3678
3679 #[test]
3680 fn test_load_largest_accounts() {
3681 let accounts = Accounts::new_with_config_for_tests(
3682 Vec::new(),
3683 &ClusterType::Development,
3684 AccountSecondaryIndexes::default(),
3685 false,
3686 AccountShrinkThreshold::default(),
3687 );
3688
3689 let mut keys = vec![];
3699 for _idx in 0..3 {
3700 keys.push(Pubkey::new_unique());
3701 }
3702 keys.sort();
3703 let pubkey2 = keys.pop().unwrap();
3704 let pubkey1 = keys.pop().unwrap();
3705 let pubkey0 = keys.pop().unwrap();
3706 let account0 = AccountSharedData::new(42, 0, &Pubkey::default());
3707 accounts.store_slow_uncached(0, &pubkey0, &account0);
3708 let account1 = AccountSharedData::new(42, 0, &Pubkey::default());
3709 accounts.store_slow_uncached(0, &pubkey1, &account1);
3710 let account2 = AccountSharedData::new(41, 0, &Pubkey::default());
3711 accounts.store_slow_uncached(0, &pubkey2, &account2);
3712
3713 let ancestors = vec![(0, 0)].into_iter().collect();
3714 let all_pubkeys: HashSet<_> = vec![pubkey0, pubkey1, pubkey2].into_iter().collect();
3715
3716 let bank_id = 0;
3718 assert_eq!(
3719 accounts
3720 .load_largest_accounts(
3721 &ancestors,
3722 bank_id,
3723 0,
3724 &HashSet::new(),
3725 AccountAddressFilter::Exclude
3726 )
3727 .unwrap(),
3728 vec![]
3729 );
3730 assert_eq!(
3731 accounts
3732 .load_largest_accounts(
3733 &ancestors,
3734 bank_id,
3735 0,
3736 &all_pubkeys,
3737 AccountAddressFilter::Include
3738 )
3739 .unwrap(),
3740 vec![]
3741 );
3742
3743 assert!(pubkey1 > pubkey0);
3745 assert_eq!(
3746 accounts
3747 .load_largest_accounts(
3748 &ancestors,
3749 bank_id,
3750 1,
3751 &HashSet::new(),
3752 AccountAddressFilter::Exclude
3753 )
3754 .unwrap(),
3755 vec![(pubkey1, 42)]
3756 );
3757 assert_eq!(
3758 accounts
3759 .load_largest_accounts(
3760 &ancestors,
3761 bank_id,
3762 2,
3763 &HashSet::new(),
3764 AccountAddressFilter::Exclude
3765 )
3766 .unwrap(),
3767 vec![(pubkey1, 42), (pubkey0, 42)]
3768 );
3769 assert_eq!(
3770 accounts
3771 .load_largest_accounts(
3772 &ancestors,
3773 bank_id,
3774 3,
3775 &HashSet::new(),
3776 AccountAddressFilter::Exclude
3777 )
3778 .unwrap(),
3779 vec![(pubkey1, 42), (pubkey0, 42), (pubkey2, 41)]
3780 );
3781
3782 assert_eq!(
3784 accounts
3785 .load_largest_accounts(
3786 &ancestors,
3787 bank_id,
3788 6,
3789 &HashSet::new(),
3790 AccountAddressFilter::Exclude
3791 )
3792 .unwrap(),
3793 vec![(pubkey1, 42), (pubkey0, 42), (pubkey2, 41)]
3794 );
3795
3796 let exclude1: HashSet<_> = vec![pubkey1].into_iter().collect();
3798 assert_eq!(
3799 accounts
3800 .load_largest_accounts(
3801 &ancestors,
3802 bank_id,
3803 1,
3804 &exclude1,
3805 AccountAddressFilter::Exclude
3806 )
3807 .unwrap(),
3808 vec![(pubkey0, 42)]
3809 );
3810 assert_eq!(
3811 accounts
3812 .load_largest_accounts(
3813 &ancestors,
3814 bank_id,
3815 2,
3816 &exclude1,
3817 AccountAddressFilter::Exclude
3818 )
3819 .unwrap(),
3820 vec![(pubkey0, 42), (pubkey2, 41)]
3821 );
3822 assert_eq!(
3823 accounts
3824 .load_largest_accounts(
3825 &ancestors,
3826 bank_id,
3827 3,
3828 &exclude1,
3829 AccountAddressFilter::Exclude
3830 )
3831 .unwrap(),
3832 vec![(pubkey0, 42), (pubkey2, 41)]
3833 );
3834
3835 let include1_2: HashSet<_> = vec![pubkey1, pubkey2].into_iter().collect();
3837 assert_eq!(
3838 accounts
3839 .load_largest_accounts(
3840 &ancestors,
3841 bank_id,
3842 1,
3843 &include1_2,
3844 AccountAddressFilter::Include
3845 )
3846 .unwrap(),
3847 vec![(pubkey1, 42)]
3848 );
3849 assert_eq!(
3850 accounts
3851 .load_largest_accounts(
3852 &ancestors,
3853 bank_id,
3854 2,
3855 &include1_2,
3856 AccountAddressFilter::Include
3857 )
3858 .unwrap(),
3859 vec![(pubkey1, 42), (pubkey2, 41)]
3860 );
3861 assert_eq!(
3862 accounts
3863 .load_largest_accounts(
3864 &ancestors,
3865 bank_id,
3866 3,
3867 &include1_2,
3868 AccountAddressFilter::Include
3869 )
3870 .unwrap(),
3871 vec![(pubkey1, 42), (pubkey2, 41)]
3872 );
3873 }
3874
3875 fn zero_len_account_size() -> usize {
3876 std::mem::size_of::<AccountSharedData>() + std::mem::size_of::<Pubkey>()
3877 }
3878
3879 #[test]
3880 fn test_calc_scan_result_size() {
3881 for len in 0..3 {
3882 assert_eq!(
3883 Accounts::calc_scan_result_size(&AccountSharedData::new(
3884 0,
3885 len,
3886 &Pubkey::default()
3887 )),
3888 zero_len_account_size() + len
3889 );
3890 }
3891 }
3892
3893 #[test]
3894 fn test_maybe_abort_scan() {
3895 assert!(Accounts::maybe_abort_scan(ScanResult::Ok(vec![]), &ScanConfig::default()).is_ok());
3896 let config = ScanConfig::default().recreate_with_abort();
3897 assert!(Accounts::maybe_abort_scan(ScanResult::Ok(vec![]), &config).is_ok());
3898 config.abort();
3899 assert!(Accounts::maybe_abort_scan(ScanResult::Ok(vec![]), &config).is_err());
3900 }
3901
3902 #[test]
3903 fn test_accumulate_and_check_scan_result_size() {
3904 for (account, byte_limit_for_scan, result) in [
3905 (AccountSharedData::default(), zero_len_account_size(), false),
3906 (
3907 AccountSharedData::new(0, 1, &Pubkey::default()),
3908 zero_len_account_size(),
3909 true,
3910 ),
3911 (
3912 AccountSharedData::new(0, 2, &Pubkey::default()),
3913 zero_len_account_size() + 3,
3914 false,
3915 ),
3916 ] {
3917 let sum = AtomicUsize::default();
3918 assert_eq!(
3919 result,
3920 Accounts::accumulate_and_check_scan_result_size(
3921 &sum,
3922 &account,
3923 &Some(byte_limit_for_scan)
3924 )
3925 );
3926 assert!(Accounts::accumulate_and_check_scan_result_size(
3928 &sum,
3929 &account,
3930 &Some(byte_limit_for_scan)
3931 ));
3932 assert!(!Accounts::accumulate_and_check_scan_result_size(
3933 &sum, &account, &None
3934 ));
3935 }
3936 }
3937}