solana_runtime/
accounts.rs

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/// This structure handles synchronization for db
120#[derive(Debug, AbiExample)]
121pub struct Accounts {
122    /// Single global AccountsDb
123    pub accounts_db: Arc<AccountsDb>,
124
125    /// set of read-only and writable accounts which are currently
126    /// being processed by banking/replay threads
127    pub(crate) account_locks: Mutex<AccountLocks>,
128}
129
130// for the load instructions
131pub 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, // exclude all addresses matching the filter
145    Include, // only include addresses matching the filter
146}
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        // Copy all the accounts
266        let message = tx.message();
267        // NOTE: this check will never fail because `tx` is sanitized
268        if tx.signatures().is_empty() && fee != 0 {
269            Err(TransactionError::MissingSignatureForFee)
270        } else {
271            // There is no way to predict what program will execute without an error
272            // If a fee can pay for execution then the program will be scheduled
273            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                    // Fill in an empty account for the program slots.
284                    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                                // The upgradeable loader requires the derived ProgramData account
345                                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            // Appends the account_deps at the end of the accounts,
382            // this way they can be accessed in a uniform way.
383            // At places where only the accounts are needed,
384            // the account_deps are truncated using e.g:
385            // accounts.iter().take(message.account_keys.len())
386            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                // Should we ever allow a fees charge to zero a nonce account's
436                // balance. The state MUST be set to uninitialized in that case
437                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            // Add loader to chain
510            let program_owner = *program.owner();
511            account_indices.insert(0, program_account_index);
512            if bpf_loader_upgradeable::check_id(&program_owner) {
513                // The upgradeable loader requires the derived ProgramData account
514                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                    // Update nonce with fee-subtracted accounts
597                    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    /// Slow because lock is held for 1 operation instead of many
669    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    /// scans underlying accounts_db for this delta (slot) with a map function
696    ///   from LoadedAccount to B
697    /// returns only the latest/current version of B for this slot
698    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                // Cache only has one version per key, don't need to worry about versioning
707                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                        // Detected insertion is necessary, grabs the write lock to commit the write,
719                        match accum.entry(loaded_account_pubkey) {
720                            // Double check in case another thread interleaved a write between the read + write.
721                            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    /// only called at startup vs steady-state runtime
813    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    /// Only called from startup or test code.
840    #[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        // Don't ever load zero lamport accounts into runtime because
876        // the existence of zero-lamport accounts are never deterministic!!
877        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    /// Accumulate size of (pubkey + account) into sum.
951    /// Return true iff sum > 'byte_limit_for_scan'
952    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                            // total size of results exceeds size limit, so abort scan
1008                            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            "", // disable logging of this. We now parallelize it and this results in multiple parallel logs
1062            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    /// Slow because lock is held for 1 operation instead of many.
1072    /// WARNING: This noncached version is only to be used for tests/benchmarking
1073    /// as bypassing the cache in general is not supported
1074    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    /// This function will prevent multiple threads from modifying the same account state at the
1142    /// same time
1143    #[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    /// Once accounts are unlocked, new transactions that modify that state can enter the pipeline
1194    #[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    /// Store the accounts into the DB
1223    // allow(clippy) needed for various gating flags
1224    #[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    /// Add a slot to root.  Root slots cannot be purged
1257    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                // Don't store any accounts if tx failed to load
1280                continue;
1281            }
1282
1283            let execution_status = match &execution_results[i] {
1284                TransactionExecutionResult::Executed { details, .. } => &details.status,
1285                // Don't store any accounts if tx wasn't executed
1286                TransactionExecutionResult::NotExecuted(_) => continue,
1287            };
1288
1289            let maybe_nonce = match (execution_status, &*nonce) {
1290                (Ok(_), _) => None, // Success, don't do any additional nonce processing
1291                (Err(_), Some(nonce)) => {
1292                    Some((nonce, true /* rollback */))
1293                }
1294                (Err(_), None) => {
1295                    // Fees for failed transactions which don't use durable nonces are
1296                    // deducted in Bank::filter_program_errors_and_collect_fee
1297                    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                        // Add to the accounts to store
1343                        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                // The transaction failed which would normally drop the account
1366                // processing changes, since this account is now being included
1367                // in the accounts written back to the db, roll it back to
1368                // pre-processing state.
1369                *account = nonce.account().clone();
1370            }
1371
1372            // Advance the stored blockhash to prevent fee theft by someone
1373            // replaying nonce transactions that have failed with an
1374            // `InstructionError`.
1375            //
1376            // Since we know we are dealing with a valid nonce account,
1377            // unwrap is safe here
1378            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                    // Instruction error and fee-payer for this nonce tx is not
1393                    // the nonce account itself, rollback the fee payer to the
1394                    // fee-paid original state.
1395                    *account = fee_payer_account.clone();
1396                }
1397            }
1398
1399            false
1400        }
1401    } else {
1402        false
1403    }
1404}
1405
1406/// A set of utility functions used for testing and benchmarking
1407pub 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    // Only used by bench, not safe to call otherwise accounts can conflict with the
1426    // accounts cache!
1427    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        // use bins * 2 to get the first half of the range within bin 0
1581        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()); // <-- owner is not the system program
1728        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        // Fee leaves min_balance balance succeeds
1783        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        // Fee leaves zero balance fails
1798        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        // Fee leaves non-zero, but sub-min_balance balance fails
1813        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                        // +1 to skip first not loader account
2058                        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        // Load accounts owned by various programs into AccountsDb
2227        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, // only one executable marked as readonly
2274            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        // Mark executables as readonly
2289        message.account_keys = vec![key0, key1, key2]; // revert key change
2290        message.header.num_readonly_unsigned_accounts = 2; // mark both executables as readonly
2291        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()); // create mock bpf_loader_upgradeable
2349        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, // only one executable marked as readonly
2358            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        // Solution 1: include bpf_loader_upgradeable account
2373        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        // Solution 2: mark programdata as readonly
2384        message.account_keys = vec![key0, key1, key2]; // revert key change
2385        message.header.num_readonly_unsigned_accounts = 2; // mark both executables as readonly
2386        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, // only the program marked as readonly
2431            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        // Solution 1: include bpf_loader_upgradeable account
2446        let mut account = AccountSharedData::new(40, 1, &native_loader::id()); // create mock bpf_loader_upgradeable
2447        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        // Solution 2: mark programdata as readonly
2469        message.account_keys = vec![key0, key1, key2]; // revert key change
2470        message.header.num_readonly_unsigned_accounts = 2; // extend readonly set to include programdata
2471        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        // Allow up to MAX_TX_ACCOUNT_LOCKS
2562        {
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        // Disallow over MAX_TX_ACCOUNT_LOCKS
2584        {
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()); // Read-only account (keypair1) can be referenced multiple times
2677        assert!(results1[1].is_err()); // Read-only account (keypair1) cannot also be locked as writable
2678        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()); // Now keypair1 account can be locked as writable
2703
2704        // Check that read-only lock with zero references is deleted
2705        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, // All accounts marked as writable
2830            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        // Instruction program-id account demoted to readonly
2839        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        // Non-program accounts remain writable
2850        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()); // Read-only account (keypair0) can be referenced multiple times
2933        assert!(results[1].is_err()); // is not locked due to !qos_results[1].is_ok()
2934        assert!(results[2].is_ok()); // Read-only account (keypair0) can be referenced multiple times
2935
2936        // verify that keypair0 read-only lock twice (for tx0 and tx2)
2937        assert_eq!(
2938            *accounts
2939                .account_locks
2940                .lock()
2941                .unwrap()
2942                .readonly_locks
2943                .get(&keypair0.pubkey())
2944                .unwrap(),
2945            2
2946        );
2947        // verify that keypair2 (for tx1) is not write-locked
2948        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        // check all locks to be removed
2959        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, // preserve_rent_epoch_for_rent_exempt_accounts
3062        );
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        // Ensure readonly_lock reflects lock
3080        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        // Verify expect_account's relationship
3243        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        // Wrong key
3342        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, // preserve_rent_epoch_for_rent_exempt_accounts
3546        );
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, // preserve_rent_epoch_for_rent_exempt_accounts
3661        );
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        /* This test assumes pubkey0 < pubkey1 < pubkey2.
3690         * But the keys created with new_unique() does not gurantee this
3691         * order because of the endianness.  new_unique() calls add 1 at each
3692         * key generaration as the little endian integer.  A pubkey stores its
3693         * value in a 32-byte array bytes, and its eq-partial trait considers
3694         * the lower-address bytes more significant, which is the big-endian
3695         * order.
3696         * So, sort first to ensure the order assumption holds.
3697         */
3698        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        // num == 0 should always return empty set
3717        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        // list should be sorted by balance, then pubkey, descending
3744        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        // larger num should not affect results
3783        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        // AccountAddressFilter::Exclude should exclude entry
3797        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        // AccountAddressFilter::Include should limit entries
3836        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            // calling a second time should accumulate above the threshold
3927            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}